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, y  - the vectors

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

 49:    Level: advanced

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

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

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

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

 81:    Collective

 83:    Input Parameters:
 84: .  x, y - the vectors

 86:    Output Parameter:
 87: .  val - the dot product

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

 96:    Level: intermediate

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

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

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

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

134: /*@
135:    VecDotRealPart - Computes the real part of the vector dot product.

137:    Collective

139:    Input Parameters:
140: .  x, y - the vectors

142:    Output Parameter:
143: .  val - the real part of the dot product;

145:    Level: intermediate

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

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

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

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

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

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

171:   PetscFunctionBegin;
172:   PetscCall(VecDot(x, y, &fdot));
173:   *val = PetscRealPart(fdot);
174:   PetscFunctionReturn(PETSC_SUCCESS);
175: }

177: /*@
178:    VecNorm  - Computes the vector norm.

180:    Collective

182:    Input Parameters:
183: +  x - the vector
184: -  type - the type of the norm requested

186:    Output Parameter:
187: .  val - the norm

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

195:     Level: intermediate

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

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

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

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

221:   PetscFunctionBegin;
224:   VecCheckAssembled(x);

228:   /* Cached data? */
229:   PetscCall(VecNormAvailable(x, type, &flg, val));
230:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

232:   PetscCall(VecLockReadPush(x));
233:   PetscCall(PetscLogEventBegin(VEC_Norm, x, 0, 0, 0));
234:   PetscUseTypeMethod(x, norm, type, val);
235:   PetscCall(PetscLogEventEnd(VEC_Norm, x, 0, 0, 0));
236:   PetscCall(VecLockReadPop(x));

238:   if (type != NORM_1_AND_2) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[type], *val));
239:   PetscFunctionReturn(PETSC_SUCCESS);
240: }

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

245:    Not Collective

247:    Input Parameters:
248: +  x - the vector
249: -  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
250:           `NORM_1_AND_2`, which computes both norms and stores them
251:           in a two element array.

253:    Output Parameters:
254: +  available - `PETSC_TRUE` if the val returned is valid
255: -  val - the norm

257:    Level: intermediate

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

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

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

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

290: /*@
291:    VecNormalize - Normalizes a vector by its 2-norm.

293:    Collective

295:    Input Parameter:
296: .  x - the vector

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

301:    Level: intermediate

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

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

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

329:    Collective

331:    Input Parameter:
332: .  x - the vector

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

338:    Level: intermediate

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

343:    Returns the smallest index with the maximum value

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

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

366:    Collective

368:    Input Parameter:
369: .  x - the vector

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

375:    Level: intermediate

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

380:    This returns the smallest index with the minimum value

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

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

404:    Collective

406:    Input Parameters:
407: .  x, y - the vectors

409:    Output Parameter:
410: .  val - the dot product

412:    Level: intermediate

414:    Notes for Users of Complex Numbers:
415:    For complex vectors, VecTDot() computes the indefinite form
416: $     val = (x,y) = y^T x,
417:    where y^T denotes the transpose of y.

419:    Use VecDot() for the inner product
420: $     val = (x,y) = y^H x,
421:    where y^H denotes the conjugate transpose of y.

423: .seealso: [](chapter_vectors), `Vec`, `VecDot()`, `VecMTDot()`
424: @*/
425: PetscErrorCode VecTDot(Vec x, Vec y, PetscScalar *val)
426: {
427:   PetscFunctionBegin;
433:   PetscCheckSameTypeAndComm(x, 1, y, 2);
434:   VecCheckSameSize(x, 1, y, 2);
435:   VecCheckAssembled(x);
436:   VecCheckAssembled(y);

438:   PetscCall(VecLockReadPush(x));
439:   PetscCall(VecLockReadPush(y));
440:   PetscCall(PetscLogEventBegin(VEC_TDot, x, y, 0, 0));
441:   PetscUseTypeMethod(x, tdot, y, val);
442:   PetscCall(PetscLogEventEnd(VEC_TDot, x, y, 0, 0));
443:   PetscCall(VecLockReadPop(x));
444:   PetscCall(VecLockReadPop(y));
445:   PetscFunctionReturn(PETSC_SUCCESS);
446: }

448: /*@
449:    VecScale - Scales a vector.

451:    Not collective

453:    Input Parameters:
454: +  x - the vector
455: -  alpha - the scalar

457:    Level: intermediate

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

462: .seealso: [](chapter_vectors), `Vec`, `VecSet()`
463: @*/
464: PetscErrorCode VecScale(Vec x, PetscScalar alpha)
465: {
466:   PetscReal norms[4];
467:   PetscBool flgs[4];

469:   PetscFunctionBegin;
472:   VecCheckAssembled(x);
473:   PetscCall(VecSetErrorIfLocked(x, 1));
474:   if (alpha == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);

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

479:   PetscCall(PetscLogEventBegin(VEC_Scale, x, 0, 0, 0));
480:   PetscUseTypeMethod(x, scale, alpha);
481:   PetscCall(PetscLogEventEnd(VEC_Scale, x, 0, 0, 0));

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

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

494:    Logically Collective

496:    Input Parameters:
497: +  x  - the vector
498: -  alpha - the scalar

500:    Level: beginner

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

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

511: .seealso: [](chapter_vectors), `Vec`, `VecSetValues()`, `VecSetValuesBlocked()`, `VecSetRandom()`
512: @*/
513: PetscErrorCode VecSet(Vec x, PetscScalar alpha)
514: {
515:   PetscFunctionBegin;
518:   VecCheckAssembled(x);
520:   PetscCall(VecSetErrorIfLocked(x, 1));

522:   PetscCall(PetscLogEventBegin(VEC_Set, x, 0, 0, 0));
523:   PetscUseTypeMethod(x, set, alpha);
524:   PetscCall(PetscLogEventEnd(VEC_Set, x, 0, 0, 0));
525:   PetscCall(PetscObjectStateIncrease((PetscObject)x));

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

529:   {
530:     PetscReal      val = PetscAbsScalar(alpha);
531:     const PetscInt N   = x->map->N;

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

551: /*@
552:    VecAXPY - Computes `y = alpha x + y`.

554:    Logically Collective

556:    Input Parameters:
557: +  alpha - the scalar
558: -  x, y  - the vectors

560:    Output Parameter:
561: .  y - output vector

563:    Level: intermediate

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

576: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
577: @*/
578: PetscErrorCode VecAXPY(Vec y, PetscScalar alpha, Vec x)
579: {
580:   PetscFunctionBegin;
585:   PetscCheckSameTypeAndComm(x, 3, y, 1);
586:   VecCheckSameSize(x, 3, y, 1);
587:   VecCheckAssembled(x);
588:   VecCheckAssembled(y);
590:   if (alpha == (PetscScalar)0.0) PetscFunctionReturn(PETSC_SUCCESS);
591:   PetscCall(VecSetErrorIfLocked(y, 1));
592:   if (x == y) {
593:     PetscCall(VecScale(y, alpha + 1.0));
594:     PetscFunctionReturn(PETSC_SUCCESS);
595:   }
596:   PetscCall(VecLockReadPush(x));
597:   PetscCall(PetscLogEventBegin(VEC_AXPY, x, y, 0, 0));
598:   PetscUseTypeMethod(y, axpy, alpha, x);
599:   PetscCall(PetscLogEventEnd(VEC_AXPY, x, y, 0, 0));
600:   PetscCall(VecLockReadPop(x));
601:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
602:   PetscFunctionReturn(PETSC_SUCCESS);
603: }

605: /*@
606:    VecAYPX - Computes `y = x + beta y`.

608:    Logically Collective

610:    Input Parameters:
611: +  beta - the scalar
612: .  x - the unscaled vector
613: -  y - the vector to be scaled

615:    Output Parameter:
616: .  y - output vector

618:    Level: intermediate

620:    Developer Note:
621:     The implementation is optimized for beta of -1.0, 0.0, and 1.0

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

655: /*@
656:    VecAXPBY - Computes `y = alpha x + beta y`.

658:    Logically Collective

660:    Input Parameters:
661: +  alpha,beta - the scalars
662: .  x - the first scaled vector
663: -  y - the second scaled vector

665:    Output Parameter:
666: .  y - output vector

668:    Level: intermediate

670:    Developer Note:
671:    The implementation is optimized for alpha and/or beta values of 0.0 and 1.0

673: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`
674: @*/
675: PetscErrorCode VecAXPBY(Vec y, PetscScalar alpha, PetscScalar beta, Vec x)
676: {
677:   PetscFunctionBegin;
682:   PetscCheckSameTypeAndComm(x, 4, y, 1);
683:   VecCheckSameSize(y, 1, x, 4);
684:   VecCheckAssembled(x);
685:   VecCheckAssembled(y);
688:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);
689:   if (x == y) {
690:     PetscCall(VecScale(y, alpha + beta));
691:     PetscFunctionReturn(PETSC_SUCCESS);
692:   }

694:   PetscCall(VecSetErrorIfLocked(y, 1));
695:   PetscCall(VecLockReadPush(x));
696:   PetscCall(PetscLogEventBegin(VEC_AXPY, y, x, 0, 0));
697:   PetscUseTypeMethod(y, axpby, alpha, beta, x);
698:   PetscCall(PetscLogEventEnd(VEC_AXPY, y, x, 0, 0));
699:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
700:   PetscCall(VecLockReadPop(x));
701:   PetscFunctionReturn(PETSC_SUCCESS);
702: }

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

707:    Logically Collective

709:    Input Parameters:
710: +  alpha,beta, gamma - the scalars
711: -  x, y, z  - the vectors

713:    Output Parameter:
714: .  z - output vector

716:    Level: intermediate

718:    Note:
719:    `x`, `y` and `z` must be different vectors

721:    Developer Note:
722:     The implementation is optimized for alpha of 1.0 and gamma of 1.0 or 0.0

724: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBY()`
725: @*/
726: PetscErrorCode VecAXPBYPCZ(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y)
727: {
728:   PetscFunctionBegin;
735:   PetscCheckSameTypeAndComm(x, 5, y, 6);
736:   PetscCheckSameTypeAndComm(x, 5, z, 1);
737:   VecCheckSameSize(x, 1, y, 5);
738:   VecCheckSameSize(x, 1, z, 6);
739:   PetscCheck(x != y && x != z, PetscObjectComm((PetscObject)x), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
740:   PetscCheck(y != z, PetscObjectComm((PetscObject)y), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
741:   VecCheckAssembled(x);
742:   VecCheckAssembled(y);
743:   VecCheckAssembled(z);
747:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);

749:   PetscCall(VecSetErrorIfLocked(z, 1));
750:   PetscCall(VecLockReadPush(x));
751:   PetscCall(VecLockReadPush(y));
752:   PetscCall(PetscLogEventBegin(VEC_AXPBYPCZ, x, y, z, 0));
753:   PetscUseTypeMethod(z, axpbypcz, alpha, beta, gamma, x, y);
754:   PetscCall(PetscLogEventEnd(VEC_AXPBYPCZ, x, y, z, 0));
755:   PetscCall(PetscObjectStateIncrease((PetscObject)z));
756:   PetscCall(VecLockReadPop(x));
757:   PetscCall(VecLockReadPop(y));
758:   PetscFunctionReturn(PETSC_SUCCESS);
759: }

761: /*@
762:    VecWAXPY - Computes `w = alpha x + y`.

764:    Logically Collective

766:    Input Parameters:
767: +  alpha - the scalar
768: -  x, y  - the vectors

770:    Output Parameter:
771: .  w - the result

773:    Level: intermediate

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

778:    Developer Note:
779:     The implementation is optimized for alpha of -1.0, 0.0, and 1.0

781: .seealso: [](chapter_vectors), `Vec`, `VecAXPY()`, `VecAYPX()`, `VecAXPBY()`, `VecMAXPY()`, `VecAXPBYPCZ()`
782: @*/
783: PetscErrorCode VecWAXPY(Vec w, PetscScalar alpha, Vec x, Vec y)
784: {
785:   PetscFunctionBegin;
792:   PetscCheckSameTypeAndComm(x, 3, y, 4);
793:   PetscCheckSameTypeAndComm(y, 4, w, 1);
794:   VecCheckSameSize(x, 3, y, 4);
795:   VecCheckSameSize(x, 3, w, 1);
796:   PetscCheck(w != y, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector y, suggest VecAXPY()");
797:   PetscCheck(w != x, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector x, suggest VecAYPX()");
798:   VecCheckAssembled(x);
799:   VecCheckAssembled(y);
801:   PetscCall(VecSetErrorIfLocked(w, 1));

803:   PetscCall(VecLockReadPush(x));
804:   PetscCall(VecLockReadPush(y));
805:   if (alpha == (PetscScalar)0.0) {
806:     PetscCall(VecCopy(y, w));
807:   } else {
808:     PetscCall(PetscLogEventBegin(VEC_WAXPY, x, y, w, 0));
809:     PetscUseTypeMethod(w, waxpy, alpha, x, y);
810:     PetscCall(PetscLogEventEnd(VEC_WAXPY, x, y, w, 0));
811:     PetscCall(PetscObjectStateIncrease((PetscObject)w));
812:   }
813:   PetscCall(VecLockReadPop(x));
814:   PetscCall(VecLockReadPop(y));
815:   PetscFunctionReturn(PETSC_SUCCESS);
816: }

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

821:    Not Collective

823:    Input Parameters:
824: +  x - vector to insert in
825: .  ni - number of elements to add
826: .  ix - indices where to add
827: .  y - array of values
828: -  iora - either `INSERT_VALUES` to replace the current values or `ADD_VALUES` to add values to any existing entries

830:    Level: beginner

832:    Notes:
833: .vb
834:    `VecSetValues()` sets x[ix[i]] = y[i], for i=0,...,ni-1.
835: .ve

837:    Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
838:    options cannot be mixed without intervening calls to the assembly
839:    routines.

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

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

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

852: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesLocal()`,
853:           `VecSetValue()`, `VecSetValuesBlocked()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `VecGetValues()`
854: @*/
855: PetscErrorCode VecSetValues(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
856: {
857:   PetscFunctionBeginHot;
859:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);

864:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
865:   PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
866:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
867:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
868:   PetscFunctionReturn(PETSC_SUCCESS);
869: }

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

875:     Not Collective

877:    Input Parameters:
878: +  x - vector to get values from
879: .  ni - number of elements to get
880: -  ix - indices where to get them from (in global 1d numbering)

882:    Output Parameter:
883: .   y - array of values

885:    Level: beginner

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

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

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

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

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

900: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`
901: @*/
902: PetscErrorCode VecGetValues(Vec x, PetscInt ni, const PetscInt ix[], PetscScalar y[])
903: {
904:   PetscFunctionBegin;
906:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
910:   VecCheckAssembled(x);
911:   PetscUseTypeMethod(x, getvalues, ni, ix, y);
912:   PetscFunctionReturn(PETSC_SUCCESS);
913: }

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

918:    Not Collective

920:    Input Parameters:
921: +  x - vector to insert in
922: .  ni - number of blocks to add
923: .  ix - indices where to add in block count, rather than element count
924: .  y - array of values
925: -  iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES`, adds values to any existing entries

927:    Level: intermediate

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

933:    Calls to `VecSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
934:    options cannot be mixed without intervening calls to the assembly
935:    routines.

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

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

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

947: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesBlockedLocal()`,
948:           `VecSetValues()`
949: @*/
950: PetscErrorCode VecSetValuesBlocked(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
951: {
952:   PetscFunctionBeginHot;
954:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);

959:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
960:   PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
961:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
962:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
963:   PetscFunctionReturn(PETSC_SUCCESS);
964: }

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

970:    Not Collective

972:    Input Parameters:
973: +  x - vector to insert in
974: .  ni - number of elements to add
975: .  ix - indices where to add
976: .  y - array of values
977: -  iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries

979:    Level: intermediate

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

984:    Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
985:    options cannot be mixed without intervening calls to the assembly
986:    routines.

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

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

993: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetLocalToGlobalMapping()`,
994:           `VecSetValuesBlockedLocal()`
995: @*/
996: PetscErrorCode VecSetValuesLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
997: {
998:   PetscInt lixp[128], *lix = lixp;

1000:   PetscFunctionBeginHot;
1002:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);

1007:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1008:   if (!x->ops->setvalueslocal) {
1009:     if (x->map->mapping) {
1010:       if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1011:       PetscCall(ISLocalToGlobalMappingApply(x->map->mapping, ni, (PetscInt *)ix, lix));
1012:       PetscUseTypeMethod(x, setvalues, ni, lix, y, iora);
1013:       if (ni > 128) PetscCall(PetscFree(lix));
1014:     } else PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
1015:   } else PetscUseTypeMethod(x, setvalueslocal, ni, ix, y, iora);
1016:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1017:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1018:   PetscFunctionReturn(PETSC_SUCCESS);
1019: }

1021: /*@
1022:    VecSetValuesBlockedLocal - Inserts or adds values into certain locations of a vector,
1023:    using a local ordering of the nodes.

1025:    Not Collective

1027:    Input Parameters:
1028: +  x - vector to insert in
1029: .  ni - number of blocks to add
1030: .  ix - indices where to add in block count, not element count
1031: .  y - array of values
1032: -  iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries

1034:    Level: intermediate

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

1040:    Calls to `VecSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1041:    options cannot be mixed without intervening calls to the assembly
1042:    routines.

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

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

1049: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetValuesBlocked()`,
1050:           `VecSetLocalToGlobalMapping()`
1051: @*/
1052: PetscErrorCode VecSetValuesBlockedLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1053: {
1054:   PetscInt lixp[128], *lix = lixp;

1056:   PetscFunctionBeginHot;
1058:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1062:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1063:   if (x->map->mapping) {
1064:     if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1065:     PetscCall(ISLocalToGlobalMappingApplyBlock(x->map->mapping, ni, (PetscInt *)ix, lix));
1066:     PetscUseTypeMethod(x, setvaluesblocked, ni, lix, y, iora);
1067:     if (ni > 128) PetscCall(PetscFree(lix));
1068:   } else {
1069:     PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1070:   }
1071:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1072:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1073:   PetscFunctionReturn(PETSC_SUCCESS);
1074: }

1076: static PetscErrorCode VecMXDot_Private(Vec x, PetscInt nv, const Vec y[], PetscScalar result[], PetscErrorCode (*mxdot)(Vec, PetscInt, const Vec[], PetscScalar[]), PetscLogEvent event)
1077: {
1078:   PetscFunctionBegin;
1081:   VecCheckAssembled(x);
1083:   if (!nv) PetscFunctionReturn(PETSC_SUCCESS);
1085:   for (PetscInt i = 0; i < nv; ++i) {
1088:     PetscCheckSameTypeAndComm(x, 1, y[i], 3);
1089:     VecCheckSameSize(x, 1, y[i], 3);
1090:     VecCheckAssembled(y[i]);
1091:     PetscCall(VecLockReadPush(y[i]));
1092:   }

1096:   PetscCall(VecLockReadPush(x));
1097:   PetscCall(PetscLogEventBegin(event, x, *y, 0, 0));
1098:   PetscCall((*mxdot)(x, nv, y, result));
1099:   PetscCall(PetscLogEventEnd(event, x, *y, 0, 0));
1100:   PetscCall(VecLockReadPop(x));
1101:   for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(y[i]));
1102:   PetscFunctionReturn(PETSC_SUCCESS);
1103: }

1105: /*@
1106:    VecMTDot - Computes indefinite vector multiple dot products.
1107:    That is, it does NOT use the complex conjugate.

1109:    Collective

1111:    Input Parameters:
1112: +  x - one vector
1113: .  nv - number of vectors
1114: -  y - array of vectors.  Note that vectors are pointers

1116:    Output Parameter:
1117: .  val - array of the dot products

1119:    Level: intermediate

1121:    Notes for Users of Complex Numbers:
1122:    For complex vectors, `VecMTDot()` computes the indefinite form
1123: $      val = (x,y) = y^T x,
1124:    where y^T denotes the transpose of y.

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

1130: .seealso: [](chapter_vectors), `Vec`, `VecMDot()`, `VecTDot()`
1131: @*/
1132: PetscErrorCode VecMTDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1133: {
1134:   PetscFunctionBegin;
1136:   PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mtdot, VEC_MTDot));
1137:   PetscFunctionReturn(PETSC_SUCCESS);
1138: }

1140: /*@
1141:    VecMDot - Computes multiple vector dot products.

1143:    Collective

1145:    Input Parameters:
1146: +  x - one vector
1147: .  nv - number of vectors
1148: -  y - array of vectors.

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

1153:    Level: intermediate

1155:    Notes for Users of Complex Numbers:
1156:    For complex vectors, `VecMDot()` computes
1157: $     val = (x,y) = y^H x,
1158:    where y^H denotes the conjugate transpose of y.

1160:    Use `VecMTDot()` for the indefinite form
1161: $     val = (x,y) = y^T x,
1162:    where y^T denotes the transpose of y.

1164: .seealso: [](chapter_vectors), `Vec`, `VecMTDot()`, `VecDot()`
1165: @*/
1166: PetscErrorCode VecMDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1167: {
1168:   PetscFunctionBegin;
1170:   PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mdot, VEC_MDot));
1171:   PetscFunctionReturn(PETSC_SUCCESS);
1172: }

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

1177:    Logically Collective

1179:    Input Parameters:
1180: +  nv - number of scalars and x-vectors
1181: .  alpha - array of scalars
1182: .  y - one vector
1183: -  x - array of vectors

1185:    Level: intermediate

1187:    Note:
1188:     `y` cannot be any of the `x` vectors

1190: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
1191: @*/
1192: PetscErrorCode VecMAXPY(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[])
1193: {
1194:   PetscFunctionBegin;
1196:   VecCheckAssembled(y);
1198:   PetscCall(VecSetErrorIfLocked(y, 1));
1199:   PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);
1200:   if (nv) {
1201:     PetscInt zeros = 0;

1205:     for (PetscInt i = 0; i < nv; ++i) {
1209:       PetscCheckSameTypeAndComm(y, 1, x[i], 4);
1210:       VecCheckSameSize(y, 1, x[i], 4);
1211:       PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1212:       VecCheckAssembled(x[i]);
1213:       PetscCall(VecLockReadPush(x[i]));
1214:       zeros += alpha[i] == (PetscScalar)0.0;
1215:     }

1217:     if (zeros < nv) {
1218:       PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1219:       PetscUseTypeMethod(y, maxpy, nv, alpha, x);
1220:       PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1221:       PetscCall(PetscObjectStateIncrease((PetscObject)y));
1222:     }

1224:     for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1225:   }
1226:   PetscFunctionReturn(PETSC_SUCCESS);
1227: }

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

1234:    Collective

1236:    Input Parameters:
1237: +  nx   - number of vectors to be concatenated
1238: -  X    - array containing the vectors to be concatenated in the order of concatenation

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

1244:    Level: advanced

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

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

1256: .seealso: [](chapter_vectors), `Vec`, `VECNEST`, `VECSCATTER`, `VecScatterCreate()`
1257: @*/
1258: PetscErrorCode VecConcatenate(PetscInt nx, const Vec X[], Vec *Y, IS *x_is[])
1259: {
1260:   MPI_Comm comm;
1261:   VecType  vec_type;
1262:   Vec      Ytmp, Xtmp;
1263:   IS      *is_tmp;
1264:   PetscInt i, shift = 0, Xnl, Xng, Xbegin;

1266:   PetscFunctionBegin;

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

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

1312:     Input Parameters:
1313: +   X - the original vector
1314: -   is - the index set of the subvector

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

1321: */
1322: PetscErrorCode VecGetSubVectorContiguityAndBS_Private(Vec X, IS is, PetscBool *contig, PetscInt *start, PetscInt *blocksize)
1323: {
1324:   PetscInt  gstart, gend, lstart;
1325:   PetscBool red[2] = {PETSC_TRUE /*contiguous*/, PETSC_TRUE /*validVBS*/};
1326:   PetscInt  n, N, ibs, vbs, bs = -1;

1328:   PetscFunctionBegin;
1329:   PetscCall(ISGetLocalSize(is, &n));
1330:   PetscCall(ISGetSize(is, &N));
1331:   PetscCall(ISGetBlockSize(is, &ibs));
1332:   PetscCall(VecGetBlockSize(X, &vbs));
1333:   PetscCall(VecGetOwnershipRange(X, &gstart, &gend));
1334:   PetscCall(ISContiguousLocal(is, gstart, gend, &lstart, &red[0]));
1335:   /* block size is given by IS if ibs > 1; otherwise, check the vector */
1336:   if (ibs > 1) {
1337:     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, red, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1338:     bs = ibs;
1339:   } else {
1340:     if (n % vbs || vbs == 1) red[1] = PETSC_FALSE; /* this process invalidate the collectiveness of block size */
1341:     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, red, 2, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1342:     if (red[0] && red[1]) bs = vbs; /* all processes have a valid block size and the access will be contiguous */
1343:   }

1345:   *contig    = red[0];
1346:   *start     = lstart;
1347:   *blocksize = bs;
1348:   PetscFunctionReturn(PETSC_SUCCESS);
1349: }

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

1353:     Input Parameters:
1354: +   X - the original vector
1355: .   is - the index set of the subvector
1356: -   bs - the block size of the subvector, gotten from VecGetSubVectorContiguityAndBS_Private()

1358:     Output Parameters:
1359: .   Z  - the subvector, which will compose the VecScatter context on output
1360: */
1361: PetscErrorCode VecGetSubVectorThroughVecScatter_Private(Vec X, IS is, PetscInt bs, Vec *Z)
1362: {
1363:   PetscInt   n, N;
1364:   VecScatter vscat;
1365:   Vec        Y;

1367:   PetscFunctionBegin;
1368:   PetscCall(ISGetLocalSize(is, &n));
1369:   PetscCall(ISGetSize(is, &N));
1370:   PetscCall(VecCreate(PetscObjectComm((PetscObject)is), &Y));
1371:   PetscCall(VecSetSizes(Y, n, N));
1372:   PetscCall(VecSetBlockSize(Y, bs));
1373:   PetscCall(VecSetType(Y, ((PetscObject)X)->type_name));
1374:   PetscCall(VecScatterCreate(X, is, Y, NULL, &vscat));
1375:   PetscCall(VecScatterBegin(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1376:   PetscCall(VecScatterEnd(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1377:   PetscCall(PetscObjectCompose((PetscObject)Y, "VecGetSubVector_Scatter", (PetscObject)vscat));
1378:   PetscCall(VecScatterDestroy(&vscat));
1379:   *Z = Y;
1380:   PetscFunctionReturn(PETSC_SUCCESS);
1381: }

1383: /*@
1384:    VecGetSubVector - Gets a vector representing part of another vector

1386:    Collective

1388:    Input Parameters:
1389: +  X - vector from which to extract a subvector
1390: -  is - index set representing portion of `X` to extract

1392:    Output Parameter:
1393: .  Y - subvector corresponding to `is`

1395:    Level: advanced

1397:    Notes:
1398:    The subvector `Y` should be returned with `VecRestoreSubVector()`.
1399:    `X` and must be defined on the same communicator

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

1404:    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`.

1406: .seealso: [](chapter_vectors), `Vec`, `IS`, `VECNEST`, `MatCreateSubMatrix()`
1407: @*/
1408: PetscErrorCode VecGetSubVector(Vec X, IS is, Vec *Y)
1409: {
1410:   Vec Z;

1412:   PetscFunctionBegin;
1415:   PetscCheckSameComm(X, 1, is, 2);
1417:   if (X->ops->getsubvector) {
1418:     PetscUseTypeMethod(X, getsubvector, is, &Z);
1419:   } else { /* Default implementation currently does no caching */
1420:     PetscBool contig;
1421:     PetscInt  n, N, start, bs;

1423:     PetscCall(ISGetLocalSize(is, &n));
1424:     PetscCall(ISGetSize(is, &N));
1425:     PetscCall(VecGetSubVectorContiguityAndBS_Private(X, is, &contig, &start, &bs));
1426:     if (contig) { /* We can do a no-copy implementation */
1427:       const PetscScalar *x;
1428:       PetscInt           state = 0;
1429:       PetscBool          isstd, iscuda, iship;

1431:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &isstd, VECSEQ, VECMPI, VECSTANDARD, ""));
1432:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1433:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));
1434:       if (iscuda) {
1435: #if defined(PETSC_HAVE_CUDA)
1436:         const PetscScalar *x_d;
1437:         PetscMPIInt        size;
1438:         PetscOffloadMask   flg;

1440:         PetscCall(VecCUDAGetArrays_Private(X, &x, &x_d, &flg));
1441:         PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1442:         PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1443:         if (x) x += start;
1444:         if (x_d) x_d += start;
1445:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1446:         if (size == 1) {
1447:           PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1448:         } else {
1449:           PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1450:         }
1451:         Z->offloadmask = flg;
1452: #endif
1453:       } else if (iship) {
1454: #if defined(PETSC_HAVE_HIP)
1455:         const PetscScalar *x_d;
1456:         PetscMPIInt        size;
1457:         PetscOffloadMask   flg;

1459:         PetscCall(VecHIPGetArrays_Private(X, &x, &x_d, &flg));
1460:         PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1461:         PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1462:         if (x) x += start;
1463:         if (x_d) x_d += start;
1464:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1465:         if (size == 1) {
1466:           PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1467:         } else {
1468:           PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1469:         }
1470:         Z->offloadmask = flg;
1471: #endif
1472:       } else if (isstd) {
1473:         PetscMPIInt size;

1475:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1476:         PetscCall(VecGetArrayRead(X, &x));
1477:         if (x) x += start;
1478:         if (size == 1) {
1479:           PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)X), bs, n, x, &Z));
1480:         } else {
1481:           PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)X), bs, n, N, x, &Z));
1482:         }
1483:         PetscCall(VecRestoreArrayRead(X, &x));
1484:       } else { /* default implementation: use place array */
1485:         PetscCall(VecGetArrayRead(X, &x));
1486:         PetscCall(VecCreate(PetscObjectComm((PetscObject)X), &Z));
1487:         PetscCall(VecSetType(Z, ((PetscObject)X)->type_name));
1488:         PetscCall(VecSetSizes(Z, n, N));
1489:         PetscCall(VecSetBlockSize(Z, bs));
1490:         PetscCall(VecPlaceArray(Z, x ? x + start : NULL));
1491:         PetscCall(VecRestoreArrayRead(X, &x));
1492:       }

1494:       /* this is relevant only in debug mode */
1495:       PetscCall(VecLockGet(X, &state));
1496:       if (state) PetscCall(VecLockReadPush(Z));
1497:       Z->ops->placearray   = NULL;
1498:       Z->ops->replacearray = NULL;
1499:     } else { /* Have to create a scatter and do a copy */
1500:       PetscCall(VecGetSubVectorThroughVecScatter_Private(X, is, bs, &Z));
1501:     }
1502:   }
1503:   /* Record the state when the subvector was gotten so we know whether its values need to be put back */
1504:   if (VecGetSubVectorSavedStateId < 0) PetscCall(PetscObjectComposedDataRegister(&VecGetSubVectorSavedStateId));
1505:   PetscCall(PetscObjectComposedDataSetInt((PetscObject)Z, VecGetSubVectorSavedStateId, 1));
1506:   *Y = Z;
1507:   PetscFunctionReturn(PETSC_SUCCESS);
1508: }

1510: /*@
1511:    VecRestoreSubVector - Restores a subvector extracted using `VecGetSubVector()`

1513:    Collective

1515:    Input Parameters:
1516: + X - vector from which subvector was obtained
1517: . is - index set representing the subset of `X`
1518: - Y - subvector being restored

1520:    Level: advanced

1522: .seealso: [](chapter_vectors), `Vec`, `IS`, `VecGetSubVector()`
1523: @*/
1524: PetscErrorCode VecRestoreSubVector(Vec X, IS is, Vec *Y)
1525: {
1526:   PETSC_UNUSED PetscObjectState dummystate = 0;
1527:   PetscBool                     unchanged;

1529:   PetscFunctionBegin;
1532:   PetscCheckSameComm(X, 1, is, 2);

1536:   if (X->ops->restoresubvector) PetscUseTypeMethod(X, restoresubvector, is, Y);
1537:   else {
1538:     PetscCall(PetscObjectComposedDataGetInt((PetscObject)*Y, VecGetSubVectorSavedStateId, dummystate, unchanged));
1539:     if (!unchanged) { /* If Y's state has not changed since VecGetSubVector(), we only need to destroy Y */
1540:       VecScatter scatter;
1541:       PetscInt   state;

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

1546:       PetscCall(PetscObjectQuery((PetscObject)*Y, "VecGetSubVector_Scatter", (PetscObject *)&scatter));
1547:       if (scatter) {
1548:         PetscCall(VecScatterBegin(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1549:         PetscCall(VecScatterEnd(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1550:       } else {
1551:         PetscBool iscuda, iship;
1552:         PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1553:         PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));

1555:         if (iscuda) {
1556: #if defined(PETSC_HAVE_CUDA)
1557:           PetscOffloadMask ymask = (*Y)->offloadmask;

1559:           /* The offloadmask of X dictates where to move memory
1560:               If X GPU data is valid, then move Y data on GPU if needed
1561:               Otherwise, move back to the CPU */
1562:           switch (X->offloadmask) {
1563:           case PETSC_OFFLOAD_BOTH:
1564:             if (ymask == PETSC_OFFLOAD_CPU) {
1565:               PetscCall(VecCUDAResetArray(*Y));
1566:             } else if (ymask == PETSC_OFFLOAD_GPU) {
1567:               X->offloadmask = PETSC_OFFLOAD_GPU;
1568:             }
1569:             break;
1570:           case PETSC_OFFLOAD_GPU:
1571:             if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecCUDAResetArray(*Y));
1572:             break;
1573:           case PETSC_OFFLOAD_CPU:
1574:             if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1575:             break;
1576:           case PETSC_OFFLOAD_UNALLOCATED:
1577:           case PETSC_OFFLOAD_KOKKOS:
1578:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1579:           }
1580: #endif
1581:         } else if (iship) {
1582: #if defined(PETSC_HAVE_HIP)
1583:           PetscOffloadMask ymask = (*Y)->offloadmask;

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

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

1623:    Not collective.

1625:    Input parameter:
1626: .  v - The vector for which the local vector is desired.

1628:    Output parameter:
1629: .  w - Upon exit this contains the local vector.

1631:    Level: beginner

1633: .seealso: [](chapter_vectors), `Vec`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecRestoreLocalVector()`
1634: @*/
1635: PetscErrorCode VecCreateLocalVector(Vec v, Vec *w)
1636: {
1637:   PetscMPIInt size;

1639:   PetscFunctionBegin;
1642:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
1643:   if (size == 1) PetscCall(VecDuplicate(v, w));
1644:   else if (v->ops->createlocalvector) PetscUseTypeMethod(v, createlocalvector, w);
1645:   else {
1646:     VecType  type;
1647:     PetscInt n;

1649:     PetscCall(VecCreate(PETSC_COMM_SELF, w));
1650:     PetscCall(VecGetLocalSize(v, &n));
1651:     PetscCall(VecSetSizes(*w, n, n));
1652:     PetscCall(VecGetBlockSize(v, &n));
1653:     PetscCall(VecSetBlockSize(*w, n));
1654:     PetscCall(VecGetType(v, &type));
1655:     PetscCall(VecSetType(*w, type));
1656:   }
1657:   PetscFunctionReturn(PETSC_SUCCESS);
1658: }

1660: /*@
1661:    VecGetLocalVectorRead - Maps the local portion of a vector into a
1662:    vector.

1664:    Not collective.

1666:    Input parameter:
1667: .  v - The vector for which the local vector is desired.

1669:    Output parameter:
1670: .  w - Upon exit this contains the local vector.

1672:    Level: beginner

1674:    Notes:
1675:    You must call `VecRestoreLocalVectorRead()` when the local
1676:    vector is no longer needed.

1678:    This function is similar to `VecGetArrayRead()` which maps the local
1679:    portion into a raw pointer.  `VecGetLocalVectorRead()` is usually
1680:    almost as efficient as `VecGetArrayRead()` but in certain circumstances
1681:    `VecGetLocalVectorRead()` can be much more efficient than
1682:    `VecGetArrayRead()`.  This is because the construction of a contiguous
1683:    array representing the vector data required by `VecGetArrayRead()` can
1684:    be an expensive operation for certain vector types.  For example, for
1685:    GPU vectors `VecGetArrayRead()` requires that the data between device
1686:    and host is synchronized.

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

1691: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1692: @*/
1693: PetscErrorCode VecGetLocalVectorRead(Vec v, Vec w)
1694: {
1695:   PetscFunctionBegin;
1698:   VecCheckSameLocalSize(v, 1, w, 2);
1699:   if (v->ops->getlocalvectorread) {
1700:     PetscUseTypeMethod(v, getlocalvectorread, w);
1701:   } else {
1702:     PetscScalar *a;

1704:     PetscCall(VecGetArrayRead(v, (const PetscScalar **)&a));
1705:     PetscCall(VecPlaceArray(w, a));
1706:   }
1707:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1708:   PetscCall(VecLockReadPush(v));
1709:   PetscCall(VecLockReadPush(w));
1710:   PetscFunctionReturn(PETSC_SUCCESS);
1711: }

1713: /*@
1714:    VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1715:    previously mapped into a vector using `VecGetLocalVectorRead()`.

1717:    Not collective.

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

1723:    Level: beginner

1725: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1726: @*/
1727: PetscErrorCode VecRestoreLocalVectorRead(Vec v, Vec w)
1728: {
1729:   PetscFunctionBegin;
1732:   if (v->ops->restorelocalvectorread) {
1733:     PetscUseTypeMethod(v, restorelocalvectorread, w);
1734:   } else {
1735:     const PetscScalar *a;

1737:     PetscCall(VecGetArrayRead(w, &a));
1738:     PetscCall(VecRestoreArrayRead(v, &a));
1739:     PetscCall(VecResetArray(w));
1740:   }
1741:   PetscCall(VecLockReadPop(v));
1742:   PetscCall(VecLockReadPop(w));
1743:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1744:   PetscFunctionReturn(PETSC_SUCCESS);
1745: }

1747: /*@
1748:    VecGetLocalVector - Maps the local portion of a vector into a
1749:    vector.

1751:    Collective

1753:    Input parameter:
1754: .  v - The vector for which the local vector is desired.

1756:    Output parameter:
1757: .  w - Upon exit this contains the local vector.

1759:    Level: beginner

1761:    Notes:
1762:    You must call `VecRestoreLocalVector()` when the local
1763:    vector is no longer needed.

1765:    This function is similar to `VecGetArray()` which maps the local
1766:    portion into a raw pointer.  `VecGetLocalVector()` is usually about as
1767:    efficient as `VecGetArray()` but in certain circumstances
1768:    `VecGetLocalVector()` can be much more efficient than `VecGetArray()`.
1769:    This is because the construction of a contiguous array representing
1770:    the vector data required by `VecGetArray()` can be an expensive
1771:    operation for certain vector types.  For example, for GPU vectors
1772:    `VecGetArray()` requires that the data between device and host is
1773:    synchronized.

1775: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVector()`, `VecGetLocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1776: @*/
1777: PetscErrorCode VecGetLocalVector(Vec v, Vec w)
1778: {
1779:   PetscFunctionBegin;
1782:   VecCheckSameLocalSize(v, 1, w, 2);
1783:   if (v->ops->getlocalvector) {
1784:     PetscUseTypeMethod(v, getlocalvector, w);
1785:   } else {
1786:     PetscScalar *a;

1788:     PetscCall(VecGetArray(v, &a));
1789:     PetscCall(VecPlaceArray(w, a));
1790:   }
1791:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1792:   PetscFunctionReturn(PETSC_SUCCESS);
1793: }

1795: /*@
1796:    VecRestoreLocalVector - Unmaps the local portion of a vector
1797:    previously mapped into a vector using `VecGetLocalVector()`.

1799:    Logically collective.

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

1805:    Level: beginner

1807: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVector()`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `LocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1808: @*/
1809: PetscErrorCode VecRestoreLocalVector(Vec v, Vec w)
1810: {
1811:   PetscFunctionBegin;
1814:   if (v->ops->restorelocalvector) {
1815:     PetscUseTypeMethod(v, restorelocalvector, w);
1816:   } else {
1817:     PetscScalar *a;
1818:     PetscCall(VecGetArray(w, &a));
1819:     PetscCall(VecRestoreArray(v, &a));
1820:     PetscCall(VecResetArray(w));
1821:   }
1822:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1823:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
1824:   PetscFunctionReturn(PETSC_SUCCESS);
1825: }

1827: /*@C
1828:    VecGetArray - Returns a pointer to a contiguous array that contains this
1829:    processor's portion of the vector data. For the standard PETSc
1830:    vectors, `VecGetArray()` returns a pointer to the local data array and
1831:    does not use any copies. If the underlying vector data is not stored
1832:    in a contiguous array this routine will copy the data to a contiguous
1833:    array and return a pointer to that. You MUST call `VecRestoreArray()`
1834:    when you no longer need access to the array.

1836:    Logically Collective

1838:    Input Parameter:
1839: .  x - the vector

1841:    Output Parameter:
1842: .  a - location to put pointer to the array

1844:    Level: beginner

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

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

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

1868:    Logically Collective

1870:    Input Parameters:
1871: +  x - the vector
1872: -  a - location of pointer to array obtained from `VecGetArray()`

1874:    Level: beginner

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

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

1897:    Not Collective

1899:    Input Parameter:
1900: .  x - the vector

1902:    Output Parameter:
1903: .  a - the array

1905:    Level: beginner

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

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

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

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

1919: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
1920: @*/
1921: PetscErrorCode VecGetArrayRead(Vec x, const PetscScalar **a)
1922: {
1923:   PetscFunctionBegin;
1926:   if (x->ops->getarrayread) {
1927:     PetscUseTypeMethod(x, getarrayread, a);
1928:   } else if (x->ops->getarray) {
1929:     PetscObjectState state;

1931:     /* VECNEST, VECCUDA, VECKOKKOS etc */
1932:     // x->ops->getarray may bump the object state, but since we know this is a read-only get
1933:     // we can just undo that
1934:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
1935:     PetscUseTypeMethod(x, getarray, (PetscScalar **)a);
1936:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
1937:   } else if (x->petscnative) {
1938:     /* VECSTANDARD */
1939:     *a = *((PetscScalar **)x->data);
1940:   } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array read for vector type \"%s\"", ((PetscObject)x)->type_name);
1941:   PetscFunctionReturn(PETSC_SUCCESS);
1942: }

1944: /*@C
1945:    VecRestoreArrayRead - Restore array obtained with `VecGetArrayRead()`

1947:    Not Collective

1949:    Input Parameters:
1950: +  vec - the vector
1951: -  array - the array

1953:    Level: beginner

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

1958: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
1959: @*/
1960: PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar **a)
1961: {
1962:   PetscFunctionBegin;
1965:   if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
1966:     /* nothing */
1967:   } else if (x->ops->restorearrayread) { /* VECNEST */
1968:     PetscUseTypeMethod(x, restorearrayread, a);
1969:   } else { /* No one? */
1970:     PetscObjectState state;

1972:     // x->ops->restorearray may bump the object state, but since we know this is a read-restore
1973:     // we can just undo that
1974:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
1975:     PetscUseTypeMethod(x, restorearray, (PetscScalar **)a);
1976:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
1977:   }
1978:   if (a) *a = NULL;
1979:   PetscFunctionReturn(PETSC_SUCCESS);
1980: }

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

1987:    Logically Collective

1989:    Input Parameter:
1990: .  x - the vector

1992:    Output Parameter:
1993: .  a - location to put pointer to the array

1995:    Level: intermediate

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

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

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

2006: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayWriteF90()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`, `VecPlaceArray()`, `VecGetArray2d()`,
2007:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArray()`, `VecRestoreArrayWrite()`
2008: @*/
2009: PetscErrorCode VecGetArrayWrite(Vec x, PetscScalar **a)
2010: {
2011:   PetscFunctionBegin;
2014:   PetscCall(VecSetErrorIfLocked(x, 1));
2015:   if (x->ops->getarraywrite) {
2016:     PetscUseTypeMethod(x, getarraywrite, a);
2017:   } else {
2018:     PetscCall(VecGetArray(x, a));
2019:   }
2020:   PetscFunctionReturn(PETSC_SUCCESS);
2021: }

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

2026:    Logically Collective

2028:    Input Parameters:
2029: +  x - the vector
2030: -  a - location of pointer to array obtained from `VecGetArray()`

2032:    Level: beginner

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

2037:  .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayWriteF90()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2038:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`
2039: @*/
2040: PetscErrorCode VecRestoreArrayWrite(Vec x, PetscScalar **a)
2041: {
2042:   PetscFunctionBegin;
2045:   if (x->ops->restorearraywrite) {
2046:     PetscUseTypeMethod(x, restorearraywrite, a);
2047:   } else if (x->ops->restorearray) {
2048:     PetscUseTypeMethod(x, restorearray, a);
2049:   }
2050:   if (a) *a = NULL;
2051:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2052:   PetscFunctionReturn(PETSC_SUCCESS);
2053: }

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

2059:    Logically Collective; No Fortran Support

2061:    Input Parameters:
2062: +  x - the vectors
2063: -  n - the number of vectors

2065:    Output Parameter:
2066: .  a - location to put pointer to the array

2068:    Level: intermediate

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

2073: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrays()`
2074: @*/
2075: PetscErrorCode VecGetArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2076: {
2077:   PetscInt      i;
2078:   PetscScalar **q;

2080:   PetscFunctionBegin;
2084:   PetscCheck(n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must get at least one array n = %" PetscInt_FMT, n);
2085:   PetscCall(PetscMalloc1(n, &q));
2086:   for (i = 0; i < n; ++i) PetscCall(VecGetArray(x[i], &q[i]));
2087:   *a = q;
2088:   PetscFunctionReturn(PETSC_SUCCESS);
2089: }

2091: /*@C
2092:    VecRestoreArrays - Restores a group of vectors after `VecGetArrays()`
2093:    has been called.

2095:    Logically Collective; No Fortran Support

2097:    Input Parameters:
2098: +  x - the vector
2099: .  n - the number of vectors
2100: -  a - location of pointer to arrays obtained from `VecGetArrays()`

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

2108:    Level: intermediate

2110: .seealso: [](chapter_vectors), `Vec`, `VecGetArrays()`, `VecRestoreArray()`
2111: @*/
2112: PetscErrorCode VecRestoreArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2113: {
2114:   PetscInt      i;
2115:   PetscScalar **q = *a;

2117:   PetscFunctionBegin;

2122:   for (i = 0; i < n; ++i) PetscCall(VecRestoreArray(x[i], &q[i]));
2123:   PetscCall(PetscFree(q));
2124:   PetscFunctionReturn(PETSC_SUCCESS);
2125: }

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

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

2135:    Logically Collective; No Fortran Support

2137:    Input Parameter:
2138: .  x - the vector

2140:    Output Parameters:
2141: +  a - location to put pointer to the array
2142: -  mtype - memory type of the array

2144:    Level: beginner

2146:    Note:
2147:    Use `VecRestoreArrayAndMemType()` when the array access is no longer needed

2149: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`,
2150:           `VecPlaceArray()`, `VecGetArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2151: @*/
2152: PetscErrorCode VecGetArrayAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2153: {
2154:   PetscFunctionBegin;
2159:   PetscCall(VecSetErrorIfLocked(x, 1));
2160:   if (x->ops->getarrayandmemtype) {
2161:     /* VECCUDA, VECKOKKOS etc */
2162:     PetscUseTypeMethod(x, getarrayandmemtype, a, mtype);
2163:   } else {
2164:     /* VECSTANDARD, VECNEST, VECVIENNACL */
2165:     PetscCall(VecGetArray(x, a));
2166:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2167:   }
2168:   PetscFunctionReturn(PETSC_SUCCESS);
2169: }

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

2174:    Logically Collective; No Fortran Support

2176:    Input Parameters:
2177: +  x - the vector
2178: -  a - location of pointer to array obtained from `VecGetArrayAndMemType()`

2180:    Level: beginner

2182: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`,
2183:           `VecPlaceArray()`, `VecRestoreArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2184: @*/
2185: PetscErrorCode VecRestoreArrayAndMemType(Vec x, PetscScalar **a)
2186: {
2187:   PetscFunctionBegin;
2191:   if (x->ops->restorearrayandmemtype) {
2192:     /* VECCUDA, VECKOKKOS etc */
2193:     PetscUseTypeMethod(x, restorearrayandmemtype, a);
2194:   } else {
2195:     /* VECNEST, VECVIENNACL */
2196:     PetscCall(VecRestoreArray(x, a));
2197:   } /* VECSTANDARD does nothing */
2198:   if (a) *a = NULL;
2199:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2200:   PetscFunctionReturn(PETSC_SUCCESS);
2201: }

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

2207:    Not Collective; No Fortran Support

2209:    Input Parameter:
2210: .  x - the vector

2212:    Output Parameters:
2213: +  a - the array
2214: -  mtype - memory type of the array

2216:    Level: beginner

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

2221: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayAndMemType()`
2222: @*/
2223: PetscErrorCode VecGetArrayReadAndMemType(Vec x, const PetscScalar **a, PetscMemType *mtype)
2224: {
2225:   PetscFunctionBegin;
2230:   if (x->ops->getarrayreadandmemtype) {
2231:     /* VECCUDA/VECHIP though they are also petscnative */
2232:     PetscUseTypeMethod(x, getarrayreadandmemtype, a, mtype);
2233:   } else if (x->ops->getarrayandmemtype) {
2234:     /* VECKOKKOS */
2235:     PetscObjectState state;

2237:     // see VecGetArrayRead() for why
2238:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2239:     PetscUseTypeMethod(x, getarrayandmemtype, (PetscScalar **)a, mtype);
2240:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
2241:   } else {
2242:     PetscCall(VecGetArrayRead(x, a));
2243:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2244:   }
2245:   PetscFunctionReturn(PETSC_SUCCESS);
2246: }

2248: /*@C
2249:    VecRestoreArrayReadAndMemType - Restore array obtained with `VecGetArrayReadAndMemType()`

2251:    Not Collective; No Fortran Support

2253:    Input Parameters:
2254: +  vec - the vector
2255: -  array - the array

2257:    Level: beginner

2259: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayReadAndMemType()`, `VecRestoreArrayAndMemType()`, `VecRestoreArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2260: @*/
2261: PetscErrorCode VecRestoreArrayReadAndMemType(Vec x, const PetscScalar **a)
2262: {
2263:   PetscFunctionBegin;
2267:   if (x->ops->restorearrayreadandmemtype) {
2268:     /* VECCUDA/VECHIP */
2269:     PetscUseTypeMethod(x, restorearrayreadandmemtype, a);
2270:   } else if (!x->petscnative) {
2271:     /* VECNEST */
2272:     PetscCall(VecRestoreArrayRead(x, a));
2273:   }
2274:   if (a) *a = NULL;
2275:   PetscFunctionReturn(PETSC_SUCCESS);
2276: }

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

2282:    Not Collective; No Fortran Support

2284:    Input Parameter:
2285: .  x - the vector

2287:    Output Parameters:
2288: +  a - the array
2289: -  mtype - memory type of the array

2291:    Level: beginner

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

2296: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayWriteAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2297: @*/
2298: PetscErrorCode VecGetArrayWriteAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2299: {
2300:   PetscFunctionBegin;
2303:   PetscCall(VecSetErrorIfLocked(x, 1));
2306:   if (x->ops->getarraywriteandmemtype) {
2307:     /* VECCUDA, VECHIP, VECKOKKOS etc, though they are also petscnative */
2308:     PetscUseTypeMethod(x, getarraywriteandmemtype, a, mtype);
2309:   } else if (x->ops->getarrayandmemtype) {
2310:     PetscCall(VecGetArrayAndMemType(x, a, mtype));
2311:   } else {
2312:     /* VECNEST, VECVIENNACL */
2313:     PetscCall(VecGetArrayWrite(x, a));
2314:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2315:   }
2316:   PetscFunctionReturn(PETSC_SUCCESS);
2317: }

2319: /*@C
2320:    VecRestoreArrayWriteAndMemType - Restore array obtained with `VecGetArrayWriteAndMemType()`

2322:    Not Collective; No Fortran Support

2324:    Input Parameters:
2325: +  vec - the vector
2326: -  array - the array

2328:    Level: beginner

2330: .seealso: [](chapter_vectors), `Vec`, `VecGetArrayWriteAndMemType()`, `VecRestoreArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2331: @*/
2332: PetscErrorCode VecRestoreArrayWriteAndMemType(Vec x, PetscScalar **a)
2333: {
2334:   PetscFunctionBegin;
2337:   PetscCall(VecSetErrorIfLocked(x, 1));
2339:   if (x->ops->restorearraywriteandmemtype) {
2340:     /* VECCUDA/VECHIP */
2341:     PetscMemType PETSC_UNUSED mtype; // since this function doesn't accept a memtype?
2342:     PetscUseTypeMethod(x, restorearraywriteandmemtype, a, &mtype);
2343:   } else if (x->ops->restorearrayandmemtype) {
2344:     PetscCall(VecRestoreArrayAndMemType(x, a));
2345:   } else {
2346:     PetscCall(VecRestoreArray(x, a));
2347:   }
2348:   if (a) *a = NULL;
2349:   PetscFunctionReturn(PETSC_SUCCESS);
2350: }

2352: /*@
2353:    VecPlaceArray - Allows one to replace the array in a vector with an
2354:    array provided by the user. This is useful to avoid copying an array
2355:    into a vector.

2357:    Not Collective; No Fortran Support

2359:    Input Parameters:
2360: +  vec - the vector
2361: -  array - the array

2363:    Level: developer

2365:    Notes:
2366:    Use `VecReplaceArray()` instead to permanently replace the array

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

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

2375: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`
2376: @*/
2377: PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2378: {
2379:   PetscFunctionBegin;
2383:   PetscUseTypeMethod(vec, placearray, array);
2384:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2385:   PetscFunctionReturn(PETSC_SUCCESS);
2386: }

2388: /*@C
2389:    VecReplaceArray - Allows one to replace the array in a vector with an
2390:    array provided by the user. This is useful to avoid copying an array
2391:    into a vector.

2393:    Not Collective; No Fortran Support

2395:    Input Parameters:
2396: +  vec - the vector
2397: -  array - the array

2399:    Level: developer

2401:    Notes:
2402:    This permanently replaces the array and frees the memory associated
2403:    with the old array. Use `VecPlaceArray()` to temporarily replace the array.

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

2408: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`
2409: @*/
2410: PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2411: {
2412:   PetscFunctionBegin;
2415:   PetscUseTypeMethod(vec, replacearray, array);
2416:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2417:   PetscFunctionReturn(PETSC_SUCCESS);
2418: }

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

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

2427:     Collective

2429:     Input Parameters:
2430: +   x - a vector to mimic
2431: -   n - the number of vectors to obtain

2433:     Output Parameters:
2434: +   y - Fortran pointer to the array of vectors
2435: -   ierr - error code

2437:     Example of Usage:
2438: .vb
2439: #include <petsc/finclude/petscvec.h>
2440:     use petscvec

2442:     Vec x
2443:     Vec, pointer :: y(:)
2444:     ....
2445:     call VecDuplicateVecsF90(x,2,y,ierr)
2446:     call VecSet(y(2),alpha,ierr)
2447:     call VecSet(y(2),alpha,ierr)
2448:     ....
2449:     call VecDestroyVecsF90(2,y,ierr)
2450: .ve

2452:     Level: beginner

2454:     Note:
2455:     Use `VecDestroyVecsF90()` to free the space.

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

2460: /*MC
2461:     VecRestoreArrayF90 - Restores a vector to a usable state after a call to
2462:     `VecGetArrayF90()`.

2464:     Synopsis:
2465:     VecRestoreArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2467:     Logically Collective

2469:     Input Parameters:
2470: +   x - vector
2471: -   xx_v - the Fortran pointer to the array

2473:     Output Parameter:
2474: .   ierr - error code

2476:     Example of Usage:
2477: .vb
2478: #include <petsc/finclude/petscvec.h>
2479:     use petscvec

2481:     PetscScalar, pointer :: xx_v(:)
2482:     ....
2483:     call VecGetArrayF90(x,xx_v,ierr)
2484:     xx_v(3) = a
2485:     call VecRestoreArrayF90(x,xx_v,ierr)
2486: .ve

2488:     Level: beginner

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

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

2496:     Synopsis:
2497:     VecDestroyVecsF90(PetscInt n,{Vec, pointer :: x(:)},PetscErrorCode ierr)

2499:     Collective

2501:     Input Parameters:
2502: +   n - the number of vectors previously obtained
2503: -   x - pointer to array of vector pointers

2505:     Output Parameter:
2506: .   ierr - error code

2508:     Level: beginner

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

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

2519:     Synopsis:
2520:     VecGetArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2522:     Logically Collective

2524:     Input Parameter:
2525: .   x - vector

2527:     Output Parameters:
2528: +   xx_v - the Fortran pointer to the array
2529: -   ierr - error code

2531:     Example of Usage:
2532: .vb
2533: #include <petsc/finclude/petscvec.h>
2534:     use petscvec

2536:     PetscScalar, pointer :: xx_v(:)
2537:     ....
2538:     call VecGetArrayF90(x,xx_v,ierr)
2539:     xx_v(3) = a
2540:     call VecRestoreArrayF90(x,xx_v,ierr)
2541: .ve

2543:      Level: beginner

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

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

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

2557:     Synopsis:
2558:     VecGetArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2560:     Logically Collective

2562:     Input Parameter:
2563: .   x - vector

2565:     Output Parameters:
2566: +   xx_v - the Fortran pointer to the array
2567: -   ierr - error code

2569:     Example of Usage:
2570: .vb
2571: #include <petsc/finclude/petscvec.h>
2572:     use petscvec

2574:     PetscScalar, pointer :: xx_v(:)
2575:     ....
2576:     call VecGetArrayReadF90(x,xx_v,ierr)
2577:     a = xx_v(3)
2578:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2579: .ve

2581:     Level: beginner

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

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

2589: /*MC
2590:     VecRestoreArrayReadF90 - Restores a readonly vector to a usable state after a call to
2591:     `VecGetArrayReadF90()`.

2593:     Synopsis:
2594:     VecRestoreArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2596:     Logically Collective

2598:     Input Parameters:
2599: +   x - vector
2600: -   xx_v - the Fortran pointer to the array

2602:     Output Parameter:
2603: .   ierr - error code

2605:     Example of Usage:
2606: .vb
2607: #include <petsc/finclude/petscvec.h>
2608:     use petscvec

2610:     PetscScalar, pointer :: xx_v(:)
2611:     ....
2612:     call VecGetArrayReadF90(x,xx_v,ierr)
2613:     a = xx_v(3)
2614:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2615: .ve

2617:     Level: beginner

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

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

2627:    Logically Collective

2629:    Input Parameters:
2630: +  x - the vector
2631: .  m - first dimension of two dimensional array
2632: .  n - second dimension of two dimensional array
2633: .  mstart - first index you will use in first coordinate direction (often 0)
2634: -  nstart - first index in the second coordinate direction (often 0)

2636:    Output Parameter:
2637: .  a - location to put pointer to the array

2639:    Level: developer

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

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

2649: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2650:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2651:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2652: @*/
2653: PetscErrorCode VecGetArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2654: {
2655:   PetscInt     i, N;
2656:   PetscScalar *aa;

2658:   PetscFunctionBegin;
2662:   PetscCall(VecGetLocalSize(x, &N));
2663:   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);
2664:   PetscCall(VecGetArray(x, &aa));

2666:   PetscCall(PetscMalloc1(m, a));
2667:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2668:   *a -= mstart;
2669:   PetscFunctionReturn(PETSC_SUCCESS);
2670: }

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

2677:    Logically Collective

2679:    Input Parameters:
2680: +  x - the vector
2681: .  m - first dimension of two dimensional array
2682: .  n - second dimension of two dimensional array
2683: .  mstart - first index you will use in first coordinate direction (often 0)
2684: -  nstart - first index in the second coordinate direction (often 0)

2686:    Output Parameter:
2687: .  a - location to put pointer to the array

2689:    Level: developer

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

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

2699: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2700:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2701:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2702: @*/
2703: PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2704: {
2705:   PetscInt     i, N;
2706:   PetscScalar *aa;

2708:   PetscFunctionBegin;
2712:   PetscCall(VecGetLocalSize(x, &N));
2713:   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);
2714:   PetscCall(VecGetArrayWrite(x, &aa));

2716:   PetscCall(PetscMalloc1(m, a));
2717:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2718:   *a -= mstart;
2719:   PetscFunctionReturn(PETSC_SUCCESS);
2720: }

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

2725:    Logically Collective

2727:    Input Parameters:
2728: +  x - the vector
2729: .  m - first dimension of two dimensional array
2730: .  n - second dimension of the two dimensional array
2731: .  mstart - first index you will use in first coordinate direction (often 0)
2732: .  nstart - first index in the second coordinate direction (often 0)
2733: -  a - location of pointer to array obtained from `VecGetArray2d()`

2735:    Level: developer

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

2743:    This routine actually zeros out the a pointer.

2745: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2746:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2747:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2748: @*/
2749: PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2750: {
2751:   void *dummy;

2753:   PetscFunctionBegin;
2757:   dummy = (void *)(*a + mstart);
2758:   PetscCall(PetscFree(dummy));
2759:   PetscCall(VecRestoreArray(x, NULL));
2760:   PetscFunctionReturn(PETSC_SUCCESS);
2761: }

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

2766:    Logically Collective

2768:    Input Parameters:
2769: +  x - the vector
2770: .  m - first dimension of two dimensional array
2771: .  n - second dimension of the two dimensional array
2772: .  mstart - first index you will use in first coordinate direction (often 0)
2773: .  nstart - first index in the second coordinate direction (often 0)
2774: -  a - location of pointer to array obtained from `VecGetArray2d()`

2776:    Level: developer

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

2784:    This routine actually zeros out the a pointer.

2786: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2787:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2788:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2789: @*/
2790: PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2791: {
2792:   void *dummy;

2794:   PetscFunctionBegin;
2798:   dummy = (void *)(*a + mstart);
2799:   PetscCall(PetscFree(dummy));
2800:   PetscCall(VecRestoreArrayWrite(x, NULL));
2801:   PetscFunctionReturn(PETSC_SUCCESS);
2802: }

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

2809:    Logically Collective

2811:    Input Parameters:
2812: +  x - the vector
2813: .  m - first dimension of two dimensional array
2814: -  mstart - first index you will use in first coordinate direction (often 0)

2816:    Output Parameter:
2817: .  a - location to put pointer to the array

2819:    Level: developer

2821:   Notes:
2822:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
2823:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2824:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

2828: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2829:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2830:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2831: @*/
2832: PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2833: {
2834:   PetscInt N;

2836:   PetscFunctionBegin;
2840:   PetscCall(VecGetLocalSize(x, &N));
2841:   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);
2842:   PetscCall(VecGetArray(x, a));
2843:   *a -= mstart;
2844:   PetscFunctionReturn(PETSC_SUCCESS);
2845: }

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

2852:    Logically Collective

2854:    Input Parameters:
2855: +  x - the vector
2856: .  m - first dimension of two dimensional array
2857: -  mstart - first index you will use in first coordinate direction (often 0)

2859:    Output Parameter:
2860: .  a - location to put pointer to the array

2862:    Level: developer

2864:   Notes:
2865:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
2866:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2867:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

2871: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2872:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2873:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2874: @*/
2875: PetscErrorCode VecGetArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2876: {
2877:   PetscInt N;

2879:   PetscFunctionBegin;
2883:   PetscCall(VecGetLocalSize(x, &N));
2884:   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);
2885:   PetscCall(VecGetArrayWrite(x, a));
2886:   *a -= mstart;
2887:   PetscFunctionReturn(PETSC_SUCCESS);
2888: }

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

2893:    Logically Collective

2895:    Input Parameters:
2896: +  x - the vector
2897: .  m - first dimension of two dimensional array
2898: .  mstart - first index you will use in first coordinate direction (often 0)
2899: -  a - location of pointer to array obtained from `VecGetArray1d()`

2901:    Level: developer

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

2909:    This routine actually zeros out the a pointer.

2911: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2912:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2913:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2914: @*/
2915: PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2916: {
2917:   PetscFunctionBegin;
2920:   PetscCall(VecRestoreArray(x, NULL));
2921:   PetscFunctionReturn(PETSC_SUCCESS);
2922: }

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

2927:    Logically Collective

2929:    Input Parameters:
2930: +  x - the vector
2931: .  m - first dimension of two dimensional array
2932: .  mstart - first index you will use in first coordinate direction (often 0)
2933: -  a - location of pointer to array obtained from `VecGetArray1d()`

2935:    Level: developer

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

2943:    This routine actually zeros out the a pointer.

2945: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2946:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2947:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2948: @*/
2949: PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2950: {
2951:   PetscFunctionBegin;
2954:   PetscCall(VecRestoreArrayWrite(x, NULL));
2955:   PetscFunctionReturn(PETSC_SUCCESS);
2956: }

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

2963:    Logically Collective

2965:    Input Parameters:
2966: +  x - the vector
2967: .  m - first dimension of three dimensional array
2968: .  n - second dimension of three dimensional array
2969: .  p - third dimension of three dimensional array
2970: .  mstart - first index you will use in first coordinate direction (often 0)
2971: .  nstart - first index in the second coordinate direction (often 0)
2972: -  pstart - first index in the third coordinate direction (often 0)

2974:    Output Parameter:
2975: .  a - location to put pointer to the array

2977:    Level: developer

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

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

2987: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2988:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2989:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2990: @*/
2991: PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
2992: {
2993:   PetscInt     i, N, j;
2994:   PetscScalar *aa, **b;

2996:   PetscFunctionBegin;
3000:   PetscCall(VecGetLocalSize(x, &N));
3001:   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);
3002:   PetscCall(VecGetArray(x, &aa));

3004:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3005:   b = (PetscScalar **)((*a) + m);
3006:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3007:   for (i = 0; i < m; i++)
3008:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;
3009:   *a -= mstart;
3010:   PetscFunctionReturn(PETSC_SUCCESS);
3011: }

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

3018:    Logically Collective

3020:    Input Parameters:
3021: +  x - the vector
3022: .  m - first dimension of three dimensional array
3023: .  n - second dimension of three dimensional array
3024: .  p - third dimension of three dimensional array
3025: .  mstart - first index you will use in first coordinate direction (often 0)
3026: .  nstart - first index in the second coordinate direction (often 0)
3027: -  pstart - first index in the third coordinate direction (often 0)

3029:    Output Parameter:
3030: .  a - location to put pointer to the array

3032:    Level: developer

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

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

3042: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3043:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3044:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3045: @*/
3046: PetscErrorCode VecGetArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3047: {
3048:   PetscInt     i, N, j;
3049:   PetscScalar *aa, **b;

3051:   PetscFunctionBegin;
3055:   PetscCall(VecGetLocalSize(x, &N));
3056:   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);
3057:   PetscCall(VecGetArrayWrite(x, &aa));

3059:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3060:   b = (PetscScalar **)((*a) + m);
3061:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3062:   for (i = 0; i < m; i++)
3063:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;

3065:   *a -= mstart;
3066:   PetscFunctionReturn(PETSC_SUCCESS);
3067: }

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

3072:    Logically Collective

3074:    Input Parameters:
3075: +  x - the vector
3076: .  m - first dimension of three dimensional array
3077: .  n - second dimension of the three dimensional array
3078: .  p - third dimension of the three dimensional array
3079: .  mstart - first index you will use in first coordinate direction (often 0)
3080: .  nstart - first index in the second coordinate direction (often 0)
3081: .  pstart - first index in the third coordinate direction (often 0)
3082: -  a - location of pointer to array obtained from VecGetArray3d()

3084:    Level: developer

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

3092:    This routine actually zeros out the a pointer.

3094: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3095:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3096:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3097: @*/
3098: PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3099: {
3100:   void *dummy;

3102:   PetscFunctionBegin;
3106:   dummy = (void *)(*a + mstart);
3107:   PetscCall(PetscFree(dummy));
3108:   PetscCall(VecRestoreArray(x, NULL));
3109:   PetscFunctionReturn(PETSC_SUCCESS);
3110: }

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

3115:    Logically Collective

3117:    Input Parameters:
3118: +  x - the vector
3119: .  m - first dimension of three dimensional array
3120: .  n - second dimension of the three dimensional array
3121: .  p - third dimension of the three dimensional array
3122: .  mstart - first index you will use in first coordinate direction (often 0)
3123: .  nstart - first index in the second coordinate direction (often 0)
3124: .  pstart - first index in the third coordinate direction (often 0)
3125: -  a - location of pointer to array obtained from VecGetArray3d()

3127:    Level: developer

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

3135:    This routine actually zeros out the a pointer.

3137: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3138:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3139:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3140: @*/
3141: PetscErrorCode VecRestoreArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3142: {
3143:   void *dummy;

3145:   PetscFunctionBegin;
3149:   dummy = (void *)(*a + mstart);
3150:   PetscCall(PetscFree(dummy));
3151:   PetscCall(VecRestoreArrayWrite(x, NULL));
3152:   PetscFunctionReturn(PETSC_SUCCESS);
3153: }

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

3160:    Logically Collective

3162:    Input Parameters:
3163: +  x - the vector
3164: .  m - first dimension of four dimensional array
3165: .  n - second dimension of four dimensional array
3166: .  p - third dimension of four dimensional array
3167: .  q - fourth dimension of four dimensional array
3168: .  mstart - first index you will use in first coordinate direction (often 0)
3169: .  nstart - first index in the second coordinate direction (often 0)
3170: .  pstart - first index in the third coordinate direction (often 0)
3171: -  qstart - first index in the fourth coordinate direction (often 0)

3173:    Output Parameter:
3174: .  a - location to put pointer to the array

3176:    Level: beginner

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

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

3186: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3187:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3188:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3189: @*/
3190: PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3191: {
3192:   PetscInt     i, N, j, k;
3193:   PetscScalar *aa, ***b, **c;

3195:   PetscFunctionBegin;
3199:   PetscCall(VecGetLocalSize(x, &N));
3200:   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);
3201:   PetscCall(VecGetArray(x, &aa));

3203:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3204:   b = (PetscScalar ***)((*a) + m);
3205:   c = (PetscScalar **)(b + m * n);
3206:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3207:   for (i = 0; i < m; i++)
3208:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3209:   for (i = 0; i < m; i++)
3210:     for (j = 0; j < n; j++)
3211:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3212:   *a -= mstart;
3213:   PetscFunctionReturn(PETSC_SUCCESS);
3214: }

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

3221:    Logically Collective

3223:    Input Parameters:
3224: +  x - the vector
3225: .  m - first dimension of four dimensional array
3226: .  n - second dimension of four dimensional array
3227: .  p - third dimension of four dimensional array
3228: .  q - fourth dimension of four dimensional array
3229: .  mstart - first index you will use in first coordinate direction (often 0)
3230: .  nstart - first index in the second coordinate direction (often 0)
3231: .  pstart - first index in the third coordinate direction (often 0)
3232: -  qstart - first index in the fourth coordinate direction (often 0)

3234:    Output Parameter:
3235: .  a - location to put pointer to the array

3237:    Level: beginner

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

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

3247: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3248:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3249:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3250: @*/
3251: PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3252: {
3253:   PetscInt     i, N, j, k;
3254:   PetscScalar *aa, ***b, **c;

3256:   PetscFunctionBegin;
3260:   PetscCall(VecGetLocalSize(x, &N));
3261:   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);
3262:   PetscCall(VecGetArrayWrite(x, &aa));

3264:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3265:   b = (PetscScalar ***)((*a) + m);
3266:   c = (PetscScalar **)(b + m * n);
3267:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3268:   for (i = 0; i < m; i++)
3269:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3270:   for (i = 0; i < m; i++)
3271:     for (j = 0; j < n; j++)
3272:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3273:   *a -= mstart;
3274:   PetscFunctionReturn(PETSC_SUCCESS);
3275: }

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

3280:    Logically Collective

3282:    Input Parameters:
3283: +  x - the vector
3284: .  m - first dimension of four dimensional array
3285: .  n - second dimension of the four dimensional array
3286: .  p - third dimension of the four dimensional array
3287: .  q - fourth dimension of the four dimensional array
3288: .  mstart - first index you will use in first coordinate direction (often 0)
3289: .  nstart - first index in the second coordinate direction (often 0)
3290: .  pstart - first index in the third coordinate direction (often 0)
3291: .  qstart - first index in the fourth coordinate direction (often 0)
3292: -  a - location of pointer to array obtained from VecGetArray4d()

3294:    Level: beginner

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

3302:    This routine actually zeros out the a pointer.

3304: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3305:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3306:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3307: @*/
3308: PetscErrorCode VecRestoreArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3309: {
3310:   void *dummy;

3312:   PetscFunctionBegin;
3316:   dummy = (void *)(*a + mstart);
3317:   PetscCall(PetscFree(dummy));
3318:   PetscCall(VecRestoreArray(x, NULL));
3319:   PetscFunctionReturn(PETSC_SUCCESS);
3320: }

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

3325:    Logically Collective

3327:    Input Parameters:
3328: +  x - the vector
3329: .  m - first dimension of four dimensional array
3330: .  n - second dimension of the four dimensional array
3331: .  p - third dimension of the four dimensional array
3332: .  q - fourth dimension of the four dimensional array
3333: .  mstart - first index you will use in first coordinate direction (often 0)
3334: .  nstart - first index in the second coordinate direction (often 0)
3335: .  pstart - first index in the third coordinate direction (often 0)
3336: .  qstart - first index in the fourth coordinate direction (often 0)
3337: -  a - location of pointer to array obtained from `VecGetArray4d()`

3339:    Level: beginner

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

3347:    This routine actually zeros out the a pointer.

3349: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3350:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3351:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3352: @*/
3353: PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3354: {
3355:   void *dummy;

3357:   PetscFunctionBegin;
3361:   dummy = (void *)(*a + mstart);
3362:   PetscCall(PetscFree(dummy));
3363:   PetscCall(VecRestoreArrayWrite(x, NULL));
3364:   PetscFunctionReturn(PETSC_SUCCESS);
3365: }

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

3372:    Logically Collective

3374:    Input Parameters:
3375: +  x - the vector
3376: .  m - first dimension of two dimensional array
3377: .  n - second dimension of two dimensional array
3378: .  mstart - first index you will use in first coordinate direction (often 0)
3379: -  nstart - first index in the second coordinate direction (often 0)

3381:    Output Parameter:
3382: .  a - location to put pointer to the array

3384:    Level: developer

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

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

3394: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3395:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3396:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3397: @*/
3398: PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3399: {
3400:   PetscInt           i, N;
3401:   const PetscScalar *aa;

3403:   PetscFunctionBegin;
3407:   PetscCall(VecGetLocalSize(x, &N));
3408:   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);
3409:   PetscCall(VecGetArrayRead(x, &aa));

3411:   PetscCall(PetscMalloc1(m, a));
3412:   for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3413:   *a -= mstart;
3414:   PetscFunctionReturn(PETSC_SUCCESS);
3415: }

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

3420:    Logically Collective

3422:    Input Parameters:
3423: +  x - the vector
3424: .  m - first dimension of two dimensional array
3425: .  n - second dimension of the two dimensional array
3426: .  mstart - first index you will use in first coordinate direction (often 0)
3427: .  nstart - first index in the second coordinate direction (often 0)
3428: -  a - location of pointer to array obtained from VecGetArray2d()

3430:    Level: developer

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

3438:    This routine actually zeros out the a pointer.

3440: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3441:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3442:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3443: @*/
3444: PetscErrorCode VecRestoreArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3445: {
3446:   void *dummy;

3448:   PetscFunctionBegin;
3452:   dummy = (void *)(*a + mstart);
3453:   PetscCall(PetscFree(dummy));
3454:   PetscCall(VecRestoreArrayRead(x, NULL));
3455:   PetscFunctionReturn(PETSC_SUCCESS);
3456: }

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

3463:    Logically Collective

3465:    Input Parameters:
3466: +  x - the vector
3467: .  m - first dimension of two dimensional array
3468: -  mstart - first index you will use in first coordinate direction (often 0)

3470:    Output Parameter:
3471: .  a - location to put pointer to the array

3473:    Level: developer

3475:   Notes:
3476:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
3477:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3478:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

3482: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3483:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3484:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3485: @*/
3486: PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3487: {
3488:   PetscInt N;

3490:   PetscFunctionBegin;
3494:   PetscCall(VecGetLocalSize(x, &N));
3495:   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);
3496:   PetscCall(VecGetArrayRead(x, (const PetscScalar **)a));
3497:   *a -= mstart;
3498:   PetscFunctionReturn(PETSC_SUCCESS);
3499: }

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

3504:    Logically Collective

3506:    Input Parameters:
3507: +  x - the vector
3508: .  m - first dimension of two dimensional array
3509: .  mstart - first index you will use in first coordinate direction (often 0)
3510: -  a - location of pointer to array obtained from `VecGetArray1dRead()`

3512:    Level: developer

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

3520:    This routine actually zeros out the a pointer.

3522: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3523:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3524:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3525: @*/
3526: PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3527: {
3528:   PetscFunctionBegin;
3531:   PetscCall(VecRestoreArrayRead(x, NULL));
3532:   PetscFunctionReturn(PETSC_SUCCESS);
3533: }

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

3540:    Logically Collective

3542:    Input Parameters:
3543: +  x - the vector
3544: .  m - first dimension of three dimensional array
3545: .  n - second dimension of three dimensional array
3546: .  p - third dimension of three dimensional array
3547: .  mstart - first index you will use in first coordinate direction (often 0)
3548: .  nstart - first index in the second coordinate direction (often 0)
3549: -  pstart - first index in the third coordinate direction (often 0)

3551:    Output Parameter:
3552: .  a - location to put pointer to the array

3554:    Level: developer

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

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

3564: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3565:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3566:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3567: @*/
3568: PetscErrorCode VecGetArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3569: {
3570:   PetscInt           i, N, j;
3571:   const PetscScalar *aa;
3572:   PetscScalar      **b;

3574:   PetscFunctionBegin;
3578:   PetscCall(VecGetLocalSize(x, &N));
3579:   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);
3580:   PetscCall(VecGetArrayRead(x, &aa));

3582:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3583:   b = (PetscScalar **)((*a) + m);
3584:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3585:   for (i = 0; i < m; i++)
3586:     for (j = 0; j < n; j++) b[i * n + j] = (PetscScalar *)aa + i * n * p + j * p - pstart;
3587:   *a -= mstart;
3588:   PetscFunctionReturn(PETSC_SUCCESS);
3589: }

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

3594:    Logically Collective

3596:    Input Parameters:
3597: +  x - the vector
3598: .  m - first dimension of three dimensional array
3599: .  n - second dimension of the three dimensional array
3600: .  p - third dimension of the three dimensional array
3601: .  mstart - first index you will use in first coordinate direction (often 0)
3602: .  nstart - first index in the second coordinate direction (often 0)
3603: .  pstart - first index in the third coordinate direction (often 0)
3604: -  a - location of pointer to array obtained from `VecGetArray3dRead()`

3606:    Level: developer

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

3614:    This routine actually zeros out the a pointer.

3616: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3617:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3618:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3619: @*/
3620: PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3621: {
3622:   void *dummy;

3624:   PetscFunctionBegin;
3628:   dummy = (void *)(*a + mstart);
3629:   PetscCall(PetscFree(dummy));
3630:   PetscCall(VecRestoreArrayRead(x, NULL));
3631:   PetscFunctionReturn(PETSC_SUCCESS);
3632: }

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

3639:    Logically Collective

3641:    Input Parameters:
3642: +  x - the vector
3643: .  m - first dimension of four dimensional array
3644: .  n - second dimension of four dimensional array
3645: .  p - third dimension of four dimensional array
3646: .  q - fourth dimension of four dimensional array
3647: .  mstart - first index you will use in first coordinate direction (often 0)
3648: .  nstart - first index in the second coordinate direction (often 0)
3649: .  pstart - first index in the third coordinate direction (often 0)
3650: -  qstart - first index in the fourth coordinate direction (often 0)

3652:    Output Parameter:
3653: .  a - location to put pointer to the array

3655:    Level: beginner

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

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

3665: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3666:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3667:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3668: @*/
3669: PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3670: {
3671:   PetscInt           i, N, j, k;
3672:   const PetscScalar *aa;
3673:   PetscScalar     ***b, **c;

3675:   PetscFunctionBegin;
3679:   PetscCall(VecGetLocalSize(x, &N));
3680:   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);
3681:   PetscCall(VecGetArrayRead(x, &aa));

3683:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3684:   b = (PetscScalar ***)((*a) + m);
3685:   c = (PetscScalar **)(b + m * n);
3686:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3687:   for (i = 0; i < m; i++)
3688:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3689:   for (i = 0; i < m; i++)
3690:     for (j = 0; j < n; j++)
3691:       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;
3692:   *a -= mstart;
3693:   PetscFunctionReturn(PETSC_SUCCESS);
3694: }

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

3699:    Logically Collective

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

3713:    Level: beginner

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

3721:    This routine actually zeros out the a pointer.

3723: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3724:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3725:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3726: @*/
3727: PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3728: {
3729:   void *dummy;

3731:   PetscFunctionBegin;
3735:   dummy = (void *)(*a + mstart);
3736:   PetscCall(PetscFree(dummy));
3737:   PetscCall(VecRestoreArrayRead(x, NULL));
3738:   PetscFunctionReturn(PETSC_SUCCESS);
3739: }

3741: #if defined(PETSC_USE_DEBUG)

3743: /*@
3744:    VecLockGet  - Gets the current lock status of a vector

3746:    Logically Collective

3748:    Input Parameter:
3749: .  x - the vector

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

3755:    Level: advanced

3757: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
3758: @*/
3759: PetscErrorCode VecLockGet(Vec x, PetscInt *state)
3760: {
3761:   PetscFunctionBegin;
3763:   *state = x->lock;
3764:   PetscFunctionReturn(PETSC_SUCCESS);
3765: }

3767: PetscErrorCode VecLockGetLocation(Vec x, const char *file[], const char *func[], int *line)
3768: {
3769:   PetscFunctionBegin;
3774:   #if !PetscDefined(HAVE_THREADSAFETY)
3775:   {
3776:     const int index = x->lockstack.currentsize - 1;

3778:     PetscCheck(index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupted vec lock stack, have negative index %d", index);
3779:     *file = x->lockstack.file[index];
3780:     *func = x->lockstack.function[index];
3781:     *line = x->lockstack.line[index];
3782:   }
3783:   #else
3784:   *file = NULL;
3785:   *func = NULL;
3786:   *line = 0;
3787:   #endif
3788:   PetscFunctionReturn(PETSC_SUCCESS);
3789: }

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

3794:    Logically Collective

3796:    Input Parameter:
3797: .  x - the vector

3799:    Level: intermediate

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

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

3807: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPop()`, `VecLockGet()`
3808: @*/
3809: PetscErrorCode VecLockReadPush(Vec x)
3810: {
3811:   PetscFunctionBegin;
3813:   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");
3814:   #if !PetscDefined(HAVE_THREADSAFETY)
3815:   {
3816:     const char *file, *func;
3817:     int         index, line;

3819:     if ((index = petscstack.currentsize - 2) == -1) {
3820:       // vec was locked "outside" of petsc, either in user-land or main. the error message will
3821:       // now show this function as the culprit, but it will include the stacktrace
3822:       file = "unknown user-file";
3823:       func = "unknown_user_function";
3824:       line = 0;
3825:     } else {
3826:       PetscCheck(index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected petscstack, have negative index %d", index);
3827:       file = petscstack.file[index];
3828:       func = petscstack.function[index];
3829:       line = petscstack.line[index];
3830:     }
3831:     PetscStackPush_Private(x->lockstack, file, func, line, petscstack.petscroutine[index], PETSC_FALSE);
3832:   }
3833:   #endif
3834:   PetscFunctionReturn(PETSC_SUCCESS);
3835: }

3837: /*@
3838:    VecLockReadPop  - Pops a read-only lock from a vector

3840:    Logically Collective

3842:    Input Parameter:
3843: .  x - the vector

3845:    Level: intermediate

3847: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockGet()`
3848: @*/
3849: PetscErrorCode VecLockReadPop(Vec x)
3850: {
3851:   PetscFunctionBegin;
3853:   PetscCheck(--x->lock >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector has been unlocked from read-only access too many times");
3854:   #if !PetscDefined(HAVE_THREADSAFETY)
3855:   {
3856:     const char *previous = x->lockstack.function[x->lockstack.currentsize - 1];

3858:     PetscStackPop_Private(x->lockstack, previous);
3859:   }
3860:   #endif
3861:   PetscFunctionReturn(PETSC_SUCCESS);
3862: }

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

3867:    Logically Collective

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

3873:    Level: intermediate

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

3881: .vb
3882:        VecGetArray(x,&xdata); // begin phase
3883:        VecLockWriteSet(v,PETSC_TRUE);

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

3887:        VecRestoreArray(x,&vdata); // end phase
3888:        VecLockWriteSet(v,PETSC_FALSE);
3889: .ve

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

3894: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
3895: @*/
3896: PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
3897: {
3898:   PetscFunctionBegin;
3900:   if (flg) {
3901:     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");
3902:     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");
3903:     x->lock = -1;
3904:   } else {
3905:     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");
3906:     x->lock = 0;
3907:   }
3908:   PetscFunctionReturn(PETSC_SUCCESS);
3909: }

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

3914:    Level: deprecated

3916: .seealso: [](chapter_vectors), `Vec`, `VecLockReadPush()`
3917: @*/
3918: PetscErrorCode VecLockPush(Vec x)
3919: {
3920:   PetscFunctionBegin;
3921:   PetscCall(VecLockReadPush(x));
3922:   PetscFunctionReturn(PETSC_SUCCESS);
3923: }

3925: /*@
3926:    VecLockPop  - Pops a read-only lock from a vector

3928:    Level: deprecated

3930: .seealso: [](chapter_vectors), `Vec`, `VecLockReadPop()`
3931: @*/
3932: PetscErrorCode VecLockPop(Vec x)
3933: {
3934:   PetscFunctionBegin;
3935:   PetscCall(VecLockReadPop(x));
3936:   PetscFunctionReturn(PETSC_SUCCESS);
3937: }

3939: #endif