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`, `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.

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()`
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 location of val (pass `NULL` if you don't want this)
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 location of val (pass `NULL` if you don't want this location)
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
461: $      x[i] = alpha * x[i], for i=1,...,n.

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

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

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

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

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

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

495:    Logically Collective

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

501:    Output Parameter:
502: .  x  - the vector

504:    Level: beginner

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

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

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

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

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

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

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

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

559:    Logically Collective

561:    Input Parameters:
562: +  alpha - the scalar
563: -  x, y  - the vectors

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

568:    Level: intermediate

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

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

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

613:    Logically Collective

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

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

623:    Level: intermediate

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

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

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

663:    Logically Collective

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

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

673:    Level: intermediate

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

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

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

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

712:    Logically Collective

714:    Input Parameters:
715: +  alpha,beta, gamma - the scalars
716: -  x, y, z  - the vectors

718:    Output Parameter:
719: .  z - output vector

721:    Level: intermediate

723:    Note:
724:    `x`, `y` and `z` must be different vectors

726:    Developer Note:
727:     The implementation is optimized for alpha of 1.0 and gamma of 1.0 or 0.0

729: .seealso: [](chapter_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBY()`
730: @*/
731: PetscErrorCode VecAXPBYPCZ(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y)
732: {
733:   PetscFunctionBegin;
740:   PetscCheckSameTypeAndComm(x, 5, y, 6);
741:   PetscCheckSameTypeAndComm(x, 5, z, 1);
742:   VecCheckSameSize(x, 1, y, 5);
743:   VecCheckSameSize(x, 1, z, 6);
744:   PetscCheck(x != y && x != z, PetscObjectComm((PetscObject)x), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
745:   PetscCheck(y != z, PetscObjectComm((PetscObject)y), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
746:   VecCheckAssembled(x);
747:   VecCheckAssembled(y);
748:   VecCheckAssembled(z);
752:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);

754:   PetscCall(VecSetErrorIfLocked(z, 1));
755:   PetscCall(VecLockReadPush(x));
756:   PetscCall(VecLockReadPush(y));
757:   PetscCall(PetscLogEventBegin(VEC_AXPBYPCZ, x, y, z, 0));
758:   PetscUseTypeMethod(z, axpbypcz, alpha, beta, gamma, x, y);
759:   PetscCall(PetscLogEventEnd(VEC_AXPBYPCZ, x, y, z, 0));
760:   PetscCall(PetscObjectStateIncrease((PetscObject)z));
761:   PetscCall(VecLockReadPop(x));
762:   PetscCall(VecLockReadPop(y));
763:   PetscFunctionReturn(PETSC_SUCCESS);
764: }

766: /*@
767:    VecWAXPY - Computes `w = alpha x + y`.

769:    Logically Collective

771:    Input Parameters:
772: +  alpha - the scalar
773: -  x, y  - the vectors

775:    Output Parameter:
776: .  w - the result

778:    Level: intermediate

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

783:    Developer Note:
784:     The implementation is optimized for alpha of -1.0, 0.0, and 1.0

786: .seealso: [](chapter_vectors), `Vec`, `VecAXPY()`, `VecAYPX()`, `VecAXPBY()`, `VecMAXPY()`, `VecAXPBYPCZ()`
787: @*/
788: PetscErrorCode VecWAXPY(Vec w, PetscScalar alpha, Vec x, Vec y)
789: {
790:   PetscFunctionBegin;
797:   PetscCheckSameTypeAndComm(x, 3, y, 4);
798:   PetscCheckSameTypeAndComm(y, 4, w, 1);
799:   VecCheckSameSize(x, 3, y, 4);
800:   VecCheckSameSize(x, 3, w, 1);
801:   PetscCheck(w != y, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector y, suggest VecAXPY()");
802:   PetscCheck(w != x, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector x, suggest VecAYPX()");
803:   VecCheckAssembled(x);
804:   VecCheckAssembled(y);
806:   PetscCall(VecSetErrorIfLocked(w, 1));

808:   PetscCall(VecLockReadPush(x));
809:   PetscCall(VecLockReadPush(y));
810:   if (alpha == (PetscScalar)0.0) {
811:     PetscCall(VecCopy(y, w));
812:   } else {
813:     PetscCall(PetscLogEventBegin(VEC_WAXPY, x, y, w, 0));
814:     PetscUseTypeMethod(w, waxpy, alpha, x, y);
815:     PetscCall(PetscLogEventEnd(VEC_WAXPY, x, y, w, 0));
816:     PetscCall(PetscObjectStateIncrease((PetscObject)w));
817:   }
818:   PetscCall(VecLockReadPop(x));
819:   PetscCall(VecLockReadPop(y));
820:   PetscFunctionReturn(PETSC_SUCCESS);
821: }

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

826:    Not Collective

828:    Input Parameters:
829: +  x - vector to insert in
830: .  ni - number of elements to add
831: .  ix - indices where to add
832: .  y - array of values
833: -  iora - either `INSERT_VALUES` or `ADD_VALUES`, where
834:    `ADD_VALUES` adds values to any existing entries, and
835:    `INSERT_VALUES` replaces existing entries with new values

837:    Level: beginner

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

842:    Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
843:    options cannot be mixed without intervening calls to the assembly
844:    routines.

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

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

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

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

869:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
870:   PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
871:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
872:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
873:   PetscFunctionReturn(PETSC_SUCCESS);
874: }

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

880:     Not Collective

882:    Input Parameters:
883: +  x - vector to get values from
884: .  ni - number of elements to get
885: -  ix - indices where to get them from (in global 1d numbering)

887:    Output Parameter:
888: .   y - array of values

890:    Level: beginner

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

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

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

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

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

905: .seealso: [](chapter_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`
906: @*/
907: PetscErrorCode VecGetValues(Vec x, PetscInt ni, const PetscInt ix[], PetscScalar y[])
908: {
909:   PetscFunctionBegin;
911:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
915:   VecCheckAssembled(x);
916:   PetscUseTypeMethod(x, getvalues, ni, ix, y);
917:   PetscFunctionReturn(PETSC_SUCCESS);
918: }

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

923:    Not Collective

925:    Input Parameters:
926: +  x - vector to insert in
927: .  ni - number of blocks to add
928: .  ix - indices where to add in block count, rather than element count
929: .  y - array of values
930: -  iora - either `INSERT_VALUES` or `ADD_VALUES`, where
931:    `ADD_VALUES` adds values to any existing entries, and
932:    `INSERT_VALUES` replaces existing entries with new values

934:    Level: intermediate

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

940:    Calls to `VecSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
941:    options cannot be mixed without intervening calls to the assembly
942:    routines.

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

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

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

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

966:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
967:   PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
968:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
969:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
970:   PetscFunctionReturn(PETSC_SUCCESS);
971: }

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

977:    Not Collective

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

988:    Level: intermediate

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

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

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

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

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

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

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

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

1034:    Not Collective

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

1045:    Level: intermediate

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

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

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

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

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

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

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

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

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

1120:    Collective

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

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

1130:    Level: intermediate

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

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

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

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

1154:    Collective

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

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

1164:    Level: intermediate

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

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

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

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

1188:    Logically Collective

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

1196:    Level: intermediate

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

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

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

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

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

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

1245:    Collective

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

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

1255:    Level: advanced

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

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

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

1277:   PetscFunctionBegin;

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

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

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

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

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

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

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

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

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

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

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

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

1397:    Collective

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

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

1406:    Level: advanced

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

1412:    This function may return a subvector without making a copy, therefore it is not safe to use the original vector while
1413:    modifying the subvector.  Other non-overlapping subvectors can still be obtained from X using this function.
1414:    The resulting subvector inherits the block size from the IS if greater than one. Otherwise, the block size is guessed from the block size of the original vec.

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

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

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

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

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

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

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

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

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

1523:    Collective

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

1530:    Level: advanced

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

1539:   PetscFunctionBegin;
1542:   PetscCheckSameComm(X, 1, is, 2);

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

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

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

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

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

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

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

1633:    Not collective.

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

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

1641:    Level: beginner

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

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

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

1670: /*@
1671:    VecGetLocalVectorRead - Maps the local portion of a vector into a
1672:    vector.  You must call `VecRestoreLocalVectorRead()` when the local
1673:    vector is no longer needed.

1675:    Not collective.

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

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

1683:    Level: beginner

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

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

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

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

1721: /*@
1722:    VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1723:    previously mapped into a vector using `VecGetLocalVectorRead()`.

1725:    Not collective.

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

1731:    Level: beginner

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

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

1755: /*@
1756:    VecGetLocalVector - Maps the local portion of a vector into a
1757:    vector.

1759:    Collective on v, not collective on w.

1761:    Input parameter:
1762: .  v - The vector for which the local vector is desired.

1764:    Output parameter:
1765: .  w - Upon exit this contains the local vector.

1767:    Level: beginner

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

1780: .seealso: [](chapter_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVector()`, `VecGetLocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1781: @*/
1782: PetscErrorCode VecGetLocalVector(Vec v, Vec w)
1783: {
1784:   PetscFunctionBegin;
1787:   VecCheckSameLocalSize(v, 1, w, 2);
1788:   if (v->ops->getlocalvector) {
1789:     PetscUseTypeMethod(v, getlocalvector, w);
1790:   } else {
1791:     PetscScalar *a;

1793:     PetscCall(VecGetArray(v, &a));
1794:     PetscCall(VecPlaceArray(w, a));
1795:   }
1796:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1797:   PetscFunctionReturn(PETSC_SUCCESS);
1798: }

1800: /*@
1801:    VecRestoreLocalVector - Unmaps the local portion of a vector
1802:    previously mapped into a vector using `VecGetLocalVector()`.

1804:    Logically collective.

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

1810:    Level: beginner

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

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

1841:    Logically Collective

1843:    Input Parameter:
1844: .  x - the vector

1846:    Output Parameter:
1847: .  a - location to put pointer to the array

1849:    Level: beginner

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

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

1870: /*@C
1871:    VecRestoreArray - Restores a vector after `VecGetArray()` has been called.

1873:    Logically Collective

1875:    Input Parameters:
1876: +  x - the vector
1877: -  a - location of pointer to array obtained from `VecGetArray()`

1879:    Level: beginner

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

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

1902:    Not Collective

1904:    Input Parameter:
1905: .  x - the vector

1907:    Output Parameter:
1908: .  a - the array

1910:    Level: beginner

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

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

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

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

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

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

1949: /*@C
1950:    VecRestoreArrayRead - Restore array obtained with `VecGetArrayRead()`

1952:    Not Collective

1954:    Input Parameters:
1955: +  vec - the vector
1956: -  array - the array

1958:    Level: beginner

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

1963: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
1964: @*/
1965: PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar **a)
1966: {
1967:   PetscFunctionBegin;
1970:   if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
1971:     /* nothing */
1972:   } else if (x->ops->restorearrayread) { /* VECNEST */
1973:     PetscUseTypeMethod(x, restorearrayread, a);
1974:   } else { /* No one? */
1975:     PetscObjectState state;

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

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

1992:    Logically Collective

1994:    Input Parameter:
1995: .  x - the vector

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

2000:    Level: intermediate

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

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

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

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

2029:    Logically Collective

2031:    Input Parameters:
2032: +  x - the vector
2033: -  a - location of pointer to array obtained from `VecGetArray()`

2035:    Level: beginner

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

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

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

2063:    Logically Collective; No Fortran Support

2065:    Input Parameters:
2066: +  x - the vectors
2067: -  n - the number of vectors

2069:    Output Parameter:
2070: .  a - location to put pointer to the array

2072:    Level: intermediate

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

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

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

2096:    Logically Collective; No Fortran Support

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

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

2109:    Level: intermediate

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

2118:   PetscFunctionBegin;

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

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

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

2136:    Logically Collective; No Fortran Support

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

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

2145:    Level: beginner

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

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

2172:    Logically Collective; No Fortran Support

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

2178:    Level: beginner

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

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

2204:    Not Collective; No Fortran Support

2206:    Input Parameter:
2207: .  x - the vector

2209:    Output Parameters:
2210: +  a - the array
2211: -  mtype - memory type of the array

2213:    Level: beginner

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

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

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

2245: /*@C
2246:    VecRestoreArrayReadAndMemType - Restore array obtained with `VecGetArrayReadAndMemType()`

2248:    Not Collective; No Fortran Support

2250:    Input Parameters:
2251: +  vec - the vector
2252: -  array - the array

2254:    Level: beginner

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

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

2279:    Not Collective; No Fortran Support

2281:    Input Parameter:
2282: .  x - the vector

2284:    Output Parameters:
2285: +  a - the array
2286: -  mtype - memory type of the array

2288:    Level: beginner

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

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

2316: /*@C
2317:    VecRestoreArrayWriteAndMemType - Restore array obtained with `VecGetArrayWriteAndMemType()`

2319:    Not Collective; No Fortran Support

2321:    Input Parameters:
2322: +  vec - the vector
2323: -  array - the array

2325:    Level: beginner

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

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

2354:    Not Collective; No Fortran Support

2356:    Input Parameters:
2357: +  vec - the vector
2358: -  array - the array

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

2366:    Level: developer

2368: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`
2369: @*/
2370: PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2371: {
2372:   PetscFunctionBegin;
2376:   PetscUseTypeMethod(vec, placearray, array);
2377:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2378:   PetscFunctionReturn(PETSC_SUCCESS);
2379: }

2381: /*@C
2382:    VecReplaceArray - Allows one to replace the array in a vector with an
2383:    array provided by the user. This is useful to avoid copying an array
2384:    into a vector.

2386:    Not Collective; No Fortran Support

2388:    Input Parameters:
2389: +  vec - the vector
2390: -  array - the array

2392:    Level: developer

2394:    Notes:
2395:    This permanently replaces the array and frees the memory associated
2396:    with the old array.

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

2401: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`
2402: @*/
2403: PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2404: {
2405:   PetscFunctionBegin;
2408:   PetscUseTypeMethod(vec, replacearray, array);
2409:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2410:   PetscFunctionReturn(PETSC_SUCCESS);
2411: }

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

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

2420:     Collective

2422:     Input Parameters:
2423: +   x - a vector to mimic
2424: -   n - the number of vectors to obtain

2426:     Output Parameters:
2427: +   y - Fortran pointer to the array of vectors
2428: -   ierr - error code

2430:     Example of Usage:
2431: .vb
2432: #include <petsc/finclude/petscvec.h>
2433:     use petscvec

2435:     Vec x
2436:     Vec, pointer :: y(:)
2437:     ....
2438:     call VecDuplicateVecsF90(x,2,y,ierr)
2439:     call VecSet(y(2),alpha,ierr)
2440:     call VecSet(y(2),alpha,ierr)
2441:     ....
2442:     call VecDestroyVecsF90(2,y,ierr)
2443: .ve

2445:     Level: beginner

2447:     Note:
2448:     Use `VecDestroyVecsF90()` to free the space.

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

2453: /*MC
2454:     VecRestoreArrayF90 - Restores a vector to a usable state after a call to
2455:     `VecGetArrayF90()`.

2457:     Synopsis:
2458:     VecRestoreArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2460:     Logically Collective

2462:     Input Parameters:
2463: +   x - vector
2464: -   xx_v - the Fortran pointer to the array

2466:     Output Parameter:
2467: .   ierr - error code

2469:     Example of Usage:
2470: .vb
2471: #include <petsc/finclude/petscvec.h>
2472:     use petscvec

2474:     PetscScalar, pointer :: xx_v(:)
2475:     ....
2476:     call VecGetArrayF90(x,xx_v,ierr)
2477:     xx_v(3) = a
2478:     call VecRestoreArrayF90(x,xx_v,ierr)
2479: .ve

2481:     Level: beginner

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

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

2489:     Synopsis:
2490:     VecDestroyVecsF90(PetscInt n,{Vec, pointer :: x(:)},PetscErrorCode ierr)

2492:     Collective

2494:     Input Parameters:
2495: +   n - the number of vectors previously obtained
2496: -   x - pointer to array of vector pointers

2498:     Output Parameter:
2499: .   ierr - error code

2501:     Level: beginner

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

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

2512:     Synopsis:
2513:     VecGetArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2515:     Logically Collective

2517:     Input Parameter:
2518: .   x - vector

2520:     Output Parameters:
2521: +   xx_v - the Fortran pointer to the array
2522: -   ierr - error code

2524:     Example of Usage:
2525: .vb
2526: #include <petsc/finclude/petscvec.h>
2527:     use petscvec

2529:     PetscScalar, pointer :: xx_v(:)
2530:     ....
2531:     call VecGetArrayF90(x,xx_v,ierr)
2532:     xx_v(3) = a
2533:     call VecRestoreArrayF90(x,xx_v,ierr)
2534: .ve

2536:      Level: beginner

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

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

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

2550:     Synopsis:
2551:     VecGetArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2553:     Logically Collective

2555:     Input Parameter:
2556: .   x - vector

2558:     Output Parameters:
2559: +   xx_v - the Fortran pointer to the array
2560: -   ierr - error code

2562:     Example of Usage:
2563: .vb
2564: #include <petsc/finclude/petscvec.h>
2565:     use petscvec

2567:     PetscScalar, pointer :: xx_v(:)
2568:     ....
2569:     call VecGetArrayReadF90(x,xx_v,ierr)
2570:     a = xx_v(3)
2571:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2572: .ve

2574:     Level: beginner

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

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

2582: /*MC
2583:     VecRestoreArrayReadF90 - Restores a readonly vector to a usable state after a call to
2584:     `VecGetArrayReadF90()`.

2586:     Synopsis:
2587:     VecRestoreArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2589:     Logically Collective

2591:     Input Parameters:
2592: +   x - vector
2593: -   xx_v - the Fortran pointer to the array

2595:     Output Parameter:
2596: .   ierr - error code

2598:     Example of Usage:
2599: .vb
2600: #include <petsc/finclude/petscvec.h>
2601:     use petscvec

2603:     PetscScalar, pointer :: xx_v(:)
2604:     ....
2605:     call VecGetArrayReadF90(x,xx_v,ierr)
2606:     a = xx_v(3)
2607:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2608: .ve

2610:     Level: beginner

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

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

2620:    Logically Collective

2622:    Input Parameters:
2623: +  x - the vector
2624: .  m - first dimension of two dimensional array
2625: .  n - second dimension of two dimensional array
2626: .  mstart - first index you will use in first coordinate direction (often 0)
2627: -  nstart - first index in the second coordinate direction (often 0)

2629:    Output Parameter:
2630: .  a - location to put pointer to the array

2632:    Level: developer

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

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

2642: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2643:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2644:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2645: @*/
2646: PetscErrorCode VecGetArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2647: {
2648:   PetscInt     i, N;
2649:   PetscScalar *aa;

2651:   PetscFunctionBegin;
2655:   PetscCall(VecGetLocalSize(x, &N));
2656:   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);
2657:   PetscCall(VecGetArray(x, &aa));

2659:   PetscCall(PetscMalloc1(m, a));
2660:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2661:   *a -= mstart;
2662:   PetscFunctionReturn(PETSC_SUCCESS);
2663: }

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

2670:    Logically Collective

2672:    Input Parameters:
2673: +  x - the vector
2674: .  m - first dimension of two dimensional array
2675: .  n - second dimension of two dimensional array
2676: .  mstart - first index you will use in first coordinate direction (often 0)
2677: -  nstart - first index in the second coordinate direction (often 0)

2679:    Output Parameter:
2680: .  a - location to put pointer to the array

2682:    Level: developer

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

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

2692: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2693:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2694:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2695: @*/
2696: PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2697: {
2698:   PetscInt     i, N;
2699:   PetscScalar *aa;

2701:   PetscFunctionBegin;
2705:   PetscCall(VecGetLocalSize(x, &N));
2706:   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);
2707:   PetscCall(VecGetArrayWrite(x, &aa));

2709:   PetscCall(PetscMalloc1(m, a));
2710:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2711:   *a -= mstart;
2712:   PetscFunctionReturn(PETSC_SUCCESS);
2713: }

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

2718:    Logically Collective

2720:    Input Parameters:
2721: +  x - the vector
2722: .  m - first dimension of two dimensional array
2723: .  n - second dimension of the two dimensional array
2724: .  mstart - first index you will use in first coordinate direction (often 0)
2725: .  nstart - first index in the second coordinate direction (often 0)
2726: -  a - location of pointer to array obtained from `VecGetArray2d()`

2728:    Level: developer

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

2736:    This routine actually zeros out the a pointer.

2738: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2739:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2740:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2741: @*/
2742: PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2743: {
2744:   void *dummy;

2746:   PetscFunctionBegin;
2750:   dummy = (void *)(*a + mstart);
2751:   PetscCall(PetscFree(dummy));
2752:   PetscCall(VecRestoreArray(x, NULL));
2753:   PetscFunctionReturn(PETSC_SUCCESS);
2754: }

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

2759:    Logically Collective

2761:    Input Parameters:
2762: +  x - the vector
2763: .  m - first dimension of two dimensional array
2764: .  n - second dimension of the two dimensional array
2765: .  mstart - first index you will use in first coordinate direction (often 0)
2766: .  nstart - first index in the second coordinate direction (often 0)
2767: -  a - location of pointer to array obtained from `VecGetArray2d()`

2769:    Level: developer

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

2777:    This routine actually zeros out the a pointer.

2779: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2780:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2781:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2782: @*/
2783: PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2784: {
2785:   void *dummy;

2787:   PetscFunctionBegin;
2791:   dummy = (void *)(*a + mstart);
2792:   PetscCall(PetscFree(dummy));
2793:   PetscCall(VecRestoreArrayWrite(x, NULL));
2794:   PetscFunctionReturn(PETSC_SUCCESS);
2795: }

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

2802:    Logically Collective

2804:    Input Parameters:
2805: +  x - the vector
2806: .  m - first dimension of two dimensional array
2807: -  mstart - first index you will use in first coordinate direction (often 0)

2809:    Output Parameter:
2810: .  a - location to put pointer to the array

2812:    Level: developer

2814:   Notes:
2815:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
2816:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2817:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

2821: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2822:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2823:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2824: @*/
2825: PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2826: {
2827:   PetscInt N;

2829:   PetscFunctionBegin;
2833:   PetscCall(VecGetLocalSize(x, &N));
2834:   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);
2835:   PetscCall(VecGetArray(x, a));
2836:   *a -= mstart;
2837:   PetscFunctionReturn(PETSC_SUCCESS);
2838: }

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

2845:    Logically Collective

2847:    Input Parameters:
2848: +  x - the vector
2849: .  m - first dimension of two dimensional array
2850: -  mstart - first index you will use in first coordinate direction (often 0)

2852:    Output Parameter:
2853: .  a - location to put pointer to the array

2855:    Level: developer

2857:   Notes:
2858:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
2859:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2860:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

2864: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2865:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2866:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2867: @*/
2868: PetscErrorCode VecGetArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2869: {
2870:   PetscInt N;

2872:   PetscFunctionBegin;
2876:   PetscCall(VecGetLocalSize(x, &N));
2877:   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);
2878:   PetscCall(VecGetArrayWrite(x, a));
2879:   *a -= mstart;
2880:   PetscFunctionReturn(PETSC_SUCCESS);
2881: }

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

2886:    Logically Collective

2888:    Input Parameters:
2889: +  x - the vector
2890: .  m - first dimension of two dimensional array
2891: .  mstart - first index you will use in first coordinate direction (often 0)
2892: -  a - location of pointer to array obtained from `VecGetArray1d()`

2894:    Level: developer

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

2902:    This routine actually zeros out the a pointer.

2904: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2905:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2906:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2907: @*/
2908: PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2909: {
2910:   PetscFunctionBegin;
2913:   PetscCall(VecRestoreArray(x, NULL));
2914:   PetscFunctionReturn(PETSC_SUCCESS);
2915: }

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

2920:    Logically Collective

2922:    Input Parameters:
2923: +  x - the vector
2924: .  m - first dimension of two dimensional array
2925: .  mstart - first index you will use in first coordinate direction (often 0)
2926: -  a - location of pointer to array obtained from `VecGetArray1d()`

2928:    Level: developer

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

2936:    This routine actually zeros out the a pointer.

2938: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2939:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2940:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2941: @*/
2942: PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2943: {
2944:   PetscFunctionBegin;
2947:   PetscCall(VecRestoreArrayWrite(x, NULL));
2948:   PetscFunctionReturn(PETSC_SUCCESS);
2949: }

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

2956:    Logically Collective

2958:    Input Parameters:
2959: +  x - the vector
2960: .  m - first dimension of three dimensional array
2961: .  n - second dimension of three dimensional array
2962: .  p - third dimension of three dimensional array
2963: .  mstart - first index you will use in first coordinate direction (often 0)
2964: .  nstart - first index in the second coordinate direction (often 0)
2965: -  pstart - first index in the third coordinate direction (often 0)

2967:    Output Parameter:
2968: .  a - location to put pointer to the array

2970:    Level: developer

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

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

2980: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2981:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2982:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2983: @*/
2984: PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
2985: {
2986:   PetscInt     i, N, j;
2987:   PetscScalar *aa, **b;

2989:   PetscFunctionBegin;
2993:   PetscCall(VecGetLocalSize(x, &N));
2994:   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);
2995:   PetscCall(VecGetArray(x, &aa));

2997:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
2998:   b = (PetscScalar **)((*a) + m);
2999:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3000:   for (i = 0; i < m; i++)
3001:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;
3002:   *a -= mstart;
3003:   PetscFunctionReturn(PETSC_SUCCESS);
3004: }

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

3011:    Logically Collective

3013:    Input Parameters:
3014: +  x - the vector
3015: .  m - first dimension of three dimensional array
3016: .  n - second dimension of three dimensional array
3017: .  p - third dimension of three dimensional array
3018: .  mstart - first index you will use in first coordinate direction (often 0)
3019: .  nstart - first index in the second coordinate direction (often 0)
3020: -  pstart - first index in the third coordinate direction (often 0)

3022:    Output Parameter:
3023: .  a - location to put pointer to the array

3025:    Level: developer

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

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

3035: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3036:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3037:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3038: @*/
3039: PetscErrorCode VecGetArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3040: {
3041:   PetscInt     i, N, j;
3042:   PetscScalar *aa, **b;

3044:   PetscFunctionBegin;
3048:   PetscCall(VecGetLocalSize(x, &N));
3049:   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);
3050:   PetscCall(VecGetArrayWrite(x, &aa));

3052:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3053:   b = (PetscScalar **)((*a) + m);
3054:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3055:   for (i = 0; i < m; i++)
3056:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;

3058:   *a -= mstart;
3059:   PetscFunctionReturn(PETSC_SUCCESS);
3060: }

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

3065:    Logically Collective

3067:    Input Parameters:
3068: +  x - the vector
3069: .  m - first dimension of three dimensional array
3070: .  n - second dimension of the three dimensional array
3071: .  p - third dimension of the three dimensional array
3072: .  mstart - first index you will use in first coordinate direction (often 0)
3073: .  nstart - first index in the second coordinate direction (often 0)
3074: .  pstart - first index in the third coordinate direction (often 0)
3075: -  a - location of pointer to array obtained from VecGetArray3d()

3077:    Level: developer

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

3085:    This routine actually zeros out the a pointer.

3087: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3088:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3089:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3090: @*/
3091: PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3092: {
3093:   void *dummy;

3095:   PetscFunctionBegin;
3099:   dummy = (void *)(*a + mstart);
3100:   PetscCall(PetscFree(dummy));
3101:   PetscCall(VecRestoreArray(x, NULL));
3102:   PetscFunctionReturn(PETSC_SUCCESS);
3103: }

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

3108:    Logically Collective

3110:    Input Parameters:
3111: +  x - the vector
3112: .  m - first dimension of three dimensional array
3113: .  n - second dimension of the three dimensional array
3114: .  p - third dimension of the three dimensional array
3115: .  mstart - first index you will use in first coordinate direction (often 0)
3116: .  nstart - first index in the second coordinate direction (often 0)
3117: .  pstart - first index in the third coordinate direction (often 0)
3118: -  a - location of pointer to array obtained from VecGetArray3d()

3120:    Level: developer

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

3128:    This routine actually zeros out the a pointer.

3130: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3131:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3132:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3133: @*/
3134: PetscErrorCode VecRestoreArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3135: {
3136:   void *dummy;

3138:   PetscFunctionBegin;
3142:   dummy = (void *)(*a + mstart);
3143:   PetscCall(PetscFree(dummy));
3144:   PetscCall(VecRestoreArrayWrite(x, NULL));
3145:   PetscFunctionReturn(PETSC_SUCCESS);
3146: }

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

3153:    Logically Collective

3155:    Input Parameters:
3156: +  x - the vector
3157: .  m - first dimension of four dimensional array
3158: .  n - second dimension of four dimensional array
3159: .  p - third dimension of four dimensional array
3160: .  q - fourth dimension of four dimensional array
3161: .  mstart - first index you will use in first coordinate direction (often 0)
3162: .  nstart - first index in the second coordinate direction (often 0)
3163: .  pstart - first index in the third coordinate direction (often 0)
3164: -  qstart - first index in the fourth coordinate direction (often 0)

3166:    Output Parameter:
3167: .  a - location to put pointer to the array

3169:    Level: beginner

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

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

3179: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3180:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3181:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3182: @*/
3183: PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3184: {
3185:   PetscInt     i, N, j, k;
3186:   PetscScalar *aa, ***b, **c;

3188:   PetscFunctionBegin;
3192:   PetscCall(VecGetLocalSize(x, &N));
3193:   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);
3194:   PetscCall(VecGetArray(x, &aa));

3196:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3197:   b = (PetscScalar ***)((*a) + m);
3198:   c = (PetscScalar **)(b + m * n);
3199:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3200:   for (i = 0; i < m; i++)
3201:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3202:   for (i = 0; i < m; i++)
3203:     for (j = 0; j < n; j++)
3204:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3205:   *a -= mstart;
3206:   PetscFunctionReturn(PETSC_SUCCESS);
3207: }

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

3214:    Logically Collective

3216:    Input Parameters:
3217: +  x - the vector
3218: .  m - first dimension of four dimensional array
3219: .  n - second dimension of four dimensional array
3220: .  p - third dimension of four dimensional array
3221: .  q - fourth dimension of four dimensional array
3222: .  mstart - first index you will use in first coordinate direction (often 0)
3223: .  nstart - first index in the second coordinate direction (often 0)
3224: .  pstart - first index in the third coordinate direction (often 0)
3225: -  qstart - first index in the fourth coordinate direction (often 0)

3227:    Output Parameter:
3228: .  a - location to put pointer to the array

3230:    Level: beginner

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

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

3240: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3241:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3242:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3243: @*/
3244: PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3245: {
3246:   PetscInt     i, N, j, k;
3247:   PetscScalar *aa, ***b, **c;

3249:   PetscFunctionBegin;
3253:   PetscCall(VecGetLocalSize(x, &N));
3254:   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);
3255:   PetscCall(VecGetArrayWrite(x, &aa));

3257:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3258:   b = (PetscScalar ***)((*a) + m);
3259:   c = (PetscScalar **)(b + m * n);
3260:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3261:   for (i = 0; i < m; i++)
3262:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3263:   for (i = 0; i < m; i++)
3264:     for (j = 0; j < n; j++)
3265:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3266:   *a -= mstart;
3267:   PetscFunctionReturn(PETSC_SUCCESS);
3268: }

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

3273:    Logically Collective

3275:    Input Parameters:
3276: +  x - the vector
3277: .  m - first dimension of four dimensional array
3278: .  n - second dimension of the four dimensional array
3279: .  p - third dimension of the four dimensional array
3280: .  q - fourth dimension of the four dimensional array
3281: .  mstart - first index you will use in first coordinate direction (often 0)
3282: .  nstart - first index in the second coordinate direction (often 0)
3283: .  pstart - first index in the third coordinate direction (often 0)
3284: .  qstart - first index in the fourth coordinate direction (often 0)
3285: -  a - location of pointer to array obtained from VecGetArray4d()

3287:    Level: beginner

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

3295:    This routine actually zeros out the a pointer.

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

3305:   PetscFunctionBegin;
3309:   dummy = (void *)(*a + mstart);
3310:   PetscCall(PetscFree(dummy));
3311:   PetscCall(VecRestoreArray(x, NULL));
3312:   PetscFunctionReturn(PETSC_SUCCESS);
3313: }

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

3318:    Logically Collective

3320:    Input Parameters:
3321: +  x - the vector
3322: .  m - first dimension of four dimensional array
3323: .  n - second dimension of the four dimensional array
3324: .  p - third dimension of the four dimensional array
3325: .  q - fourth dimension of the four dimensional array
3326: .  mstart - first index you will use in first coordinate direction (often 0)
3327: .  nstart - first index in the second coordinate direction (often 0)
3328: .  pstart - first index in the third coordinate direction (often 0)
3329: .  qstart - first index in the fourth coordinate direction (often 0)
3330: -  a - location of pointer to array obtained from `VecGetArray4d()`

3332:    Level: beginner

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

3340:    This routine actually zeros out the a pointer.

3342: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3343:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3344:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3345: @*/
3346: PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3347: {
3348:   void *dummy;

3350:   PetscFunctionBegin;
3354:   dummy = (void *)(*a + mstart);
3355:   PetscCall(PetscFree(dummy));
3356:   PetscCall(VecRestoreArrayWrite(x, NULL));
3357:   PetscFunctionReturn(PETSC_SUCCESS);
3358: }

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

3365:    Logically Collective

3367:    Input Parameters:
3368: +  x - the vector
3369: .  m - first dimension of two dimensional array
3370: .  n - second dimension of two dimensional array
3371: .  mstart - first index you will use in first coordinate direction (often 0)
3372: -  nstart - first index in the second coordinate direction (often 0)

3374:    Output Parameter:
3375: .  a - location to put pointer to the array

3377:    Level: developer

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

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

3387: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3388:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3389:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3390: @*/
3391: PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3392: {
3393:   PetscInt           i, N;
3394:   const PetscScalar *aa;

3396:   PetscFunctionBegin;
3400:   PetscCall(VecGetLocalSize(x, &N));
3401:   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);
3402:   PetscCall(VecGetArrayRead(x, &aa));

3404:   PetscCall(PetscMalloc1(m, a));
3405:   for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3406:   *a -= mstart;
3407:   PetscFunctionReturn(PETSC_SUCCESS);
3408: }

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

3413:    Logically Collective

3415:    Input Parameters:
3416: +  x - the vector
3417: .  m - first dimension of two dimensional array
3418: .  n - second dimension of the two dimensional array
3419: .  mstart - first index you will use in first coordinate direction (often 0)
3420: .  nstart - first index in the second coordinate direction (often 0)
3421: -  a - location of pointer to array obtained from VecGetArray2d()

3423:    Level: developer

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

3431:    This routine actually zeros out the a pointer.

3433: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3434:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3435:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3436: @*/
3437: PetscErrorCode VecRestoreArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3438: {
3439:   void *dummy;

3441:   PetscFunctionBegin;
3445:   dummy = (void *)(*a + mstart);
3446:   PetscCall(PetscFree(dummy));
3447:   PetscCall(VecRestoreArrayRead(x, NULL));
3448:   PetscFunctionReturn(PETSC_SUCCESS);
3449: }

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

3456:    Logically Collective

3458:    Input Parameters:
3459: +  x - the vector
3460: .  m - first dimension of two dimensional array
3461: -  mstart - first index you will use in first coordinate direction (often 0)

3463:    Output Parameter:
3464: .  a - location to put pointer to the array

3466:    Level: developer

3468:   Notes:
3469:    For a vector obtained from `DMCreateLocalVector()` mstart are likely
3470:    obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3471:    `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

3475: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3476:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3477:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3478: @*/
3479: PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3480: {
3481:   PetscInt N;

3483:   PetscFunctionBegin;
3487:   PetscCall(VecGetLocalSize(x, &N));
3488:   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);
3489:   PetscCall(VecGetArrayRead(x, (const PetscScalar **)a));
3490:   *a -= mstart;
3491:   PetscFunctionReturn(PETSC_SUCCESS);
3492: }

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

3497:    Logically Collective

3499:    Input Parameters:
3500: +  x - the vector
3501: .  m - first dimension of two dimensional array
3502: .  mstart - first index you will use in first coordinate direction (often 0)
3503: -  a - location of pointer to array obtained from `VecGetArray1dRead()`

3505:    Level: developer

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

3513:    This routine actually zeros out the a pointer.

3515: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3516:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3517:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3518: @*/
3519: PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3520: {
3521:   PetscFunctionBegin;
3524:   PetscCall(VecRestoreArrayRead(x, NULL));
3525:   PetscFunctionReturn(PETSC_SUCCESS);
3526: }

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

3533:    Logically Collective

3535:    Input Parameters:
3536: +  x - the vector
3537: .  m - first dimension of three dimensional array
3538: .  n - second dimension of three dimensional array
3539: .  p - third dimension of three dimensional array
3540: .  mstart - first index you will use in first coordinate direction (often 0)
3541: .  nstart - first index in the second coordinate direction (often 0)
3542: -  pstart - first index in the third coordinate direction (often 0)

3544:    Output Parameter:
3545: .  a - location to put pointer to the array

3547:    Level: developer

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

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

3557: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3558:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3559:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3560: @*/
3561: PetscErrorCode VecGetArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3562: {
3563:   PetscInt           i, N, j;
3564:   const PetscScalar *aa;
3565:   PetscScalar      **b;

3567:   PetscFunctionBegin;
3571:   PetscCall(VecGetLocalSize(x, &N));
3572:   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);
3573:   PetscCall(VecGetArrayRead(x, &aa));

3575:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3576:   b = (PetscScalar **)((*a) + m);
3577:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3578:   for (i = 0; i < m; i++)
3579:     for (j = 0; j < n; j++) b[i * n + j] = (PetscScalar *)aa + i * n * p + j * p - pstart;
3580:   *a -= mstart;
3581:   PetscFunctionReturn(PETSC_SUCCESS);
3582: }

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

3587:    Logically Collective

3589:    Input Parameters:
3590: +  x - the vector
3591: .  m - first dimension of three dimensional array
3592: .  n - second dimension of the three dimensional array
3593: .  p - third dimension of the three dimensional array
3594: .  mstart - first index you will use in first coordinate direction (often 0)
3595: .  nstart - first index in the second coordinate direction (often 0)
3596: .  pstart - first index in the third coordinate direction (often 0)
3597: -  a - location of pointer to array obtained from `VecGetArray3dRead()`

3599:    Level: developer

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

3607:    This routine actually zeros out the a pointer.

3609: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3610:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3611:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3612: @*/
3613: PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3614: {
3615:   void *dummy;

3617:   PetscFunctionBegin;
3621:   dummy = (void *)(*a + mstart);
3622:   PetscCall(PetscFree(dummy));
3623:   PetscCall(VecRestoreArrayRead(x, NULL));
3624:   PetscFunctionReturn(PETSC_SUCCESS);
3625: }

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

3632:    Logically Collective

3634:    Input Parameters:
3635: +  x - the vector
3636: .  m - first dimension of four dimensional array
3637: .  n - second dimension of four dimensional array
3638: .  p - third dimension of four dimensional array
3639: .  q - fourth dimension of four dimensional array
3640: .  mstart - first index you will use in first coordinate direction (often 0)
3641: .  nstart - first index in the second coordinate direction (often 0)
3642: .  pstart - first index in the third coordinate direction (often 0)
3643: -  qstart - first index in the fourth coordinate direction (often 0)

3645:    Output Parameter:
3646: .  a - location to put pointer to the array

3648:    Level: beginner

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

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

3658: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3659:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3660:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3661: @*/
3662: PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3663: {
3664:   PetscInt           i, N, j, k;
3665:   const PetscScalar *aa;
3666:   PetscScalar     ***b, **c;

3668:   PetscFunctionBegin;
3672:   PetscCall(VecGetLocalSize(x, &N));
3673:   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);
3674:   PetscCall(VecGetArrayRead(x, &aa));

3676:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3677:   b = (PetscScalar ***)((*a) + m);
3678:   c = (PetscScalar **)(b + m * n);
3679:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3680:   for (i = 0; i < m; i++)
3681:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3682:   for (i = 0; i < m; i++)
3683:     for (j = 0; j < n; j++)
3684:       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;
3685:   *a -= mstart;
3686:   PetscFunctionReturn(PETSC_SUCCESS);
3687: }

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

3692:    Logically Collective

3694:    Input Parameters:
3695: +  x - the vector
3696: .  m - first dimension of four dimensional array
3697: .  n - second dimension of the four dimensional array
3698: .  p - third dimension of the four dimensional array
3699: .  q - fourth dimension of the four dimensional array
3700: .  mstart - first index you will use in first coordinate direction (often 0)
3701: .  nstart - first index in the second coordinate direction (often 0)
3702: .  pstart - first index in the third coordinate direction (often 0)
3703: .  qstart - first index in the fourth coordinate direction (often 0)
3704: -  a - location of pointer to array obtained from `VecGetArray4dRead()`

3706:    Level: beginner

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

3714:    This routine actually zeros out the a pointer.

3716: .seealso: [](chapter_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3717:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3718:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3719: @*/
3720: PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3721: {
3722:   void *dummy;

3724:   PetscFunctionBegin;
3728:   dummy = (void *)(*a + mstart);
3729:   PetscCall(PetscFree(dummy));
3730:   PetscCall(VecRestoreArrayRead(x, NULL));
3731:   PetscFunctionReturn(PETSC_SUCCESS);
3732: }

3734: #if defined(PETSC_USE_DEBUG)

3736: /*@
3737:    VecLockGet  - Gets the current lock status of a vector

3739:    Logically Collective

3741:    Input Parameter:
3742: .  x - the vector

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

3748:    Level: beginner

3750: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
3751: @*/
3752: PetscErrorCode VecLockGet(Vec x, PetscInt *state)
3753: {
3754:   PetscFunctionBegin;
3756:   *state = x->lock;
3757:   PetscFunctionReturn(PETSC_SUCCESS);
3758: }

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

3771:     PetscCheck(index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Corrupted vec lock stack, have negative index %d", index);
3772:     *file = x->lockstack.file[index];
3773:     *func = x->lockstack.function[index];
3774:     *line = x->lockstack.line[index];
3775:   }
3776:   #else
3777:   *file = NULL;
3778:   *func = NULL;
3779:   *line = 0;
3780:   #endif
3781:   PetscFunctionReturn(PETSC_SUCCESS);
3782: }

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

3787:    Logically Collective

3789:    Input Parameter:
3790: .  x - the vector

3792:    Level: beginner

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

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

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

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

3830: /*@
3831:    VecLockReadPop  - Pops a read-only lock from a vector

3833:    Logically Collective

3835:    Input Parameter:
3836: .  x - the vector

3838:    Level: beginner

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

3851:     PetscStackPop_Private(x->lockstack, previous);
3852:   }
3853:   #endif
3854:   PetscFunctionReturn(PETSC_SUCCESS);
3855: }

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

3860:    Logically Collective

3862:    Input Parameters:
3863: +  x   - the vector
3864: -  flg - PETSC_TRUE to lock the vector for exclusive read/write access; PETSC_FALSE to unlock it.

3866:    Level: beginner

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

3874: .vb
3875:        VecGetArray(x,&xdata); // begin phase
3876:        VecLockWriteSet(v,PETSC_TRUE);

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

3880:        VecRestoreArray(x,&vdata); // end phase
3881:        VecLockWriteSet(v,PETSC_FALSE);
3882: .ve

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

3887: .seealso: [](chapter_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
3888: @*/
3889: PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
3890: {
3891:   PetscFunctionBegin;
3893:   if (flg) {
3894:     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");
3895:     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");
3896:     x->lock = -1;
3897:   } else {
3898:     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");
3899:     x->lock = 0;
3900:   }
3901:   PetscFunctionReturn(PETSC_SUCCESS);
3902: }

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

3907:    Level: deprecated

3909: .seealso: [](chapter_vectors), `Vec`, `VecLockReadPush()`
3910: @*/
3911: PetscErrorCode VecLockPush(Vec x)
3912: {
3913:   PetscFunctionBegin;
3914:   PetscCall(VecLockReadPush(x));
3915:   PetscFunctionReturn(PETSC_SUCCESS);
3916: }

3918: /*@
3919:    VecLockPop  - Pops a read-only lock from a vector

3921:    Level: deprecated

3923: .seealso: [](chapter_vectors), `Vec`, `VecLockReadPop()`
3924: @*/
3925: PetscErrorCode VecLockPop(Vec x)
3926: {
3927:   PetscFunctionBegin;
3928:   PetscCall(VecLockReadPop(x));
3929:   PetscFunctionReturn(PETSC_SUCCESS);
3930: }

3932: #endif