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>

  9: PetscInt VecGetSubVectorSavedStateId = -1;

 11: #if PetscDefined(USE_DEBUG)
 12: // this is a no-op '0' macro in optimized builds
 13: PetscErrorCode VecValidValues_Internal(Vec vec, PetscInt argnum, PetscBool begin)
 14: {
 15:   PetscFunctionBegin;
 16:   if (vec->petscnative || vec->ops->getarray) {
 17:     PetscInt           n;
 18:     const PetscScalar *x;
 19:     PetscOffloadMask   mask;

 21:     PetscCall(VecGetOffloadMask(vec, &mask));
 22:     if (!PetscOffloadHost(mask)) PetscFunctionReturn(PETSC_SUCCESS);
 23:     PetscCall(VecGetLocalSize(vec, &n));
 24:     PetscCall(VecGetArrayRead(vec, &x));
 25:     for (PetscInt i = 0; i < n; i++) {
 26:       if (begin) {
 27:         PetscCheck(!PetscIsInfOrNanScalar(x[i]), PETSC_COMM_SELF, PETSC_ERR_FP, "Vec entry at local location %" PetscInt_FMT " is not-a-number or infinite at beginning of function: Parameter number %" PetscInt_FMT, i, argnum);
 28:       } else {
 29:         PetscCheck(!PetscIsInfOrNanScalar(x[i]), PETSC_COMM_SELF, PETSC_ERR_FP, "Vec entry at local location %" PetscInt_FMT " is not-a-number or infinite at end of function: Parameter number %" PetscInt_FMT, i, argnum);
 30:       }
 31:     }
 32:     PetscCall(VecRestoreArrayRead(vec, &x));
 33:   }
 34:   PetscFunctionReturn(PETSC_SUCCESS);
 35: }
 36: #endif

 38: /*@
 39:    VecMaxPointwiseDivide - Computes the maximum of the componentwise division `max = max_i abs(x[i]/y[i])`.

 41:    Logically Collective

 43:    Input Parameters:
 44: +  x - the numerators
 45: -  y - the denominators

 47:    Output Parameter:
 48: .  max - the result

 50:    Level: advanced

 52:    Notes:
 53:    `x` and `y` may be the same vector

 55:   if a particular `y[i]` is zero, it is treated as 1 in the above formula

 57: .seealso: [](chapter_vectors), `Vec`, `VecPointwiseDivide()`, `VecPointwiseMult()`, `VecPointwiseMax()`, `VecPointwiseMin()`, `VecPointwiseMaxAbs()`
 58: @*/
 59: PetscErrorCode VecMaxPointwiseDivide(Vec x, Vec y, PetscReal *max)
 60: {
 61:   PetscFunctionBegin;
 67:   PetscCheckSameTypeAndComm(x, 1, y, 2);
 68:   VecCheckSameSize(x, 1, y, 2);
 69:   VecCheckAssembled(x);
 70:   VecCheckAssembled(y);
 71:   PetscCall(VecLockReadPush(x));
 72:   PetscCall(VecLockReadPush(y));
 73:   PetscUseTypeMethod(x, maxpointwisedivide, y, max);
 74:   PetscCall(VecLockReadPop(x));
 75:   PetscCall(VecLockReadPop(y));
 76:   PetscFunctionReturn(PETSC_SUCCESS);
 77: }

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

 82:    Collective

 84:    Input Parameters:
 85: +  x - first vector
 86: -  y - second vector

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

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

 98:    Level: intermediate

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

107:    Use `VecTDot()` for the indefinite form
108: $     val = (x,y) = y^T x,
109:    where y^T denotes the transpose of y.

111: .seealso: [](chapter_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDotRealPart()`
112: @*/
113: PetscErrorCode VecDot(Vec x, Vec y, PetscScalar *val)
114: {
115:   PetscFunctionBegin;
121:   PetscCheckSameTypeAndComm(x, 1, y, 2);
122:   VecCheckSameSize(x, 1, y, 2);
123:   VecCheckAssembled(x);
124:   VecCheckAssembled(y);

126:   PetscCall(VecLockReadPush(x));
127:   PetscCall(VecLockReadPush(y));
128:   PetscCall(PetscLogEventBegin(VEC_Dot, x, y, 0, 0));
129:   PetscUseTypeMethod(x, dot, y, val);
130:   PetscCall(PetscLogEventEnd(VEC_Dot, x, y, 0, 0));
131:   PetscCall(VecLockReadPop(x));
132:   PetscCall(VecLockReadPop(y));
133:   PetscFunctionReturn(PETSC_SUCCESS);
134: }

136: /*@
137:    VecDotRealPart - Computes the real part of the vector dot product.

139:    Collective

141:    Input Parameters:
142: +  x - first vector
143: -  y - second vector

145:    Output Parameter:
146: .  val - the real part of the dot product;

148:    Level: intermediate

150:    Performance Issues:
151: .vb
152:     per-processor memory bandwidth
153:     interprocessor latency
154:     work load imbalance that causes certain processes to arrive much earlier than others
155: .ve

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

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

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

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

168: .seealso: [](chapter_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDot()`, `VecDotNorm2()`
169: @*/
170: PetscErrorCode VecDotRealPart(Vec x, Vec y, PetscReal *val)
171: {
172:   PetscScalar fdot;

174:   PetscFunctionBegin;
175:   PetscCall(VecDot(x, y, &fdot));
176:   *val = PetscRealPart(fdot);
177:   PetscFunctionReturn(PETSC_SUCCESS);
178: }

180: /*@
181:    VecNorm  - Computes the vector norm.

183:    Collective

185:    Input Parameters:
186: +  x - the vector
187: -  type - the type of the norm requested

189:    Output Parameter:
190: .  val - the norm

192:    Values of NormType:
193: +     `NORM_1` - sum_i |x[i]|
194: .     `NORM_2` - sqrt(sum_i |x[i]|^2)
195: .     `NORM_INFINITY` - max_i |x[i]|
196: -     `NORM_1_AND_2` - computes efficiently both  `NORM_1` and `NORM_2` and stores them each in an output array

198:     Level: intermediate

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

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

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

217: .seealso: [](chapter_vectors), `Vec`, `NormType`, `VecDot()`, `VecTDot()`, `VecDotBegin()`, `VecDotEnd()`, `VecNormAvailable()`,
218:           `VecNormBegin()`, `VecNormEnd()`, `NormType()`
219: @*/
220: PetscErrorCode VecNorm(Vec x, NormType type, PetscReal *val)
221: {
222:   PetscBool flg = PETSC_TRUE;

224:   PetscFunctionBegin;
227:   VecCheckAssembled(x);

231:   /* Cached data? */
232:   PetscCall(VecNormAvailable(x, type, &flg, val));
233:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

235:   PetscCall(VecLockReadPush(x));
236:   PetscCall(PetscLogEventBegin(VEC_Norm, x, 0, 0, 0));
237:   PetscUseTypeMethod(x, norm, type, val);
238:   PetscCall(PetscLogEventEnd(VEC_Norm, x, 0, 0, 0));
239:   PetscCall(VecLockReadPop(x));

241:   if (type != NORM_1_AND_2) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[type], *val));
242:   PetscFunctionReturn(PETSC_SUCCESS);
243: }

245: /*@
246:    VecNormAvailable  - Returns the vector norm if it is already known. That is, it has been previously computed and cached in the vector

248:    Not Collective

250:    Input Parameters:
251: +  x - the vector
252: -  type - one of `NORM_1` (sum_i |x[i]|), `NORM_2` sqrt(sum_i (x[i])^2), `NORM_INFINITY` max_i |x[i]|.  Also available
253:           `NORM_1_AND_2`, which computes both norms and stores them
254:           in a two element array.

256:    Output Parameters:
257: +  available - `PETSC_TRUE` if the val returned is valid
258: -  val - the norm

260:    Level: intermediate

262:    Performance Issues:
263: .vb
264:     per-processor memory bandwidth
265:     interprocessor latency
266:     work load imbalance that causes certain processes to arrive much earlier than others
267: .ve

269:    Developer Note:
270:    `PETSC_HAVE_SLOW_BLAS_NORM2` will cause a C (loop unrolled) version of the norm to be used, rather
271:    than the BLAS. This should probably only be used when one is using the FORTRAN BLAS routines
272:    (as opposed to vendor provided) because the FORTRAN BLAS `NRM2()` routine is very slow.

274: .seealso: [](chapter_vectors), `Vec`, `VecDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`,
275:           `VecNormBegin()`, `VecNormEnd()`
276: @*/
277: PetscErrorCode VecNormAvailable(Vec x, NormType type, PetscBool *available, PetscReal *val)
278: {
279:   PetscFunctionBegin;

285:   if (type == NORM_1_AND_2) {
286:     *available = PETSC_FALSE;
287:   } else {
288:     PetscCall(PetscObjectComposedDataGetReal((PetscObject)x, NormIds[type], *val, *available));
289:   }
290:   PetscFunctionReturn(PETSC_SUCCESS);
291: }

293: /*@
294:    VecNormalize - Normalizes a vector by its 2-norm.

296:    Collective

298:    Input Parameter:
299: .  x - the vector

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

304:    Level: intermediate

306: .seealso: [](chapter_vectors), `Vec`, `VecNorm()`, `NORM_2`, `NormType`
307: @*/
308: PetscErrorCode VecNormalize(Vec x, PetscReal *val)
309: {
310:   PetscReal norm;

312:   PetscFunctionBegin;
315:   PetscCall(VecSetErrorIfLocked(x, 1));
317:   PetscCall(PetscLogEventBegin(VEC_Normalize, x, 0, 0, 0));
318:   PetscCall(VecNorm(x, NORM_2, &norm));
319:   if (norm == 0.0) {
320:     PetscCall(PetscInfo(x, "Vector of zero norm can not be normalized; Returning only the zero norm\n"));
321:   } else if (norm != 1.0) {
322:     PetscCall(VecScale(x, 1.0 / norm));
323:   }
324:   PetscCall(PetscLogEventEnd(VEC_Normalize, x, 0, 0, 0));
325:   if (val) *val = norm;
326:   PetscFunctionReturn(PETSC_SUCCESS);
327: }

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

332:    Collective

334:    Input Parameter:
335: .  x - the vector

337:    Output Parameters:
338: +  p - the index of `val` (pass `NULL` if you don't want this) in the vector
339: -  val - the maximum component

341:    Level: intermediate

343:  Notes:
344:    Returns the value `PETSC_MIN_REAL` and negative `p` if the vector is of length 0.

346:    Returns the smallest index with the maximum value

348: .seealso: [](chapter_vectors), `Vec`, `VecNorm()`, `VecMin()`
349: @*/
350: PetscErrorCode VecMax(Vec x, PetscInt *p, PetscReal *val)
351: {
352:   PetscFunctionBegin;
355:   VecCheckAssembled(x);
358:   PetscCall(VecLockReadPush(x));
359:   PetscCall(PetscLogEventBegin(VEC_Max, x, 0, 0, 0));
360:   PetscUseTypeMethod(x, max, p, val);
361:   PetscCall(PetscLogEventEnd(VEC_Max, x, 0, 0, 0));
362:   PetscCall(VecLockReadPop(x));
363:   PetscFunctionReturn(PETSC_SUCCESS);
364: }

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

369:    Collective

371:    Input Parameter:
372: .  x - the vector

374:    Output Parameters:
375: +  p - the index of `val` (pass `NULL` if you don't want this location) in the vector
376: -  val - the minimum component

378:    Level: intermediate

380:    Notes:
381:    Returns the value `PETSC_MAX_REAL` and negative `p` if the vector is of length 0.

383:    This returns the smallest index with the minimum value

385: .seealso: [](chapter_vectors), `Vec`, `VecMax()`
386: @*/
387: PetscErrorCode VecMin(Vec x, PetscInt *p, PetscReal *val)
388: {
389:   PetscFunctionBegin;
392:   VecCheckAssembled(x);
395:   PetscCall(VecLockReadPush(x));
396:   PetscCall(PetscLogEventBegin(VEC_Min, x, 0, 0, 0));
397:   PetscUseTypeMethod(x, min, p, val);
398:   PetscCall(PetscLogEventEnd(VEC_Min, x, 0, 0, 0));
399:   PetscCall(VecLockReadPop(x));
400:   PetscFunctionReturn(PETSC_SUCCESS);
401: }

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

407:    Collective

409:    Input Parameters:
410: +  x - first vector
411: -  y - second vector

413:    Output Parameter:
414: .  val - the dot product

416:    Level: intermediate

418:    Notes for Users of Complex Numbers:
419:    For complex vectors, VecTDot() computes the indefinite form
420: $     val = (x,y) = y^T x,
421:    where y^T denotes the transpose of y.

423:    Use VecDot() for the inner product
424: $     val = (x,y) = y^H x,
425:    where y^H denotes the conjugate transpose of y.

427: .seealso: [](chapter_vectors), `Vec`, `VecDot()`, `VecMTDot()`
428: @*/
429: PetscErrorCode VecTDot(Vec x, Vec y, PetscScalar *val)
430: {
431:   PetscFunctionBegin;
437:   PetscCheckSameTypeAndComm(x, 1, y, 2);
438:   VecCheckSameSize(x, 1, y, 2);
439:   VecCheckAssembled(x);
440:   VecCheckAssembled(y);

442:   PetscCall(VecLockReadPush(x));
443:   PetscCall(VecLockReadPush(y));
444:   PetscCall(PetscLogEventBegin(VEC_TDot, x, y, 0, 0));
445:   PetscUseTypeMethod(x, tdot, y, val);
446:   PetscCall(PetscLogEventEnd(VEC_TDot, x, y, 0, 0));
447:   PetscCall(VecLockReadPop(x));
448:   PetscCall(VecLockReadPop(y));
449:   PetscFunctionReturn(PETSC_SUCCESS);
450: }

452: /*@
453:    VecScale - Scales a vector.

455:    Not Collective

457:    Input Parameters:
458: +  x - the vector
459: -  alpha - the scalar

461:    Level: intermediate

463:  Note:
464:    For a vector with n components, `VecScale()` computes  x[i] = alpha * x[i], for i=1,...,n.

466: .seealso: [](chapter_vectors), `Vec`, `VecSet()`
467: @*/
468: PetscErrorCode VecScale(Vec x, PetscScalar alpha)
469: {
470:   PetscReal norms[4];
471:   PetscBool flgs[4];

473:   PetscFunctionBegin;
476:   VecCheckAssembled(x);
477:   PetscCall(VecSetErrorIfLocked(x, 1));
478:   if (alpha == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);

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

483:   PetscCall(PetscLogEventBegin(VEC_Scale, x, 0, 0, 0));
484:   PetscUseTypeMethod(x, scale, alpha);
485:   PetscCall(PetscLogEventEnd(VEC_Scale, x, 0, 0, 0));

487:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
488:   /* put the scaled stashed norms back into the Vec */
489:   for (PetscInt i = 0; i < 4; i++) {
490:     if (flgs[i]) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[i], PetscAbsScalar(alpha) * norms[i]));
491:   }
492:   PetscFunctionReturn(PETSC_SUCCESS);
493: }

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

498:    Logically Collective

500:    Input Parameters:
501: +  x  - the vector
502: -  alpha - the scalar

504:    Level: beginner

506:    Notes:
507:    For a vector of dimension n, `VecSet()` sets x[i] = alpha, for i=1,...,n,
508:    so that all vector entries then equal the identical
509:    scalar value, `alpha`.  Use the more general routine
510:    `VecSetValues()` to set different vector entries.

512:    You CANNOT call this after you have called `VecSetValues()` but before you call
513:    `VecAssemblyBegin()`

515: .seealso: [](chapter_vectors), `Vec`, `VecSetValues()`, `VecSetValuesBlocked()`, `VecSetRandom()`
516: @*/
517: PetscErrorCode VecSet(Vec x, PetscScalar alpha)
518: {
519:   PetscFunctionBegin;
522:   VecCheckAssembled(x);
524:   PetscCall(VecSetErrorIfLocked(x, 1));

526:   PetscCall(PetscLogEventBegin(VEC_Set, x, 0, 0, 0));
527:   PetscUseTypeMethod(x, set, alpha);
528:   PetscCall(PetscLogEventEnd(VEC_Set, x, 0, 0, 0));
529:   PetscCall(PetscObjectStateIncrease((PetscObject)x));

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

533:   {
534:     PetscReal      val = PetscAbsScalar(alpha);
535:     const PetscInt N   = x->map->N;

537:     if (N == 0) {
538:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_1], 0.0l));
539:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], 0.0));
540:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_2], 0.0));
541:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_FROBENIUS], 0.0));
542:     } else if (val > PETSC_MAX_REAL / N) {
543:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], val));
544:     } else {
545:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_1], N * val));
546:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], val));
547:       val *= PetscSqrtReal((PetscReal)N);
548:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_2], val));
549:       PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_FROBENIUS], val));
550:     }
551:   }
552:   PetscFunctionReturn(PETSC_SUCCESS);
553: }

555: /*@
556:    VecAXPY - Computes `y = alpha x + y`.

558:    Logically Collective

560:    Input Parameters:
561: +  alpha - the scalar
562: .  x - vector scale by `alpha`
563: -  y - vector accumulated into

565:    Output Parameter:
566: .  y - output vector

568:    Level: intermediate

570:    Notes:
571:     This routine is optimized for alpha of 0.0, otherwise it calls the BLAS routine
572: .vb
573:     VecAXPY(y,alpha,x)                   y = alpha x           +      y
574:     VecAYPX(y,beta,x)                    y =       x           + beta y
575:     VecAXPBY(y,alpha,beta,x)             y = alpha x           + beta y
576:     VecWAXPY(w,alpha,x,y)                w = alpha x           +      y
577:     VecAXPBYPCZ(w,alpha,beta,gamma,x,y)  z = alpha x           + beta y + gamma z
578:     VecMAXPY(y,nv,alpha[],x[])           y = sum alpha[i] x[i] +      y
579: .ve

581: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
582: @*/
583: PetscErrorCode VecAXPY(Vec y, PetscScalar alpha, Vec x)
584: {
585:   PetscFunctionBegin;
590:   PetscCheckSameTypeAndComm(x, 3, y, 1);
591:   VecCheckSameSize(x, 3, y, 1);
592:   VecCheckAssembled(x);
593:   VecCheckAssembled(y);
595:   if (alpha == (PetscScalar)0.0) PetscFunctionReturn(PETSC_SUCCESS);
596:   PetscCall(VecSetErrorIfLocked(y, 1));
597:   if (x == y) {
598:     PetscCall(VecScale(y, alpha + 1.0));
599:     PetscFunctionReturn(PETSC_SUCCESS);
600:   }
601:   PetscCall(VecLockReadPush(x));
602:   PetscCall(PetscLogEventBegin(VEC_AXPY, x, y, 0, 0));
603:   PetscUseTypeMethod(y, axpy, alpha, x);
604:   PetscCall(PetscLogEventEnd(VEC_AXPY, x, y, 0, 0));
605:   PetscCall(VecLockReadPop(x));
606:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
607:   PetscFunctionReturn(PETSC_SUCCESS);
608: }

610: /*@
611:    VecAYPX - Computes `y = x + beta y`.

613:    Logically Collective

615:    Input Parameters:
616: +  beta - the scalar
617: .  x - the unscaled vector
618: -  y - the vector to be scaled

620:    Output Parameter:
621: .  y - output vector

623:    Level: intermediate

625:    Developer Note:
626:     The implementation is optimized for `beta` of -1.0, 0.0, and 1.0

628: .seealso: [](chapter_vectors), `Vec`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
629: @*/
630: PetscErrorCode VecAYPX(Vec y, PetscScalar beta, Vec x)
631: {
632:   PetscFunctionBegin;
637:   PetscCheckSameTypeAndComm(x, 3, y, 1);
638:   VecCheckSameSize(x, 1, y, 3);
639:   VecCheckAssembled(x);
640:   VecCheckAssembled(y);
642:   PetscCall(VecSetErrorIfLocked(y, 1));
643:   if (x == y) {
644:     PetscCall(VecScale(y, beta + 1.0));
645:     PetscFunctionReturn(PETSC_SUCCESS);
646:   }
647:   PetscCall(VecLockReadPush(x));
648:   if (beta == (PetscScalar)0.0) {
649:     PetscCall(VecCopy(x, y));
650:   } else {
651:     PetscCall(PetscLogEventBegin(VEC_AYPX, x, y, 0, 0));
652:     PetscUseTypeMethod(y, aypx, beta, x);
653:     PetscCall(PetscLogEventEnd(VEC_AYPX, x, y, 0, 0));
654:     PetscCall(PetscObjectStateIncrease((PetscObject)y));
655:   }
656:   PetscCall(VecLockReadPop(x));
657:   PetscFunctionReturn(PETSC_SUCCESS);
658: }

660: /*@
661:    VecAXPBY - Computes `y = alpha x + beta y`.

663:    Logically Collective

665:    Input Parameters:
666: +  alpha - first scalar
667: .  beta - second scalar
668: .  x - the first scaled vector
669: -  y - the second scaled vector

671:    Output Parameter:
672: .  y - output vector

674:    Level: intermediate

676:    Developer Note:
677:    The implementation is optimized for `alpha` and/or `beta` values of 0.0 and 1.0

679: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`
680: @*/
681: PetscErrorCode VecAXPBY(Vec y, PetscScalar alpha, PetscScalar beta, Vec x)
682: {
683:   PetscFunctionBegin;
688:   PetscCheckSameTypeAndComm(x, 4, y, 1);
689:   VecCheckSameSize(y, 1, x, 4);
690:   VecCheckAssembled(x);
691:   VecCheckAssembled(y);
694:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);
695:   if (x == y) {
696:     PetscCall(VecScale(y, alpha + beta));
697:     PetscFunctionReturn(PETSC_SUCCESS);
698:   }

700:   PetscCall(VecSetErrorIfLocked(y, 1));
701:   PetscCall(VecLockReadPush(x));
702:   PetscCall(PetscLogEventBegin(VEC_AXPY, y, x, 0, 0));
703:   PetscUseTypeMethod(y, axpby, alpha, beta, x);
704:   PetscCall(PetscLogEventEnd(VEC_AXPY, y, x, 0, 0));
705:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
706:   PetscCall(VecLockReadPop(x));
707:   PetscFunctionReturn(PETSC_SUCCESS);
708: }

710: /*@
711:    VecAXPBYPCZ - Computes `z = alpha x + beta y + gamma z`

713:    Logically Collective

715:    Input Parameters:
716: +  alpha - first scalar
717: .  beta - second scalar
718: .  gamma - third scalar
719: .  x  - first vector
720: .  y  - second vector
721: -  z  - third vector

723:    Output Parameter:
724: .  z - output vector

726:    Level: intermediate

728:    Note:
729:    `x`, `y` and `z` must be different vectors

731:    Developer Note:
732:     The implementation is optimized for `alpha` of 1.0 and `gamma` of 1.0 or 0.0

734: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBY()`
735: @*/
736: PetscErrorCode VecAXPBYPCZ(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y)
737: {
738:   PetscFunctionBegin;
745:   PetscCheckSameTypeAndComm(x, 5, y, 6);
746:   PetscCheckSameTypeAndComm(x, 5, z, 1);
747:   VecCheckSameSize(x, 1, y, 5);
748:   VecCheckSameSize(x, 1, z, 6);
749:   PetscCheck(x != y && x != z, PetscObjectComm((PetscObject)x), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
750:   PetscCheck(y != z, PetscObjectComm((PetscObject)y), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
751:   VecCheckAssembled(x);
752:   VecCheckAssembled(y);
753:   VecCheckAssembled(z);
757:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);

759:   PetscCall(VecSetErrorIfLocked(z, 1));
760:   PetscCall(VecLockReadPush(x));
761:   PetscCall(VecLockReadPush(y));
762:   PetscCall(PetscLogEventBegin(VEC_AXPBYPCZ, x, y, z, 0));
763:   PetscUseTypeMethod(z, axpbypcz, alpha, beta, gamma, x, y);
764:   PetscCall(PetscLogEventEnd(VEC_AXPBYPCZ, x, y, z, 0));
765:   PetscCall(PetscObjectStateIncrease((PetscObject)z));
766:   PetscCall(VecLockReadPop(x));
767:   PetscCall(VecLockReadPop(y));
768:   PetscFunctionReturn(PETSC_SUCCESS);
769: }

771: /*@
772:    VecWAXPY - Computes `w = alpha x + y`.

774:    Logically Collective

776:    Input Parameters:
777: +  alpha - the scalar
778: .  x  - first vector, multiplied by `alpha`
779: -  y  - second vector

781:    Output Parameter:
782: .  w - the result

784:    Level: intermediate

786:    Note:
787:     `w` cannot be either `x` or `y`, but `x` and `y` can be the same

789:    Developer Note:
790:     The implementation is optimized for alpha of -1.0, 0.0, and 1.0

792: .seealso: [](chapter_vectors), `Vec`, `VecAXPY()`, `VecAYPX()`, `VecAXPBY()`, `VecMAXPY()`, `VecAXPBYPCZ()`
793: @*/
794: PetscErrorCode VecWAXPY(Vec w, PetscScalar alpha, Vec x, Vec y)
795: {
796:   PetscFunctionBegin;
803:   PetscCheckSameTypeAndComm(x, 3, y, 4);
804:   PetscCheckSameTypeAndComm(y, 4, w, 1);
805:   VecCheckSameSize(x, 3, y, 4);
806:   VecCheckSameSize(x, 3, w, 1);
807:   PetscCheck(w != y, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector y, suggest VecAXPY()");
808:   PetscCheck(w != x, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector x, suggest VecAYPX()");
809:   VecCheckAssembled(x);
810:   VecCheckAssembled(y);
812:   PetscCall(VecSetErrorIfLocked(w, 1));

814:   PetscCall(VecLockReadPush(x));
815:   PetscCall(VecLockReadPush(y));
816:   if (alpha == (PetscScalar)0.0) {
817:     PetscCall(VecCopy(y, w));
818:   } else {
819:     PetscCall(PetscLogEventBegin(VEC_WAXPY, x, y, w, 0));
820:     PetscUseTypeMethod(w, waxpy, alpha, x, y);
821:     PetscCall(PetscLogEventEnd(VEC_WAXPY, x, y, w, 0));
822:     PetscCall(PetscObjectStateIncrease((PetscObject)w));
823:   }
824:   PetscCall(VecLockReadPop(x));
825:   PetscCall(VecLockReadPop(y));
826:   PetscFunctionReturn(PETSC_SUCCESS);
827: }

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

832:    Not Collective

834:    Input Parameters:
835: +  x - vector to insert in
836: .  ni - number of elements to add
837: .  ix - indices where to add
838: .  y - array of values
839: -  iora - either `INSERT_VALUES` to replace the current values or `ADD_VALUES` to add values to any existing entries

841:    Level: beginner

843:    Notes:
844: .vb
845:    `VecSetValues()` sets x[ix[i]] = y[i], for i=0,...,ni-1.
846: .ve

848:    Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
849:    options cannot be mixed without intervening calls to the assembly
850:    routines.

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

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

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

863: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesLocal()`,
864:           `VecSetValue()`, `VecSetValuesBlocked()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `VecGetValues()`
865: @*/
866: PetscErrorCode VecSetValues(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
867: {
868:   PetscFunctionBeginHot;
870:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);

875:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
876:   PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
877:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
878:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
879:   PetscFunctionReturn(PETSC_SUCCESS);
880: }

882: /*@C
883:    VecGetValues - Gets values from certain locations of a vector. Currently
884:           can only get values on the same processor on which they are owned

886:     Not Collective

888:    Input Parameters:
889: +  x - vector to get values from
890: .  ni - number of elements to get
891: -  ix - indices where to get them from (in global 1d numbering)

893:    Output Parameter:
894: .   y - array of values

896:    Level: beginner

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

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

903:    `VecAssemblyBegin()` and `VecAssemblyEnd()`  MUST be called before calling this if `VecSetValues()` or related routine has been called

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

907:    If you call `VecSetOption`(x, `VEC_IGNORE_NEGATIVE_INDICES`,`PETSC_TRUE`),
908:    negative indices may be passed in ix. These rows are
909:    simply ignored.

911: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`
912: @*/
913: PetscErrorCode VecGetValues(Vec x, PetscInt ni, const PetscInt ix[], PetscScalar y[])
914: {
915:   PetscFunctionBegin;
917:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
921:   VecCheckAssembled(x);
922:   PetscUseTypeMethod(x, getvalues, ni, ix, y);
923:   PetscFunctionReturn(PETSC_SUCCESS);
924: }

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

929:    Not Collective

931:    Input Parameters:
932: +  x - vector to insert in
933: .  ni - number of blocks to add
934: .  ix - indices where to add in block count, rather than element count
935: .  y - array of values
936: -  iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES`, adds values to any existing entries

938:    Level: intermediate

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

944:    Calls to `VecSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
945:    options cannot be mixed without intervening calls to the assembly
946:    routines.

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

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

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

958: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesBlockedLocal()`,
959:           `VecSetValues()`
960: @*/
961: PetscErrorCode VecSetValuesBlocked(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
962: {
963:   PetscFunctionBeginHot;
965:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);

970:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
971:   PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
972:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
973:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
974:   PetscFunctionReturn(PETSC_SUCCESS);
975: }

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

981:    Not Collective

983:    Input Parameters:
984: +  x - vector to insert in
985: .  ni - number of elements to add
986: .  ix - indices where to add
987: .  y - array of values
988: -  iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries

990:    Level: intermediate

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

995:    Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
996:    options cannot be mixed without intervening calls to the assembly
997:    routines.

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

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

1004: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetLocalToGlobalMapping()`,
1005:           `VecSetValuesBlockedLocal()`
1006: @*/
1007: PetscErrorCode VecSetValuesLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1008: {
1009:   PetscInt lixp[128], *lix = lixp;

1011:   PetscFunctionBeginHot;
1013:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);

1018:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1019:   if (!x->ops->setvalueslocal) {
1020:     if (x->map->mapping) {
1021:       if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1022:       PetscCall(ISLocalToGlobalMappingApply(x->map->mapping, ni, (PetscInt *)ix, lix));
1023:       PetscUseTypeMethod(x, setvalues, ni, lix, y, iora);
1024:       if (ni > 128) PetscCall(PetscFree(lix));
1025:     } else PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
1026:   } else PetscUseTypeMethod(x, setvalueslocal, ni, ix, y, iora);
1027:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1028:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1029:   PetscFunctionReturn(PETSC_SUCCESS);
1030: }

1032: /*@
1033:    VecSetValuesBlockedLocal - Inserts or adds values into certain locations of a vector,
1034:    using a local ordering of the nodes.

1036:    Not Collective

1038:    Input Parameters:
1039: +  x - vector to insert in
1040: .  ni - number of blocks to add
1041: .  ix - indices where to add in block count, not element count
1042: .  y - array of values
1043: -  iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries

1045:    Level: intermediate

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

1051:    Calls to `VecSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1052:    options cannot be mixed without intervening calls to the assembly
1053:    routines.

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

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

1060: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetValuesBlocked()`,
1061:           `VecSetLocalToGlobalMapping()`
1062: @*/
1063: PetscErrorCode VecSetValuesBlockedLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1064: {
1065:   PetscInt lixp[128], *lix = lixp;

1067:   PetscFunctionBeginHot;
1069:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1073:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1074:   if (x->map->mapping) {
1075:     if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1076:     PetscCall(ISLocalToGlobalMappingApplyBlock(x->map->mapping, ni, (PetscInt *)ix, lix));
1077:     PetscUseTypeMethod(x, setvaluesblocked, ni, lix, y, iora);
1078:     if (ni > 128) PetscCall(PetscFree(lix));
1079:   } else {
1080:     PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1081:   }
1082:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1083:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1084:   PetscFunctionReturn(PETSC_SUCCESS);
1085: }

1087: static PetscErrorCode VecMXDot_Private(Vec x, PetscInt nv, const Vec y[], PetscScalar result[], PetscErrorCode (*mxdot)(Vec, PetscInt, const Vec[], PetscScalar[]), PetscLogEvent event)
1088: {
1089:   PetscFunctionBegin;
1092:   VecCheckAssembled(x);
1094:   if (!nv) PetscFunctionReturn(PETSC_SUCCESS);
1096:   for (PetscInt i = 0; i < nv; ++i) {
1099:     PetscCheckSameTypeAndComm(x, 1, y[i], 3);
1100:     VecCheckSameSize(x, 1, y[i], 3);
1101:     VecCheckAssembled(y[i]);
1102:     PetscCall(VecLockReadPush(y[i]));
1103:   }

1107:   PetscCall(VecLockReadPush(x));
1108:   PetscCall(PetscLogEventBegin(event, x, *y, 0, 0));
1109:   PetscCall((*mxdot)(x, nv, y, result));
1110:   PetscCall(PetscLogEventEnd(event, x, *y, 0, 0));
1111:   PetscCall(VecLockReadPop(x));
1112:   for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(y[i]));
1113:   PetscFunctionReturn(PETSC_SUCCESS);
1114: }

1116: /*@
1117:    VecMTDot - Computes indefinite vector multiple dot products.
1118:    That is, it does NOT use the complex conjugate.

1120:    Collective

1122:    Input Parameters:
1123: +  x - one vector
1124: .  nv - number of vectors
1125: -  y - array of vectors.  Note that vectors are pointers

1127:    Output Parameter:
1128: .  val - array of the dot products

1130:    Level: intermediate

1132:    Notes for Users of Complex Numbers:
1133:    For complex vectors, `VecMTDot()` computes the indefinite form
1134: $      val = (x,y) = y^T x,
1135:    where y^T denotes the transpose of y.

1137:    Use `VecMDot()` for the inner product
1138: $      val = (x,y) = y^H x,
1139:    where y^H denotes the conjugate transpose of y.

1141: .seealso: [](chapter_vectors), `Vec`, `VecMDot()`, `VecTDot()`
1142: @*/
1143: PetscErrorCode VecMTDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1144: {
1145:   PetscFunctionBegin;
1147:   PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mtdot, VEC_MTDot));
1148:   PetscFunctionReturn(PETSC_SUCCESS);
1149: }

1151: /*@
1152:    VecMDot - Computes multiple vector dot products.

1154:    Collective

1156:    Input Parameters:
1157: +  x - one vector
1158: .  nv - number of vectors
1159: -  y - array of vectors.

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

1164:    Level: intermediate

1166:    Notes for Users of Complex Numbers:
1167:    For complex vectors, `VecMDot()` computes
1168: $     val = (x,y) = y^H x,
1169:    where y^H denotes the conjugate transpose of y.

1171:    Use `VecMTDot()` for the indefinite form
1172: $     val = (x,y) = y^T x,
1173:    where y^T denotes the transpose of y.

1175: .seealso: [](chapter_vectors), `Vec`, `VecMTDot()`, `VecDot()`
1176: @*/
1177: PetscErrorCode VecMDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1178: {
1179:   PetscFunctionBegin;
1181:   PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mdot, VEC_MDot));
1182:   PetscFunctionReturn(PETSC_SUCCESS);
1183: }

1185: /*@
1186:    VecMAXPY - Computes `y = y + sum alpha[i] x[i]`

1188:    Logically Collective

1190:    Input Parameters:
1191: +  nv - number of scalars and x-vectors
1192: .  alpha - array of scalars
1193: .  y - one vector
1194: -  x - array of vectors

1196:    Level: intermediate

1198:    Note:
1199:     `y` cannot be any of the `x` vectors

1201: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
1202: @*/
1203: PetscErrorCode VecMAXPY(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[])
1204: {
1205:   PetscFunctionBegin;
1207:   VecCheckAssembled(y);
1209:   PetscCall(VecSetErrorIfLocked(y, 1));
1210:   PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);
1211:   if (nv) {
1212:     PetscInt zeros = 0;

1216:     for (PetscInt i = 0; i < nv; ++i) {
1220:       PetscCheckSameTypeAndComm(y, 1, x[i], 4);
1221:       VecCheckSameSize(y, 1, x[i], 4);
1222:       PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1223:       VecCheckAssembled(x[i]);
1224:       PetscCall(VecLockReadPush(x[i]));
1225:       zeros += alpha[i] == (PetscScalar)0.0;
1226:     }

1228:     if (zeros < nv) {
1229:       PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1230:       PetscUseTypeMethod(y, maxpy, nv, alpha, x);
1231:       PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1232:       PetscCall(PetscObjectStateIncrease((PetscObject)y));
1233:     }

1235:     for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1236:   }
1237:   PetscFunctionReturn(PETSC_SUCCESS);
1238: }

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

1245:    Collective

1247:    Input Parameters:
1248: +  nx   - number of vectors to be concatenated
1249: -  X    - array containing the vectors to be concatenated in the order of concatenation

1251:    Output Parameters:
1252: +  Y    - concatenated vector
1253: -  x_is - array of index sets corresponding to the concatenated components of `Y` (pass `NULL` if not needed)

1255:    Level: advanced

1257:    Notes:
1258:    Concatenation is similar to the functionality of a `VECNEST` object; they both represent combination of
1259:    different vector spaces. However, concatenated vectors do not store any information about their
1260:    sub-vectors and own their own data. Consequently, this function provides index sets to enable the
1261:    manipulation of data in the concatenated vector that corresponds to the original components at creation.

1263:    This is a useful tool for outer loop algorithms, particularly constrained optimizers, where the solver
1264:    has to operate on combined vector spaces and cannot utilize `VECNEST` objects due to incompatibility with
1265:    bound projections.

1267: .seealso: [](chapter_vectors), `Vec`, `VECNEST`, `VECSCATTER`, `VecScatterCreate()`
1268: @*/
1269: PetscErrorCode VecConcatenate(PetscInt nx, const Vec X[], Vec *Y, IS *x_is[])
1270: {
1271:   MPI_Comm comm;
1272:   VecType  vec_type;
1273:   Vec      Ytmp, Xtmp;
1274:   IS      *is_tmp;
1275:   PetscInt i, shift = 0, Xnl, Xng, Xbegin;

1277:   PetscFunctionBegin;

1283:   if ((*X)->ops->concatenate) {
1284:     /* use the dedicated concatenation function if available */
1285:     PetscCall((*(*X)->ops->concatenate)(nx, X, Y, x_is));
1286:   } else {
1287:     /* loop over vectors and start creating IS */
1288:     comm = PetscObjectComm((PetscObject)(*X));
1289:     PetscCall(VecGetType(*X, &vec_type));
1290:     PetscCall(PetscMalloc1(nx, &is_tmp));
1291:     for (i = 0; i < nx; i++) {
1292:       PetscCall(VecGetSize(X[i], &Xng));
1293:       PetscCall(VecGetLocalSize(X[i], &Xnl));
1294:       PetscCall(VecGetOwnershipRange(X[i], &Xbegin, NULL));
1295:       PetscCall(ISCreateStride(comm, Xnl, shift + Xbegin, 1, &is_tmp[i]));
1296:       shift += Xng;
1297:     }
1298:     /* create the concatenated vector */
1299:     PetscCall(VecCreate(comm, &Ytmp));
1300:     PetscCall(VecSetType(Ytmp, vec_type));
1301:     PetscCall(VecSetSizes(Ytmp, PETSC_DECIDE, shift));
1302:     PetscCall(VecSetUp(Ytmp));
1303:     /* copy data from X array to Y and return */
1304:     for (i = 0; i < nx; i++) {
1305:       PetscCall(VecGetSubVector(Ytmp, is_tmp[i], &Xtmp));
1306:       PetscCall(VecCopy(X[i], Xtmp));
1307:       PetscCall(VecRestoreSubVector(Ytmp, is_tmp[i], &Xtmp));
1308:     }
1309:     *Y = Ytmp;
1310:     if (x_is) {
1311:       *x_is = is_tmp;
1312:     } else {
1313:       for (i = 0; i < nx; i++) PetscCall(ISDestroy(&is_tmp[i]));
1314:       PetscCall(PetscFree(is_tmp));
1315:     }
1316:   }
1317:   PetscFunctionReturn(PETSC_SUCCESS);
1318: }

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

1323:     Input Parameters:
1324: +   X - the original vector
1325: -   is - the index set of the subvector

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

1332: */
1333: PetscErrorCode VecGetSubVectorContiguityAndBS_Private(Vec X, IS is, PetscBool *contig, PetscInt *start, PetscInt *blocksize)
1334: {
1335:   PetscInt  gstart, gend, lstart;
1336:   PetscBool red[2] = {PETSC_TRUE /*contiguous*/, PETSC_TRUE /*validVBS*/};
1337:   PetscInt  n, N, ibs, vbs, bs = -1;

1339:   PetscFunctionBegin;
1340:   PetscCall(ISGetLocalSize(is, &n));
1341:   PetscCall(ISGetSize(is, &N));
1342:   PetscCall(ISGetBlockSize(is, &ibs));
1343:   PetscCall(VecGetBlockSize(X, &vbs));
1344:   PetscCall(VecGetOwnershipRange(X, &gstart, &gend));
1345:   PetscCall(ISContiguousLocal(is, gstart, gend, &lstart, &red[0]));
1346:   /* block size is given by IS if ibs > 1; otherwise, check the vector */
1347:   if (ibs > 1) {
1348:     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, red, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1349:     bs = ibs;
1350:   } else {
1351:     if (n % vbs || vbs == 1) red[1] = PETSC_FALSE; /* this process invalidate the collectiveness of block size */
1352:     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, red, 2, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1353:     if (red[0] && red[1]) bs = vbs; /* all processes have a valid block size and the access will be contiguous */
1354:   }

1356:   *contig    = red[0];
1357:   *start     = lstart;
1358:   *blocksize = bs;
1359:   PetscFunctionReturn(PETSC_SUCCESS);
1360: }

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

1364:     Input Parameters:
1365: +   X - the original vector
1366: .   is - the index set of the subvector
1367: -   bs - the block size of the subvector, gotten from VecGetSubVectorContiguityAndBS_Private()

1369:     Output Parameter:
1370: .   Z  - the subvector, which will compose the VecScatter context on output
1371: */
1372: PetscErrorCode VecGetSubVectorThroughVecScatter_Private(Vec X, IS is, PetscInt bs, Vec *Z)
1373: {
1374:   PetscInt   n, N;
1375:   VecScatter vscat;
1376:   Vec        Y;

1378:   PetscFunctionBegin;
1379:   PetscCall(ISGetLocalSize(is, &n));
1380:   PetscCall(ISGetSize(is, &N));
1381:   PetscCall(VecCreate(PetscObjectComm((PetscObject)is), &Y));
1382:   PetscCall(VecSetSizes(Y, n, N));
1383:   PetscCall(VecSetBlockSize(Y, bs));
1384:   PetscCall(VecSetType(Y, ((PetscObject)X)->type_name));
1385:   PetscCall(VecScatterCreate(X, is, Y, NULL, &vscat));
1386:   PetscCall(VecScatterBegin(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1387:   PetscCall(VecScatterEnd(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1388:   PetscCall(PetscObjectCompose((PetscObject)Y, "VecGetSubVector_Scatter", (PetscObject)vscat));
1389:   PetscCall(VecScatterDestroy(&vscat));
1390:   *Z = Y;
1391:   PetscFunctionReturn(PETSC_SUCCESS);
1392: }

1394: /*@
1395:    VecGetSubVector - Gets a vector representing part of another vector

1397:    Collective

1399:    Input Parameters:
1400: +  X - vector from which to extract a subvector
1401: -  is - index set representing portion of `X` to extract

1403:    Output Parameter:
1404: .  Y - subvector corresponding to `is`

1406:    Level: advanced

1408:    Notes:
1409:    The subvector `Y` should be returned with `VecRestoreSubVector()`.
1410:    `X` and must be defined on the same communicator

1412:    This function may return a subvector without making a copy, therefore it is not safe to use the original vector while
1413:    modifying the subvector.  Other non-overlapping subvectors can still be obtained from X using this function.

1415:    The resulting subvector inherits the block size from `is` if greater than one. Otherwise, the block size is guessed from the block size of the original `X`.

1417: .seealso: [](chapter_vectors), `Vec`, `IS`, `VECNEST`, `MatCreateSubMatrix()`
1418: @*/
1419: PetscErrorCode VecGetSubVector(Vec X, IS is, Vec *Y)
1420: {
1421:   Vec Z;

1423:   PetscFunctionBegin;
1426:   PetscCheckSameComm(X, 1, is, 2);
1428:   if (X->ops->getsubvector) {
1429:     PetscUseTypeMethod(X, getsubvector, is, &Z);
1430:   } else { /* Default implementation currently does no caching */
1431:     PetscBool contig;
1432:     PetscInt  n, N, start, bs;

1434:     PetscCall(ISGetLocalSize(is, &n));
1435:     PetscCall(ISGetSize(is, &N));
1436:     PetscCall(VecGetSubVectorContiguityAndBS_Private(X, is, &contig, &start, &bs));
1437:     if (contig) { /* We can do a no-copy implementation */
1438:       const PetscScalar *x;
1439:       PetscInt           state = 0;
1440:       PetscBool          isstd, iscuda, iship;

1442:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &isstd, VECSEQ, VECMPI, VECSTANDARD, ""));
1443:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1444:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));
1445:       if (iscuda) {
1446: #if defined(PETSC_HAVE_CUDA)
1447:         const PetscScalar *x_d;
1448:         PetscMPIInt        size;
1449:         PetscOffloadMask   flg;

1451:         PetscCall(VecCUDAGetArrays_Private(X, &x, &x_d, &flg));
1452:         PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1453:         PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1454:         if (x) x += start;
1455:         if (x_d) x_d += start;
1456:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1457:         if (size == 1) {
1458:           PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1459:         } else {
1460:           PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1461:         }
1462:         Z->offloadmask = flg;
1463: #endif
1464:       } else if (iship) {
1465: #if defined(PETSC_HAVE_HIP)
1466:         const PetscScalar *x_d;
1467:         PetscMPIInt        size;
1468:         PetscOffloadMask   flg;

1470:         PetscCall(VecHIPGetArrays_Private(X, &x, &x_d, &flg));
1471:         PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1472:         PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1473:         if (x) x += start;
1474:         if (x_d) x_d += start;
1475:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1476:         if (size == 1) {
1477:           PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1478:         } else {
1479:           PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1480:         }
1481:         Z->offloadmask = flg;
1482: #endif
1483:       } else if (isstd) {
1484:         PetscMPIInt size;

1486:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1487:         PetscCall(VecGetArrayRead(X, &x));
1488:         if (x) x += start;
1489:         if (size == 1) {
1490:           PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)X), bs, n, x, &Z));
1491:         } else {
1492:           PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)X), bs, n, N, x, &Z));
1493:         }
1494:         PetscCall(VecRestoreArrayRead(X, &x));
1495:       } else { /* default implementation: use place array */
1496:         PetscCall(VecGetArrayRead(X, &x));
1497:         PetscCall(VecCreate(PetscObjectComm((PetscObject)X), &Z));
1498:         PetscCall(VecSetType(Z, ((PetscObject)X)->type_name));
1499:         PetscCall(VecSetSizes(Z, n, N));
1500:         PetscCall(VecSetBlockSize(Z, bs));
1501:         PetscCall(VecPlaceArray(Z, x ? x + start : NULL));
1502:         PetscCall(VecRestoreArrayRead(X, &x));
1503:       }

1505:       /* this is relevant only in debug mode */
1506:       PetscCall(VecLockGet(X, &state));
1507:       if (state) PetscCall(VecLockReadPush(Z));
1508:       Z->ops->placearray   = NULL;
1509:       Z->ops->replacearray = NULL;
1510:     } else { /* Have to create a scatter and do a copy */
1511:       PetscCall(VecGetSubVectorThroughVecScatter_Private(X, is, bs, &Z));
1512:     }
1513:   }
1514:   /* Record the state when the subvector was gotten so we know whether its values need to be put back */
1515:   if (VecGetSubVectorSavedStateId < 0) PetscCall(PetscObjectComposedDataRegister(&VecGetSubVectorSavedStateId));
1516:   PetscCall(PetscObjectComposedDataSetInt((PetscObject)Z, VecGetSubVectorSavedStateId, 1));
1517:   *Y = Z;
1518:   PetscFunctionReturn(PETSC_SUCCESS);
1519: }

1521: /*@
1522:    VecRestoreSubVector - Restores a subvector extracted using `VecGetSubVector()`

1524:    Collective

1526:    Input Parameters:
1527: + X - vector from which subvector was obtained
1528: . is - index set representing the subset of `X`
1529: - Y - subvector being restored

1531:    Level: advanced

1533: .seealso: [](chapter_vectors), `Vec`, `IS`, `VecGetSubVector()`
1534: @*/
1535: PetscErrorCode VecRestoreSubVector(Vec X, IS is, Vec *Y)
1536: {
1537:   PETSC_UNUSED PetscObjectState dummystate = 0;
1538:   PetscBool                     unchanged;

1540:   PetscFunctionBegin;
1543:   PetscCheckSameComm(X, 1, is, 2);

1547:   if (X->ops->restoresubvector) PetscUseTypeMethod(X, restoresubvector, is, Y);
1548:   else {
1549:     PetscCall(PetscObjectComposedDataGetInt((PetscObject)*Y, VecGetSubVectorSavedStateId, dummystate, unchanged));
1550:     if (!unchanged) { /* If Y's state has not changed since VecGetSubVector(), we only need to destroy Y */
1551:       VecScatter scatter;
1552:       PetscInt   state;

1554:       PetscCall(VecLockGet(X, &state));
1555:       PetscCheck(state == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vec X is locked for read-only or read/write access");

1557:       PetscCall(PetscObjectQuery((PetscObject)*Y, "VecGetSubVector_Scatter", (PetscObject *)&scatter));
1558:       if (scatter) {
1559:         PetscCall(VecScatterBegin(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1560:         PetscCall(VecScatterEnd(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1561:       } else {
1562:         PetscBool iscuda, iship;
1563:         PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1564:         PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));

1566:         if (iscuda) {
1567: #if defined(PETSC_HAVE_CUDA)
1568:           PetscOffloadMask ymask = (*Y)->offloadmask;

1570:           /* The offloadmask of X dictates where to move memory
1571:               If X GPU data is valid, then move Y data on GPU if needed
1572:               Otherwise, move back to the CPU */
1573:           switch (X->offloadmask) {
1574:           case PETSC_OFFLOAD_BOTH:
1575:             if (ymask == PETSC_OFFLOAD_CPU) {
1576:               PetscCall(VecCUDAResetArray(*Y));
1577:             } else if (ymask == PETSC_OFFLOAD_GPU) {
1578:               X->offloadmask = PETSC_OFFLOAD_GPU;
1579:             }
1580:             break;
1581:           case PETSC_OFFLOAD_GPU:
1582:             if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecCUDAResetArray(*Y));
1583:             break;
1584:           case PETSC_OFFLOAD_CPU:
1585:             if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1586:             break;
1587:           case PETSC_OFFLOAD_UNALLOCATED:
1588:           case PETSC_OFFLOAD_KOKKOS:
1589:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1590:           }
1591: #endif
1592:         } else if (iship) {
1593: #if defined(PETSC_HAVE_HIP)
1594:           PetscOffloadMask ymask = (*Y)->offloadmask;

1596:           /* The offloadmask of X dictates where to move memory
1597:               If X GPU data is valid, then move Y data on GPU if needed
1598:               Otherwise, move back to the CPU */
1599:           switch (X->offloadmask) {
1600:           case PETSC_OFFLOAD_BOTH:
1601:             if (ymask == PETSC_OFFLOAD_CPU) {
1602:               PetscCall(VecHIPResetArray(*Y));
1603:             } else if (ymask == PETSC_OFFLOAD_GPU) {
1604:               X->offloadmask = PETSC_OFFLOAD_GPU;
1605:             }
1606:             break;
1607:           case PETSC_OFFLOAD_GPU:
1608:             if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecHIPResetArray(*Y));
1609:             break;
1610:           case PETSC_OFFLOAD_CPU:
1611:             if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1612:             break;
1613:           case PETSC_OFFLOAD_UNALLOCATED:
1614:           case PETSC_OFFLOAD_KOKKOS:
1615:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1616:           }
1617: #endif
1618:         } else {
1619:           /* If OpenCL vecs updated the device memory, this triggers a copy on the CPU */
1620:           PetscCall(VecResetArray(*Y));
1621:         }
1622:         PetscCall(PetscObjectStateIncrease((PetscObject)X));
1623:       }
1624:     }
1625:   }
1626:   PetscCall(VecDestroy(Y));
1627:   PetscFunctionReturn(PETSC_SUCCESS);
1628: }

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

1634:    Not Collective.

1636:    Input parameter:
1637: .  v - The vector for which the local vector is desired.

1639:    Output parameter:
1640: .  w - Upon exit this contains the local vector.

1642:    Level: beginner

1644: .seealso: [](chapter_vectors), `Vec`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecRestoreLocalVector()`
1645: @*/
1646: PetscErrorCode VecCreateLocalVector(Vec v, Vec *w)
1647: {
1648:   PetscMPIInt size;

1650:   PetscFunctionBegin;
1653:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
1654:   if (size == 1) PetscCall(VecDuplicate(v, w));
1655:   else if (v->ops->createlocalvector) PetscUseTypeMethod(v, createlocalvector, w);
1656:   else {
1657:     VecType  type;
1658:     PetscInt n;

1660:     PetscCall(VecCreate(PETSC_COMM_SELF, w));
1661:     PetscCall(VecGetLocalSize(v, &n));
1662:     PetscCall(VecSetSizes(*w, n, n));
1663:     PetscCall(VecGetBlockSize(v, &n));
1664:     PetscCall(VecSetBlockSize(*w, n));
1665:     PetscCall(VecGetType(v, &type));
1666:     PetscCall(VecSetType(*w, type));
1667:   }
1668:   PetscFunctionReturn(PETSC_SUCCESS);
1669: }

1671: /*@
1672:    VecGetLocalVectorRead - Maps the local portion of a vector into a
1673:    vector.

1675:    Not Collective.

1677:    Input parameter:
1678: .  v - The vector for which the local vector is desired.

1680:    Output parameter:
1681: .  w - Upon exit this contains the local vector.

1683:    Level: beginner

1685:    Notes:
1686:    You must call `VecRestoreLocalVectorRead()` when the local
1687:    vector is no longer needed.

1689:    This function is similar to `VecGetArrayRead()` which maps the local
1690:    portion into a raw pointer.  `VecGetLocalVectorRead()` is usually
1691:    almost as efficient as `VecGetArrayRead()` but in certain circumstances
1692:    `VecGetLocalVectorRead()` can be much more efficient than
1693:    `VecGetArrayRead()`.  This is because the construction of a contiguous
1694:    array representing the vector data required by `VecGetArrayRead()` can
1695:    be an expensive operation for certain vector types.  For example, for
1696:    GPU vectors `VecGetArrayRead()` requires that the data between device
1697:    and host is synchronized.

1699:    Unlike `VecGetLocalVector()`, this routine is not collective and
1700:    preserves cached information.

1702: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1703: @*/
1704: PetscErrorCode VecGetLocalVectorRead(Vec v, Vec w)
1705: {
1706:   PetscFunctionBegin;
1709:   VecCheckSameLocalSize(v, 1, w, 2);
1710:   if (v->ops->getlocalvectorread) {
1711:     PetscUseTypeMethod(v, getlocalvectorread, w);
1712:   } else {
1713:     PetscScalar *a;

1715:     PetscCall(VecGetArrayRead(v, (const PetscScalar **)&a));
1716:     PetscCall(VecPlaceArray(w, a));
1717:   }
1718:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1719:   PetscCall(VecLockReadPush(v));
1720:   PetscCall(VecLockReadPush(w));
1721:   PetscFunctionReturn(PETSC_SUCCESS);
1722: }

1724: /*@
1725:    VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1726:    previously mapped into a vector using `VecGetLocalVectorRead()`.

1728:    Not Collective.

1730:    Input parameter:
1731: +  v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVectorRead()`.
1732: -  w - The vector into which the local portion of `v` was mapped.

1734:    Level: beginner

1736: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1737: @*/
1738: PetscErrorCode VecRestoreLocalVectorRead(Vec v, Vec w)
1739: {
1740:   PetscFunctionBegin;
1743:   if (v->ops->restorelocalvectorread) {
1744:     PetscUseTypeMethod(v, restorelocalvectorread, w);
1745:   } else {
1746:     const PetscScalar *a;

1748:     PetscCall(VecGetArrayRead(w, &a));
1749:     PetscCall(VecRestoreArrayRead(v, &a));
1750:     PetscCall(VecResetArray(w));
1751:   }
1752:   PetscCall(VecLockReadPop(v));
1753:   PetscCall(VecLockReadPop(w));
1754:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1755:   PetscFunctionReturn(PETSC_SUCCESS);
1756: }

1758: /*@
1759:    VecGetLocalVector - Maps the local portion of a vector into a
1760:    vector.

1762:    Collective

1764:    Input parameter:
1765: .  v - The vector for which the local vector is desired.

1767:    Output parameter:
1768: .  w - Upon exit this contains the local vector.

1770:    Level: beginner

1772:    Notes:
1773:    You must call `VecRestoreLocalVector()` when the local
1774:    vector is no longer needed.

1776:    This function is similar to `VecGetArray()` which maps the local
1777:    portion into a raw pointer.  `VecGetLocalVector()` is usually about as
1778:    efficient as `VecGetArray()` but in certain circumstances
1779:    `VecGetLocalVector()` can be much more efficient than `VecGetArray()`.
1780:    This is because the construction of a contiguous array representing
1781:    the vector data required by `VecGetArray()` can be an expensive
1782:    operation for certain vector types.  For example, for GPU vectors
1783:    `VecGetArray()` requires that the data between device and host is
1784:    synchronized.

1786: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVector()`, `VecGetLocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1787: @*/
1788: PetscErrorCode VecGetLocalVector(Vec v, Vec w)
1789: {
1790:   PetscFunctionBegin;
1793:   VecCheckSameLocalSize(v, 1, w, 2);
1794:   if (v->ops->getlocalvector) {
1795:     PetscUseTypeMethod(v, getlocalvector, w);
1796:   } else {
1797:     PetscScalar *a;

1799:     PetscCall(VecGetArray(v, &a));
1800:     PetscCall(VecPlaceArray(w, a));
1801:   }
1802:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1803:   PetscFunctionReturn(PETSC_SUCCESS);
1804: }

1806: /*@
1807:    VecRestoreLocalVector - Unmaps the local portion of a vector
1808:    previously mapped into a vector using `VecGetLocalVector()`.

1810:    Logically Collective.

1812:    Input parameter:
1813: +  v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVector()`.
1814: -  w - The vector into which the local portion of `v` was mapped.

1816:    Level: beginner

1818: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVector()`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `LocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1819: @*/
1820: PetscErrorCode VecRestoreLocalVector(Vec v, Vec w)
1821: {
1822:   PetscFunctionBegin;
1825:   if (v->ops->restorelocalvector) {
1826:     PetscUseTypeMethod(v, restorelocalvector, w);
1827:   } else {
1828:     PetscScalar *a;
1829:     PetscCall(VecGetArray(w, &a));
1830:     PetscCall(VecRestoreArray(v, &a));
1831:     PetscCall(VecResetArray(w));
1832:   }
1833:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1834:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
1835:   PetscFunctionReturn(PETSC_SUCCESS);
1836: }

1838: /*@C
1839:    VecGetArray - Returns a pointer to a contiguous array that contains this
1840:    processor's portion of the vector data. For the standard PETSc
1841:    vectors, `VecGetArray()` returns a pointer to the local data array and
1842:    does not use any copies. If the underlying vector data is not stored
1843:    in a contiguous array this routine will copy the data to a contiguous
1844:    array and return a pointer to that. You MUST call `VecRestoreArray()`
1845:    when you no longer need access to the array.

1847:    Logically Collective

1849:    Input Parameter:
1850: .  x - the vector

1852:    Output Parameter:
1853: .  a - location to put pointer to the array

1855:    Level: beginner

1857:    Fortran Note:
1858:    `VecGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `VecGetArrayF90()`

1860: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`, `VecPlaceArray()`, `VecGetArray2d()`,
1861:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
1862: @*/
1863: PetscErrorCode VecGetArray(Vec x, PetscScalar **a)
1864: {
1865:   PetscFunctionBegin;
1867:   PetscCall(VecSetErrorIfLocked(x, 1));
1868:   if (x->ops->getarray) { /* The if-else order matters! VECNEST, VECCUDA etc should have ops->getarray while VECCUDA etc are petscnative */
1869:     PetscUseTypeMethod(x, getarray, a);
1870:   } else if (x->petscnative) { /* VECSTANDARD */
1871:     *a = *((PetscScalar **)x->data);
1872:   } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array for vector type \"%s\"", ((PetscObject)x)->type_name);
1873:   PetscFunctionReturn(PETSC_SUCCESS);
1874: }

1876: /*@C
1877:    VecRestoreArray - Restores a vector after `VecGetArray()` has been called and the array is no longer needed

1879:    Logically Collective

1881:    Input Parameters:
1882: +  x - the vector
1883: -  a - location of pointer to array obtained from `VecGetArray()`

1885:    Level: beginner

1887:    Fortran Note:
1888:    `VecRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `VecRestoreArrayF90()`

1890: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
1891:           `VecGetArrayPair()`, `VecRestoreArrayPair()`
1892: @*/
1893: PetscErrorCode VecRestoreArray(Vec x, PetscScalar **a)
1894: {
1895:   PetscFunctionBegin;
1898:   if (x->ops->restorearray) {
1899:     PetscUseTypeMethod(x, restorearray, a);
1900:   } else PetscCheck(x->petscnative, PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot restore array for vector type \"%s\"", ((PetscObject)x)->type_name);
1901:   if (a) *a = NULL;
1902:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1903:   PetscFunctionReturn(PETSC_SUCCESS);
1904: }
1905: /*@C
1906:    VecGetArrayRead - Get read-only pointer to contiguous array containing this processor's portion of the vector data.

1908:    Not Collective

1910:    Input Parameter:
1911: .  x - the vector

1913:    Output Parameter:
1914: .  a - the array

1916:    Level: beginner

1918:    Notes:
1919:    The array must be returned using a matching call to `VecRestoreArrayRead()`.

1921:    Unlike `VecGetArray()`, preserves cached information like vector norms.

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

1927:    Fortran Note:
1928:    `VecGetArrayRead()` Fortran binding is deprecated (since PETSc 3.19), use `VecGetArrayReadF90()`

1930: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
1931: @*/
1932: PetscErrorCode VecGetArrayRead(Vec x, const PetscScalar **a)
1933: {
1934:   PetscFunctionBegin;
1937:   if (x->ops->getarrayread) {
1938:     PetscUseTypeMethod(x, getarrayread, a);
1939:   } else if (x->ops->getarray) {
1940:     PetscObjectState state;

1942:     /* VECNEST, VECCUDA, VECKOKKOS etc */
1943:     // x->ops->getarray may bump the object state, but since we know this is a read-only get
1944:     // we can just undo that
1945:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
1946:     PetscUseTypeMethod(x, getarray, (PetscScalar **)a);
1947:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
1948:   } else if (x->petscnative) {
1949:     /* VECSTANDARD */
1950:     *a = *((PetscScalar **)x->data);
1951:   } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array read for vector type \"%s\"", ((PetscObject)x)->type_name);
1952:   PetscFunctionReturn(PETSC_SUCCESS);
1953: }

1955: /*@C
1956:    VecRestoreArrayRead - Restore array obtained with `VecGetArrayRead()`

1958:    Not Collective

1960:    Input Parameters:
1961: +  vec - the vector
1962: -  array - the array

1964:    Level: beginner

1966:    Fortran Note:
1967:    `VecRestoreArrayRead()` Fortran binding is deprecated (since PETSc 3.19), use `VecRestoreArrayReadF90()`

1969: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
1970: @*/
1971: PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar **a)
1972: {
1973:   PetscFunctionBegin;
1976:   if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
1977:     /* nothing */
1978:   } else if (x->ops->restorearrayread) { /* VECNEST */
1979:     PetscUseTypeMethod(x, restorearrayread, a);
1980:   } else { /* No one? */
1981:     PetscObjectState state;

1983:     // x->ops->restorearray may bump the object state, but since we know this is a read-restore
1984:     // we can just undo that
1985:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
1986:     PetscUseTypeMethod(x, restorearray, (PetscScalar **)a);
1987:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
1988:   }
1989:   if (a) *a = NULL;
1990:   PetscFunctionReturn(PETSC_SUCCESS);
1991: }

1993: /*@C
1994:    VecGetArrayWrite - Returns a pointer to a contiguous array that WILL contain this
1995:    processor's portion of the vector data. The values in this array are NOT valid, the caller of this
1996:    routine is responsible for putting values into the array; any values it does not set will be invalid

1998:    Logically Collective

2000:    Input Parameter:
2001: .  x - the vector

2003:    Output Parameter:
2004: .  a - location to put pointer to the array

2006:    Level: intermediate

2008:    Note:
2009:    The array must be returned using a matching call to `VecRestoreArrayRead()`.

2011:    For vectors associated with GPUs, the host and device vectors are not synchronized before giving access. If you need correct
2012:    values in the array use `VecGetArray()`

2014:    Fortran Note:
2015:    `VecGetArrayWrite()` Fortran binding is deprecated (since PETSc 3.19), use `VecGetArrayWriteF90()`

2017: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayWriteF90()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`, `VecPlaceArray()`, `VecGetArray2d()`,
2018:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArray()`, `VecRestoreArrayWrite()`
2019: @*/
2020: PetscErrorCode VecGetArrayWrite(Vec x, PetscScalar **a)
2021: {
2022:   PetscFunctionBegin;
2025:   PetscCall(VecSetErrorIfLocked(x, 1));
2026:   if (x->ops->getarraywrite) {
2027:     PetscUseTypeMethod(x, getarraywrite, a);
2028:   } else {
2029:     PetscCall(VecGetArray(x, a));
2030:   }
2031:   PetscFunctionReturn(PETSC_SUCCESS);
2032: }

2034: /*@C
2035:    VecRestoreArrayWrite - Restores a vector after `VecGetArrayWrite()` has been called.

2037:    Logically Collective

2039:    Input Parameters:
2040: +  x - the vector
2041: -  a - location of pointer to array obtained from `VecGetArray()`

2043:    Level: beginner

2045:    Fortran Note:
2046:    `VecRestoreArrayWrite()` Fortran binding is deprecated (since PETSc 3.19), use `VecRestoreArrayWriteF90()`

2048: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayWriteF90()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2049:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`
2050: @*/
2051: PetscErrorCode VecRestoreArrayWrite(Vec x, PetscScalar **a)
2052: {
2053:   PetscFunctionBegin;
2056:   if (x->ops->restorearraywrite) {
2057:     PetscUseTypeMethod(x, restorearraywrite, a);
2058:   } else if (x->ops->restorearray) {
2059:     PetscUseTypeMethod(x, restorearray, a);
2060:   }
2061:   if (a) *a = NULL;
2062:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2063:   PetscFunctionReturn(PETSC_SUCCESS);
2064: }

2066: /*@C
2067:    VecGetArrays - Returns a pointer to the arrays in a set of vectors
2068:    that were created by a call to `VecDuplicateVecs()`.

2070:    Logically Collective; No Fortran Support

2072:    Input Parameters:
2073: +  x - the vectors
2074: -  n - the number of vectors

2076:    Output Parameter:
2077: .  a - location to put pointer to the array

2079:    Level: intermediate

2081:    Note:
2082:    You MUST call `VecRestoreArrays()` when you no longer need access to the arrays.

2084: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrays()`
2085: @*/
2086: PetscErrorCode VecGetArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2087: {
2088:   PetscInt      i;
2089:   PetscScalar **q;

2091:   PetscFunctionBegin;
2095:   PetscCheck(n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must get at least one array n = %" PetscInt_FMT, n);
2096:   PetscCall(PetscMalloc1(n, &q));
2097:   for (i = 0; i < n; ++i) PetscCall(VecGetArray(x[i], &q[i]));
2098:   *a = q;
2099:   PetscFunctionReturn(PETSC_SUCCESS);
2100: }

2102: /*@C
2103:    VecRestoreArrays - Restores a group of vectors after `VecGetArrays()`
2104:    has been called.

2106:    Logically Collective; No Fortran Support

2108:    Input Parameters:
2109: +  x - the vector
2110: .  n - the number of vectors
2111: -  a - location of pointer to arrays obtained from `VecGetArrays()`

2113:    Notes:
2114:    For regular PETSc vectors this routine does not involve any copies. For
2115:    any special vectors that do not store local vector data in a contiguous
2116:    array, this routine will copy the data back into the underlying
2117:    vector data structure from the arrays obtained with `VecGetArrays()`.

2119:    Level: intermediate

2121: .seealso: [](chapter_vectors), `Vec`, `VecGetArrays()`, `VecRestoreArray()`
2122: @*/
2123: PetscErrorCode VecRestoreArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2124: {
2125:   PetscInt      i;
2126:   PetscScalar **q = *a;

2128:   PetscFunctionBegin;

2133:   for (i = 0; i < n; ++i) PetscCall(VecRestoreArray(x[i], &q[i]));
2134:   PetscCall(PetscFree(q));
2135:   PetscFunctionReturn(PETSC_SUCCESS);
2136: }

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

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

2146:    Logically Collective; No Fortran Support

2148:    Input Parameter:
2149: .  x - the vector

2151:    Output Parameters:
2152: +  a - location to put pointer to the array
2153: -  mtype - memory type of the array

2155:    Level: beginner

2157:    Note:
2158:    Use `VecRestoreArrayAndMemType()` when the array access is no longer needed

2160: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`,
2161:           `VecPlaceArray()`, `VecGetArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2162: @*/
2163: PetscErrorCode VecGetArrayAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2164: {
2165:   PetscFunctionBegin;
2170:   PetscCall(VecSetErrorIfLocked(x, 1));
2171:   if (x->ops->getarrayandmemtype) {
2172:     /* VECCUDA, VECKOKKOS etc */
2173:     PetscUseTypeMethod(x, getarrayandmemtype, a, mtype);
2174:   } else {
2175:     /* VECSTANDARD, VECNEST, VECVIENNACL */
2176:     PetscCall(VecGetArray(x, a));
2177:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2178:   }
2179:   PetscFunctionReturn(PETSC_SUCCESS);
2180: }

2182: /*@C
2183:    VecRestoreArrayAndMemType - Restores a vector after `VecGetArrayAndMemType()` has been called.

2185:    Logically Collective; No Fortran Support

2187:    Input Parameters:
2188: +  x - the vector
2189: -  a - location of pointer to array obtained from `VecGetArrayAndMemType()`

2191:    Level: beginner

2193: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`,
2194:           `VecPlaceArray()`, `VecRestoreArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2195: @*/
2196: PetscErrorCode VecRestoreArrayAndMemType(Vec x, PetscScalar **a)
2197: {
2198:   PetscFunctionBegin;
2202:   if (x->ops->restorearrayandmemtype) {
2203:     /* VECCUDA, VECKOKKOS etc */
2204:     PetscUseTypeMethod(x, restorearrayandmemtype, a);
2205:   } else {
2206:     /* VECNEST, VECVIENNACL */
2207:     PetscCall(VecRestoreArray(x, a));
2208:   } /* VECSTANDARD does nothing */
2209:   if (a) *a = NULL;
2210:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2211:   PetscFunctionReturn(PETSC_SUCCESS);
2212: }

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

2218:    Not Collective; No Fortran Support

2220:    Input Parameter:
2221: .  x - the vector

2223:    Output Parameters:
2224: +  a - the array
2225: -  mtype - memory type of the array

2227:    Level: beginner

2229:    Notes:
2230:    The array must be returned using a matching call to `VecRestoreArrayReadAndMemType()`.

2232: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayAndMemType()`
2233: @*/
2234: PetscErrorCode VecGetArrayReadAndMemType(Vec x, const PetscScalar **a, PetscMemType *mtype)
2235: {
2236:   PetscFunctionBegin;
2241:   if (x->ops->getarrayreadandmemtype) {
2242:     /* VECCUDA/VECHIP though they are also petscnative */
2243:     PetscUseTypeMethod(x, getarrayreadandmemtype, a, mtype);
2244:   } else if (x->ops->getarrayandmemtype) {
2245:     /* VECKOKKOS */
2246:     PetscObjectState state;

2248:     // see VecGetArrayRead() for why
2249:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2250:     PetscUseTypeMethod(x, getarrayandmemtype, (PetscScalar **)a, mtype);
2251:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
2252:   } else {
2253:     PetscCall(VecGetArrayRead(x, a));
2254:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2255:   }
2256:   PetscFunctionReturn(PETSC_SUCCESS);
2257: }

2259: /*@C
2260:    VecRestoreArrayReadAndMemType - Restore array obtained with `VecGetArrayReadAndMemType()`

2262:    Not Collective; No Fortran Support

2264:    Input Parameters:
2265: +  vec - the vector
2266: -  array - the array

2268:    Level: beginner

2270: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayReadAndMemType()`, `VecRestoreArrayAndMemType()`, `VecRestoreArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2271: @*/
2272: PetscErrorCode VecRestoreArrayReadAndMemType(Vec x, const PetscScalar **a)
2273: {
2274:   PetscFunctionBegin;
2278:   if (x->ops->restorearrayreadandmemtype) {
2279:     /* VECCUDA/VECHIP */
2280:     PetscUseTypeMethod(x, restorearrayreadandmemtype, a);
2281:   } else if (!x->petscnative) {
2282:     /* VECNEST */
2283:     PetscCall(VecRestoreArrayRead(x, a));
2284:   }
2285:   if (a) *a = NULL;
2286:   PetscFunctionReturn(PETSC_SUCCESS);
2287: }

2289: /*@C
2290:    VecGetArrayWriteAndMemType - Like `VecGetArrayWrite()`, but if this is a device vector it will always return
2291:     a device pointer to the device memory that contains this processor's portion of the vector data.

2293:    Not Collective; No Fortran Support

2295:    Input Parameter:
2296: .  x - the vector

2298:    Output Parameters:
2299: +  a - the array
2300: -  mtype - memory type of the array

2302:    Level: beginner

2304:    Note:
2305:    The array must be returned using a matching call to `VecRestoreArrayWriteAndMemType()`, where it will label the device memory as most recent.

2307: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayWriteAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2308: @*/
2309: PetscErrorCode VecGetArrayWriteAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2310: {
2311:   PetscFunctionBegin;
2314:   PetscCall(VecSetErrorIfLocked(x, 1));
2317:   if (x->ops->getarraywriteandmemtype) {
2318:     /* VECCUDA, VECHIP, VECKOKKOS etc, though they are also petscnative */
2319:     PetscUseTypeMethod(x, getarraywriteandmemtype, a, mtype);
2320:   } else if (x->ops->getarrayandmemtype) {
2321:     PetscCall(VecGetArrayAndMemType(x, a, mtype));
2322:   } else {
2323:     /* VECNEST, VECVIENNACL */
2324:     PetscCall(VecGetArrayWrite(x, a));
2325:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2326:   }
2327:   PetscFunctionReturn(PETSC_SUCCESS);
2328: }

2330: /*@C
2331:    VecRestoreArrayWriteAndMemType - Restore array obtained with `VecGetArrayWriteAndMemType()`

2333:    Not Collective; No Fortran Support

2335:    Input Parameters:
2336: +  vec - the vector
2337: -  array - the array

2339:    Level: beginner

2341: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayWriteAndMemType()`, `VecRestoreArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2342: @*/
2343: PetscErrorCode VecRestoreArrayWriteAndMemType(Vec x, PetscScalar **a)
2344: {
2345:   PetscFunctionBegin;
2348:   PetscCall(VecSetErrorIfLocked(x, 1));
2350:   if (x->ops->restorearraywriteandmemtype) {
2351:     /* VECCUDA/VECHIP */
2352:     PetscMemType PETSC_UNUSED mtype; // since this function doesn't accept a memtype?
2353:     PetscUseTypeMethod(x, restorearraywriteandmemtype, a, &mtype);
2354:   } else if (x->ops->restorearrayandmemtype) {
2355:     PetscCall(VecRestoreArrayAndMemType(x, a));
2356:   } else {
2357:     PetscCall(VecRestoreArray(x, a));
2358:   }
2359:   if (a) *a = NULL;
2360:   PetscFunctionReturn(PETSC_SUCCESS);
2361: }

2363: /*@
2364:    VecPlaceArray - Allows one to replace the array in a vector with an
2365:    array provided by the user. This is useful to avoid copying an array
2366:    into a vector.

2368:    Not Collective; No Fortran Support

2370:    Input Parameters:
2371: +  vec - the vector
2372: -  array - the array

2374:    Level: developer

2376:    Notes:
2377:    Use `VecReplaceArray()` instead to permanently replace the array

2379:    You can return to the original array with a call to `VecResetArray()`. `vec` does not take
2380:    ownership of `array` in any way.

2382:    The user must free `array` themselves but be careful not to
2383:    do so before the vector has either been destroyed, had its original array restored with
2384:    `VecResetArray()` or permanently replaced with `VecReplaceArray()`.

2386: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`
2387: @*/
2388: PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2389: {
2390:   PetscFunctionBegin;
2394:   PetscUseTypeMethod(vec, placearray, array);
2395:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2396:   PetscFunctionReturn(PETSC_SUCCESS);
2397: }

2399: /*@C
2400:    VecReplaceArray - Allows one to replace the array in a vector with an
2401:    array provided by the user. This is useful to avoid copying an array
2402:    into a vector.

2404:    Not Collective; No Fortran Support

2406:    Input Parameters:
2407: +  vec - the vector
2408: -  array - the array

2410:    Level: developer

2412:    Notes:
2413:    This permanently replaces the array and frees the memory associated
2414:    with the old array. Use `VecPlaceArray()` to temporarily replace the array.

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

2419: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`
2420: @*/
2421: PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2422: {
2423:   PetscFunctionBegin;
2426:   PetscUseTypeMethod(vec, replacearray, array);
2427:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2428:   PetscFunctionReturn(PETSC_SUCCESS);
2429: }

2431: /*MC
2432:     VecDuplicateVecsF90 - Creates several vectors of the same type as an existing vector
2433:     and makes them accessible via a Fortran pointer.

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

2438:     Collective

2440:     Input Parameters:
2441: +   x - a vector to mimic
2442: -   n - the number of vectors to obtain

2444:     Output Parameters:
2445: +   y - Fortran pointer to the array of vectors
2446: -   ierr - error code

2448:     Example of Usage:
2449: .vb
2450: #include <petsc/finclude/petscvec.h>
2451:     use petscvec

2453:     Vec x
2454:     Vec, pointer :: y(:)
2455:     ....
2456:     call VecDuplicateVecsF90(x,2,y,ierr)
2457:     call VecSet(y(2),alpha,ierr)
2458:     call VecSet(y(2),alpha,ierr)
2459:     ....
2460:     call VecDestroyVecsF90(2,y,ierr)
2461: .ve

2463:     Level: beginner

2465:     Note:
2466:     Use `VecDestroyVecsF90()` to free the space.

2468: .seealso: [](chapter_vectors), `Vec`, `VecDestroyVecsF90()`, `VecDuplicateVecs()`
2469: M*/

2471: /*MC
2472:     VecRestoreArrayF90 - Restores a vector to a usable state after a call to
2473:     `VecGetArrayF90()`.

2475:     Synopsis:
2476:     VecRestoreArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2478:     Logically Collective

2480:     Input Parameters:
2481: +   x - vector
2482: -   xx_v - the Fortran pointer to the array

2484:     Output Parameter:
2485: .   ierr - error code

2487:     Example of Usage:
2488: .vb
2489: #include <petsc/finclude/petscvec.h>
2490:     use petscvec

2492:     PetscScalar, pointer :: xx_v(:)
2493:     ....
2494:     call VecGetArrayF90(x,xx_v,ierr)
2495:     xx_v(3) = a
2496:     call VecRestoreArrayF90(x,xx_v,ierr)
2497: .ve

2499:     Level: beginner

2501: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrayReadF90()`
2502: M*/

2504: /*MC
2505:     VecDestroyVecsF90 - Frees a block of vectors obtained with `VecDuplicateVecsF90()`.

2507:     Synopsis:
2508:     VecDestroyVecsF90(PetscInt n,{Vec, pointer :: x(:)},PetscErrorCode ierr)

2510:     Collective

2512:     Input Parameters:
2513: +   n - the number of vectors previously obtained
2514: -   x - pointer to array of vector pointers

2516:     Output Parameter:
2517: .   ierr - error code

2519:     Level: beginner

2521: .seealso: [](chapter_vectors), `Vec`, `VecDestroyVecs()`, `VecDuplicateVecsF90()`
2522: M*/

2524: /*MC
2525:     VecGetArrayF90 - Accesses a vector array from Fortran. For default PETSc
2526:     vectors, `VecGetArrayF90()` returns a pointer to the local data array. Otherwise,
2527:     this routine is implementation dependent. You MUST call `VecRestoreArrayF90()`
2528:     when you no longer need access to the array.

2530:     Synopsis:
2531:     VecGetArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2533:     Logically Collective

2535:     Input Parameter:
2536: .   x - vector

2538:     Output Parameters:
2539: +   xx_v - the Fortran pointer to the array
2540: -   ierr - error code

2542:     Example of Usage:
2543: .vb
2544: #include <petsc/finclude/petscvec.h>
2545:     use petscvec

2547:     PetscScalar, pointer :: xx_v(:)
2548:     ....
2549:     call VecGetArrayF90(x,xx_v,ierr)
2550:     xx_v(3) = a
2551:     call VecRestoreArrayF90(x,xx_v,ierr)
2552: .ve

2554:      Level: beginner

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

2559: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayReadF90()`
2560: M*/

2562: /*MC
2563:     VecGetArrayReadF90 - Accesses a read only array from Fortran. For default PETSc
2564:     vectors, `VecGetArrayF90()` returns a pointer to the local data array. Otherwise,
2565:     this routine is implementation dependent. You MUST call `VecRestoreArrayReadF90()`
2566:     when you no longer need access to the array.

2568:     Synopsis:
2569:     VecGetArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2571:     Logically Collective

2573:     Input Parameter:
2574: .   x - vector

2576:     Output Parameters:
2577: +   xx_v - the Fortran pointer to the array
2578: -   ierr - error code

2580:     Example of Usage:
2581: .vb
2582: #include <petsc/finclude/petscvec.h>
2583:     use petscvec

2585:     PetscScalar, pointer :: xx_v(:)
2586:     ....
2587:     call VecGetArrayReadF90(x,xx_v,ierr)
2588:     a = xx_v(3)
2589:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2590: .ve

2592:     Level: beginner

2594:     Note:
2595:     If you intend to write entries into the array you must use `VecGetArrayF90()`.

2597: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecRestoreArrayRead()`, `VecGetArrayF90()`
2598: M*/

2600: /*MC
2601:     VecRestoreArrayReadF90 - Restores a readonly vector to a usable state after a call to
2602:     `VecGetArrayReadF90()`.

2604:     Synopsis:
2605:     VecRestoreArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2607:     Logically Collective

2609:     Input Parameters:
2610: +   x - vector
2611: -   xx_v - the Fortran pointer to the array

2613:     Output Parameter:
2614: .   ierr - error code

2616:     Example of Usage:
2617: .vb
2618: #include <petsc/finclude/petscvec.h>
2619:     use petscvec

2621:     PetscScalar, pointer :: xx_v(:)
2622:     ....
2623:     call VecGetArrayReadF90(x,xx_v,ierr)
2624:     a = xx_v(3)
2625:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2626: .ve

2628:     Level: beginner

2630: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecRestoreArrayRead()`, `VecRestoreArrayF90()`
2631: M*/

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

2638:    Logically Collective

2640:    Input Parameters:
2641: +  x - the vector
2642: .  m - first dimension of two dimensional array
2643: .  n - second dimension of two dimensional array
2644: .  mstart - first index you will use in first coordinate direction (often 0)
2645: -  nstart - first index in the second coordinate direction (often 0)

2647:    Output Parameter:
2648: .  a - location to put pointer to the array

2650:    Level: developer

2652:   Notes:
2653:    For a vector obtained from `DMCreateLocalVector()` mstart and nstart are likely
2654:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2655:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2656:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.

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

2660: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2661:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2662:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2663: @*/
2664: PetscErrorCode VecGetArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2665: {
2666:   PetscInt     i, N;
2667:   PetscScalar *aa;

2669:   PetscFunctionBegin;
2673:   PetscCall(VecGetLocalSize(x, &N));
2674:   PetscCheck(m * n == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 2d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n);
2675:   PetscCall(VecGetArray(x, &aa));

2677:   PetscCall(PetscMalloc1(m, a));
2678:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2679:   *a -= mstart;
2680:   PetscFunctionReturn(PETSC_SUCCESS);
2681: }

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

2688:    Logically Collective

2690:    Input Parameters:
2691: +  x - the vector
2692: .  m - first dimension of two dimensional array
2693: .  n - second dimension of two dimensional array
2694: .  mstart - first index you will use in first coordinate direction (often 0)
2695: -  nstart - first index in the second coordinate direction (often 0)

2697:    Output Parameter:
2698: .  a - location to put pointer to the array

2700:    Level: developer

2702:   Notes:
2703:    For a vector obtained from `DMCreateLocalVector()` mstart and nstart are likely
2704:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2705:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2706:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.

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

2710: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2711:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2712:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2713: @*/
2714: PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2715: {
2716:   PetscInt     i, N;
2717:   PetscScalar *aa;

2719:   PetscFunctionBegin;
2723:   PetscCall(VecGetLocalSize(x, &N));
2724:   PetscCheck(m * n == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 2d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n);
2725:   PetscCall(VecGetArrayWrite(x, &aa));

2727:   PetscCall(PetscMalloc1(m, a));
2728:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2729:   *a -= mstart;
2730:   PetscFunctionReturn(PETSC_SUCCESS);
2731: }

2733: /*@C
2734:    VecRestoreArray2d - Restores a vector after `VecGetArray2d()` has been called.

2736:    Logically Collective

2738:    Input Parameters:
2739: +  x - the vector
2740: .  m - first dimension of two dimensional array
2741: .  n - second dimension of the two dimensional array
2742: .  mstart - first index you will use in first coordinate direction (often 0)
2743: .  nstart - first index in the second coordinate direction (often 0)
2744: -  a - location of pointer to array obtained from `VecGetArray2d()`

2746:    Level: developer

2748:    Notes:
2749:    For regular PETSc vectors this routine does not involve any copies. For
2750:    any special vectors that do not store local vector data in a contiguous
2751:    array, this routine will copy the data back into the underlying
2752:    vector data structure from the array obtained with `VecGetArray()`.

2754:    This routine actually zeros out the a pointer.

2756: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2757:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2758:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2759: @*/
2760: PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2761: {
2762:   void *dummy;

2764:   PetscFunctionBegin;
2768:   dummy = (void *)(*a + mstart);
2769:   PetscCall(PetscFree(dummy));
2770:   PetscCall(VecRestoreArray(x, NULL));
2771:   PetscFunctionReturn(PETSC_SUCCESS);
2772: }

2774: /*@C
2775:    VecRestoreArray2dWrite - Restores a vector after VecGetArray2dWrite`()` has been called.

2777:    Logically Collective

2779:    Input Parameters:
2780: +  x - the vector
2781: .  m - first dimension of two dimensional array
2782: .  n - second dimension of the two dimensional array
2783: .  mstart - first index you will use in first coordinate direction (often 0)
2784: .  nstart - first index in the second coordinate direction (often 0)
2785: -  a - location of pointer to array obtained from `VecGetArray2d()`

2787:    Level: developer

2789:    Notes:
2790:    For regular PETSc vectors this routine does not involve any copies. For
2791:    any special vectors that do not store local vector data in a contiguous
2792:    array, this routine will copy the data back into the underlying
2793:    vector data structure from the array obtained with `VecGetArray()`.

2795:    This routine actually zeros out the a pointer.

2797: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2798:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2799:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2800: @*/
2801: PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2802: {
2803:   void *dummy;

2805:   PetscFunctionBegin;
2809:   dummy = (void *)(*a + mstart);
2810:   PetscCall(PetscFree(dummy));
2811:   PetscCall(VecRestoreArrayWrite(x, NULL));
2812:   PetscFunctionReturn(PETSC_SUCCESS);
2813: }

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

2820:    Logically Collective

2822:    Input Parameters:
2823: +  x - the vector
2824: .  m - first dimension of two dimensional array
2825: -  mstart - first index you will use in first coordinate direction (often 0)

2827:    Output Parameter:
2828: .  a - location to put pointer to the array

2830:    Level: developer

2832:   Notes:
2833:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
2834:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2835:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

2839: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2840:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2841:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2842: @*/
2843: PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2844: {
2845:   PetscInt N;

2847:   PetscFunctionBegin;
2851:   PetscCall(VecGetLocalSize(x, &N));
2852:   PetscCheck(m == N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local array size %" PetscInt_FMT " does not match 1d array dimensions %" PetscInt_FMT, N, m);
2853:   PetscCall(VecGetArray(x, a));
2854:   *a -= mstart;
2855:   PetscFunctionReturn(PETSC_SUCCESS);
2856: }

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

2863:    Logically Collective

2865:    Input Parameters:
2866: +  x - the vector
2867: .  m - first dimension of two dimensional array
2868: -  mstart - first index you will use in first coordinate direction (often 0)

2870:    Output Parameter:
2871: .  a - location to put pointer to the array

2873:    Level: developer

2875:   Notes:
2876:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
2877:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2878:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

2882: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2883:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2884:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2885: @*/
2886: PetscErrorCode VecGetArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2887: {
2888:   PetscInt N;

2890:   PetscFunctionBegin;
2894:   PetscCall(VecGetLocalSize(x, &N));
2895:   PetscCheck(m == N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local array size %" PetscInt_FMT " does not match 1d array dimensions %" PetscInt_FMT, N, m);
2896:   PetscCall(VecGetArrayWrite(x, a));
2897:   *a -= mstart;
2898:   PetscFunctionReturn(PETSC_SUCCESS);
2899: }

2901: /*@C
2902:    VecRestoreArray1d - Restores a vector after `VecGetArray1d()` has been called.

2904:    Logically Collective

2906:    Input Parameters:
2907: +  x - the vector
2908: .  m - first dimension of two dimensional array
2909: .  mstart - first index you will use in first coordinate direction (often 0)
2910: -  a - location of pointer to array obtained from `VecGetArray1d()`

2912:    Level: developer

2914:    Notes:
2915:    For regular PETSc vectors this routine does not involve any copies. For
2916:    any special vectors that do not store local vector data in a contiguous
2917:    array, this routine will copy the data back into the underlying
2918:    vector data structure from the array obtained with `VecGetArray1d()`.

2920:    This routine actually zeros out the a pointer.

2922: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2923:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2924:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2925: @*/
2926: PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2927: {
2928:   PetscFunctionBegin;
2931:   PetscCall(VecRestoreArray(x, NULL));
2932:   PetscFunctionReturn(PETSC_SUCCESS);
2933: }

2935: /*@C
2936:    VecRestoreArray1dWrite - Restores a vector after `VecGetArray1dWrite()` has been called.

2938:    Logically Collective

2940:    Input Parameters:
2941: +  x - the vector
2942: .  m - first dimension of two dimensional array
2943: .  mstart - first index you will use in first coordinate direction (often 0)
2944: -  a - location of pointer to array obtained from `VecGetArray1d()`

2946:    Level: developer

2948:    Notes:
2949:    For regular PETSc vectors this routine does not involve any copies. For
2950:    any special vectors that do not store local vector data in a contiguous
2951:    array, this routine will copy the data back into the underlying
2952:    vector data structure from the array obtained with `VecGetArray1d()`.

2954:    This routine actually zeros out the a pointer.

2956: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2957:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2958:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2959: @*/
2960: PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2961: {
2962:   PetscFunctionBegin;
2965:   PetscCall(VecRestoreArrayWrite(x, NULL));
2966:   PetscFunctionReturn(PETSC_SUCCESS);
2967: }

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

2974:    Logically Collective

2976:    Input Parameters:
2977: +  x - the vector
2978: .  m - first dimension of three dimensional array
2979: .  n - second dimension of three dimensional array
2980: .  p - third dimension of three dimensional array
2981: .  mstart - first index you will use in first coordinate direction (often 0)
2982: .  nstart - first index in the second coordinate direction (often 0)
2983: -  pstart - first index in the third coordinate direction (often 0)

2985:    Output Parameter:
2986: .  a - location to put pointer to the array

2988:    Level: developer

2990:   Notes:
2991:    For a vector obtained from `DMCreateLocalVector()` mstart, nstart, and pstart are likely
2992:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2993:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2994:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.

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

2998: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2999:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3000:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3001: @*/
3002: PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3003: {
3004:   PetscInt     i, N, j;
3005:   PetscScalar *aa, **b;

3007:   PetscFunctionBegin;
3011:   PetscCall(VecGetLocalSize(x, &N));
3012:   PetscCheck(m * n * p == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 3d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n, p);
3013:   PetscCall(VecGetArray(x, &aa));

3015:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3016:   b = (PetscScalar **)((*a) + m);
3017:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3018:   for (i = 0; i < m; i++)
3019:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;
3020:   *a -= mstart;
3021:   PetscFunctionReturn(PETSC_SUCCESS);
3022: }

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

3029:    Logically Collective

3031:    Input Parameters:
3032: +  x - the vector
3033: .  m - first dimension of three dimensional array
3034: .  n - second dimension of three dimensional array
3035: .  p - third dimension of three dimensional array
3036: .  mstart - first index you will use in first coordinate direction (often 0)
3037: .  nstart - first index in the second coordinate direction (often 0)
3038: -  pstart - first index in the third coordinate direction (often 0)

3040:    Output Parameter:
3041: .  a - location to put pointer to the array

3043:    Level: developer

3045:   Notes:
3046:    For a vector obtained from `DMCreateLocalVector()` mstart, nstart, and pstart are likely
3047:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3048:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3049:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.

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

3053: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3054:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3055:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3056: @*/
3057: PetscErrorCode VecGetArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3058: {
3059:   PetscInt     i, N, j;
3060:   PetscScalar *aa, **b;

3062:   PetscFunctionBegin;
3066:   PetscCall(VecGetLocalSize(x, &N));
3067:   PetscCheck(m * n * p == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 3d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n, p);
3068:   PetscCall(VecGetArrayWrite(x, &aa));

3070:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3071:   b = (PetscScalar **)((*a) + m);
3072:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3073:   for (i = 0; i < m; i++)
3074:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;

3076:   *a -= mstart;
3077:   PetscFunctionReturn(PETSC_SUCCESS);
3078: }

3080: /*@C
3081:    VecRestoreArray3d - Restores a vector after `VecGetArray3d()` has been called.

3083:    Logically Collective

3085:    Input Parameters:
3086: +  x - the vector
3087: .  m - first dimension of three dimensional array
3088: .  n - second dimension of the three dimensional array
3089: .  p - third dimension of the three dimensional array
3090: .  mstart - first index you will use in first coordinate direction (often 0)
3091: .  nstart - first index in the second coordinate direction (often 0)
3092: .  pstart - first index in the third coordinate direction (often 0)
3093: -  a - location of pointer to array obtained from VecGetArray3d()

3095:    Level: developer

3097:    Notes:
3098:    For regular PETSc vectors this routine does not involve any copies. For
3099:    any special vectors that do not store local vector data in a contiguous
3100:    array, this routine will copy the data back into the underlying
3101:    vector data structure from the array obtained with `VecGetArray()`.

3103:    This routine actually zeros out the a pointer.

3105: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3106:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3107:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3108: @*/
3109: PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3110: {
3111:   void *dummy;

3113:   PetscFunctionBegin;
3117:   dummy = (void *)(*a + mstart);
3118:   PetscCall(PetscFree(dummy));
3119:   PetscCall(VecRestoreArray(x, NULL));
3120:   PetscFunctionReturn(PETSC_SUCCESS);
3121: }

3123: /*@C
3124:    VecRestoreArray3dWrite - Restores a vector after `VecGetArray3dWrite()` has been called.

3126:    Logically Collective

3128:    Input Parameters:
3129: +  x - the vector
3130: .  m - first dimension of three dimensional array
3131: .  n - second dimension of the three dimensional array
3132: .  p - third dimension of the three dimensional array
3133: .  mstart - first index you will use in first coordinate direction (often 0)
3134: .  nstart - first index in the second coordinate direction (often 0)
3135: .  pstart - first index in the third coordinate direction (often 0)
3136: -  a - location of pointer to array obtained from VecGetArray3d()

3138:    Level: developer

3140:    Notes:
3141:    For regular PETSc vectors this routine does not involve any copies. For
3142:    any special vectors that do not store local vector data in a contiguous
3143:    array, this routine will copy the data back into the underlying
3144:    vector data structure from the array obtained with `VecGetArray()`.

3146:    This routine actually zeros out the a pointer.

3148: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3149:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3150:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3151: @*/
3152: PetscErrorCode VecRestoreArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3153: {
3154:   void *dummy;

3156:   PetscFunctionBegin;
3160:   dummy = (void *)(*a + mstart);
3161:   PetscCall(PetscFree(dummy));
3162:   PetscCall(VecRestoreArrayWrite(x, NULL));
3163:   PetscFunctionReturn(PETSC_SUCCESS);
3164: }

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

3171:    Logically Collective

3173:    Input Parameters:
3174: +  x - the vector
3175: .  m - first dimension of four dimensional array
3176: .  n - second dimension of four dimensional array
3177: .  p - third dimension of four dimensional array
3178: .  q - fourth dimension of four dimensional array
3179: .  mstart - first index you will use in first coordinate direction (often 0)
3180: .  nstart - first index in the second coordinate direction (often 0)
3181: .  pstart - first index in the third coordinate direction (often 0)
3182: -  qstart - first index in the fourth coordinate direction (often 0)

3184:    Output Parameter:
3185: .  a - location to put pointer to the array

3187:    Level: beginner

3189:   Notes:
3190:    For a vector obtained from `DMCreateLocalVector()` mstart, nstart, and pstart are likely
3191:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3192:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3193:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.

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

3197: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3198:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3199:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3200: @*/
3201: PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3202: {
3203:   PetscInt     i, N, j, k;
3204:   PetscScalar *aa, ***b, **c;

3206:   PetscFunctionBegin;
3210:   PetscCall(VecGetLocalSize(x, &N));
3211:   PetscCheck(m * n * p * q == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 4d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n, p, q);
3212:   PetscCall(VecGetArray(x, &aa));

3214:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3215:   b = (PetscScalar ***)((*a) + m);
3216:   c = (PetscScalar **)(b + m * n);
3217:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3218:   for (i = 0; i < m; i++)
3219:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3220:   for (i = 0; i < m; i++)
3221:     for (j = 0; j < n; j++)
3222:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3223:   *a -= mstart;
3224:   PetscFunctionReturn(PETSC_SUCCESS);
3225: }

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

3232:    Logically Collective

3234:    Input Parameters:
3235: +  x - the vector
3236: .  m - first dimension of four dimensional array
3237: .  n - second dimension of four dimensional array
3238: .  p - third dimension of four dimensional array
3239: .  q - fourth dimension of four dimensional array
3240: .  mstart - first index you will use in first coordinate direction (often 0)
3241: .  nstart - first index in the second coordinate direction (often 0)
3242: .  pstart - first index in the third coordinate direction (often 0)
3243: -  qstart - first index in the fourth coordinate direction (often 0)

3245:    Output Parameter:
3246: .  a - location to put pointer to the array

3248:    Level: beginner

3250:   Notes:
3251:    For a vector obtained from `DMCreateLocalVector()` mstart, nstart, and pstart are likely
3252:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3253:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3254:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.

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

3258: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3259:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3260:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3261: @*/
3262: PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3263: {
3264:   PetscInt     i, N, j, k;
3265:   PetscScalar *aa, ***b, **c;

3267:   PetscFunctionBegin;
3271:   PetscCall(VecGetLocalSize(x, &N));
3272:   PetscCheck(m * n * p * q == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 4d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n, p, q);
3273:   PetscCall(VecGetArrayWrite(x, &aa));

3275:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3276:   b = (PetscScalar ***)((*a) + m);
3277:   c = (PetscScalar **)(b + m * n);
3278:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3279:   for (i = 0; i < m; i++)
3280:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3281:   for (i = 0; i < m; i++)
3282:     for (j = 0; j < n; j++)
3283:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3284:   *a -= mstart;
3285:   PetscFunctionReturn(PETSC_SUCCESS);
3286: }

3288: /*@C
3289:    VecRestoreArray4d - Restores a vector after `VecGetArray4d()` has been called.

3291:    Logically Collective

3293:    Input Parameters:
3294: +  x - the vector
3295: .  m - first dimension of four dimensional array
3296: .  n - second dimension of the four dimensional array
3297: .  p - third dimension of the four dimensional array
3298: .  q - fourth dimension of the four dimensional array
3299: .  mstart - first index you will use in first coordinate direction (often 0)
3300: .  nstart - first index in the second coordinate direction (often 0)
3301: .  pstart - first index in the third coordinate direction (often 0)
3302: .  qstart - first index in the fourth coordinate direction (often 0)
3303: -  a - location of pointer to array obtained from VecGetArray4d()

3305:    Level: beginner

3307:    Notes:
3308:    For regular PETSc vectors this routine does not involve any copies. For
3309:    any special vectors that do not store local vector data in a contiguous
3310:    array, this routine will copy the data back into the underlying
3311:    vector data structure from the array obtained with `VecGetArray()`.

3313:    This routine actually zeros out the a pointer.

3315: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3316:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3317:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3318: @*/
3319: PetscErrorCode VecRestoreArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3320: {
3321:   void *dummy;

3323:   PetscFunctionBegin;
3327:   dummy = (void *)(*a + mstart);
3328:   PetscCall(PetscFree(dummy));
3329:   PetscCall(VecRestoreArray(x, NULL));
3330:   PetscFunctionReturn(PETSC_SUCCESS);
3331: }

3333: /*@C
3334:    VecRestoreArray4dWrite - Restores a vector after `VecGetArray4dWrite()` has been called.

3336:    Logically Collective

3338:    Input Parameters:
3339: +  x - the vector
3340: .  m - first dimension of four dimensional array
3341: .  n - second dimension of the four dimensional array
3342: .  p - third dimension of the four dimensional array
3343: .  q - fourth dimension of the four dimensional array
3344: .  mstart - first index you will use in first coordinate direction (often 0)
3345: .  nstart - first index in the second coordinate direction (often 0)
3346: .  pstart - first index in the third coordinate direction (often 0)
3347: .  qstart - first index in the fourth coordinate direction (often 0)
3348: -  a - location of pointer to array obtained from `VecGetArray4d()`

3350:    Level: beginner

3352:    Notes:
3353:    For regular PETSc vectors this routine does not involve any copies. For
3354:    any special vectors that do not store local vector data in a contiguous
3355:    array, this routine will copy the data back into the underlying
3356:    vector data structure from the array obtained with `VecGetArray()`.

3358:    This routine actually zeros out the a pointer.

3360: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3361:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3362:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3363: @*/
3364: PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3365: {
3366:   void *dummy;

3368:   PetscFunctionBegin;
3372:   dummy = (void *)(*a + mstart);
3373:   PetscCall(PetscFree(dummy));
3374:   PetscCall(VecRestoreArrayWrite(x, NULL));
3375:   PetscFunctionReturn(PETSC_SUCCESS);
3376: }

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

3383:    Logically Collective

3385:    Input Parameters:
3386: +  x - the vector
3387: .  m - first dimension of two dimensional array
3388: .  n - second dimension of two dimensional array
3389: .  mstart - first index you will use in first coordinate direction (often 0)
3390: -  nstart - first index in the second coordinate direction (often 0)

3392:    Output Parameter:
3393: .  a - location to put pointer to the array

3395:    Level: developer

3397:   Notes:
3398:    For a vector obtained from `DMCreateLocalVector()` mstart and nstart are likely
3399:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3400:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3401:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.

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

3405: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3406:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3407:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3408: @*/
3409: PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3410: {
3411:   PetscInt           i, N;
3412:   const PetscScalar *aa;

3414:   PetscFunctionBegin;
3418:   PetscCall(VecGetLocalSize(x, &N));
3419:   PetscCheck(m * n == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 2d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n);
3420:   PetscCall(VecGetArrayRead(x, &aa));

3422:   PetscCall(PetscMalloc1(m, a));
3423:   for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3424:   *a -= mstart;
3425:   PetscFunctionReturn(PETSC_SUCCESS);
3426: }

3428: /*@C
3429:    VecRestoreArray2dRead - Restores a vector after `VecGetArray2dRead()` has been called.

3431:    Logically Collective

3433:    Input Parameters:
3434: +  x - the vector
3435: .  m - first dimension of two dimensional array
3436: .  n - second dimension of the two dimensional array
3437: .  mstart - first index you will use in first coordinate direction (often 0)
3438: .  nstart - first index in the second coordinate direction (often 0)
3439: -  a - location of pointer to array obtained from VecGetArray2d()

3441:    Level: developer

3443:    Notes:
3444:    For regular PETSc vectors this routine does not involve any copies. For
3445:    any special vectors that do not store local vector data in a contiguous
3446:    array, this routine will copy the data back into the underlying
3447:    vector data structure from the array obtained with `VecGetArray()`.

3449:    This routine actually zeros out the a pointer.

3451: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3452:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3453:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3454: @*/
3455: PetscErrorCode VecRestoreArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3456: {
3457:   void *dummy;

3459:   PetscFunctionBegin;
3463:   dummy = (void *)(*a + mstart);
3464:   PetscCall(PetscFree(dummy));
3465:   PetscCall(VecRestoreArrayRead(x, NULL));
3466:   PetscFunctionReturn(PETSC_SUCCESS);
3467: }

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

3474:    Logically Collective

3476:    Input Parameters:
3477: +  x - the vector
3478: .  m - first dimension of two dimensional array
3479: -  mstart - first index you will use in first coordinate direction (often 0)

3481:    Output Parameter:
3482: .  a - location to put pointer to the array

3484:    Level: developer

3486:   Notes:
3487:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
3488:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3489:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

3493: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3494:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3495:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3496: @*/
3497: PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3498: {
3499:   PetscInt N;

3501:   PetscFunctionBegin;
3505:   PetscCall(VecGetLocalSize(x, &N));
3506:   PetscCheck(m == N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local array size %" PetscInt_FMT " does not match 1d array dimensions %" PetscInt_FMT, N, m);
3507:   PetscCall(VecGetArrayRead(x, (const PetscScalar **)a));
3508:   *a -= mstart;
3509:   PetscFunctionReturn(PETSC_SUCCESS);
3510: }

3512: /*@C
3513:    VecRestoreArray1dRead - Restores a vector after `VecGetArray1dRead()` has been called.

3515:    Logically Collective

3517:    Input Parameters:
3518: +  x - the vector
3519: .  m - first dimension of two dimensional array
3520: .  mstart - first index you will use in first coordinate direction (often 0)
3521: -  a - location of pointer to array obtained from `VecGetArray1dRead()`

3523:    Level: developer

3525:    Notes:
3526:    For regular PETSc vectors this routine does not involve any copies. For
3527:    any special vectors that do not store local vector data in a contiguous
3528:    array, this routine will copy the data back into the underlying
3529:    vector data structure from the array obtained with `VecGetArray1dRead()`.

3531:    This routine actually zeros out the a pointer.

3533: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3534:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3535:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3536: @*/
3537: PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3538: {
3539:   PetscFunctionBegin;
3542:   PetscCall(VecRestoreArrayRead(x, NULL));
3543:   PetscFunctionReturn(PETSC_SUCCESS);
3544: }

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

3551:    Logically Collective

3553:    Input Parameters:
3554: +  x - the vector
3555: .  m - first dimension of three dimensional array
3556: .  n - second dimension of three dimensional array
3557: .  p - third dimension of three dimensional array
3558: .  mstart - first index you will use in first coordinate direction (often 0)
3559: .  nstart - first index in the second coordinate direction (often 0)
3560: -  pstart - first index in the third coordinate direction (often 0)

3562:    Output Parameter:
3563: .  a - location to put pointer to the array

3565:    Level: developer

3567:   Notes:
3568:    For a vector obtained from `DMCreateLocalVector()` mstart, nstart, and pstart are likely
3569:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3570:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3571:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3dRead()`.

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

3575: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3576:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3577:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3578: @*/
3579: PetscErrorCode VecGetArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3580: {
3581:   PetscInt           i, N, j;
3582:   const PetscScalar *aa;
3583:   PetscScalar      **b;

3585:   PetscFunctionBegin;
3589:   PetscCall(VecGetLocalSize(x, &N));
3590:   PetscCheck(m * n * p == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 3d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n, p);
3591:   PetscCall(VecGetArrayRead(x, &aa));

3593:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3594:   b = (PetscScalar **)((*a) + m);
3595:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3596:   for (i = 0; i < m; i++)
3597:     for (j = 0; j < n; j++) b[i * n + j] = (PetscScalar *)aa + i * n * p + j * p - pstart;
3598:   *a -= mstart;
3599:   PetscFunctionReturn(PETSC_SUCCESS);
3600: }

3602: /*@C
3603:    VecRestoreArray3dRead - Restores a vector after `VecGetArray3dRead()` has been called.

3605:    Logically Collective

3607:    Input Parameters:
3608: +  x - the vector
3609: .  m - first dimension of three dimensional array
3610: .  n - second dimension of the three dimensional array
3611: .  p - third dimension of the three dimensional array
3612: .  mstart - first index you will use in first coordinate direction (often 0)
3613: .  nstart - first index in the second coordinate direction (often 0)
3614: .  pstart - first index in the third coordinate direction (often 0)
3615: -  a - location of pointer to array obtained from `VecGetArray3dRead()`

3617:    Level: developer

3619:    Notes:
3620:    For regular PETSc vectors this routine does not involve any copies. For
3621:    any special vectors that do not store local vector data in a contiguous
3622:    array, this routine will copy the data back into the underlying
3623:    vector data structure from the array obtained with `VecGetArray()`.

3625:    This routine actually zeros out the a pointer.

3627: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3628:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3629:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3630: @*/
3631: PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3632: {
3633:   void *dummy;

3635:   PetscFunctionBegin;
3639:   dummy = (void *)(*a + mstart);
3640:   PetscCall(PetscFree(dummy));
3641:   PetscCall(VecRestoreArrayRead(x, NULL));
3642:   PetscFunctionReturn(PETSC_SUCCESS);
3643: }

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

3650:    Logically Collective

3652:    Input Parameters:
3653: +  x - the vector
3654: .  m - first dimension of four dimensional array
3655: .  n - second dimension of four dimensional array
3656: .  p - third dimension of four dimensional array
3657: .  q - fourth dimension of four dimensional array
3658: .  mstart - first index you will use in first coordinate direction (often 0)
3659: .  nstart - first index in the second coordinate direction (often 0)
3660: .  pstart - first index in the third coordinate direction (often 0)
3661: -  qstart - first index in the fourth coordinate direction (often 0)

3663:    Output Parameter:
3664: .  a - location to put pointer to the array

3666:    Level: beginner

3668:   Notes:
3669:    For a vector obtained from `DMCreateLocalVector()` mstart, nstart, and pstart are likely
3670:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3671:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3672:    the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.

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

3676: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3677:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3678:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3679: @*/
3680: PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3681: {
3682:   PetscInt           i, N, j, k;
3683:   const PetscScalar *aa;
3684:   PetscScalar     ***b, **c;

3686:   PetscFunctionBegin;
3690:   PetscCall(VecGetLocalSize(x, &N));
3691:   PetscCheck(m * n * p * q == N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local array size %" PetscInt_FMT " does not match 4d array dimensions %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT " by %" PetscInt_FMT, N, m, n, p, q);
3692:   PetscCall(VecGetArrayRead(x, &aa));

3694:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3695:   b = (PetscScalar ***)((*a) + m);
3696:   c = (PetscScalar **)(b + m * n);
3697:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3698:   for (i = 0; i < m; i++)
3699:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3700:   for (i = 0; i < m; i++)
3701:     for (j = 0; j < n; j++)
3702:       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;
3703:   *a -= mstart;
3704:   PetscFunctionReturn(PETSC_SUCCESS);
3705: }

3707: /*@C
3708:    VecRestoreArray4dRead - Restores a vector after `VecGetArray4d()` has been called.

3710:    Logically Collective

3712:    Input Parameters:
3713: +  x - the vector
3714: .  m - first dimension of four dimensional array
3715: .  n - second dimension of the four dimensional array
3716: .  p - third dimension of the four dimensional array
3717: .  q - fourth dimension of the four dimensional array
3718: .  mstart - first index you will use in first coordinate direction (often 0)
3719: .  nstart - first index in the second coordinate direction (often 0)
3720: .  pstart - first index in the third coordinate direction (often 0)
3721: .  qstart - first index in the fourth coordinate direction (often 0)
3722: -  a - location of pointer to array obtained from `VecGetArray4dRead()`

3724:    Level: beginner

3726:    Notes:
3727:    For regular PETSc vectors this routine does not involve any copies. For
3728:    any special vectors that do not store local vector data in a contiguous
3729:    array, this routine will copy the data back into the underlying
3730:    vector data structure from the array obtained with `VecGetArray()`.

3732:    This routine actually zeros out the a pointer.

3734: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3735:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3736:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3737: @*/
3738: PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3739: {
3740:   void *dummy;

3742:   PetscFunctionBegin;
3746:   dummy = (void *)(*a + mstart);
3747:   PetscCall(PetscFree(dummy));
3748:   PetscCall(VecRestoreArrayRead(x, NULL));
3749:   PetscFunctionReturn(PETSC_SUCCESS);
3750: }

3752: #if defined(PETSC_USE_DEBUG)

3754: /*@
3755:    VecLockGet  - Gets the current lock status of a vector

3757:    Logically Collective

3759:    Input Parameter:
3760: .  x - the vector

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

3766:    Level: advanced

3768: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
3769: @*/
3770: PetscErrorCode VecLockGet(Vec x, PetscInt *state)
3771: {
3772:   PetscFunctionBegin;
3774:   *state = x->lock;
3775:   PetscFunctionReturn(PETSC_SUCCESS);
3776: }

3778: PetscErrorCode VecLockGetLocation(Vec x, const char *file[], const char *func[], int *line)
3779: {
3780:   PetscFunctionBegin;
3785:   #if !PetscDefined(HAVE_THREADSAFETY)
3786:   {
3787:     const int index = x->lockstack.currentsize - 1;

3789:     PetscCheck(index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupted vec lock stack, have negative index %d", index);
3790:     *file = x->lockstack.file[index];
3791:     *func = x->lockstack.function[index];
3792:     *line = x->lockstack.line[index];
3793:   }
3794:   #else
3795:   *file = NULL;
3796:   *func = NULL;
3797:   *line = 0;
3798:   #endif
3799:   PetscFunctionReturn(PETSC_SUCCESS);
3800: }

3802: /*@
3803:    VecLockReadPush  - Pushes a read-only lock on a vector to prevent it from being written to

3805:    Logically Collective

3807:    Input Parameter:
3808: .  x - the vector

3810:    Level: intermediate

3812:    Notes:
3813:     If this is set then calls to `VecGetArray()` or `VecSetValues()` or any other routines that change the vectors values will generate an error.

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

3818: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPop()`, `VecLockGet()`
3819: @*/
3820: PetscErrorCode VecLockReadPush(Vec x)
3821: {
3822:   PetscFunctionBegin;
3824:   PetscCheck(x->lock++ >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector is already locked for exclusive write access but you want to read it");
3825:   #if !PetscDefined(HAVE_THREADSAFETY)
3826:   {
3827:     const char *file, *func;
3828:     int         index, line;

3830:     if ((index = petscstack.currentsize - 2) == -1) {
3831:       // vec was locked "outside" of petsc, either in user-land or main. the error message will
3832:       // now show this function as the culprit, but it will include the stacktrace
3833:       file = "unknown user-file";
3834:       func = "unknown_user_function";
3835:       line = 0;
3836:     } else {
3837:       PetscCheck(index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected petscstack, have negative index %d", index);
3838:       file = petscstack.file[index];
3839:       func = petscstack.function[index];
3840:       line = petscstack.line[index];
3841:     }
3842:     PetscStackPush_Private(x->lockstack, file, func, line, petscstack.petscroutine[index], PETSC_FALSE);
3843:   }
3844:   #endif
3845:   PetscFunctionReturn(PETSC_SUCCESS);
3846: }

3848: /*@
3849:    VecLockReadPop  - Pops a read-only lock from a vector

3851:    Logically Collective

3853:    Input Parameter:
3854: .  x - the vector

3856:    Level: intermediate

3858: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockGet()`
3859: @*/
3860: PetscErrorCode VecLockReadPop(Vec x)
3861: {
3862:   PetscFunctionBegin;
3864:   PetscCheck(--x->lock >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector has been unlocked from read-only access too many times");
3865:   #if !PetscDefined(HAVE_THREADSAFETY)
3866:   {
3867:     const char *previous = x->lockstack.function[x->lockstack.currentsize - 1];

3869:     PetscStackPop_Private(x->lockstack, previous);
3870:   }
3871:   #endif
3872:   PetscFunctionReturn(PETSC_SUCCESS);
3873: }

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

3878:    Logically Collective

3880:    Input Parameters:
3881: +  x   - the vector
3882: -  flg - `PETSC_TRUE` to lock the vector for exclusive read/write access; `PETSC_FALSE` to unlock it.

3884:    Level: intermediate

3886:    Notes:
3887:     The function is useful in split-phase computations, which usually have a begin phase and an end phase.
3888:     One can call `VecLockWriteSet`(x,`PETSC_TRUE`) in the begin phase to lock a vector for exclusive
3889:     access, and call `VecLockWriteSet`(x,`PETSC_FALSE`) in the end phase to unlock the vector from exclusive
3890:     access. In this way, one is ensured no other operations can access the vector in between. The code may like

3892: .vb
3893:        VecGetArray(x,&xdata); // begin phase
3894:        VecLockWriteSet(v,PETSC_TRUE);

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

3898:        VecRestoreArray(x,&vdata); // end phase
3899:        VecLockWriteSet(v,PETSC_FALSE);
3900: .ve

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

3905: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
3906: @*/
3907: PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
3908: {
3909:   PetscFunctionBegin;
3911:   if (flg) {
3912:     PetscCheck(x->lock <= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector is already locked for read-only access but you want to write it");
3913:     PetscCheck(x->lock >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector is already locked for exclusive write access but you want to write it");
3914:     x->lock = -1;
3915:   } else {
3916:     PetscCheck(x->lock == -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector is not locked for exclusive write access but you want to unlock it from that");
3917:     x->lock = 0;
3918:   }
3919:   PetscFunctionReturn(PETSC_SUCCESS);
3920: }

3922: /*@
3923:    VecLockPush  - Pushes a read-only lock on a vector to prevent it from being written to

3925:    Level: deprecated

3927: .seealso: [](chapter_vectors), `Vec`, `VecLockReadPush()`
3928: @*/
3929: PetscErrorCode VecLockPush(Vec x)
3930: {
3931:   PetscFunctionBegin;
3932:   PetscCall(VecLockReadPush(x));
3933:   PetscFunctionReturn(PETSC_SUCCESS);
3934: }

3936: /*@
3937:    VecLockPop  - Pops a read-only lock from a vector

3939:    Level: deprecated

3941: .seealso: [](chapter_vectors), `Vec`, `VecLockReadPop()`
3942: @*/
3943: PetscErrorCode VecLockPop(Vec x)
3944: {
3945:   PetscFunctionBegin;
3946:   PetscCall(VecLockReadPop(x));
3947:   PetscFunctionReturn(PETSC_SUCCESS);
3948: }

3950: #endif