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/vecimpl.h>

  7: PetscInt VecGetSubVectorSavedStateId = -1;

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

 19:     PetscCall(VecGetOffloadMask(vec, &mask));
 20:     if (!PetscOffloadHost(mask)) PetscFunctionReturn(PETSC_SUCCESS);
 21:     PetscCall(VecGetLocalSize(vec, &n));
 22:     PetscCall(VecGetArrayRead(vec, &x));
 23:     for (PetscInt i = 0; i < n; i++) {
 24:       if (begin) {
 25:         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);
 26:       } else {
 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 end of function: Parameter number %" PetscInt_FMT, i, argnum);
 28:       }
 29:     }
 30:     PetscCall(VecRestoreArrayRead(vec, &x));
 31:   }
 32:   PetscFunctionReturn(PETSC_SUCCESS);
 33: }
 34: #endif

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

 39:   Logically Collective

 41:   Input Parameters:
 42: + x - the numerators
 43: - y - the denominators

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

 48:   Level: advanced

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

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

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

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

 80:   Collective

 82:   Input Parameters:
 83: + x - first vector
 84: - y - second vector

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

 89:   Level: intermediate

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

 98:   Use `VecTDot()` for the indefinite form
 99: $     val = (x,y) = y^T x,
100:   where y^T denotes the transpose of y.

102: .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDotRealPart()`
103: @*/
104: PetscErrorCode VecDot(Vec x, Vec y, PetscScalar *val)
105: {
106:   PetscFunctionBegin;
109:   PetscAssertPointer(val, 3);
112:   PetscCheckSameTypeAndComm(x, 1, y, 2);
113:   VecCheckSameSize(x, 1, y, 2);
114:   VecCheckAssembled(x);
115:   VecCheckAssembled(y);

117:   PetscCall(VecLockReadPush(x));
118:   PetscCall(VecLockReadPush(y));
119:   PetscCall(PetscLogEventBegin(VEC_Dot, x, y, 0, 0));
120:   PetscUseTypeMethod(x, dot, y, val);
121:   PetscCall(PetscLogEventEnd(VEC_Dot, x, y, 0, 0));
122:   PetscCall(VecLockReadPop(x));
123:   PetscCall(VecLockReadPop(y));
124:   PetscFunctionReturn(PETSC_SUCCESS);
125: }

127: /*@
128:   VecDotRealPart - Computes the real part of the vector dot product.

130:   Collective

132:   Input Parameters:
133: + x - first vector
134: - y - second vector

136:   Output Parameter:
137: . val - the real part of the dot product;

139:   Level: intermediate

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

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

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

149:   Developer Notes:
150:   This is not currently optimized to compute only the real part of the dot product.

152: .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDot()`, `VecDotNorm2()`
153: @*/
154: PetscErrorCode VecDotRealPart(Vec x, Vec y, PetscReal *val)
155: {
156:   PetscScalar fdot;

158:   PetscFunctionBegin;
159:   PetscCall(VecDot(x, y, &fdot));
160:   *val = PetscRealPart(fdot);
161:   PetscFunctionReturn(PETSC_SUCCESS);
162: }

164: /*@
165:   VecNorm  - Computes the vector norm.

167:   Collective

169:   Input Parameters:
170: + x    - the vector
171: - type - the type of the norm requested

173:   Output Parameter:
174: . val - the norm

176:   Level: intermediate

178:   Notes:
179:   See `NormType` for descriptions of each norm.

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

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

192: .seealso: [](ch_vectors), `Vec`, `NormType`, `VecDot()`, `VecTDot()`, `VecDotBegin()`, `VecDotEnd()`, `VecNormAvailable()`,
193:           `VecNormBegin()`, `VecNormEnd()`, `NormType()`
194: @*/
195: PetscErrorCode VecNorm(Vec x, NormType type, PetscReal *val)
196: {
197:   PetscBool flg = PETSC_TRUE;

199:   PetscFunctionBegin;
202:   VecCheckAssembled(x);
204:   PetscAssertPointer(val, 3);

206:   PetscCall(VecNormAvailable(x, type, &flg, val));
207:   // check that all MPI processes call this routine together and have same availability
208:   if (PetscDefined(USE_DEBUG)) {
209:     PetscMPIInt b0 = (PetscMPIInt)flg, b1[2], b2[2];
210:     b1[0]          = -b0;
211:     b1[1]          = b0;
212:     PetscCallMPI(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)x)));
213:     PetscCheck(-b2[0] == b2[1], PetscObjectComm((PetscObject)x), PETSC_ERR_ARG_WRONGSTATE, "Some MPI processes have cached %s norm, others do not. This may happen when some MPI processes call VecGetArray() and some others do not.", NormTypes[type]);
214:     if (flg) {
215:       PetscReal b1[2], b2[2];
216:       b1[0] = -(*val);
217:       b1[1] = *val;
218:       PetscCallMPI(MPIU_Allreduce(b1, b2, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)x)));
219:       PetscCheck((PetscIsNanReal(b2[0]) && PetscIsNanReal(b2[1])) || (-b2[0] == b2[1]), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Difference in cached %s norms: local %g", NormTypes[type], (double)*val);
220:     }
221:   }
222:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

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

230:   if (type != NORM_1_AND_2) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[type], *val));
231:   PetscFunctionReturn(PETSC_SUCCESS);
232: }

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

237:   Not Collective

239:   Input Parameters:
240: + x    - the vector
241: - 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
242:           `NORM_1_AND_2`, which computes both norms and stores them
243:           in a two element array.

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

249:   Level: intermediate

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

256: .seealso: [](ch_vectors), `Vec`, `VecDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`,
257:           `VecNormBegin()`, `VecNormEnd()`
258: @*/
259: PetscErrorCode VecNormAvailable(Vec x, NormType type, PetscBool *available, PetscReal *val)
260: {
261:   PetscFunctionBegin;
264:   PetscAssertPointer(available, 3);
265:   PetscAssertPointer(val, 4);

267:   if (type == NORM_1_AND_2) {
268:     *available = PETSC_FALSE;
269:   } else {
270:     PetscCall(PetscObjectComposedDataGetReal((PetscObject)x, NormIds[type], *val, *available));
271:   }
272:   PetscFunctionReturn(PETSC_SUCCESS);
273: }

275: /*@
276:   VecNormalize - Normalizes a vector by its 2-norm.

278:   Collective

280:   Input Parameter:
281: . x - the vector

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

286:   Level: intermediate

288: .seealso: [](ch_vectors), `Vec`, `VecNorm()`, `NORM_2`, `NormType`
289: @*/
290: PetscErrorCode VecNormalize(Vec x, PetscReal *val)
291: {
292:   PetscReal norm;

294:   PetscFunctionBegin;
297:   PetscCall(VecSetErrorIfLocked(x, 1));
298:   if (val) PetscAssertPointer(val, 2);
299:   PetscCall(PetscLogEventBegin(VEC_Normalize, x, 0, 0, 0));
300:   PetscCall(VecNorm(x, NORM_2, &norm));
301:   if (norm == 0.0) PetscCall(PetscInfo(x, "Vector of zero norm can not be normalized; Returning only the zero norm\n"));
302:   else if (PetscIsInfOrNanReal(norm)) PetscCall(PetscInfo(x, "Vector with Inf or Nan norm can not be normalized; Returning only the norm\n"));
303:   else {
304:     PetscScalar s = 1.0 / norm;
305:     PetscCall(VecScale(x, s));
306:   }
307:   PetscCall(PetscLogEventEnd(VEC_Normalize, x, 0, 0, 0));
308:   if (val) *val = norm;
309:   PetscFunctionReturn(PETSC_SUCCESS);
310: }

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

315:   Collective

317:   Input Parameter:
318: . x - the vector

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

324:   Level: intermediate

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

329:   Returns the smallest index with the maximum value

331:   Developer Note:
332:   The Nag Fortran compiler does not like the symbol name VecMax

334: .seealso: [](ch_vectors), `Vec`, `VecNorm()`, `VecMin()`
335: @*/
336: PetscErrorCode VecMax(Vec x, PetscInt *p, PetscReal *val)
337: {
338:   PetscFunctionBegin;
341:   VecCheckAssembled(x);
342:   if (p) PetscAssertPointer(p, 2);
343:   PetscAssertPointer(val, 3);
344:   PetscCall(VecLockReadPush(x));
345:   PetscCall(PetscLogEventBegin(VEC_Max, x, 0, 0, 0));
346:   PetscUseTypeMethod(x, max, p, val);
347:   PetscCall(PetscLogEventEnd(VEC_Max, x, 0, 0, 0));
348:   PetscCall(VecLockReadPop(x));
349:   PetscFunctionReturn(PETSC_SUCCESS);
350: }

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

355:   Collective

357:   Input Parameter:
358: . x - the vector

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

364:   Level: intermediate

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

369:   This returns the smallest index with the minimum value

371:   Developer Note:
372:   The Nag Fortran compiler does not like the symbol name VecMin

374: .seealso: [](ch_vectors), `Vec`, `VecMax()`
375: @*/
376: PetscErrorCode VecMin(Vec x, PetscInt *p, PetscReal *val)
377: {
378:   PetscFunctionBegin;
381:   VecCheckAssembled(x);
382:   if (p) PetscAssertPointer(p, 2);
383:   PetscAssertPointer(val, 3);
384:   PetscCall(VecLockReadPush(x));
385:   PetscCall(PetscLogEventBegin(VEC_Min, x, 0, 0, 0));
386:   PetscUseTypeMethod(x, min, p, val);
387:   PetscCall(PetscLogEventEnd(VEC_Min, x, 0, 0, 0));
388:   PetscCall(VecLockReadPop(x));
389:   PetscFunctionReturn(PETSC_SUCCESS);
390: }

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

396:   Collective

398:   Input Parameters:
399: + x - first vector
400: - y - second vector

402:   Output Parameter:
403: . val - the dot product

405:   Level: intermediate

407:   Notes for Users of Complex Numbers:
408:   For complex vectors, `VecTDot()` computes the indefinite form
409: $     val = (x,y) = y^T x,
410:   where y^T denotes the transpose of y.

412:   Use `VecDot()` for the inner product
413: $     val = (x,y) = y^H x,
414:   where y^H denotes the conjugate transpose of y.

416: .seealso: [](ch_vectors), `Vec`, `VecDot()`, `VecMTDot()`
417: @*/
418: PetscErrorCode VecTDot(Vec x, Vec y, PetscScalar *val)
419: {
420:   PetscFunctionBegin;
423:   PetscAssertPointer(val, 3);
426:   PetscCheckSameTypeAndComm(x, 1, y, 2);
427:   VecCheckSameSize(x, 1, y, 2);
428:   VecCheckAssembled(x);
429:   VecCheckAssembled(y);

431:   PetscCall(VecLockReadPush(x));
432:   PetscCall(VecLockReadPush(y));
433:   PetscCall(PetscLogEventBegin(VEC_TDot, x, y, 0, 0));
434:   PetscUseTypeMethod(x, tdot, y, val);
435:   PetscCall(PetscLogEventEnd(VEC_TDot, x, y, 0, 0));
436:   PetscCall(VecLockReadPop(x));
437:   PetscCall(VecLockReadPop(y));
438:   PetscFunctionReturn(PETSC_SUCCESS);
439: }

441: PetscErrorCode VecScaleAsync_Private(Vec x, PetscScalar alpha, PetscDeviceContext dctx)
442: {
443:   PetscReal   norms[4];
444:   PetscBool   flgs[4];
445:   PetscScalar one = 1.0;

447:   PetscFunctionBegin;
450:   VecCheckAssembled(x);
451:   PetscCall(VecSetErrorIfLocked(x, 1));
453:   if (alpha == one) PetscFunctionReturn(PETSC_SUCCESS);

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

458:   PetscCall(PetscLogEventBegin(VEC_Scale, x, 0, 0, 0));
459:   VecMethodDispatch(x, dctx, VecAsyncFnName(Scale), scale, (Vec, PetscScalar, PetscDeviceContext), alpha);
460:   PetscCall(PetscLogEventEnd(VEC_Scale, x, 0, 0, 0));

462:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
463:   /* put the scaled stashed norms back into the Vec */
464:   for (PetscInt i = 0; i < 4; i++) {
465:     PetscReal ar = PetscAbsScalar(alpha);
466:     if (flgs[i]) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[i], ar * norms[i]));
467:   }
468:   PetscFunctionReturn(PETSC_SUCCESS);
469: }

471: /*@
472:   VecScale - Scales a vector.

474:   Logically Collective

476:   Input Parameters:
477: + x     - the vector
478: - alpha - the scalar

480:   Level: intermediate

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

485: .seealso: [](ch_vectors), `Vec`, `VecSet()`
486: @*/
487: PetscErrorCode VecScale(Vec x, PetscScalar alpha)
488: {
489:   PetscFunctionBegin;
490:   PetscCall(VecScaleAsync_Private(x, alpha, NULL));
491:   PetscFunctionReturn(PETSC_SUCCESS);
492: }

494: PetscErrorCode VecSetAsync_Private(Vec x, PetscScalar alpha, PetscDeviceContext dctx)
495: {
496:   PetscFunctionBegin;
499:   VecCheckAssembled(x);
501:   PetscCall(VecSetErrorIfLocked(x, 1));

503:   if (alpha == 0) {
504:     PetscReal norm;
505:     PetscBool set;

507:     PetscCall(VecNormAvailable(x, NORM_2, &set, &norm));
508:     if (set == PETSC_TRUE && norm == 0) PetscFunctionReturn(PETSC_SUCCESS);
509:   }
510:   PetscCall(PetscLogEventBegin(VEC_Set, x, 0, 0, 0));
511:   VecMethodDispatch(x, dctx, VecAsyncFnName(Set), set, (Vec, PetscScalar, PetscDeviceContext), alpha);
512:   PetscCall(PetscLogEventEnd(VEC_Set, x, 0, 0, 0));
513:   PetscCall(PetscObjectStateIncrease((PetscObject)x));

515:   /*  norms can be simply set (if |alpha|*N not too large) */
516:   {
517:     PetscReal      val = PetscAbsScalar(alpha);
518:     const PetscInt N   = x->map->N;

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

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

541:   Logically Collective

543:   Input Parameters:
544: + x     - the vector
545: - alpha - the scalar

547:   Level: beginner

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

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

558:   If `alpha` is zero and the norm of the vector is known to be zero then this skips the unneeded zeroing process

560: .seealso: [](ch_vectors), `Vec`, `VecSetValues()`, `VecSetValuesBlocked()`, `VecSetRandom()`
561: @*/
562: PetscErrorCode VecSet(Vec x, PetscScalar alpha)
563: {
564:   PetscFunctionBegin;
565:   PetscCall(VecSetAsync_Private(x, alpha, NULL));
566:   PetscFunctionReturn(PETSC_SUCCESS);
567: }

569: PetscErrorCode VecAXPYAsync_Private(Vec y, PetscScalar alpha, Vec x, PetscDeviceContext dctx)
570: {
571:   PetscFunctionBegin;
576:   PetscCheckSameTypeAndComm(x, 3, y, 1);
577:   VecCheckSameSize(x, 3, y, 1);
578:   VecCheckAssembled(x);
579:   VecCheckAssembled(y);
581:   if (alpha == (PetscScalar)0.0) PetscFunctionReturn(PETSC_SUCCESS);
582:   PetscCall(VecSetErrorIfLocked(y, 1));
583:   if (x == y) {
584:     PetscCall(VecScale(y, alpha + 1.0));
585:     PetscFunctionReturn(PETSC_SUCCESS);
586:   }
587:   PetscCall(VecLockReadPush(x));
588:   PetscCall(PetscLogEventBegin(VEC_AXPY, x, y, 0, 0));
589:   VecMethodDispatch(y, dctx, VecAsyncFnName(AXPY), axpy, (Vec, PetscScalar, Vec, PetscDeviceContext), alpha, x);
590:   PetscCall(PetscLogEventEnd(VEC_AXPY, x, y, 0, 0));
591:   PetscCall(VecLockReadPop(x));
592:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
593:   PetscFunctionReturn(PETSC_SUCCESS);
594: }
595: /*@
596:   VecAXPY - Computes `y = alpha x + y`.

598:   Logically Collective

600:   Input Parameters:
601: + alpha - the scalar
602: . x     - vector scale by `alpha`
603: - y     - vector accumulated into

605:   Output Parameter:
606: . y - output vector

608:   Level: intermediate

610:   Notes:
611:   This routine is optimized for alpha of 0.0, otherwise it calls the BLAS routine
612: .vb
613:     VecAXPY(y,alpha,x)                   y = alpha x           +      y
614:     VecAYPX(y,beta,x)                    y =       x           + beta y
615:     VecAXPBY(y,alpha,beta,x)             y = alpha x           + beta y
616:     VecWAXPY(w,alpha,x,y)                w = alpha x           +      y
617:     VecAXPBYPCZ(z,alpha,beta,gamma,x,y)  z = alpha x           + beta y + gamma z
618:     VecMAXPY(y,nv,alpha[],x[])           y = sum alpha[i] x[i] +      y
619: .ve

621: .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
622: @*/
623: PetscErrorCode VecAXPY(Vec y, PetscScalar alpha, Vec x)
624: {
625:   PetscFunctionBegin;
626:   PetscCall(VecAXPYAsync_Private(y, alpha, x, NULL));
627:   PetscFunctionReturn(PETSC_SUCCESS);
628: }

630: PetscErrorCode VecAYPXAsync_Private(Vec y, PetscScalar beta, Vec x, PetscDeviceContext dctx)
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:     VecMethodDispatch(y, dctx, VecAsyncFnName(AYPX), aypx, (Vec, PetscScalar, Vec, PetscDeviceContext), 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:   VecAYPX - Computes `y = x + beta y`.

663:   Logically Collective

665:   Input Parameters:
666: + beta - the scalar
667: . x    - the unscaled vector
668: - y    - the vector to be scaled

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

673:   Level: intermediate

675:   Developer Notes:
676:   The implementation is optimized for `beta` of -1.0, 0.0, and 1.0

678: .seealso: [](ch_vectors), `Vec`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
679: @*/
680: PetscErrorCode VecAYPX(Vec y, PetscScalar beta, Vec x)
681: {
682:   PetscFunctionBegin;
683:   PetscCall(VecAYPXAsync_Private(y, beta, x, NULL));
684:   PetscFunctionReturn(PETSC_SUCCESS);
685: }

687: PetscErrorCode VecAXPBYAsync_Private(Vec y, PetscScalar alpha, PetscScalar beta, Vec x, PetscDeviceContext dctx)
688: {
689:   PetscFunctionBegin;
694:   PetscCheckSameTypeAndComm(x, 4, y, 1);
695:   VecCheckSameSize(y, 1, x, 4);
696:   VecCheckAssembled(x);
697:   VecCheckAssembled(y);
700:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);
701:   if (x == y) {
702:     PetscCall(VecScale(y, alpha + beta));
703:     PetscFunctionReturn(PETSC_SUCCESS);
704:   }

706:   PetscCall(VecSetErrorIfLocked(y, 1));
707:   PetscCall(VecLockReadPush(x));
708:   PetscCall(PetscLogEventBegin(VEC_AXPY, y, x, 0, 0));
709:   VecMethodDispatch(y, dctx, VecAsyncFnName(AXPBY), axpby, (Vec, PetscScalar, PetscScalar, Vec, PetscDeviceContext), alpha, beta, x);
710:   PetscCall(PetscLogEventEnd(VEC_AXPY, y, x, 0, 0));
711:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
712:   PetscCall(VecLockReadPop(x));
713:   PetscFunctionReturn(PETSC_SUCCESS);
714: }

716: /*@
717:   VecAXPBY - Computes `y = alpha x + beta y`.

719:   Logically Collective

721:   Input Parameters:
722: + alpha - first scalar
723: . beta  - second scalar
724: . x     - the first scaled vector
725: - y     - the second scaled vector

727:   Output Parameter:
728: . y - output vector

730:   Level: intermediate

732:   Developer Notes:
733:   The implementation is optimized for `alpha` and/or `beta` values of 0.0 and 1.0

735: .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`
736: @*/
737: PetscErrorCode VecAXPBY(Vec y, PetscScalar alpha, PetscScalar beta, Vec x)
738: {
739:   PetscFunctionBegin;
740:   PetscCall(VecAXPBYAsync_Private(y, alpha, beta, x, NULL));
741:   PetscFunctionReturn(PETSC_SUCCESS);
742: }

744: PetscErrorCode VecAXPBYPCZAsync_Private(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y, PetscDeviceContext dctx)
745: {
746:   PetscFunctionBegin;
753:   PetscCheckSameTypeAndComm(x, 5, y, 6);
754:   PetscCheckSameTypeAndComm(x, 5, z, 1);
755:   VecCheckSameSize(x, 5, y, 6);
756:   VecCheckSameSize(x, 5, z, 1);
757:   PetscCheck(x != y && x != z, PetscObjectComm((PetscObject)x), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
758:   PetscCheck(y != z, PetscObjectComm((PetscObject)y), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
759:   VecCheckAssembled(x);
760:   VecCheckAssembled(y);
761:   VecCheckAssembled(z);
765:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);

767:   PetscCall(VecSetErrorIfLocked(z, 1));
768:   PetscCall(VecLockReadPush(x));
769:   PetscCall(VecLockReadPush(y));
770:   PetscCall(PetscLogEventBegin(VEC_AXPBYPCZ, x, y, z, 0));
771:   VecMethodDispatch(z, dctx, VecAsyncFnName(AXPBYPCZ), axpbypcz, (Vec, PetscScalar, PetscScalar, PetscScalar, Vec, Vec, PetscDeviceContext), alpha, beta, gamma, x, y);
772:   PetscCall(PetscLogEventEnd(VEC_AXPBYPCZ, x, y, z, 0));
773:   PetscCall(PetscObjectStateIncrease((PetscObject)z));
774:   PetscCall(VecLockReadPop(x));
775:   PetscCall(VecLockReadPop(y));
776:   PetscFunctionReturn(PETSC_SUCCESS);
777: }
778: /*@
779:   VecAXPBYPCZ - Computes `z = alpha x + beta y + gamma z`

781:   Logically Collective

783:   Input Parameters:
784: + alpha - first scalar
785: . beta  - second scalar
786: . gamma - third scalar
787: . x     - first vector
788: . y     - second vector
789: - z     - third vector

791:   Output Parameter:
792: . z - output vector

794:   Level: intermediate

796:   Note:
797:   `x`, `y` and `z` must be different vectors

799:   Developer Notes:
800:   The implementation is optimized for `alpha` of 1.0 and `gamma` of 1.0 or 0.0

802: .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBY()`
803: @*/
804: PetscErrorCode VecAXPBYPCZ(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y)
805: {
806:   PetscFunctionBegin;
807:   PetscCall(VecAXPBYPCZAsync_Private(z, alpha, beta, gamma, x, y, NULL));
808:   PetscFunctionReturn(PETSC_SUCCESS);
809: }

811: PetscErrorCode VecWAXPYAsync_Private(Vec w, PetscScalar alpha, Vec x, Vec y, PetscDeviceContext dctx)
812: {
813:   PetscFunctionBegin;
820:   PetscCheckSameTypeAndComm(x, 3, y, 4);
821:   PetscCheckSameTypeAndComm(y, 4, w, 1);
822:   VecCheckSameSize(x, 3, y, 4);
823:   VecCheckSameSize(x, 3, w, 1);
824:   PetscCheck(w != y, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector y, suggest VecAXPY()");
825:   PetscCheck(w != x, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector x, suggest VecAYPX()");
826:   VecCheckAssembled(x);
827:   VecCheckAssembled(y);
829:   PetscCall(VecSetErrorIfLocked(w, 1));

831:   PetscCall(VecLockReadPush(x));
832:   PetscCall(VecLockReadPush(y));
833:   if (alpha == (PetscScalar)0.0) {
834:     PetscCall(VecCopyAsync_Private(y, w, dctx));
835:   } else {
836:     PetscCall(PetscLogEventBegin(VEC_WAXPY, x, y, w, 0));
837:     VecMethodDispatch(w, dctx, VecAsyncFnName(WAXPY), waxpy, (Vec, PetscScalar, Vec, Vec, PetscDeviceContext), alpha, x, y);
838:     PetscCall(PetscLogEventEnd(VEC_WAXPY, x, y, w, 0));
839:     PetscCall(PetscObjectStateIncrease((PetscObject)w));
840:   }
841:   PetscCall(VecLockReadPop(x));
842:   PetscCall(VecLockReadPop(y));
843:   PetscFunctionReturn(PETSC_SUCCESS);
844: }

846: /*@
847:   VecWAXPY - Computes `w = alpha x + y`.

849:   Logically Collective

851:   Input Parameters:
852: + alpha - the scalar
853: . x     - first vector, multiplied by `alpha`
854: - y     - second vector

856:   Output Parameter:
857: . w - the result

859:   Level: intermediate

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

864:   Developer Notes:
865:   The implementation is optimized for alpha of -1.0, 0.0, and 1.0

867: .seealso: [](ch_vectors), `Vec`, `VecAXPY()`, `VecAYPX()`, `VecAXPBY()`, `VecMAXPY()`, `VecAXPBYPCZ()`
868: @*/
869: PetscErrorCode VecWAXPY(Vec w, PetscScalar alpha, Vec x, Vec y)
870: {
871:   PetscFunctionBegin;
872:   PetscCall(VecWAXPYAsync_Private(w, alpha, x, y, NULL));
873:   PetscFunctionReturn(PETSC_SUCCESS);
874: }

876: /*@
877:   VecSetValues - Inserts or adds values into certain locations of a vector.

879:   Not Collective

881:   Input Parameters:
882: + x    - vector to insert in
883: . ni   - number of elements to add
884: . ix   - indices where to add
885: . y    - array of values
886: - iora - either `INSERT_VALUES` to replace the current values or `ADD_VALUES` to add values to any existing entries

888:   Level: beginner

890:   Notes:
891: .vb
892:    `VecSetValues()` sets x[ix[i]] = y[i], for i=0,...,ni-1.
893: .ve

895:   Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
896:   options cannot be mixed without intervening calls to the assembly
897:   routines.

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

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

904:   If you call `VecSetOption`(x, `VEC_IGNORE_NEGATIVE_INDICES`,`PETSC_TRUE`),
905:   negative indices may be passed in ix. These rows are
906:   simply ignored. This allows easily inserting element load matrices
907:   with homogeneous Dirichlet boundary conditions that you don't want represented
908:   in the vector.

910:   Fortran Note:
911:   If any of `ix` and `y` are scalars pass them using, for example,
912: .vb
913:   VecSetValues(mat, one, [ix], [y], INSERT_VALUES)
914: .ve

916: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesLocal()`,
917:           `VecSetValue()`, `VecSetValuesBlocked()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `VecGetValues()`
918: @*/
919: PetscErrorCode VecSetValues(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
920: {
921:   PetscFunctionBeginHot;
923:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
924:   PetscAssertPointer(ix, 3);
925:   PetscAssertPointer(y, 4);

928:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
929:   PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
930:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
931:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
932:   PetscFunctionReturn(PETSC_SUCCESS);
933: }

935: /*@
936:   VecGetValues - Gets values from certain locations of a vector. Currently
937:   can only get values on the same processor on which they are owned

939:   Not Collective

941:   Input Parameters:
942: + x  - vector to get values from
943: . ni - number of elements to get
944: - ix - indices where to get them from (in global 1d numbering)

946:   Output Parameter:
947: . y - array of values, must be passed in with a length of `ni`

949:   Level: beginner

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

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

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

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

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

964: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`
965: @*/
966: PetscErrorCode VecGetValues(Vec x, PetscInt ni, const PetscInt ix[], PetscScalar y[])
967: {
968:   PetscFunctionBegin;
970:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
971:   PetscAssertPointer(ix, 3);
972:   PetscAssertPointer(y, 4);
974:   VecCheckAssembled(x);
975:   PetscUseTypeMethod(x, getvalues, ni, ix, y);
976:   PetscFunctionReturn(PETSC_SUCCESS);
977: }

979: /*@
980:   VecSetValuesBlocked - Inserts or adds blocks of values into certain locations of a vector.

982:   Not Collective

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

991:   Level: intermediate

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

997:   Calls to `VecSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
998:   options cannot be mixed without intervening calls to the assembly
999:   routines.

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

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

1006:   Negative indices may be passed in ix, these rows are
1007:   simply ignored. This allows easily inserting element load matrices
1008:   with homogeneous Dirichlet boundary conditions that you don't want represented
1009:   in the vector.

1011:   Fortran Note:
1012:   If any of `ix` and `y` are scalars pass them using, for example,
1013: .vb
1014:   VecSetValuesBlocked(mat, one, [ix], [y], INSERT_VALUES)
1015: .ve

1017: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesBlockedLocal()`,
1018:           `VecSetValues()`
1019: @*/
1020: PetscErrorCode VecSetValuesBlocked(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1021: {
1022:   PetscFunctionBeginHot;
1024:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1025:   PetscAssertPointer(ix, 3);
1026:   PetscAssertPointer(y, 4);

1029:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1030:   PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1031:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1032:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1033:   PetscFunctionReturn(PETSC_SUCCESS);
1034: }

1036: /*@
1037:   VecSetValuesLocal - Inserts or adds values into certain locations of a vector,
1038:   using a local ordering of the nodes.

1040:   Not Collective

1042:   Input Parameters:
1043: + x    - vector to insert in
1044: . ni   - number of elements to add
1045: . ix   - indices where to add
1046: . y    - array of values
1047: - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries

1049:   Level: intermediate

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

1054:   Calls to `VecSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1055:   options cannot be mixed without intervening calls to the assembly
1056:   routines.

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

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

1063:   Fortran Note:
1064:   If any of `ix` and `y` are scalars pass them using, for example,
1065: .vb
1066:   VecSetValuesLocal(mat, one, [ix], [y], INSERT_VALUES)
1067: .ve

1069: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetLocalToGlobalMapping()`,
1070:           `VecSetValuesBlockedLocal()`
1071: @*/
1072: PetscErrorCode VecSetValuesLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1073: {
1074:   PetscInt lixp[128], *lix = lixp;

1076:   PetscFunctionBeginHot;
1078:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1079:   PetscAssertPointer(ix, 3);
1080:   PetscAssertPointer(y, 4);

1083:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1084:   if (!x->ops->setvalueslocal) {
1085:     if (PetscUnlikely(!x->map->mapping && x->ops->getlocaltoglobalmapping)) PetscUseTypeMethod(x, getlocaltoglobalmapping, &x->map->mapping);
1086:     if (x->map->mapping) {
1087:       if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1088:       PetscCall(ISLocalToGlobalMappingApply(x->map->mapping, ni, (PetscInt *)ix, lix));
1089:       PetscUseTypeMethod(x, setvalues, ni, lix, y, iora);
1090:       if (ni > 128) PetscCall(PetscFree(lix));
1091:     } else PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
1092:   } else PetscUseTypeMethod(x, setvalueslocal, ni, ix, y, iora);
1093:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1094:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1095:   PetscFunctionReturn(PETSC_SUCCESS);
1096: }

1098: /*@
1099:   VecSetValuesBlockedLocal - Inserts or adds values into certain locations of a vector,
1100:   using a local ordering of the nodes.

1102:   Not Collective

1104:   Input Parameters:
1105: + x    - vector to insert in
1106: . ni   - number of blocks to add
1107: . ix   - indices where to add in block count, not element count
1108: . y    - array of values
1109: - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries

1111:   Level: intermediate

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

1117:   Calls to `VecSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1118:   options cannot be mixed without intervening calls to the assembly
1119:   routines.

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

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

1126:   Fortran Note:
1127:   If any of `ix` and `y` are scalars pass them using, for example,
1128: .vb
1129:   VecSetValuesBlockedLocal(mat, one, [ix], [y], INSERT_VALUES)
1130: .ve

1132: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetValuesBlocked()`,
1133:           `VecSetLocalToGlobalMapping()`
1134: @*/
1135: PetscErrorCode VecSetValuesBlockedLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1136: {
1137:   PetscInt lixp[128], *lix = lixp;

1139:   PetscFunctionBeginHot;
1141:   if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1142:   PetscAssertPointer(ix, 3);
1143:   PetscAssertPointer(y, 4);
1145:   PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1146:   if (PetscUnlikely(!x->map->mapping && x->ops->getlocaltoglobalmapping)) PetscUseTypeMethod(x, getlocaltoglobalmapping, &x->map->mapping);
1147:   if (x->map->mapping) {
1148:     if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1149:     PetscCall(ISLocalToGlobalMappingApplyBlock(x->map->mapping, ni, (PetscInt *)ix, lix));
1150:     PetscUseTypeMethod(x, setvaluesblocked, ni, lix, y, iora);
1151:     if (ni > 128) PetscCall(PetscFree(lix));
1152:   } else {
1153:     PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1154:   }
1155:   PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1156:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
1157:   PetscFunctionReturn(PETSC_SUCCESS);
1158: }

1160: static PetscErrorCode VecMXDot_Private(Vec x, PetscInt nv, const Vec y[], PetscScalar result[], PetscErrorCode (*mxdot)(Vec, PetscInt, const Vec[], PetscScalar[]), PetscLogEvent event)
1161: {
1162:   PetscFunctionBegin;
1165:   VecCheckAssembled(x);
1167:   if (!nv) PetscFunctionReturn(PETSC_SUCCESS);
1168:   PetscAssertPointer(y, 3);
1169:   for (PetscInt i = 0; i < nv; ++i) {
1172:     PetscCheckSameTypeAndComm(x, 1, y[i], 3);
1173:     VecCheckSameSize(x, 1, y[i], 3);
1174:     VecCheckAssembled(y[i]);
1175:     PetscCall(VecLockReadPush(y[i]));
1176:   }
1177:   PetscAssertPointer(result, 4);

1180:   PetscCall(VecLockReadPush(x));
1181:   PetscCall(PetscLogEventBegin(event, x, *y, 0, 0));
1182:   PetscCall((*mxdot)(x, nv, y, result));
1183:   PetscCall(PetscLogEventEnd(event, x, *y, 0, 0));
1184:   PetscCall(VecLockReadPop(x));
1185:   for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(y[i]));
1186:   PetscFunctionReturn(PETSC_SUCCESS);
1187: }

1189: /*@
1190:   VecMTDot - Computes indefinite vector multiple dot products.
1191:   That is, it does NOT use the complex conjugate.

1193:   Collective

1195:   Input Parameters:
1196: + x  - one vector
1197: . nv - number of vectors
1198: - y  - array of vectors.  Note that vectors are pointers

1200:   Output Parameter:
1201: . val - array of the dot products

1203:   Level: intermediate

1205:   Notes for Users of Complex Numbers:
1206:   For complex vectors, `VecMTDot()` computes the indefinite form
1207: $      val = (x,y) = y^T x,
1208:   where y^T denotes the transpose of y.

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

1214: .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`
1215: @*/
1216: PetscErrorCode VecMTDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1217: {
1218:   PetscFunctionBegin;
1220:   PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mtdot, VEC_MTDot));
1221:   PetscFunctionReturn(PETSC_SUCCESS);
1222: }

1224: /*@
1225:   VecMDot - Computes multiple vector dot products.

1227:   Collective

1229:   Input Parameters:
1230: + x  - one vector
1231: . nv - number of vectors
1232: - y  - array of vectors.

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

1237:   Level: intermediate

1239:   Notes for Users of Complex Numbers:
1240:   For complex vectors, `VecMDot()` computes
1241: $     val = (x,y) = y^H x,
1242:   where y^H denotes the conjugate transpose of y.

1244:   Use `VecMTDot()` for the indefinite form
1245: $     val = (x,y) = y^T x,
1246:   where y^T denotes the transpose of y.

1248: .seealso: [](ch_vectors), `Vec`, `VecMTDot()`, `VecDot()`
1249: @*/
1250: PetscErrorCode VecMDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1251: {
1252:   PetscFunctionBegin;
1254:   PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mdot, VEC_MDot));
1255:   PetscFunctionReturn(PETSC_SUCCESS);
1256: }

1258: PetscErrorCode VecMAXPYAsync_Private(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[], PetscDeviceContext dctx)
1259: {
1260:   PetscFunctionBegin;
1262:   VecCheckAssembled(y);
1264:   PetscCall(VecSetErrorIfLocked(y, 1));
1265:   PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);
1266:   if (nv) {
1267:     PetscInt zeros = 0;

1269:     PetscAssertPointer(alpha, 3);
1270:     PetscAssertPointer(x, 4);
1271:     for (PetscInt i = 0; i < nv; ++i) {
1275:       PetscCheckSameTypeAndComm(y, 1, x[i], 4);
1276:       VecCheckSameSize(y, 1, x[i], 4);
1277:       PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1278:       VecCheckAssembled(x[i]);
1279:       PetscCall(VecLockReadPush(x[i]));
1280:       zeros += alpha[i] == (PetscScalar)0.0;
1281:     }

1283:     if (zeros < nv) {
1284:       PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1285:       VecMethodDispatch(y, dctx, VecAsyncFnName(MAXPY), maxpy, (Vec, PetscInt, const PetscScalar[], Vec[], PetscDeviceContext), nv, alpha, x);
1286:       PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1287:       PetscCall(PetscObjectStateIncrease((PetscObject)y));
1288:     }

1290:     for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1291:   }
1292:   PetscFunctionReturn(PETSC_SUCCESS);
1293: }

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

1298:   Logically Collective

1300:   Input Parameters:
1301: + nv    - number of scalars and x-vectors
1302: . alpha - array of scalars
1303: . y     - one vector
1304: - x     - array of vectors

1306:   Level: intermediate

1308:   Note:
1309:   `y` cannot be any of the `x` vectors

1311: .seealso: [](ch_vectors), `Vec`, `VecMAXPBY()`,`VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
1312: @*/
1313: PetscErrorCode VecMAXPY(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[])
1314: {
1315:   PetscFunctionBegin;
1316:   PetscCall(VecMAXPYAsync_Private(y, nv, alpha, x, NULL));
1317:   PetscFunctionReturn(PETSC_SUCCESS);
1318: }

1320: /*@
1321:   VecMAXPBY - Computes `y = beta y + sum alpha[i] x[i]`

1323:   Logically Collective

1325:   Input Parameters:
1326: + nv    - number of scalars and x-vectors
1327: . alpha - array of scalars
1328: . beta  - scalar
1329: . y     - one vector
1330: - x     - array of vectors

1332:   Level: intermediate

1334:   Note:
1335:   `y` cannot be any of the `x` vectors.

1337:   Developer Notes:
1338:   This is a convenience routine, but implementations might be able to optimize it, for example, when `beta` is zero.

1340: .seealso: [](ch_vectors), `Vec`, `VecMAXPY()`, `VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
1341: @*/
1342: PetscErrorCode VecMAXPBY(Vec y, PetscInt nv, const PetscScalar alpha[], PetscScalar beta, Vec x[])
1343: {
1344:   PetscFunctionBegin;
1346:   VecCheckAssembled(y);
1348:   PetscCall(VecSetErrorIfLocked(y, 1));
1349:   PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);

1352:   if (y->ops->maxpby) {
1353:     PetscInt zeros = 0;

1355:     if (nv) {
1356:       PetscAssertPointer(alpha, 3);
1357:       PetscAssertPointer(x, 5);
1358:     }

1360:     for (PetscInt i = 0; i < nv; ++i) { // scan all alpha[]
1364:       PetscCheckSameTypeAndComm(y, 1, x[i], 5);
1365:       VecCheckSameSize(y, 1, x[i], 5);
1366:       PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1367:       VecCheckAssembled(x[i]);
1368:       PetscCall(VecLockReadPush(x[i]));
1369:       zeros += alpha[i] == (PetscScalar)0.0;
1370:     }

1372:     if (zeros < nv) { // has nonzero alpha
1373:       PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1374:       PetscUseTypeMethod(y, maxpby, nv, alpha, beta, x);
1375:       PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1376:       PetscCall(PetscObjectStateIncrease((PetscObject)y));
1377:     } else {
1378:       PetscCall(VecScale(y, beta));
1379:     }

1381:     for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1382:   } else { // no maxpby
1383:     if (beta == 0.0) PetscCall(VecSet(y, 0.0));
1384:     else PetscCall(VecScale(y, beta));
1385:     PetscCall(VecMAXPY(y, nv, alpha, x));
1386:   }
1387:   PetscFunctionReturn(PETSC_SUCCESS);
1388: }

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

1395:   Collective

1397:   Input Parameters:
1398: + nx - number of vectors to be concatenated
1399: - X  - array containing the vectors to be concatenated in the order of concatenation

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

1405:   Level: advanced

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

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

1417: .seealso: [](ch_vectors), `Vec`, `VECNEST`, `VECSCATTER`, `VecScatterCreate()`
1418: @*/
1419: PetscErrorCode VecConcatenate(PetscInt nx, const Vec X[], Vec *Y, IS *x_is[])
1420: {
1421:   MPI_Comm comm;
1422:   VecType  vec_type;
1423:   Vec      Ytmp, Xtmp;
1424:   IS      *is_tmp;
1425:   PetscInt i, shift = 0, Xnl, Xng, Xbegin;

1427:   PetscFunctionBegin;
1431:   PetscAssertPointer(Y, 3);

1433:   if ((*X)->ops->concatenate) {
1434:     /* use the dedicated concatenation function if available */
1435:     PetscCall((*(*X)->ops->concatenate)(nx, X, Y, x_is));
1436:   } else {
1437:     /* loop over vectors and start creating IS */
1438:     comm = PetscObjectComm((PetscObject)*X);
1439:     PetscCall(VecGetType(*X, &vec_type));
1440:     PetscCall(PetscMalloc1(nx, &is_tmp));
1441:     for (i = 0; i < nx; i++) {
1442:       PetscCall(VecGetSize(X[i], &Xng));
1443:       PetscCall(VecGetLocalSize(X[i], &Xnl));
1444:       PetscCall(VecGetOwnershipRange(X[i], &Xbegin, NULL));
1445:       PetscCall(ISCreateStride(comm, Xnl, shift + Xbegin, 1, &is_tmp[i]));
1446:       shift += Xng;
1447:     }
1448:     /* create the concatenated vector */
1449:     PetscCall(VecCreate(comm, &Ytmp));
1450:     PetscCall(VecSetType(Ytmp, vec_type));
1451:     PetscCall(VecSetSizes(Ytmp, PETSC_DECIDE, shift));
1452:     PetscCall(VecSetUp(Ytmp));
1453:     /* copy data from X array to Y and return */
1454:     for (i = 0; i < nx; i++) {
1455:       PetscCall(VecGetSubVector(Ytmp, is_tmp[i], &Xtmp));
1456:       PetscCall(VecCopy(X[i], Xtmp));
1457:       PetscCall(VecRestoreSubVector(Ytmp, is_tmp[i], &Xtmp));
1458:     }
1459:     *Y = Ytmp;
1460:     if (x_is) {
1461:       *x_is = is_tmp;
1462:     } else {
1463:       for (i = 0; i < nx; i++) PetscCall(ISDestroy(&is_tmp[i]));
1464:       PetscCall(PetscFree(is_tmp));
1465:     }
1466:   }
1467:   PetscFunctionReturn(PETSC_SUCCESS);
1468: }

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

1473:     Input Parameters:
1474: +   X - the original vector
1475: -   is - the index set of the subvector

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

1482: */
1483: PetscErrorCode VecGetSubVectorContiguityAndBS_Private(Vec X, IS is, PetscBool *contig, PetscInt *start, PetscInt *blocksize)
1484: {
1485:   PetscInt  gstart, gend, lstart;
1486:   PetscBool red[2] = {PETSC_TRUE /*contiguous*/, PETSC_TRUE /*validVBS*/};
1487:   PetscInt  n, N, ibs, vbs, bs = -1;

1489:   PetscFunctionBegin;
1490:   PetscCall(ISGetLocalSize(is, &n));
1491:   PetscCall(ISGetSize(is, &N));
1492:   PetscCall(ISGetBlockSize(is, &ibs));
1493:   PetscCall(VecGetBlockSize(X, &vbs));
1494:   PetscCall(VecGetOwnershipRange(X, &gstart, &gend));
1495:   PetscCall(ISContiguousLocal(is, gstart, gend, &lstart, &red[0]));
1496:   /* block size is given by IS if ibs > 1; otherwise, check the vector */
1497:   if (ibs > 1) {
1498:     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, red, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1499:     bs = ibs;
1500:   } else {
1501:     if (n % vbs || vbs == 1) red[1] = PETSC_FALSE; /* this process invalidate the collectiveness of block size */
1502:     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, red, 2, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1503:     if (red[0] && red[1]) bs = vbs; /* all processes have a valid block size and the access will be contiguous */
1504:   }

1506:   *contig    = red[0];
1507:   *start     = lstart;
1508:   *blocksize = bs;
1509:   PetscFunctionReturn(PETSC_SUCCESS);
1510: }

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

1514:     Input Parameters:
1515: +   X - the original vector
1516: .   is - the index set of the subvector
1517: -   bs - the block size of the subvector, gotten from VecGetSubVectorContiguityAndBS_Private()

1519:     Output Parameter:
1520: .   Z  - the subvector, which will compose the VecScatter context on output
1521: */
1522: PetscErrorCode VecGetSubVectorThroughVecScatter_Private(Vec X, IS is, PetscInt bs, Vec *Z)
1523: {
1524:   PetscInt   n, N;
1525:   VecScatter vscat;
1526:   Vec        Y;

1528:   PetscFunctionBegin;
1529:   PetscCall(ISGetLocalSize(is, &n));
1530:   PetscCall(ISGetSize(is, &N));
1531:   PetscCall(VecCreate(PetscObjectComm((PetscObject)is), &Y));
1532:   PetscCall(VecSetSizes(Y, n, N));
1533:   PetscCall(VecSetBlockSize(Y, bs));
1534:   PetscCall(VecSetType(Y, ((PetscObject)X)->type_name));
1535:   PetscCall(VecScatterCreate(X, is, Y, NULL, &vscat));
1536:   PetscCall(VecScatterBegin(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1537:   PetscCall(VecScatterEnd(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1538:   PetscCall(PetscObjectCompose((PetscObject)Y, "VecGetSubVector_Scatter", (PetscObject)vscat));
1539:   PetscCall(VecScatterDestroy(&vscat));
1540:   *Z = Y;
1541:   PetscFunctionReturn(PETSC_SUCCESS);
1542: }

1544: /*@
1545:   VecGetSubVector - Gets a vector representing part of another vector

1547:   Collective

1549:   Input Parameters:
1550: + X  - vector from which to extract a subvector
1551: - is - index set representing portion of `X` to extract

1553:   Output Parameter:
1554: . Y - subvector corresponding to `is`

1556:   Level: advanced

1558:   Notes:
1559:   The subvector `Y` should be returned with `VecRestoreSubVector()`.
1560:   `X` and `is` must be defined on the same communicator

1562:   Changes to the subvector will be reflected in the `X` vector on the call to `VecRestoreSubVector()`.

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

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

1569: .seealso: [](ch_vectors), `Vec`, `IS`, `VECNEST`, `MatCreateSubMatrix()`
1570: @*/
1571: PetscErrorCode VecGetSubVector(Vec X, IS is, Vec *Y)
1572: {
1573:   Vec Z;

1575:   PetscFunctionBegin;
1578:   PetscCheckSameComm(X, 1, is, 2);
1579:   PetscAssertPointer(Y, 3);
1580:   if (X->ops->getsubvector) {
1581:     PetscUseTypeMethod(X, getsubvector, is, &Z);
1582:   } else { /* Default implementation currently does no caching */
1583:     PetscBool contig;
1584:     PetscInt  n, N, start, bs;

1586:     PetscCall(ISGetLocalSize(is, &n));
1587:     PetscCall(ISGetSize(is, &N));
1588:     PetscCall(VecGetSubVectorContiguityAndBS_Private(X, is, &contig, &start, &bs));
1589:     if (contig) { /* We can do a no-copy implementation */
1590:       const PetscScalar *x;
1591:       PetscInt           state = 0;
1592:       PetscBool          isstd, iscuda, iship;

1594:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &isstd, VECSEQ, VECMPI, VECSTANDARD, ""));
1595:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1596:       PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));
1597:       if (iscuda) {
1598: #if defined(PETSC_HAVE_CUDA)
1599:         const PetscScalar *x_d;
1600:         PetscMPIInt        size;
1601:         PetscOffloadMask   flg;

1603:         PetscCall(VecCUDAGetArrays_Private(X, &x, &x_d, &flg));
1604:         PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1605:         PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1606:         if (x) x += start;
1607:         if (x_d) x_d += start;
1608:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1609:         if (size == 1) {
1610:           PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1611:         } else {
1612:           PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1613:         }
1614:         Z->offloadmask = flg;
1615: #endif
1616:       } else if (iship) {
1617: #if defined(PETSC_HAVE_HIP)
1618:         const PetscScalar *x_d;
1619:         PetscMPIInt        size;
1620:         PetscOffloadMask   flg;

1622:         PetscCall(VecHIPGetArrays_Private(X, &x, &x_d, &flg));
1623:         PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1624:         PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1625:         if (x) x += start;
1626:         if (x_d) x_d += start;
1627:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1628:         if (size == 1) {
1629:           PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1630:         } else {
1631:           PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1632:         }
1633:         Z->offloadmask = flg;
1634: #endif
1635:       } else if (isstd) {
1636:         PetscMPIInt size;

1638:         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1639:         PetscCall(VecGetArrayRead(X, &x));
1640:         if (x) x += start;
1641:         if (size == 1) {
1642:           PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)X), bs, n, x, &Z));
1643:         } else {
1644:           PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)X), bs, n, N, x, &Z));
1645:         }
1646:         PetscCall(VecRestoreArrayRead(X, &x));
1647:       } else { /* default implementation: use place array */
1648:         PetscCall(VecGetArrayRead(X, &x));
1649:         PetscCall(VecCreate(PetscObjectComm((PetscObject)X), &Z));
1650:         PetscCall(VecSetType(Z, ((PetscObject)X)->type_name));
1651:         PetscCall(VecSetSizes(Z, n, N));
1652:         PetscCall(VecSetBlockSize(Z, bs));
1653:         PetscCall(VecPlaceArray(Z, PetscSafePointerPlusOffset(x, start)));
1654:         PetscCall(VecRestoreArrayRead(X, &x));
1655:       }

1657:       /* this is relevant only in debug mode */
1658:       PetscCall(VecLockGet(X, &state));
1659:       if (state) PetscCall(VecLockReadPush(Z));
1660:       Z->ops->placearray   = NULL;
1661:       Z->ops->replacearray = NULL;
1662:     } else { /* Have to create a scatter and do a copy */
1663:       PetscCall(VecGetSubVectorThroughVecScatter_Private(X, is, bs, &Z));
1664:     }
1665:   }
1666:   /* Record the state when the subvector was gotten so we know whether its values need to be put back */
1667:   if (VecGetSubVectorSavedStateId < 0) PetscCall(PetscObjectComposedDataRegister(&VecGetSubVectorSavedStateId));
1668:   PetscCall(PetscObjectComposedDataSetInt((PetscObject)Z, VecGetSubVectorSavedStateId, 1));
1669:   *Y = Z;
1670:   PetscFunctionReturn(PETSC_SUCCESS);
1671: }

1673: /*@
1674:   VecRestoreSubVector - Restores a subvector extracted using `VecGetSubVector()`

1676:   Collective

1678:   Input Parameters:
1679: + X  - vector from which subvector was obtained
1680: . is - index set representing the subset of `X`
1681: - Y  - subvector being restored

1683:   Level: advanced

1685: .seealso: [](ch_vectors), `Vec`, `IS`, `VecGetSubVector()`
1686: @*/
1687: PetscErrorCode VecRestoreSubVector(Vec X, IS is, Vec *Y)
1688: {
1689:   PETSC_UNUSED PetscObjectState dummystate = 0;
1690:   PetscBool                     unchanged;

1692:   PetscFunctionBegin;
1695:   PetscCheckSameComm(X, 1, is, 2);
1696:   PetscAssertPointer(Y, 3);

1699:   if (X->ops->restoresubvector) PetscUseTypeMethod(X, restoresubvector, is, Y);
1700:   else {
1701:     PetscCall(PetscObjectComposedDataGetInt((PetscObject)*Y, VecGetSubVectorSavedStateId, dummystate, unchanged));
1702:     if (!unchanged) { /* If Y's state has not changed since VecGetSubVector(), we only need to destroy Y */
1703:       VecScatter scatter;
1704:       PetscInt   state;

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

1709:       PetscCall(PetscObjectQuery((PetscObject)*Y, "VecGetSubVector_Scatter", (PetscObject *)&scatter));
1710:       if (scatter) {
1711:         PetscCall(VecScatterBegin(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1712:         PetscCall(VecScatterEnd(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1713:       } else {
1714:         PetscBool iscuda, iship;
1715:         PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1716:         PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));

1718:         if (iscuda) {
1719: #if defined(PETSC_HAVE_CUDA)
1720:           PetscOffloadMask ymask = (*Y)->offloadmask;

1722:           /* The offloadmask of X dictates where to move memory
1723:               If X GPU data is valid, then move Y data on GPU if needed
1724:               Otherwise, move back to the CPU */
1725:           switch (X->offloadmask) {
1726:           case PETSC_OFFLOAD_BOTH:
1727:             if (ymask == PETSC_OFFLOAD_CPU) {
1728:               PetscCall(VecCUDAResetArray(*Y));
1729:             } else if (ymask == PETSC_OFFLOAD_GPU) {
1730:               X->offloadmask = PETSC_OFFLOAD_GPU;
1731:             }
1732:             break;
1733:           case PETSC_OFFLOAD_GPU:
1734:             if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecCUDAResetArray(*Y));
1735:             break;
1736:           case PETSC_OFFLOAD_CPU:
1737:             if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1738:             break;
1739:           case PETSC_OFFLOAD_UNALLOCATED:
1740:           case PETSC_OFFLOAD_KOKKOS:
1741:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1742:           }
1743: #endif
1744:         } else if (iship) {
1745: #if defined(PETSC_HAVE_HIP)
1746:           PetscOffloadMask ymask = (*Y)->offloadmask;

1748:           /* The offloadmask of X dictates where to move memory
1749:               If X GPU data is valid, then move Y data on GPU if needed
1750:               Otherwise, move back to the CPU */
1751:           switch (X->offloadmask) {
1752:           case PETSC_OFFLOAD_BOTH:
1753:             if (ymask == PETSC_OFFLOAD_CPU) {
1754:               PetscCall(VecHIPResetArray(*Y));
1755:             } else if (ymask == PETSC_OFFLOAD_GPU) {
1756:               X->offloadmask = PETSC_OFFLOAD_GPU;
1757:             }
1758:             break;
1759:           case PETSC_OFFLOAD_GPU:
1760:             if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecHIPResetArray(*Y));
1761:             break;
1762:           case PETSC_OFFLOAD_CPU:
1763:             if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1764:             break;
1765:           case PETSC_OFFLOAD_UNALLOCATED:
1766:           case PETSC_OFFLOAD_KOKKOS:
1767:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1768:           }
1769: #endif
1770:         } else {
1771:           /* If OpenCL vecs updated the device memory, this triggers a copy on the CPU */
1772:           PetscCall(VecResetArray(*Y));
1773:         }
1774:         PetscCall(PetscObjectStateIncrease((PetscObject)X));
1775:       }
1776:     }
1777:   }
1778:   PetscCall(VecDestroy(Y));
1779:   PetscFunctionReturn(PETSC_SUCCESS);
1780: }

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

1786:   Not Collective.

1788:   Input Parameter:
1789: . v - The vector for which the local vector is desired.

1791:   Output Parameter:
1792: . w - Upon exit this contains the local vector.

1794:   Level: beginner

1796: .seealso: [](ch_vectors), `Vec`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecRestoreLocalVector()`
1797: @*/
1798: PetscErrorCode VecCreateLocalVector(Vec v, Vec *w)
1799: {
1800:   PetscMPIInt size;

1802:   PetscFunctionBegin;
1804:   PetscAssertPointer(w, 2);
1805:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)v), &size));
1806:   if (size == 1) PetscCall(VecDuplicate(v, w));
1807:   else if (v->ops->createlocalvector) PetscUseTypeMethod(v, createlocalvector, w);
1808:   else {
1809:     VecType  type;
1810:     PetscInt n;

1812:     PetscCall(VecCreate(PETSC_COMM_SELF, w));
1813:     PetscCall(VecGetLocalSize(v, &n));
1814:     PetscCall(VecSetSizes(*w, n, n));
1815:     PetscCall(VecGetBlockSize(v, &n));
1816:     PetscCall(VecSetBlockSize(*w, n));
1817:     PetscCall(VecGetType(v, &type));
1818:     PetscCall(VecSetType(*w, type));
1819:   }
1820:   PetscFunctionReturn(PETSC_SUCCESS);
1821: }

1823: /*@
1824:   VecGetLocalVectorRead - Maps the local portion of a vector into a
1825:   vector.

1827:   Not Collective.

1829:   Input Parameter:
1830: . v - The vector for which the local vector is desired.

1832:   Output Parameter:
1833: . w - Upon exit this contains the local vector.

1835:   Level: beginner

1837:   Notes:
1838:   You must call `VecRestoreLocalVectorRead()` when the local
1839:   vector is no longer needed.

1841:   This function is similar to `VecGetArrayRead()` which maps the local
1842:   portion into a raw pointer.  `VecGetLocalVectorRead()` is usually
1843:   almost as efficient as `VecGetArrayRead()` but in certain circumstances
1844:   `VecGetLocalVectorRead()` can be much more efficient than
1845:   `VecGetArrayRead()`.  This is because the construction of a contiguous
1846:   array representing the vector data required by `VecGetArrayRead()` can
1847:   be an expensive operation for certain vector types.  For example, for
1848:   GPU vectors `VecGetArrayRead()` requires that the data between device
1849:   and host is synchronized.

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

1854: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1855: @*/
1856: PetscErrorCode VecGetLocalVectorRead(Vec v, Vec w)
1857: {
1858:   PetscFunctionBegin;
1861:   VecCheckSameLocalSize(v, 1, w, 2);
1862:   if (v->ops->getlocalvectorread) {
1863:     PetscUseTypeMethod(v, getlocalvectorread, w);
1864:   } else {
1865:     PetscScalar *a;

1867:     PetscCall(VecGetArrayRead(v, (const PetscScalar **)&a));
1868:     PetscCall(VecPlaceArray(w, a));
1869:   }
1870:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1871:   PetscCall(VecLockReadPush(v));
1872:   PetscCall(VecLockReadPush(w));
1873:   PetscFunctionReturn(PETSC_SUCCESS);
1874: }

1876: /*@
1877:   VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1878:   previously mapped into a vector using `VecGetLocalVectorRead()`.

1880:   Not Collective.

1882:   Input Parameters:
1883: + v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVectorRead()`.
1884: - w - The vector into which the local portion of `v` was mapped.

1886:   Level: beginner

1888: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1889: @*/
1890: PetscErrorCode VecRestoreLocalVectorRead(Vec v, Vec w)
1891: {
1892:   PetscFunctionBegin;
1895:   if (v->ops->restorelocalvectorread) {
1896:     PetscUseTypeMethod(v, restorelocalvectorread, w);
1897:   } else {
1898:     const PetscScalar *a;

1900:     PetscCall(VecGetArrayRead(w, &a));
1901:     PetscCall(VecRestoreArrayRead(v, &a));
1902:     PetscCall(VecResetArray(w));
1903:   }
1904:   PetscCall(VecLockReadPop(v));
1905:   PetscCall(VecLockReadPop(w));
1906:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1907:   PetscFunctionReturn(PETSC_SUCCESS);
1908: }

1910: /*@
1911:   VecGetLocalVector - Maps the local portion of a vector into a
1912:   vector.

1914:   Collective

1916:   Input Parameter:
1917: . v - The vector for which the local vector is desired.

1919:   Output Parameter:
1920: . w - Upon exit this contains the local vector.

1922:   Level: beginner

1924:   Notes:
1925:   You must call `VecRestoreLocalVector()` when the local
1926:   vector is no longer needed.

1928:   This function is similar to `VecGetArray()` which maps the local
1929:   portion into a raw pointer.  `VecGetLocalVector()` is usually about as
1930:   efficient as `VecGetArray()` but in certain circumstances
1931:   `VecGetLocalVector()` can be much more efficient than `VecGetArray()`.
1932:   This is because the construction of a contiguous array representing
1933:   the vector data required by `VecGetArray()` can be an expensive
1934:   operation for certain vector types.  For example, for GPU vectors
1935:   `VecGetArray()` requires that the data between device and host is
1936:   synchronized.

1938: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVector()`, `VecGetLocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1939: @*/
1940: PetscErrorCode VecGetLocalVector(Vec v, Vec w)
1941: {
1942:   PetscFunctionBegin;
1945:   VecCheckSameLocalSize(v, 1, w, 2);
1946:   if (v->ops->getlocalvector) {
1947:     PetscUseTypeMethod(v, getlocalvector, w);
1948:   } else {
1949:     PetscScalar *a;

1951:     PetscCall(VecGetArray(v, &a));
1952:     PetscCall(VecPlaceArray(w, a));
1953:   }
1954:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1955:   PetscFunctionReturn(PETSC_SUCCESS);
1956: }

1958: /*@
1959:   VecRestoreLocalVector - Unmaps the local portion of a vector
1960:   previously mapped into a vector using `VecGetLocalVector()`.

1962:   Logically Collective.

1964:   Input Parameters:
1965: + v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVector()`.
1966: - w - The vector into which the local portion of `v` was mapped.

1968:   Level: beginner

1970: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVector()`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `LocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1971: @*/
1972: PetscErrorCode VecRestoreLocalVector(Vec v, Vec w)
1973: {
1974:   PetscFunctionBegin;
1977:   if (v->ops->restorelocalvector) {
1978:     PetscUseTypeMethod(v, restorelocalvector, w);
1979:   } else {
1980:     PetscScalar *a;
1981:     PetscCall(VecGetArray(w, &a));
1982:     PetscCall(VecRestoreArray(v, &a));
1983:     PetscCall(VecResetArray(w));
1984:   }
1985:   PetscCall(PetscObjectStateIncrease((PetscObject)w));
1986:   PetscCall(PetscObjectStateIncrease((PetscObject)v));
1987:   PetscFunctionReturn(PETSC_SUCCESS);
1988: }

1990: /*@C
1991:   VecGetArray - Returns a pointer to a contiguous array that contains this
1992:   MPI processes's portion of the vector data

1994:   Logically Collective

1996:   Input Parameter:
1997: . x - the vector

1999:   Output Parameter:
2000: . a - location to put pointer to the array

2002:   Level: beginner

2004:   Notes:
2005:   For the standard PETSc vectors, `VecGetArray()` returns a pointer to the local data array and
2006:   does not use any copies. If the underlying vector data is not stored in a contiguous array
2007:   this routine will copy the data to a contiguous array and return a pointer to that. You MUST
2008:   call `VecRestoreArray()` when you no longer need access to the array.

2010:   Fortran Notes:
2011:   `VecGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `VecGetArrayF90()`

2013: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`, `VecPlaceArray()`, `VecGetArray2d()`,
2014:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2015: @*/
2016: PetscErrorCode VecGetArray(Vec x, PetscScalar **a)
2017: {
2018:   PetscFunctionBegin;
2020:   PetscCall(VecSetErrorIfLocked(x, 1));
2021:   if (x->ops->getarray) { /* The if-else order matters! VECNEST, VECCUDA etc should have ops->getarray while VECCUDA etc are petscnative */
2022:     PetscUseTypeMethod(x, getarray, a);
2023:   } else if (x->petscnative) { /* VECSTANDARD */
2024:     *a = *((PetscScalar **)x->data);
2025:   } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array for vector type \"%s\"", ((PetscObject)x)->type_name);
2026:   PetscFunctionReturn(PETSC_SUCCESS);
2027: }

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

2032:   Logically Collective

2034:   Input Parameters:
2035: + x - the vector
2036: - a - location of pointer to array obtained from `VecGetArray()`

2038:   Level: beginner

2040:   Fortran Notes:
2041:   `VecRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `VecRestoreArrayF90()`

2043: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2044:           `VecGetArrayPair()`, `VecRestoreArrayPair()`
2045: @*/
2046: PetscErrorCode VecRestoreArray(Vec x, PetscScalar **a)
2047: {
2048:   PetscFunctionBegin;
2050:   if (a) PetscAssertPointer(a, 2);
2051:   if (x->ops->restorearray) {
2052:     PetscUseTypeMethod(x, restorearray, a);
2053:   } else PetscCheck(x->petscnative, PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot restore array for vector type \"%s\"", ((PetscObject)x)->type_name);
2054:   if (a) *a = NULL;
2055:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2056:   PetscFunctionReturn(PETSC_SUCCESS);
2057: }
2058: /*@C
2059:   VecGetArrayRead - Get read-only pointer to contiguous array containing this processor's portion of the vector data.

2061:   Not Collective

2063:   Input Parameter:
2064: . x - the vector

2066:   Output Parameter:
2067: . a - the array

2069:   Level: beginner

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

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

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

2080:   Fortran Notes:
2081:   `VecGetArrayRead()` Fortran binding is deprecated (since PETSc 3.19), use `VecGetArrayReadF90()`

2083: .seealso: [](ch_vectors), `Vec`, `VecGetArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2084: @*/
2085: PetscErrorCode VecGetArrayRead(Vec x, const PetscScalar **a)
2086: {
2087:   PetscFunctionBegin;
2089:   PetscAssertPointer(a, 2);
2090:   if (x->ops->getarrayread) {
2091:     PetscUseTypeMethod(x, getarrayread, a);
2092:   } else if (x->ops->getarray) {
2093:     PetscObjectState state;

2095:     /* VECNEST, VECCUDA, VECKOKKOS etc */
2096:     // x->ops->getarray may bump the object state, but since we know this is a read-only get
2097:     // we can just undo that
2098:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2099:     PetscUseTypeMethod(x, getarray, (PetscScalar **)a);
2100:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
2101:   } else if (x->petscnative) {
2102:     /* VECSTANDARD */
2103:     *a = *((PetscScalar **)x->data);
2104:   } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array read for vector type \"%s\"", ((PetscObject)x)->type_name);
2105:   PetscFunctionReturn(PETSC_SUCCESS);
2106: }

2108: /*@C
2109:   VecRestoreArrayRead - Restore array obtained with `VecGetArrayRead()`

2111:   Not Collective

2113:   Input Parameters:
2114: + x - the vector
2115: - a - the array

2117:   Level: beginner

2119:   Fortran Notes:
2120:   `VecRestoreArrayRead()` Fortran binding is deprecated (since PETSc 3.19), use `VecRestoreArrayReadF90()`

2122: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2123: @*/
2124: PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar **a)
2125: {
2126:   PetscFunctionBegin;
2128:   if (a) PetscAssertPointer(a, 2);
2129:   if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
2130:     /* nothing */
2131:   } else if (x->ops->restorearrayread) { /* VECNEST */
2132:     PetscUseTypeMethod(x, restorearrayread, a);
2133:   } else { /* No one? */
2134:     PetscObjectState state;

2136:     // x->ops->restorearray may bump the object state, but since we know this is a read-restore
2137:     // we can just undo that
2138:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2139:     PetscUseTypeMethod(x, restorearray, (PetscScalar **)a);
2140:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
2141:   }
2142:   if (a) *a = NULL;
2143:   PetscFunctionReturn(PETSC_SUCCESS);
2144: }

2146: /*@C
2147:   VecGetArrayWrite - Returns a pointer to a contiguous array that WILL contain this
2148:   MPI processes's portion of the vector data.

2150:   Logically Collective

2152:   Input Parameter:
2153: . x - the vector

2155:   Output Parameter:
2156: . a - location to put pointer to the array

2158:   Level: intermediate

2160:   Note:
2161:   The values in this array are NOT valid, the caller of this routine is responsible for putting
2162:   values into the array; any values it does not set will be invalid.

2164:   The array must be returned using a matching call to `VecRestoreArrayWrite()`.

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

2169:   Fortran Notes:
2170:   `VecGetArrayWrite()` Fortran binding is deprecated (since PETSc 3.19), use `VecGetArrayWriteF90()`

2172: .seealso: [](ch_vectors), `Vec`, `VecGetArrayWriteF90()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`, `VecPlaceArray()`, `VecGetArray2d()`,
2173:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArray()`, `VecRestoreArrayWrite()`
2174: @*/
2175: PetscErrorCode VecGetArrayWrite(Vec x, PetscScalar **a)
2176: {
2177:   PetscFunctionBegin;
2179:   PetscAssertPointer(a, 2);
2180:   PetscCall(VecSetErrorIfLocked(x, 1));
2181:   if (x->ops->getarraywrite) {
2182:     PetscUseTypeMethod(x, getarraywrite, a);
2183:   } else {
2184:     PetscCall(VecGetArray(x, a));
2185:   }
2186:   PetscFunctionReturn(PETSC_SUCCESS);
2187: }

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

2192:   Logically Collective

2194:   Input Parameters:
2195: + x - the vector
2196: - a - location of pointer to array obtained from `VecGetArray()`

2198:   Level: beginner

2200:   Fortran Notes:
2201:   `VecRestoreArrayWrite()` Fortran binding is deprecated (since PETSc 3.19), use `VecRestoreArrayWriteF90()`

2203: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayWriteF90()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2204:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`
2205: @*/
2206: PetscErrorCode VecRestoreArrayWrite(Vec x, PetscScalar **a)
2207: {
2208:   PetscFunctionBegin;
2210:   if (a) PetscAssertPointer(a, 2);
2211:   if (x->ops->restorearraywrite) {
2212:     PetscUseTypeMethod(x, restorearraywrite, a);
2213:   } else if (x->ops->restorearray) {
2214:     PetscUseTypeMethod(x, restorearray, a);
2215:   }
2216:   if (a) *a = NULL;
2217:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2218:   PetscFunctionReturn(PETSC_SUCCESS);
2219: }

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

2225:   Logically Collective; No Fortran Support

2227:   Input Parameters:
2228: + x - the vectors
2229: - n - the number of vectors

2231:   Output Parameter:
2232: . a - location to put pointer to the array

2234:   Level: intermediate

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

2239: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrays()`
2240: @*/
2241: PetscErrorCode VecGetArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2242: {
2243:   PetscInt      i;
2244:   PetscScalar **q;

2246:   PetscFunctionBegin;
2247:   PetscAssertPointer(x, 1);
2249:   PetscAssertPointer(a, 3);
2250:   PetscCheck(n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must get at least one array n = %" PetscInt_FMT, n);
2251:   PetscCall(PetscMalloc1(n, &q));
2252:   for (i = 0; i < n; ++i) PetscCall(VecGetArray(x[i], &q[i]));
2253:   *a = q;
2254:   PetscFunctionReturn(PETSC_SUCCESS);
2255: }

2257: /*@C
2258:   VecRestoreArrays - Restores a group of vectors after `VecGetArrays()`
2259:   has been called.

2261:   Logically Collective; No Fortran Support

2263:   Input Parameters:
2264: + x - the vector
2265: . n - the number of vectors
2266: - a - location of pointer to arrays obtained from `VecGetArrays()`

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

2274:   Level: intermediate

2276: .seealso: [](ch_vectors), `Vec`, `VecGetArrays()`, `VecRestoreArray()`
2277: @*/
2278: PetscErrorCode VecRestoreArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2279: {
2280:   PetscInt      i;
2281:   PetscScalar **q = *a;

2283:   PetscFunctionBegin;
2284:   PetscAssertPointer(x, 1);
2286:   PetscAssertPointer(a, 3);

2288:   for (i = 0; i < n; ++i) PetscCall(VecRestoreArray(x[i], &q[i]));
2289:   PetscCall(PetscFree(q));
2290:   PetscFunctionReturn(PETSC_SUCCESS);
2291: }

2293: /*@C
2294:   VecGetArrayAndMemType - Like `VecGetArray()`, but if this is a standard device vector (e.g.,
2295:   `VECCUDA`), the returned pointer will be a device pointer to the device memory that contains
2296:   this MPI processes's portion of the vector data.

2298:   Logically Collective; No Fortran Support

2300:   Input Parameter:
2301: . x - the vector

2303:   Output Parameters:
2304: + a     - location to put pointer to the array
2305: - mtype - memory type of the array

2307:   Level: beginner

2309:   Note:
2310:   Device data is guaranteed to have the latest value. Otherwise, when this is a host vector
2311:   (e.g., `VECMPI`), this routine functions the same as `VecGetArray()` and returns a host
2312:   pointer.

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

2318:   Use `VecRestoreArrayAndMemType()` when the array access is no longer needed.

2320: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`,
2321:           `VecPlaceArray()`, `VecGetArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2322: @*/
2323: PetscErrorCode VecGetArrayAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2324: {
2325:   PetscFunctionBegin;
2328:   PetscAssertPointer(a, 2);
2329:   if (mtype) PetscAssertPointer(mtype, 3);
2330:   PetscCall(VecSetErrorIfLocked(x, 1));
2331:   if (x->ops->getarrayandmemtype) {
2332:     /* VECCUDA, VECKOKKOS etc */
2333:     PetscUseTypeMethod(x, getarrayandmemtype, a, mtype);
2334:   } else {
2335:     /* VECSTANDARD, VECNEST, VECVIENNACL */
2336:     PetscCall(VecGetArray(x, a));
2337:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2338:   }
2339:   PetscFunctionReturn(PETSC_SUCCESS);
2340: }

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

2345:   Logically Collective; No Fortran Support

2347:   Input Parameters:
2348: + x - the vector
2349: - a - location of pointer to array obtained from `VecGetArrayAndMemType()`

2351:   Level: beginner

2353: .seealso: [](ch_vectors), `Vec`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`,
2354:           `VecPlaceArray()`, `VecRestoreArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2355: @*/
2356: PetscErrorCode VecRestoreArrayAndMemType(Vec x, PetscScalar **a)
2357: {
2358:   PetscFunctionBegin;
2361:   if (a) PetscAssertPointer(a, 2);
2362:   if (x->ops->restorearrayandmemtype) {
2363:     /* VECCUDA, VECKOKKOS etc */
2364:     PetscUseTypeMethod(x, restorearrayandmemtype, a);
2365:   } else {
2366:     /* VECNEST, VECVIENNACL */
2367:     PetscCall(VecRestoreArray(x, a));
2368:   } /* VECSTANDARD does nothing */
2369:   if (a) *a = NULL;
2370:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2371:   PetscFunctionReturn(PETSC_SUCCESS);
2372: }

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

2378:   Not Collective; No Fortran Support

2380:   Input Parameter:
2381: . x - the vector

2383:   Output Parameters:
2384: + a     - the array
2385: - mtype - memory type of the array

2387:   Level: beginner

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

2392: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2393: @*/
2394: PetscErrorCode VecGetArrayReadAndMemType(Vec x, const PetscScalar **a, PetscMemType *mtype)
2395: {
2396:   PetscFunctionBegin;
2399:   PetscAssertPointer(a, 2);
2400:   if (mtype) PetscAssertPointer(mtype, 3);
2401:   if (x->ops->getarrayreadandmemtype) {
2402:     /* VECCUDA/VECHIP though they are also petscnative */
2403:     PetscUseTypeMethod(x, getarrayreadandmemtype, a, mtype);
2404:   } else if (x->ops->getarrayandmemtype) {
2405:     /* VECKOKKOS */
2406:     PetscObjectState state;

2408:     // see VecGetArrayRead() for why
2409:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2410:     PetscUseTypeMethod(x, getarrayandmemtype, (PetscScalar **)a, mtype);
2411:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
2412:   } else {
2413:     PetscCall(VecGetArrayRead(x, a));
2414:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2415:   }
2416:   PetscFunctionReturn(PETSC_SUCCESS);
2417: }

2419: /*@C
2420:   VecRestoreArrayReadAndMemType - Restore array obtained with `VecGetArrayReadAndMemType()`

2422:   Not Collective; No Fortran Support

2424:   Input Parameters:
2425: + x - the vector
2426: - a - the array

2428:   Level: beginner

2430: .seealso: [](ch_vectors), `Vec`, `VecGetArrayReadAndMemType()`, `VecRestoreArrayAndMemType()`, `VecRestoreArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2431: @*/
2432: PetscErrorCode VecRestoreArrayReadAndMemType(Vec x, const PetscScalar **a)
2433: {
2434:   PetscFunctionBegin;
2437:   if (a) PetscAssertPointer(a, 2);
2438:   if (x->ops->restorearrayreadandmemtype) {
2439:     /* VECCUDA/VECHIP */
2440:     PetscUseTypeMethod(x, restorearrayreadandmemtype, a);
2441:   } else if (!x->petscnative) {
2442:     /* VECNEST */
2443:     PetscCall(VecRestoreArrayRead(x, a));
2444:   }
2445:   if (a) *a = NULL;
2446:   PetscFunctionReturn(PETSC_SUCCESS);
2447: }

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

2453:   Logically Collective; No Fortran Support

2455:   Input Parameter:
2456: . x - the vector

2458:   Output Parameters:
2459: + a     - the array
2460: - mtype - memory type of the array

2462:   Level: beginner

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

2467: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayWriteAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2468: @*/
2469: PetscErrorCode VecGetArrayWriteAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2470: {
2471:   PetscFunctionBegin;
2474:   PetscCall(VecSetErrorIfLocked(x, 1));
2475:   PetscAssertPointer(a, 2);
2476:   if (mtype) PetscAssertPointer(mtype, 3);
2477:   if (x->ops->getarraywriteandmemtype) {
2478:     /* VECCUDA, VECHIP, VECKOKKOS etc, though they are also petscnative */
2479:     PetscUseTypeMethod(x, getarraywriteandmemtype, a, mtype);
2480:   } else if (x->ops->getarrayandmemtype) {
2481:     PetscCall(VecGetArrayAndMemType(x, a, mtype));
2482:   } else {
2483:     /* VECNEST, VECVIENNACL */
2484:     PetscCall(VecGetArrayWrite(x, a));
2485:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2486:   }
2487:   PetscFunctionReturn(PETSC_SUCCESS);
2488: }

2490: /*@C
2491:   VecRestoreArrayWriteAndMemType - Restore array obtained with `VecGetArrayWriteAndMemType()`

2493:   Logically Collective; No Fortran Support

2495:   Input Parameters:
2496: + x - the vector
2497: - a - the array

2499:   Level: beginner

2501: .seealso: [](ch_vectors), `Vec`, `VecGetArrayWriteAndMemType()`, `VecRestoreArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2502: @*/
2503: PetscErrorCode VecRestoreArrayWriteAndMemType(Vec x, PetscScalar **a)
2504: {
2505:   PetscFunctionBegin;
2508:   PetscCall(VecSetErrorIfLocked(x, 1));
2509:   if (a) PetscAssertPointer(a, 2);
2510:   if (x->ops->restorearraywriteandmemtype) {
2511:     /* VECCUDA/VECHIP */
2512:     PetscMemType PETSC_UNUSED mtype; // since this function doesn't accept a memtype?
2513:     PetscUseTypeMethod(x, restorearraywriteandmemtype, a, &mtype);
2514:   } else if (x->ops->restorearrayandmemtype) {
2515:     PetscCall(VecRestoreArrayAndMemType(x, a));
2516:   } else {
2517:     PetscCall(VecRestoreArray(x, a));
2518:   }
2519:   if (a) *a = NULL;
2520:   PetscFunctionReturn(PETSC_SUCCESS);
2521: }

2523: /*@
2524:   VecPlaceArray - Allows one to replace the array in a vector with an
2525:   array provided by the user. This is useful to avoid copying an array
2526:   into a vector.

2528:   Logically Collective; No Fortran Support

2530:   Input Parameters:
2531: + vec   - the vector
2532: - array - the array

2534:   Level: developer

2536:   Notes:
2537:   Use `VecReplaceArray()` instead to permanently replace the array

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

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

2546: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`
2547: @*/
2548: PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2549: {
2550:   PetscFunctionBegin;
2553:   if (array) PetscAssertPointer(array, 2);
2554:   PetscUseTypeMethod(vec, placearray, array);
2555:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2556:   PetscFunctionReturn(PETSC_SUCCESS);
2557: }

2559: /*@C
2560:   VecReplaceArray - Allows one to replace the array in a vector with an
2561:   array provided by the user. This is useful to avoid copying an array
2562:   into a vector.

2564:   Logically Collective; No Fortran Support

2566:   Input Parameters:
2567: + vec   - the vector
2568: - array - the array

2570:   Level: developer

2572:   Notes:
2573:   This permanently replaces the array and frees the memory associated
2574:   with the old array. Use `VecPlaceArray()` to temporarily replace the array.

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

2579: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`
2580: @*/
2581: PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2582: {
2583:   PetscFunctionBegin;
2586:   PetscUseTypeMethod(vec, replacearray, array);
2587:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2588:   PetscFunctionReturn(PETSC_SUCCESS);
2589: }

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

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

2598:     Collective

2600:     Input Parameters:
2601: +   x - a vector to mimic
2602: -   n - the number of vectors to obtain

2604:     Output Parameters:
2605: +   y - Fortran pointer to the array of vectors
2606: -   ierr - error code

2608:     Example of Usage:
2609: .vb
2610: #include <petsc/finclude/petscvec.h>
2611:     use petscvec

2613:     Vec x
2614:     Vec, pointer :: y(:)
2615:     ....
2616:     call VecDuplicateVecsF90(x,2,y,ierr)
2617:     call VecSet(y(2),alpha,ierr)
2618:     call VecSet(y(2),alpha,ierr)
2619:     ....
2620:     call VecDestroyVecsF90(2,y,ierr)
2621: .ve

2623:     Level: beginner

2625:     Note:
2626:     Use `VecDestroyVecsF90()` to free the space.

2628: .seealso: [](ch_vectors), `Vec`, `VecDestroyVecsF90()`, `VecDuplicateVecs()`
2629: M*/

2631: /*MC
2632:     VecRestoreArrayF90 - Restores a vector to a usable state after a call to
2633:     `VecGetArrayF90()`.

2635:     Synopsis:
2636:     VecRestoreArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2638:     Logically Collective

2640:     Input Parameters:
2641: +   x - vector
2642: -   xx_v - the Fortran pointer to the array

2644:     Output Parameter:
2645: .   ierr - error code

2647:     Example of Usage:
2648: .vb
2649: #include <petsc/finclude/petscvec.h>
2650:     use petscvec

2652:     PetscScalar, pointer :: xx_v(:)
2653:     ....
2654:     call VecGetArrayF90(x,xx_v,ierr)
2655:     xx_v(3) = a
2656:     call VecRestoreArrayF90(x,xx_v,ierr)
2657: .ve

2659:     Level: beginner

2661: .seealso: [](ch_vectors), `Vec`, `VecGetArrayF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrayReadF90()`
2662: M*/

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

2667:     Synopsis:
2668:     VecDestroyVecsF90(PetscInt n,{Vec, pointer :: x(:)},PetscErrorCode ierr)

2670:     Collective

2672:     Input Parameters:
2673: +   n - the number of vectors previously obtained
2674: -   x - pointer to array of vector pointers

2676:     Output Parameter:
2677: .   ierr - error code

2679:     Level: beginner

2681: .seealso: [](ch_vectors), `Vec`, `VecDestroyVecs()`, `VecDuplicateVecsF90()`
2682: M*/

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

2690:     Synopsis:
2691:     VecGetArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2693:     Logically Collective

2695:     Input Parameter:
2696: .   x - vector

2698:     Output Parameters:
2699: +   xx_v - the Fortran pointer to the array
2700: -   ierr - error code

2702:     Example of Usage:
2703: .vb
2704: #include <petsc/finclude/petscvec.h>
2705:     use petscvec

2707:     PetscScalar, pointer :: xx_v(:)
2708:     ....
2709:     call VecGetArrayF90(x,xx_v,ierr)
2710:     xx_v(3) = a
2711:     call VecRestoreArrayF90(x,xx_v,ierr)
2712: .ve

2714:      Level: beginner

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

2719: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayReadF90()`
2720: M*/

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

2728:     Synopsis:
2729:     VecGetArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2731:     Logically Collective

2733:     Input Parameter:
2734: .   x - vector

2736:     Output Parameters:
2737: +   xx_v - the Fortran pointer to the array
2738: -   ierr - error code

2740:     Example of Usage:
2741: .vb
2742: #include <petsc/finclude/petscvec.h>
2743:     use petscvec

2745:     PetscScalar, pointer :: xx_v(:)
2746:     ....
2747:     call VecGetArrayReadF90(x,xx_v,ierr)
2748:     a = xx_v(3)
2749:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2750: .ve

2752:     Level: beginner

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

2757: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecRestoreArrayRead()`, `VecGetArrayF90()`
2758: M*/

2760: /*MC
2761:     VecRestoreArrayReadF90 - Restores a readonly vector to a usable state after a call to
2762:     `VecGetArrayReadF90()`.

2764:     Synopsis:
2765:     VecRestoreArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

2767:     Logically Collective

2769:     Input Parameters:
2770: +   x - vector
2771: -   xx_v - the Fortran pointer to the array

2773:     Output Parameter:
2774: .   ierr - error code

2776:     Example of Usage:
2777: .vb
2778: #include <petsc/finclude/petscvec.h>
2779:     use petscvec

2781:     PetscScalar, pointer :: xx_v(:)
2782:     ....
2783:     call VecGetArrayReadF90(x,xx_v,ierr)
2784:     a = xx_v(3)
2785:     call VecRestoreArrayReadF90(x,xx_v,ierr)
2786: .ve

2788:     Level: beginner

2790: .seealso: [](ch_vectors), `Vec`, `VecGetArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecRestoreArrayRead()`, `VecRestoreArrayF90()`
2791: M*/

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

2798:   Logically Collective

2800:   Input Parameters:
2801: + x      - the vector
2802: . m      - first dimension of two dimensional array
2803: . n      - second dimension of two dimensional array
2804: . mstart - first index you will use in first coordinate direction (often 0)
2805: - nstart - first index in the second coordinate direction (often 0)

2807:   Output Parameter:
2808: . a - location to put pointer to the array

2810:   Level: developer

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

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

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

2829:   PetscFunctionBegin;
2831:   PetscAssertPointer(a, 6);
2833:   PetscCall(VecGetLocalSize(x, &N));
2834:   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);
2835:   PetscCall(VecGetArray(x, &aa));

2837:   PetscCall(PetscMalloc1(m, a));
2838:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2839:   *a -= mstart;
2840:   PetscFunctionReturn(PETSC_SUCCESS);
2841: }

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

2848:   Logically Collective

2850:   Input Parameters:
2851: + x      - the vector
2852: . m      - first dimension of two dimensional array
2853: . n      - second dimension of two dimensional array
2854: . mstart - first index you will use in first coordinate direction (often 0)
2855: - nstart - first index in the second coordinate direction (often 0)

2857:   Output Parameter:
2858: . a - location to put pointer to the array

2860:   Level: developer

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

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

2870: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
2871:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2872:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2873: @*/
2874: PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2875: {
2876:   PetscInt     i, N;
2877:   PetscScalar *aa;

2879:   PetscFunctionBegin;
2881:   PetscAssertPointer(a, 6);
2883:   PetscCall(VecGetLocalSize(x, &N));
2884:   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);
2885:   PetscCall(VecGetArrayWrite(x, &aa));

2887:   PetscCall(PetscMalloc1(m, a));
2888:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2889:   *a -= mstart;
2890:   PetscFunctionReturn(PETSC_SUCCESS);
2891: }

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

2896:   Logically Collective

2898:   Input Parameters:
2899: + x      - the vector
2900: . m      - first dimension of two dimensional array
2901: . n      - second dimension of the two dimensional array
2902: . mstart - first index you will use in first coordinate direction (often 0)
2903: . nstart - first index in the second coordinate direction (often 0)
2904: - a      - location of pointer to array obtained from `VecGetArray2d()`

2906:   Level: developer

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

2914:   This routine actually zeros out the `a` pointer.

2916: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2917:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2918:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2919: @*/
2920: PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2921: {
2922:   void *dummy;

2924:   PetscFunctionBegin;
2926:   PetscAssertPointer(a, 6);
2928:   dummy = (void *)(*a + mstart);
2929:   PetscCall(PetscFree(dummy));
2930:   PetscCall(VecRestoreArray(x, NULL));
2931:   *a = NULL;
2932:   PetscFunctionReturn(PETSC_SUCCESS);
2933: }

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

2938:   Logically Collective

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

2948:   Level: developer

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

2956:   This routine actually zeros out the `a` pointer.

2958: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
2959:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2960:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2961: @*/
2962: PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2963: {
2964:   void *dummy;

2966:   PetscFunctionBegin;
2968:   PetscAssertPointer(a, 6);
2970:   dummy = (void *)(*a + mstart);
2971:   PetscCall(PetscFree(dummy));
2972:   PetscCall(VecRestoreArrayWrite(x, NULL));
2973:   PetscFunctionReturn(PETSC_SUCCESS);
2974: }

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

2981:   Logically Collective

2983:   Input Parameters:
2984: + x      - the vector
2985: . m      - first dimension of two dimensional array
2986: - mstart - first index you will use in first coordinate direction (often 0)

2988:   Output Parameter:
2989: . a - location to put pointer to the array

2991:   Level: developer

2993:   Notes:
2994:   For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
2995:   obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2996:   `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

3000: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3001:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3002:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3003: @*/
3004: PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3005: {
3006:   PetscInt N;

3008:   PetscFunctionBegin;
3010:   PetscAssertPointer(a, 4);
3012:   PetscCall(VecGetLocalSize(x, &N));
3013:   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);
3014:   PetscCall(VecGetArray(x, a));
3015:   *a -= mstart;
3016:   PetscFunctionReturn(PETSC_SUCCESS);
3017: }

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

3024:   Logically Collective

3026:   Input Parameters:
3027: + x      - the vector
3028: . m      - first dimension of two dimensional array
3029: - mstart - first index you will use in first coordinate direction (often 0)

3031:   Output Parameter:
3032: . a - location to put pointer to the array

3034:   Level: developer

3036:   Notes:
3037:   For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
3038:   obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3039:   `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

3043: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3044:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3045:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3046: @*/
3047: PetscErrorCode VecGetArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3048: {
3049:   PetscInt N;

3051:   PetscFunctionBegin;
3053:   PetscAssertPointer(a, 4);
3055:   PetscCall(VecGetLocalSize(x, &N));
3056:   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);
3057:   PetscCall(VecGetArrayWrite(x, a));
3058:   *a -= mstart;
3059:   PetscFunctionReturn(PETSC_SUCCESS);
3060: }

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

3065:   Logically Collective

3067:   Input Parameters:
3068: + x      - the vector
3069: . m      - first dimension of two dimensional array
3070: . mstart - first index you will use in first coordinate direction (often 0)
3071: - a      - location of pointer to array obtained from `VecGetArray1d()`

3073:   Level: developer

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

3081:   This routine actually zeros out the `a` pointer.

3083: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3084:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3085:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3086: @*/
3087: PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3088: {
3089:   PetscFunctionBegin;
3092:   PetscCall(VecRestoreArray(x, NULL));
3093:   *a = NULL;
3094:   PetscFunctionReturn(PETSC_SUCCESS);
3095: }

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

3100:   Logically Collective

3102:   Input Parameters:
3103: + x      - the vector
3104: . m      - first dimension of two dimensional array
3105: . mstart - first index you will use in first coordinate direction (often 0)
3106: - a      - location of pointer to array obtained from `VecGetArray1d()`

3108:   Level: developer

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

3116:   This routine actually zeros out the `a` pointer.

3118: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3119:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3120:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3121: @*/
3122: PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3123: {
3124:   PetscFunctionBegin;
3127:   PetscCall(VecRestoreArrayWrite(x, NULL));
3128:   *a = NULL;
3129:   PetscFunctionReturn(PETSC_SUCCESS);
3130: }

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

3137:   Logically Collective

3139:   Input Parameters:
3140: + x      - the vector
3141: . m      - first dimension of three dimensional array
3142: . n      - second dimension of three dimensional array
3143: . p      - third dimension of three dimensional array
3144: . mstart - first index you will use in first coordinate direction (often 0)
3145: . nstart - first index in the second coordinate direction (often 0)
3146: - pstart - first index in the third coordinate direction (often 0)

3148:   Output Parameter:
3149: . a - location to put pointer to the array

3151:   Level: developer

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

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

3161: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3162:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecRestoreArray3d()`,
3163:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3164: @*/
3165: PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3166: {
3167:   PetscInt     i, N, j;
3168:   PetscScalar *aa, **b;

3170:   PetscFunctionBegin;
3172:   PetscAssertPointer(a, 8);
3174:   PetscCall(VecGetLocalSize(x, &N));
3175:   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);
3176:   PetscCall(VecGetArray(x, &aa));

3178:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3179:   b = (PetscScalar **)((*a) + m);
3180:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3181:   for (i = 0; i < m; i++)
3182:     for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset(aa, i * n * p + j * p - pstart);
3183:   *a -= mstart;
3184:   PetscFunctionReturn(PETSC_SUCCESS);
3185: }

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

3192:   Logically Collective

3194:   Input Parameters:
3195: + x      - the vector
3196: . m      - first dimension of three dimensional array
3197: . n      - second dimension of three dimensional array
3198: . p      - third dimension of three dimensional array
3199: . mstart - first index you will use in first coordinate direction (often 0)
3200: . nstart - first index in the second coordinate direction (often 0)
3201: - pstart - first index in the third coordinate direction (often 0)

3203:   Output Parameter:
3204: . a - location to put pointer to the array

3206:   Level: developer

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

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

3216: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3217:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3218:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3219: @*/
3220: PetscErrorCode VecGetArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3221: {
3222:   PetscInt     i, N, j;
3223:   PetscScalar *aa, **b;

3225:   PetscFunctionBegin;
3227:   PetscAssertPointer(a, 8);
3229:   PetscCall(VecGetLocalSize(x, &N));
3230:   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);
3231:   PetscCall(VecGetArrayWrite(x, &aa));

3233:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3234:   b = (PetscScalar **)((*a) + m);
3235:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3236:   for (i = 0; i < m; i++)
3237:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;

3239:   *a -= mstart;
3240:   PetscFunctionReturn(PETSC_SUCCESS);
3241: }

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

3246:   Logically Collective

3248:   Input Parameters:
3249: + x      - the vector
3250: . m      - first dimension of three dimensional array
3251: . n      - second dimension of the three dimensional array
3252: . p      - third dimension of the three dimensional array
3253: . mstart - first index you will use in first coordinate direction (often 0)
3254: . nstart - first index in the second coordinate direction (often 0)
3255: . pstart - first index in the third coordinate direction (often 0)
3256: - a      - location of pointer to array obtained from VecGetArray3d()

3258:   Level: developer

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

3266:   This routine actually zeros out the `a` pointer.

3268: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3269:           `VecGetArray2d()`, `VecGetArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3270:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3271: @*/
3272: PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3273: {
3274:   void *dummy;

3276:   PetscFunctionBegin;
3278:   PetscAssertPointer(a, 8);
3280:   dummy = (void *)(*a + mstart);
3281:   PetscCall(PetscFree(dummy));
3282:   PetscCall(VecRestoreArray(x, NULL));
3283:   *a = NULL;
3284:   PetscFunctionReturn(PETSC_SUCCESS);
3285: }

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

3290:   Logically Collective

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

3302:   Level: developer

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

3310:   This routine actually zeros out the `a` pointer.

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

3320:   PetscFunctionBegin;
3322:   PetscAssertPointer(a, 8);
3324:   dummy = (void *)(*a + mstart);
3325:   PetscCall(PetscFree(dummy));
3326:   PetscCall(VecRestoreArrayWrite(x, NULL));
3327:   *a = NULL;
3328:   PetscFunctionReturn(PETSC_SUCCESS);
3329: }

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

3336:   Logically Collective

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

3349:   Output Parameter:
3350: . a - location to put pointer to the array

3352:   Level: developer

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

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

3362: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3363:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3364:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecRestoreArray4d()`
3365: @*/
3366: PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3367: {
3368:   PetscInt     i, N, j, k;
3369:   PetscScalar *aa, ***b, **c;

3371:   PetscFunctionBegin;
3373:   PetscAssertPointer(a, 10);
3375:   PetscCall(VecGetLocalSize(x, &N));
3376:   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);
3377:   PetscCall(VecGetArray(x, &aa));

3379:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3380:   b = (PetscScalar ***)((*a) + m);
3381:   c = (PetscScalar **)(b + m * n);
3382:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3383:   for (i = 0; i < m; i++)
3384:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3385:   for (i = 0; i < m; i++)
3386:     for (j = 0; j < n; j++)
3387:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3388:   *a -= mstart;
3389:   PetscFunctionReturn(PETSC_SUCCESS);
3390: }

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

3397:   Logically Collective

3399:   Input Parameters:
3400: + x      - the vector
3401: . m      - first dimension of four dimensional array
3402: . n      - second dimension of four dimensional array
3403: . p      - third dimension of four dimensional array
3404: . q      - fourth dimension of four dimensional array
3405: . mstart - first index you will use in first coordinate direction (often 0)
3406: . nstart - first index in the second coordinate direction (often 0)
3407: . pstart - first index in the third coordinate direction (often 0)
3408: - qstart - first index in the fourth coordinate direction (often 0)

3410:   Output Parameter:
3411: . a - location to put pointer to the array

3413:   Level: developer

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

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

3423: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3424:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3425:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3426: @*/
3427: PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3428: {
3429:   PetscInt     i, N, j, k;
3430:   PetscScalar *aa, ***b, **c;

3432:   PetscFunctionBegin;
3434:   PetscAssertPointer(a, 10);
3436:   PetscCall(VecGetLocalSize(x, &N));
3437:   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);
3438:   PetscCall(VecGetArrayWrite(x, &aa));

3440:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3441:   b = (PetscScalar ***)((*a) + m);
3442:   c = (PetscScalar **)(b + m * n);
3443:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3444:   for (i = 0; i < m; i++)
3445:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3446:   for (i = 0; i < m; i++)
3447:     for (j = 0; j < n; j++)
3448:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3449:   *a -= mstart;
3450:   PetscFunctionReturn(PETSC_SUCCESS);
3451: }

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

3456:   Logically Collective

3458:   Input Parameters:
3459: + x      - the vector
3460: . m      - first dimension of four dimensional array
3461: . n      - second dimension of the four dimensional array
3462: . p      - third dimension of the four dimensional array
3463: . q      - fourth dimension of the four dimensional array
3464: . mstart - first index you will use in first coordinate direction (often 0)
3465: . nstart - first index in the second coordinate direction (often 0)
3466: . pstart - first index in the third coordinate direction (often 0)
3467: . qstart - first index in the fourth coordinate direction (often 0)
3468: - a      - location of pointer to array obtained from VecGetArray4d()

3470:   Level: developer

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

3478:   This routine actually zeros out the `a` pointer.

3480: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3481:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3482:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecGet`
3483: @*/
3484: PetscErrorCode VecRestoreArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3485: {
3486:   void *dummy;

3488:   PetscFunctionBegin;
3490:   PetscAssertPointer(a, 10);
3492:   dummy = (void *)(*a + mstart);
3493:   PetscCall(PetscFree(dummy));
3494:   PetscCall(VecRestoreArray(x, NULL));
3495:   *a = NULL;
3496:   PetscFunctionReturn(PETSC_SUCCESS);
3497: }

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

3502:   Logically Collective

3504:   Input Parameters:
3505: + x      - the vector
3506: . m      - first dimension of four dimensional array
3507: . n      - second dimension of the four dimensional array
3508: . p      - third dimension of the four dimensional array
3509: . q      - fourth dimension of the four dimensional array
3510: . mstart - first index you will use in first coordinate direction (often 0)
3511: . nstart - first index in the second coordinate direction (often 0)
3512: . pstart - first index in the third coordinate direction (often 0)
3513: . qstart - first index in the fourth coordinate direction (often 0)
3514: - a      - location of pointer to array obtained from `VecGetArray4d()`

3516:   Level: developer

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

3524:   This routine actually zeros out the `a` pointer.

3526: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3527:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3528:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3529: @*/
3530: PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3531: {
3532:   void *dummy;

3534:   PetscFunctionBegin;
3536:   PetscAssertPointer(a, 10);
3538:   dummy = (void *)(*a + mstart);
3539:   PetscCall(PetscFree(dummy));
3540:   PetscCall(VecRestoreArrayWrite(x, NULL));
3541:   *a = NULL;
3542:   PetscFunctionReturn(PETSC_SUCCESS);
3543: }

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

3550:   Logically Collective

3552:   Input Parameters:
3553: + x      - the vector
3554: . m      - first dimension of two dimensional array
3555: . n      - second dimension of two dimensional array
3556: . mstart - first index you will use in first coordinate direction (often 0)
3557: - nstart - first index in the second coordinate direction (often 0)

3559:   Output Parameter:
3560: . a - location to put pointer to the array

3562:   Level: developer

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

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

3572: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3573:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3574:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3575: @*/
3576: PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3577: {
3578:   PetscInt           i, N;
3579:   const PetscScalar *aa;

3581:   PetscFunctionBegin;
3583:   PetscAssertPointer(a, 6);
3585:   PetscCall(VecGetLocalSize(x, &N));
3586:   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);
3587:   PetscCall(VecGetArrayRead(x, &aa));

3589:   PetscCall(PetscMalloc1(m, a));
3590:   for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3591:   *a -= mstart;
3592:   PetscFunctionReturn(PETSC_SUCCESS);
3593: }

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

3598:   Logically Collective

3600:   Input Parameters:
3601: + x      - the vector
3602: . m      - first dimension of two dimensional array
3603: . n      - second dimension of the two dimensional array
3604: . mstart - first index you will use in first coordinate direction (often 0)
3605: . nstart - first index in the second coordinate direction (often 0)
3606: - a      - location of pointer to array obtained from VecGetArray2d()

3608:   Level: developer

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

3616:   This routine actually zeros out the `a` pointer.

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

3626:   PetscFunctionBegin;
3628:   PetscAssertPointer(a, 6);
3630:   dummy = (void *)(*a + mstart);
3631:   PetscCall(PetscFree(dummy));
3632:   PetscCall(VecRestoreArrayRead(x, NULL));
3633:   *a = NULL;
3634:   PetscFunctionReturn(PETSC_SUCCESS);
3635: }

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

3642:   Logically Collective

3644:   Input Parameters:
3645: + x      - the vector
3646: . m      - first dimension of two dimensional array
3647: - mstart - first index you will use in first coordinate direction (often 0)

3649:   Output Parameter:
3650: . a - location to put pointer to the array

3652:   Level: developer

3654:   Notes:
3655:   For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
3656:   obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3657:   `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

3661: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3662:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3663:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3664: @*/
3665: PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3666: {
3667:   PetscInt N;

3669:   PetscFunctionBegin;
3671:   PetscAssertPointer(a, 4);
3673:   PetscCall(VecGetLocalSize(x, &N));
3674:   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);
3675:   PetscCall(VecGetArrayRead(x, (const PetscScalar **)a));
3676:   *a -= mstart;
3677:   PetscFunctionReturn(PETSC_SUCCESS);
3678: }

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

3683:   Logically Collective

3685:   Input Parameters:
3686: + x      - the vector
3687: . m      - first dimension of two dimensional array
3688: . mstart - first index you will use in first coordinate direction (often 0)
3689: - a      - location of pointer to array obtained from `VecGetArray1dRead()`

3691:   Level: developer

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

3699:   This routine actually zeros out the `a` pointer.

3701: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3702:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3703:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3704: @*/
3705: PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3706: {
3707:   PetscFunctionBegin;
3710:   PetscCall(VecRestoreArrayRead(x, NULL));
3711:   *a = NULL;
3712:   PetscFunctionReturn(PETSC_SUCCESS);
3713: }

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

3720:   Logically Collective

3722:   Input Parameters:
3723: + x      - the vector
3724: . m      - first dimension of three dimensional array
3725: . n      - second dimension of three dimensional array
3726: . p      - third dimension of three dimensional array
3727: . mstart - first index you will use in first coordinate direction (often 0)
3728: . nstart - first index in the second coordinate direction (often 0)
3729: - pstart - first index in the third coordinate direction (often 0)

3731:   Output Parameter:
3732: . a - location to put pointer to the array

3734:   Level: developer

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

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

3744: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3745:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3746:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3747: @*/
3748: PetscErrorCode VecGetArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3749: {
3750:   PetscInt           i, N, j;
3751:   const PetscScalar *aa;
3752:   PetscScalar      **b;

3754:   PetscFunctionBegin;
3756:   PetscAssertPointer(a, 8);
3758:   PetscCall(VecGetLocalSize(x, &N));
3759:   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);
3760:   PetscCall(VecGetArrayRead(x, &aa));

3762:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3763:   b = (PetscScalar **)((*a) + m);
3764:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3765:   for (i = 0; i < m; i++)
3766:     for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset((PetscScalar *)aa, i * n * p + j * p - pstart);
3767:   *a -= mstart;
3768:   PetscFunctionReturn(PETSC_SUCCESS);
3769: }

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

3774:   Logically Collective

3776:   Input Parameters:
3777: + x      - the vector
3778: . m      - first dimension of three dimensional array
3779: . n      - second dimension of the three dimensional array
3780: . p      - third dimension of the three dimensional array
3781: . mstart - first index you will use in first coordinate direction (often 0)
3782: . nstart - first index in the second coordinate direction (often 0)
3783: . pstart - first index in the third coordinate direction (often 0)
3784: - a      - location of pointer to array obtained from `VecGetArray3dRead()`

3786:   Level: developer

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

3794:   This routine actually zeros out the `a` pointer.

3796: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3797:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3798:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3799: @*/
3800: PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3801: {
3802:   void *dummy;

3804:   PetscFunctionBegin;
3806:   PetscAssertPointer(a, 8);
3808:   dummy = (void *)(*a + mstart);
3809:   PetscCall(PetscFree(dummy));
3810:   PetscCall(VecRestoreArrayRead(x, NULL));
3811:   *a = NULL;
3812:   PetscFunctionReturn(PETSC_SUCCESS);
3813: }

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

3820:   Logically Collective

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

3833:   Output Parameter:
3834: . a - location to put pointer to the array

3836:   Level: beginner

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

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

3846: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3847:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3848:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3849: @*/
3850: PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3851: {
3852:   PetscInt           i, N, j, k;
3853:   const PetscScalar *aa;
3854:   PetscScalar     ***b, **c;

3856:   PetscFunctionBegin;
3858:   PetscAssertPointer(a, 10);
3860:   PetscCall(VecGetLocalSize(x, &N));
3861:   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);
3862:   PetscCall(VecGetArrayRead(x, &aa));

3864:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3865:   b = (PetscScalar ***)((*a) + m);
3866:   c = (PetscScalar **)(b + m * n);
3867:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3868:   for (i = 0; i < m; i++)
3869:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3870:   for (i = 0; i < m; i++)
3871:     for (j = 0; j < n; j++)
3872:       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;
3873:   *a -= mstart;
3874:   PetscFunctionReturn(PETSC_SUCCESS);
3875: }

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

3880:   Logically Collective

3882:   Input Parameters:
3883: + x      - the vector
3884: . m      - first dimension of four dimensional array
3885: . n      - second dimension of the four dimensional array
3886: . p      - third dimension of the four dimensional array
3887: . q      - fourth dimension of the four dimensional array
3888: . mstart - first index you will use in first coordinate direction (often 0)
3889: . nstart - first index in the second coordinate direction (often 0)
3890: . pstart - first index in the third coordinate direction (often 0)
3891: . qstart - first index in the fourth coordinate direction (often 0)
3892: - a      - location of pointer to array obtained from `VecGetArray4dRead()`

3894:   Level: beginner

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

3902:   This routine actually zeros out the `a` pointer.

3904: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3905:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3906:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3907: @*/
3908: PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3909: {
3910:   void *dummy;

3912:   PetscFunctionBegin;
3914:   PetscAssertPointer(a, 10);
3916:   dummy = (void *)(*a + mstart);
3917:   PetscCall(PetscFree(dummy));
3918:   PetscCall(VecRestoreArrayRead(x, NULL));
3919:   *a = NULL;
3920:   PetscFunctionReturn(PETSC_SUCCESS);
3921: }

3923: /*@
3924:   VecLockGet - Get the current lock status of a vector

3926:   Logically Collective

3928:   Input Parameter:
3929: . x - the vector

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

3935:   Level: advanced

3937: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
3938: @*/
3939: PetscErrorCode VecLockGet(Vec x, PetscInt *state)
3940: {
3941:   PetscFunctionBegin;
3943:   PetscAssertPointer(state, 2);
3944:   *state = x->lock;
3945:   PetscFunctionReturn(PETSC_SUCCESS);
3946: }

3948: PetscErrorCode VecLockGetLocation(Vec x, const char *file[], const char *func[], int *line)
3949: {
3950:   PetscFunctionBegin;
3952:   PetscAssertPointer(file, 2);
3953:   PetscAssertPointer(func, 3);
3954:   PetscAssertPointer(line, 4);
3955: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3956:   {
3957:     const int index = x->lockstack.currentsize - 1;

3959:     *file = index < 0 ? NULL : x->lockstack.file[index];
3960:     *func = index < 0 ? NULL : x->lockstack.function[index];
3961:     *line = index < 0 ? 0 : x->lockstack.line[index];
3962:   }
3963: #else
3964:   *file = NULL;
3965:   *func = NULL;
3966:   *line = 0;
3967: #endif
3968:   PetscFunctionReturn(PETSC_SUCCESS);
3969: }

3971: /*@
3972:   VecLockReadPush - Push a read-only lock on a vector to prevent it from being written to

3974:   Logically Collective

3976:   Input Parameter:
3977: . x - the vector

3979:   Level: intermediate

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

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

3987: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPop()`, `VecLockGet()`
3988: @*/
3989: PetscErrorCode VecLockReadPush(Vec x)
3990: {
3991:   PetscFunctionBegin;
3993:   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");
3994: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3995:   {
3996:     const char *file, *func;
3997:     int         index, line;

3999:     if ((index = petscstack.currentsize - 2) < 0) {
4000:       // vec was locked "outside" of petsc, either in user-land or main. the error message will
4001:       // now show this function as the culprit, but it will include the stacktrace
4002:       file = "unknown user-file";
4003:       func = "unknown_user_function";
4004:       line = 0;
4005:     } else {
4006:       file = petscstack.file[index];
4007:       func = petscstack.function[index];
4008:       line = petscstack.line[index];
4009:     }
4010:     PetscStackPush_Private(x->lockstack, file, func, line, petscstack.petscroutine[index], PETSC_FALSE);
4011:   }
4012: #endif
4013:   PetscFunctionReturn(PETSC_SUCCESS);
4014: }

4016: /*@
4017:   VecLockReadPop - Pop a read-only lock from a vector

4019:   Logically Collective

4021:   Input Parameter:
4022: . x - the vector

4024:   Level: intermediate

4026: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockGet()`
4027: @*/
4028: PetscErrorCode VecLockReadPop(Vec x)
4029: {
4030:   PetscFunctionBegin;
4032:   PetscCheck(--x->lock >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector has been unlocked from read-only access too many times");
4033: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
4034:   {
4035:     const char *previous = x->lockstack.function[x->lockstack.currentsize - 1];

4037:     PetscStackPop_Private(x->lockstack, previous);
4038:   }
4039: #endif
4040:   PetscFunctionReturn(PETSC_SUCCESS);
4041: }

4043: /*@
4044:   VecLockWriteSet - Lock or unlock a vector for exclusive read/write access

4046:   Logically Collective

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

4052:   Level: intermediate

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

4060: .vb
4061:        VecGetArray(x,&xdata); // begin phase
4062:        VecLockWriteSet(v,PETSC_TRUE);

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

4066:        VecRestoreArray(x,&vdata); // end phase
4067:        VecLockWriteSet(v,PETSC_FALSE);
4068: .ve

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

4073: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
4074: @*/
4075: PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
4076: {
4077:   PetscFunctionBegin;
4079:   if (flg) {
4080:     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");
4081:     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");
4082:     x->lock = -1;
4083:   } else {
4084:     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");
4085:     x->lock = 0;
4086:   }
4087:   PetscFunctionReturn(PETSC_SUCCESS);
4088: }