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:       PetscCheck(-b2[0] == b2[1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Difference in cached %s norms: local %g", NormTypes[type], (double)*val);
221:     }
222:   }
223:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

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

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

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

238:   Not Collective

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

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

250:   Level: intermediate

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

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

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

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

279:   Collective

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

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

287:   Level: intermediate

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

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

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

316:   Collective

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

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

325:   Level: intermediate

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

330:   Returns the smallest index with the maximum value

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

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

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

356:   Collective

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

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

365:   Level: intermediate

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

370:   This returns the smallest index with the minimum value

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

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

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

397:   Collective

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

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

406:   Level: intermediate

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

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

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

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

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

448:   PetscFunctionBegin;
451:   VecCheckAssembled(x);
452:   PetscCall(VecSetErrorIfLocked(x, 1));
454:   if (alpha == one) PetscFunctionReturn(PETSC_SUCCESS);

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

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

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

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

475:   Logically Collective

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

481:   Level: intermediate

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

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

495: PetscErrorCode VecSetAsync_Private(Vec x, PetscScalar alpha, PetscDeviceContext dctx)
496: {
497:   PetscFunctionBegin;
500:   VecCheckAssembled(x);
502:   PetscCall(VecSetErrorIfLocked(x, 1));

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

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

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

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

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

542:   Logically Collective

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

548:   Level: beginner

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

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

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

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

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

599:   Logically Collective

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

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

609:   Level: intermediate

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

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

631: PetscErrorCode VecAYPXAsync_Private(Vec y, PetscScalar beta, Vec x, PetscDeviceContext dctx)
632: {
633:   PetscFunctionBegin;
638:   PetscCheckSameTypeAndComm(x, 3, y, 1);
639:   VecCheckSameSize(x, 1, y, 3);
640:   VecCheckAssembled(x);
641:   VecCheckAssembled(y);
643:   PetscCall(VecSetErrorIfLocked(y, 1));
644:   if (x == y) {
645:     PetscCall(VecScale(y, beta + 1.0));
646:     PetscFunctionReturn(PETSC_SUCCESS);
647:   }
648:   PetscCall(VecLockReadPush(x));
649:   if (beta == (PetscScalar)0.0) {
650:     PetscCall(VecCopy(x, y));
651:   } else {
652:     PetscCall(PetscLogEventBegin(VEC_AYPX, x, y, 0, 0));
653:     VecMethodDispatch(y, dctx, VecAsyncFnName(AYPX), aypx, (Vec, PetscScalar, Vec, PetscDeviceContext), beta, x);
654:     PetscCall(PetscLogEventEnd(VEC_AYPX, x, y, 0, 0));
655:     PetscCall(PetscObjectStateIncrease((PetscObject)y));
656:   }
657:   PetscCall(VecLockReadPop(x));
658:   PetscFunctionReturn(PETSC_SUCCESS);
659: }

661: /*@
662:   VecAYPX - Computes `y = x + beta y`.

664:   Logically Collective

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

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

674:   Level: intermediate

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

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

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

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

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

720:   Logically Collective

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

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

731:   Level: intermediate

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

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

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

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

782:   Logically Collective

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

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

795:   Level: intermediate

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

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

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

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

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

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

850:   Logically Collective

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

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

860:   Level: intermediate

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

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

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

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

880:   Not Collective

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

889:   Level: beginner

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

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

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

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

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

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

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

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

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

940:   Not Collective

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

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

950:   Level: beginner

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

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

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

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

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

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

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

983:   Not Collective

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

992:   Level: intermediate

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

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

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

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

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

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

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

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

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

1041:   Not Collective

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

1050:   Level: intermediate

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

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

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

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

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

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

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

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

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

1103:   Not Collective

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

1112:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

1194:   Collective

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

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

1204:   Level: intermediate

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

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

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

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

1228:   Collective

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

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

1238:   Level: intermediate

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

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

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

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

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

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

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

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

1299:   Logically Collective

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

1307:   Level: intermediate

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

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

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

1324:   Logically Collective

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

1333:   Level: intermediate

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

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

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

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

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

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

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

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

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

1396:   Collective

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

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

1406:   Level: advanced

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

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

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

1428:   PetscFunctionBegin;
1432:   PetscAssertPointer(Y, 3);

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

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

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

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

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

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

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

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

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

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

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

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

1548:   Collective

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

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

1557:   Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

1677:   Collective

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

1684:   Level: advanced

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

1693:   PetscFunctionBegin;
1696:   PetscCheckSameComm(X, 1, is, 2);
1697:   PetscAssertPointer(Y, 3);

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

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

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

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

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

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

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

1787:   Not Collective.

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

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

1795:   Level: beginner

1797: .seealso: [](ch_vectors), `Vec`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecRestoreLocalVector()`
1798: @*/
1799: PetscErrorCode VecCreateLocalVector(Vec v, Vec *w)
1800: {
1801:   VecType  roottype;
1802:   PetscInt n;

1804:   PetscFunctionBegin;
1806:   PetscAssertPointer(w, 2);
1807:   if (v->ops->createlocalvector) {
1808:     PetscUseTypeMethod(v, createlocalvector, w);
1809:     PetscFunctionReturn(PETSC_SUCCESS);
1810:   }
1811:   PetscCall(VecGetRootType_Private(v, &roottype));
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(VecSetType(*w, roottype));
1818:   PetscFunctionReturn(PETSC_SUCCESS);
1819: }

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

1825:   Not Collective.

1827:   Input Parameter:
1828: . v - The vector for which the local vector is desired.

1830:   Output Parameter:
1831: . w - Upon exit this contains the local vector.

1833:   Level: beginner

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

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

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

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

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

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

1878:   Not Collective.

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

1884:   Level: beginner

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

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

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

1912:   Collective

1914:   Input Parameter:
1915: . v - The vector for which the local vector is desired.

1917:   Output Parameter:
1918: . w - Upon exit this contains the local vector.

1920:   Level: beginner

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

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

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

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

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

1960:   Logically Collective.

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

1966:   Level: beginner

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

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

1992:   Logically Collective

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

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

2000:   Level: beginner

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

2008:   Fortran Note:
2009: .vb
2010:   PetscScalar, pointer :: a(:)
2011: .ve

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

2058:   Not Collective

2060:   Input Parameter:
2061: . x - the vector

2063:   Output Parameter:
2064: . a - the array

2066:   Level: beginner

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

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

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

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

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

2102: /*@C
2103:   VecRestoreArrayRead - Restore array obtained with `VecGetArrayRead()`

2105:   Not Collective

2107:   Input Parameters:
2108: + x - the vector
2109: - a - the array

2111:   Level: beginner

2113: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2114: @*/
2115: PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar *a[])
2116: {
2117:   PetscFunctionBegin;
2119:   if (a) PetscAssertPointer(a, 2);
2120:   if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
2121:     /* nothing */
2122:   } else if (x->ops->restorearrayread) { /* VECNEST */
2123:     PetscUseTypeMethod(x, restorearrayread, a);
2124:   } else { /* No one? */
2125:     PetscObjectState state;

2127:     // x->ops->restorearray may bump the object state, but since we know this is a read-restore
2128:     // we can just undo that
2129:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2130:     PetscUseTypeMethod(x, restorearray, (PetscScalar **)a);
2131:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
2132:   }
2133:   if (a) *a = NULL;
2134:   PetscFunctionReturn(PETSC_SUCCESS);
2135: }

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

2141:   Logically Collective

2143:   Input Parameter:
2144: . x - the vector

2146:   Output Parameter:
2147: . a - location to put pointer to the array

2149:   Level: intermediate

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

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

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

2160: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecPlaceArray()`, `VecGetArray2d()`,
2161:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArray()`, `VecRestoreArrayWrite()`
2162: @*/
2163: PetscErrorCode VecGetArrayWrite(Vec x, PetscScalar *a[])
2164: {
2165:   PetscFunctionBegin;
2167:   PetscAssertPointer(a, 2);
2168:   PetscCall(VecSetErrorIfLocked(x, 1));
2169:   if (x->ops->getarraywrite) {
2170:     PetscUseTypeMethod(x, getarraywrite, a);
2171:   } else {
2172:     PetscCall(VecGetArray(x, a));
2173:   }
2174:   PetscFunctionReturn(PETSC_SUCCESS);
2175: }

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

2180:   Logically Collective

2182:   Input Parameters:
2183: + x - the vector
2184: - a - location of pointer to array obtained from `VecGetArray()`

2186:   Level: beginner

2188: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2189:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`
2190: @*/
2191: PetscErrorCode VecRestoreArrayWrite(Vec x, PetscScalar *a[])
2192: {
2193:   PetscFunctionBegin;
2195:   if (a) PetscAssertPointer(a, 2);
2196:   if (x->ops->restorearraywrite) {
2197:     PetscUseTypeMethod(x, restorearraywrite, a);
2198:   } else if (x->ops->restorearray) {
2199:     PetscUseTypeMethod(x, restorearray, a);
2200:   }
2201:   if (a) *a = NULL;
2202:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2203:   PetscFunctionReturn(PETSC_SUCCESS);
2204: }

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

2210:   Logically Collective; No Fortran Support

2212:   Input Parameters:
2213: + x - the vectors
2214: - n - the number of vectors

2216:   Output Parameter:
2217: . a - location to put pointer to the array

2219:   Level: intermediate

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

2224: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrays()`
2225: @*/
2226: PetscErrorCode VecGetArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2227: {
2228:   PetscInt      i;
2229:   PetscScalar **q;

2231:   PetscFunctionBegin;
2232:   PetscAssertPointer(x, 1);
2234:   PetscAssertPointer(a, 3);
2235:   PetscCheck(n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must get at least one array n = %" PetscInt_FMT, n);
2236:   PetscCall(PetscMalloc1(n, &q));
2237:   for (i = 0; i < n; ++i) PetscCall(VecGetArray(x[i], &q[i]));
2238:   *a = q;
2239:   PetscFunctionReturn(PETSC_SUCCESS);
2240: }

2242: /*@C
2243:   VecRestoreArrays - Restores a group of vectors after `VecGetArrays()`
2244:   has been called.

2246:   Logically Collective; No Fortran Support

2248:   Input Parameters:
2249: + x - the vector
2250: . n - the number of vectors
2251: - a - location of pointer to arrays obtained from `VecGetArrays()`

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

2259:   Level: intermediate

2261: .seealso: [](ch_vectors), `Vec`, `VecGetArrays()`, `VecRestoreArray()`
2262: @*/
2263: PetscErrorCode VecRestoreArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2264: {
2265:   PetscInt      i;
2266:   PetscScalar **q = *a;

2268:   PetscFunctionBegin;
2269:   PetscAssertPointer(x, 1);
2271:   PetscAssertPointer(a, 3);

2273:   for (i = 0; i < n; ++i) PetscCall(VecRestoreArray(x[i], &q[i]));
2274:   PetscCall(PetscFree(q));
2275:   PetscFunctionReturn(PETSC_SUCCESS);
2276: }

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

2283:   Logically Collective; No Fortran Support

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

2288:   Output Parameters:
2289: + a     - location to put pointer to the array
2290: - mtype - memory type of the array

2292:   Level: beginner

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

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

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

2305: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`,
2306:           `VecPlaceArray()`, `VecGetArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2307: @*/
2308: PetscErrorCode VecGetArrayAndMemType(Vec x, PetscScalar *a[], PetscMemType *mtype)
2309: {
2310:   PetscFunctionBegin;
2313:   PetscAssertPointer(a, 2);
2314:   if (mtype) PetscAssertPointer(mtype, 3);
2315:   PetscCall(VecSetErrorIfLocked(x, 1));
2316:   if (x->ops->getarrayandmemtype) {
2317:     /* VECCUDA, VECKOKKOS etc */
2318:     PetscUseTypeMethod(x, getarrayandmemtype, a, mtype);
2319:   } else {
2320:     /* VECSTANDARD, VECNEST, VECVIENNACL */
2321:     PetscCall(VecGetArray(x, a));
2322:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2323:   }
2324:   PetscFunctionReturn(PETSC_SUCCESS);
2325: }

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

2330:   Logically Collective; No Fortran Support

2332:   Input Parameters:
2333: + x - the vector
2334: - a - location of pointer to array obtained from `VecGetArrayAndMemType()`

2336:   Level: beginner

2338: .seealso: [](ch_vectors), `Vec`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`,
2339:           `VecPlaceArray()`, `VecRestoreArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2340: @*/
2341: PetscErrorCode VecRestoreArrayAndMemType(Vec x, PetscScalar *a[])
2342: {
2343:   PetscFunctionBegin;
2346:   if (a) PetscAssertPointer(a, 2);
2347:   if (x->ops->restorearrayandmemtype) {
2348:     /* VECCUDA, VECKOKKOS etc */
2349:     PetscUseTypeMethod(x, restorearrayandmemtype, a);
2350:   } else {
2351:     /* VECNEST, VECVIENNACL */
2352:     PetscCall(VecRestoreArray(x, a));
2353:   } /* VECSTANDARD does nothing */
2354:   if (a) *a = NULL;
2355:   PetscCall(PetscObjectStateIncrease((PetscObject)x));
2356:   PetscFunctionReturn(PETSC_SUCCESS);
2357: }

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

2363:   Not Collective; No Fortran Support

2365:   Input Parameter:
2366: . x - the vector

2368:   Output Parameters:
2369: + a     - the array
2370: - mtype - memory type of the array

2372:   Level: beginner

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

2377: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2378: @*/
2379: PetscErrorCode VecGetArrayReadAndMemType(Vec x, const PetscScalar *a[], PetscMemType *mtype)
2380: {
2381:   PetscFunctionBegin;
2384:   PetscAssertPointer(a, 2);
2385:   if (mtype) PetscAssertPointer(mtype, 3);
2386:   if (x->ops->getarrayreadandmemtype) {
2387:     /* VECCUDA/VECHIP though they are also petscnative */
2388:     PetscUseTypeMethod(x, getarrayreadandmemtype, a, mtype);
2389:   } else if (x->ops->getarrayandmemtype) {
2390:     /* VECKOKKOS */
2391:     PetscObjectState state;

2393:     // see VecGetArrayRead() for why
2394:     PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2395:     PetscUseTypeMethod(x, getarrayandmemtype, (PetscScalar **)a, mtype);
2396:     PetscCall(PetscObjectStateSet((PetscObject)x, state));
2397:   } else {
2398:     PetscCall(VecGetArrayRead(x, a));
2399:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2400:   }
2401:   PetscFunctionReturn(PETSC_SUCCESS);
2402: }

2404: /*@C
2405:   VecRestoreArrayReadAndMemType - Restore array obtained with `VecGetArrayReadAndMemType()`

2407:   Not Collective; No Fortran Support

2409:   Input Parameters:
2410: + x - the vector
2411: - a - the array

2413:   Level: beginner

2415: .seealso: [](ch_vectors), `Vec`, `VecGetArrayReadAndMemType()`, `VecRestoreArrayAndMemType()`, `VecRestoreArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2416: @*/
2417: PetscErrorCode VecRestoreArrayReadAndMemType(Vec x, const PetscScalar *a[])
2418: {
2419:   PetscFunctionBegin;
2422:   if (a) PetscAssertPointer(a, 2);
2423:   if (x->ops->restorearrayreadandmemtype) {
2424:     /* VECCUDA/VECHIP */
2425:     PetscUseTypeMethod(x, restorearrayreadandmemtype, a);
2426:   } else if (!x->petscnative) {
2427:     /* VECNEST */
2428:     PetscCall(VecRestoreArrayRead(x, a));
2429:   }
2430:   if (a) *a = NULL;
2431:   PetscFunctionReturn(PETSC_SUCCESS);
2432: }

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

2438:   Logically Collective; No Fortran Support

2440:   Input Parameter:
2441: . x - the vector

2443:   Output Parameters:
2444: + a     - the array
2445: - mtype - memory type of the array

2447:   Level: beginner

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

2452: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayWriteAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2453: @*/
2454: PetscErrorCode VecGetArrayWriteAndMemType(Vec x, PetscScalar *a[], PetscMemType *mtype)
2455: {
2456:   PetscFunctionBegin;
2459:   PetscCall(VecSetErrorIfLocked(x, 1));
2460:   PetscAssertPointer(a, 2);
2461:   if (mtype) PetscAssertPointer(mtype, 3);
2462:   if (x->ops->getarraywriteandmemtype) {
2463:     /* VECCUDA, VECHIP, VECKOKKOS etc, though they are also petscnative */
2464:     PetscUseTypeMethod(x, getarraywriteandmemtype, a, mtype);
2465:   } else if (x->ops->getarrayandmemtype) {
2466:     PetscCall(VecGetArrayAndMemType(x, a, mtype));
2467:   } else {
2468:     /* VECNEST, VECVIENNACL */
2469:     PetscCall(VecGetArrayWrite(x, a));
2470:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2471:   }
2472:   PetscFunctionReturn(PETSC_SUCCESS);
2473: }

2475: /*@C
2476:   VecRestoreArrayWriteAndMemType - Restore array obtained with `VecGetArrayWriteAndMemType()`

2478:   Logically Collective; No Fortran Support

2480:   Input Parameters:
2481: + x - the vector
2482: - a - the array

2484:   Level: beginner

2486: .seealso: [](ch_vectors), `Vec`, `VecGetArrayWriteAndMemType()`, `VecRestoreArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2487: @*/
2488: PetscErrorCode VecRestoreArrayWriteAndMemType(Vec x, PetscScalar *a[])
2489: {
2490:   PetscFunctionBegin;
2493:   PetscCall(VecSetErrorIfLocked(x, 1));
2494:   if (a) PetscAssertPointer(a, 2);
2495:   if (x->ops->restorearraywriteandmemtype) {
2496:     /* VECCUDA/VECHIP */
2497:     PetscMemType PETSC_UNUSED mtype; // since this function doesn't accept a memtype?
2498:     PetscUseTypeMethod(x, restorearraywriteandmemtype, a, &mtype);
2499:   } else if (x->ops->restorearrayandmemtype) {
2500:     PetscCall(VecRestoreArrayAndMemType(x, a));
2501:   } else {
2502:     PetscCall(VecRestoreArray(x, a));
2503:   }
2504:   if (a) *a = NULL;
2505:   PetscFunctionReturn(PETSC_SUCCESS);
2506: }

2508: /*@
2509:   VecPlaceArray - Allows one to replace the array in a vector with an
2510:   array provided by the user. This is useful to avoid copying an array
2511:   into a vector.

2513:   Logically Collective; No Fortran Support

2515:   Input Parameters:
2516: + vec   - the vector
2517: - array - the array

2519:   Level: developer

2521:   Notes:
2522:   Use `VecReplaceArray()` instead to permanently replace the array

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

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

2531: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`
2532: @*/
2533: PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2534: {
2535:   PetscFunctionBegin;
2538:   if (array) PetscAssertPointer(array, 2);
2539:   PetscUseTypeMethod(vec, placearray, array);
2540:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2541:   PetscFunctionReturn(PETSC_SUCCESS);
2542: }

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

2549:   Logically Collective; No Fortran Support

2551:   Input Parameters:
2552: + vec   - the vector
2553: - array - the array

2555:   Level: developer

2557:   Notes:
2558:   This permanently replaces the array and frees the memory associated
2559:   with the old array. Use `VecPlaceArray()` to temporarily replace the array.

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

2564: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`
2565: @*/
2566: PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2567: {
2568:   PetscFunctionBegin;
2571:   PetscUseTypeMethod(vec, replacearray, array);
2572:   PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2573:   PetscFunctionReturn(PETSC_SUCCESS);
2574: }

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

2581:   Logically Collective

2583:   Input Parameters:
2584: + x      - the vector
2585: . m      - first dimension of two dimensional array
2586: . n      - second dimension of two dimensional array
2587: . mstart - first index you will use in first coordinate direction (often 0)
2588: - nstart - first index in the second coordinate direction (often 0)

2590:   Output Parameter:
2591: . a - location to put pointer to the array

2593:   Level: developer

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

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

2603: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2604:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2605:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2606: @*/
2607: PetscErrorCode VecGetArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2608: {
2609:   PetscInt     i, N;
2610:   PetscScalar *aa;

2612:   PetscFunctionBegin;
2614:   PetscAssertPointer(a, 6);
2616:   PetscCall(VecGetLocalSize(x, &N));
2617:   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);
2618:   PetscCall(VecGetArray(x, &aa));

2620:   PetscCall(PetscMalloc1(m, a));
2621:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2622:   *a -= mstart;
2623:   PetscFunctionReturn(PETSC_SUCCESS);
2624: }

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

2631:   Logically Collective

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

2640:   Output Parameter:
2641: . a - location to put pointer to the array

2643:   Level: developer

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

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

2653: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2654:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2655:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2656: @*/
2657: PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2658: {
2659:   PetscInt     i, N;
2660:   PetscScalar *aa;

2662:   PetscFunctionBegin;
2664:   PetscAssertPointer(a, 6);
2666:   PetscCall(VecGetLocalSize(x, &N));
2667:   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);
2668:   PetscCall(VecGetArrayWrite(x, &aa));

2670:   PetscCall(PetscMalloc1(m, a));
2671:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2672:   *a -= mstart;
2673:   PetscFunctionReturn(PETSC_SUCCESS);
2674: }

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

2679:   Logically Collective

2681:   Input Parameters:
2682: + x      - the vector
2683: . m      - first dimension of two dimensional array
2684: . n      - second dimension of the two dimensional array
2685: . mstart - first index you will use in first coordinate direction (often 0)
2686: . nstart - first index in the second coordinate direction (often 0)
2687: - a      - location of pointer to array obtained from `VecGetArray2d()`

2689:   Level: developer

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

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

2699: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2700:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2701:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2702: @*/
2703: PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2704: {
2705:   void *dummy;

2707:   PetscFunctionBegin;
2709:   PetscAssertPointer(a, 6);
2711:   dummy = (void *)(*a + mstart);
2712:   PetscCall(PetscFree(dummy));
2713:   PetscCall(VecRestoreArray(x, NULL));
2714:   *a = NULL;
2715:   PetscFunctionReturn(PETSC_SUCCESS);
2716: }

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

2721:   Logically Collective

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

2731:   Level: developer

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

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

2741: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2742:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2743:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2744: @*/
2745: PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2746: {
2747:   void *dummy;

2749:   PetscFunctionBegin;
2751:   PetscAssertPointer(a, 6);
2753:   dummy = (void *)(*a + mstart);
2754:   PetscCall(PetscFree(dummy));
2755:   PetscCall(VecRestoreArrayWrite(x, NULL));
2756:   PetscFunctionReturn(PETSC_SUCCESS);
2757: }

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

2764:   Logically Collective

2766:   Input Parameters:
2767: + x      - the vector
2768: . m      - first dimension of two dimensional array
2769: - mstart - first index you will use in first coordinate direction (often 0)

2771:   Output Parameter:
2772: . a - location to put pointer to the array

2774:   Level: developer

2776:   Notes:
2777:   For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
2778:   obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2779:   `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

2783: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2784:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2785:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2786: @*/
2787: PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2788: {
2789:   PetscInt N;

2791:   PetscFunctionBegin;
2793:   PetscAssertPointer(a, 4);
2795:   PetscCall(VecGetLocalSize(x, &N));
2796:   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);
2797:   PetscCall(VecGetArray(x, a));
2798:   *a -= mstart;
2799:   PetscFunctionReturn(PETSC_SUCCESS);
2800: }

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

2807:   Logically Collective

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

2814:   Output Parameter:
2815: . a - location to put pointer to the array

2817:   Level: developer

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

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

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

2834:   PetscFunctionBegin;
2836:   PetscAssertPointer(a, 4);
2838:   PetscCall(VecGetLocalSize(x, &N));
2839:   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);
2840:   PetscCall(VecGetArrayWrite(x, a));
2841:   *a -= mstart;
2842:   PetscFunctionReturn(PETSC_SUCCESS);
2843: }

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

2848:   Logically Collective

2850:   Input Parameters:
2851: + x      - the vector
2852: . m      - first dimension of two dimensional array
2853: . mstart - first index you will use in first coordinate direction (often 0)
2854: - a      - location of pointer to array obtained from `VecGetArray1d()`

2856:   Level: developer

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

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

2866: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2867:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2868:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2869: @*/
2870: PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2871: {
2872:   PetscFunctionBegin;
2875:   PetscCall(VecRestoreArray(x, NULL));
2876:   *a = NULL;
2877:   PetscFunctionReturn(PETSC_SUCCESS);
2878: }

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

2883:   Logically Collective

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

2891:   Level: developer

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

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

2901: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2902:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2903:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2904: @*/
2905: PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2906: {
2907:   PetscFunctionBegin;
2910:   PetscCall(VecRestoreArrayWrite(x, NULL));
2911:   *a = NULL;
2912:   PetscFunctionReturn(PETSC_SUCCESS);
2913: }

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

2920:   Logically Collective

2922:   Input Parameters:
2923: + x      - the vector
2924: . m      - first dimension of three dimensional array
2925: . n      - second dimension of three dimensional array
2926: . p      - third dimension of three dimensional array
2927: . mstart - first index you will use in first coordinate direction (often 0)
2928: . nstart - first index in the second coordinate direction (often 0)
2929: - pstart - first index in the third coordinate direction (often 0)

2931:   Output Parameter:
2932: . a - location to put pointer to the array

2934:   Level: developer

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

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

2944: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2945:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecRestoreArray3d()`,
2946:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2947: @*/
2948: PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
2949: {
2950:   PetscInt     i, N, j;
2951:   PetscScalar *aa, **b;

2953:   PetscFunctionBegin;
2955:   PetscAssertPointer(a, 8);
2957:   PetscCall(VecGetLocalSize(x, &N));
2958:   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);
2959:   PetscCall(VecGetArray(x, &aa));

2961:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
2962:   b = (PetscScalar **)((*a) + m);
2963:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
2964:   for (i = 0; i < m; i++)
2965:     for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset(aa, i * n * p + j * p - pstart);
2966:   *a -= mstart;
2967:   PetscFunctionReturn(PETSC_SUCCESS);
2968: }

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

2975:   Logically Collective

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

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

2989:   Level: developer

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

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

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

3008:   PetscFunctionBegin;
3010:   PetscAssertPointer(a, 8);
3012:   PetscCall(VecGetLocalSize(x, &N));
3013:   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);
3014:   PetscCall(VecGetArrayWrite(x, &aa));

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

3022:   *a -= mstart;
3023:   PetscFunctionReturn(PETSC_SUCCESS);
3024: }

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

3029:   Logically Collective

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

3041:   Level: developer

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

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

3051: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3052:           `VecGetArray2d()`, `VecGetArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3053:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3054: @*/
3055: PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3056: {
3057:   void *dummy;

3059:   PetscFunctionBegin;
3061:   PetscAssertPointer(a, 8);
3063:   dummy = (void *)(*a + mstart);
3064:   PetscCall(PetscFree(dummy));
3065:   PetscCall(VecRestoreArray(x, NULL));
3066:   *a = NULL;
3067:   PetscFunctionReturn(PETSC_SUCCESS);
3068: }

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

3073:   Logically Collective

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

3085:   Level: developer

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

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

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

3103:   PetscFunctionBegin;
3105:   PetscAssertPointer(a, 8);
3107:   dummy = (void *)(*a + mstart);
3108:   PetscCall(PetscFree(dummy));
3109:   PetscCall(VecRestoreArrayWrite(x, NULL));
3110:   *a = NULL;
3111:   PetscFunctionReturn(PETSC_SUCCESS);
3112: }

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

3119:   Logically Collective

3121:   Input Parameters:
3122: + x      - the vector
3123: . m      - first dimension of four dimensional array
3124: . n      - second dimension of four dimensional array
3125: . p      - third dimension of four dimensional array
3126: . q      - fourth dimension of four dimensional array
3127: . mstart - first index you will use in first coordinate direction (often 0)
3128: . nstart - first index in the second coordinate direction (often 0)
3129: . pstart - first index in the third coordinate direction (often 0)
3130: - qstart - first index in the fourth coordinate direction (often 0)

3132:   Output Parameter:
3133: . a - location to put pointer to the array

3135:   Level: developer

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

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

3145: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3146:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3147:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecRestoreArray4d()`
3148: @*/
3149: PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3150: {
3151:   PetscInt     i, N, j, k;
3152:   PetscScalar *aa, ***b, **c;

3154:   PetscFunctionBegin;
3156:   PetscAssertPointer(a, 10);
3158:   PetscCall(VecGetLocalSize(x, &N));
3159:   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);
3160:   PetscCall(VecGetArray(x, &aa));

3162:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3163:   b = (PetscScalar ***)((*a) + m);
3164:   c = (PetscScalar **)(b + m * n);
3165:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3166:   for (i = 0; i < m; i++)
3167:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3168:   for (i = 0; i < m; i++)
3169:     for (j = 0; j < n; j++)
3170:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3171:   *a -= mstart;
3172:   PetscFunctionReturn(PETSC_SUCCESS);
3173: }

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

3180:   Logically Collective

3182:   Input Parameters:
3183: + x      - the vector
3184: . m      - first dimension of four dimensional array
3185: . n      - second dimension of four dimensional array
3186: . p      - third dimension of four dimensional array
3187: . q      - fourth dimension of four dimensional array
3188: . mstart - first index you will use in first coordinate direction (often 0)
3189: . nstart - first index in the second coordinate direction (often 0)
3190: . pstart - first index in the third coordinate direction (often 0)
3191: - qstart - first index in the fourth coordinate direction (often 0)

3193:   Output Parameter:
3194: . a - location to put pointer to the array

3196:   Level: developer

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

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

3206: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3207:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3208:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3209: @*/
3210: PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3211: {
3212:   PetscInt     i, N, j, k;
3213:   PetscScalar *aa, ***b, **c;

3215:   PetscFunctionBegin;
3217:   PetscAssertPointer(a, 10);
3219:   PetscCall(VecGetLocalSize(x, &N));
3220:   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);
3221:   PetscCall(VecGetArrayWrite(x, &aa));

3223:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3224:   b = (PetscScalar ***)((*a) + m);
3225:   c = (PetscScalar **)(b + m * n);
3226:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3227:   for (i = 0; i < m; i++)
3228:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3229:   for (i = 0; i < m; i++)
3230:     for (j = 0; j < n; j++)
3231:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3232:   *a -= mstart;
3233:   PetscFunctionReturn(PETSC_SUCCESS);
3234: }

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

3239:   Logically Collective

3241:   Input Parameters:
3242: + x      - the vector
3243: . m      - first dimension of four dimensional array
3244: . n      - second dimension of the four dimensional array
3245: . p      - third dimension of the four dimensional array
3246: . q      - fourth dimension of the four dimensional array
3247: . mstart - first index you will use in first coordinate direction (often 0)
3248: . nstart - first index in the second coordinate direction (often 0)
3249: . pstart - first index in the third coordinate direction (often 0)
3250: . qstart - first index in the fourth coordinate direction (often 0)
3251: - a      - location of pointer to array obtained from VecGetArray4d()

3253:   Level: developer

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

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

3263: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3264:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3265:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`
3266: @*/
3267: PetscErrorCode VecRestoreArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3268: {
3269:   void *dummy;

3271:   PetscFunctionBegin;
3273:   PetscAssertPointer(a, 10);
3275:   dummy = (void *)(*a + mstart);
3276:   PetscCall(PetscFree(dummy));
3277:   PetscCall(VecRestoreArray(x, NULL));
3278:   *a = NULL;
3279:   PetscFunctionReturn(PETSC_SUCCESS);
3280: }

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

3285:   Logically Collective

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

3299:   Level: developer

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

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

3309: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3310:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3311:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3312: @*/
3313: PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3314: {
3315:   void *dummy;

3317:   PetscFunctionBegin;
3319:   PetscAssertPointer(a, 10);
3321:   dummy = (void *)(*a + mstart);
3322:   PetscCall(PetscFree(dummy));
3323:   PetscCall(VecRestoreArrayWrite(x, NULL));
3324:   *a = NULL;
3325:   PetscFunctionReturn(PETSC_SUCCESS);
3326: }

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

3333:   Logically Collective

3335:   Input Parameters:
3336: + x      - the vector
3337: . m      - first dimension of two dimensional array
3338: . n      - second dimension of two dimensional array
3339: . mstart - first index you will use in first coordinate direction (often 0)
3340: - nstart - first index in the second coordinate direction (often 0)

3342:   Output Parameter:
3343: . a - location to put pointer to the array

3345:   Level: developer

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

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

3355: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3356:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3357:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3358: @*/
3359: PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3360: {
3361:   PetscInt           i, N;
3362:   const PetscScalar *aa;

3364:   PetscFunctionBegin;
3366:   PetscAssertPointer(a, 6);
3368:   PetscCall(VecGetLocalSize(x, &N));
3369:   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);
3370:   PetscCall(VecGetArrayRead(x, &aa));

3372:   PetscCall(PetscMalloc1(m, a));
3373:   for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3374:   *a -= mstart;
3375:   PetscFunctionReturn(PETSC_SUCCESS);
3376: }

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

3381:   Logically Collective

3383:   Input Parameters:
3384: + x      - the vector
3385: . m      - first dimension of two dimensional array
3386: . n      - second dimension of the two dimensional array
3387: . mstart - first index you will use in first coordinate direction (often 0)
3388: . nstart - first index in the second coordinate direction (often 0)
3389: - a      - location of pointer to array obtained from VecGetArray2d()

3391:   Level: developer

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

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

3401: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3402:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3403:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3404: @*/
3405: PetscErrorCode VecRestoreArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3406: {
3407:   void *dummy;

3409:   PetscFunctionBegin;
3411:   PetscAssertPointer(a, 6);
3413:   dummy = (void *)(*a + mstart);
3414:   PetscCall(PetscFree(dummy));
3415:   PetscCall(VecRestoreArrayRead(x, NULL));
3416:   *a = NULL;
3417:   PetscFunctionReturn(PETSC_SUCCESS);
3418: }

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

3425:   Logically Collective

3427:   Input Parameters:
3428: + x      - the vector
3429: . m      - first dimension of two dimensional array
3430: - mstart - first index you will use in first coordinate direction (often 0)

3432:   Output Parameter:
3433: . a - location to put pointer to the array

3435:   Level: developer

3437:   Notes:
3438:   For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
3439:   obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3440:   `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.

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

3444: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3445:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3446:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3447: @*/
3448: PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3449: {
3450:   PetscInt N;

3452:   PetscFunctionBegin;
3454:   PetscAssertPointer(a, 4);
3456:   PetscCall(VecGetLocalSize(x, &N));
3457:   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);
3458:   PetscCall(VecGetArrayRead(x, (const PetscScalar **)a));
3459:   *a -= mstart;
3460:   PetscFunctionReturn(PETSC_SUCCESS);
3461: }

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

3466:   Logically Collective

3468:   Input Parameters:
3469: + x      - the vector
3470: . m      - first dimension of two dimensional array
3471: . mstart - first index you will use in first coordinate direction (often 0)
3472: - a      - location of pointer to array obtained from `VecGetArray1dRead()`

3474:   Level: developer

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

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

3484: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3485:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3486:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3487: @*/
3488: PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3489: {
3490:   PetscFunctionBegin;
3493:   PetscCall(VecRestoreArrayRead(x, NULL));
3494:   *a = NULL;
3495:   PetscFunctionReturn(PETSC_SUCCESS);
3496: }

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

3503:   Logically Collective

3505:   Input Parameters:
3506: + x      - the vector
3507: . m      - first dimension of three dimensional array
3508: . n      - second dimension of three dimensional array
3509: . p      - third dimension of three 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)

3514:   Output Parameter:
3515: . a - location to put pointer to the array

3517:   Level: developer

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

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

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

3537:   PetscFunctionBegin;
3539:   PetscAssertPointer(a, 8);
3541:   PetscCall(VecGetLocalSize(x, &N));
3542:   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);
3543:   PetscCall(VecGetArrayRead(x, &aa));

3545:   PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3546:   b = (PetscScalar **)((*a) + m);
3547:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3548:   for (i = 0; i < m; i++)
3549:     for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset((PetscScalar *)aa, i * n * p + j * p - pstart);
3550:   *a -= mstart;
3551:   PetscFunctionReturn(PETSC_SUCCESS);
3552: }

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

3557:   Logically Collective

3559:   Input Parameters:
3560: + x      - the vector
3561: . m      - first dimension of three dimensional array
3562: . n      - second dimension of the three dimensional array
3563: . p      - third dimension of the three dimensional array
3564: . mstart - first index you will use in first coordinate direction (often 0)
3565: . nstart - first index in the second coordinate direction (often 0)
3566: . pstart - first index in the third coordinate direction (often 0)
3567: - a      - location of pointer to array obtained from `VecGetArray3dRead()`

3569:   Level: developer

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

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

3579: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3580:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3581:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3582: @*/
3583: PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3584: {
3585:   void *dummy;

3587:   PetscFunctionBegin;
3589:   PetscAssertPointer(a, 8);
3591:   dummy = (void *)(*a + mstart);
3592:   PetscCall(PetscFree(dummy));
3593:   PetscCall(VecRestoreArrayRead(x, NULL));
3594:   *a = NULL;
3595:   PetscFunctionReturn(PETSC_SUCCESS);
3596: }

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

3603:   Logically Collective

3605:   Input Parameters:
3606: + x      - the vector
3607: . m      - first dimension of four dimensional array
3608: . n      - second dimension of four dimensional array
3609: . p      - third dimension of four dimensional array
3610: . q      - fourth dimension of four dimensional array
3611: . mstart - first index you will use in first coordinate direction (often 0)
3612: . nstart - first index in the second coordinate direction (often 0)
3613: . pstart - first index in the third coordinate direction (often 0)
3614: - qstart - first index in the fourth coordinate direction (often 0)

3616:   Output Parameter:
3617: . a - location to put pointer to the array

3619:   Level: beginner

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

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

3629: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3630:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3631:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3632: @*/
3633: PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3634: {
3635:   PetscInt           i, N, j, k;
3636:   const PetscScalar *aa;
3637:   PetscScalar     ***b, **c;

3639:   PetscFunctionBegin;
3641:   PetscAssertPointer(a, 10);
3643:   PetscCall(VecGetLocalSize(x, &N));
3644:   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);
3645:   PetscCall(VecGetArrayRead(x, &aa));

3647:   PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3648:   b = (PetscScalar ***)((*a) + m);
3649:   c = (PetscScalar **)(b + m * n);
3650:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3651:   for (i = 0; i < m; i++)
3652:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3653:   for (i = 0; i < m; i++)
3654:     for (j = 0; j < n; j++)
3655:       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;
3656:   *a -= mstart;
3657:   PetscFunctionReturn(PETSC_SUCCESS);
3658: }

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

3663:   Logically Collective

3665:   Input Parameters:
3666: + x      - the vector
3667: . m      - first dimension of four dimensional array
3668: . n      - second dimension of the four dimensional array
3669: . p      - third dimension of the four dimensional array
3670: . q      - fourth dimension of the four dimensional array
3671: . mstart - first index you will use in first coordinate direction (often 0)
3672: . nstart - first index in the second coordinate direction (often 0)
3673: . pstart - first index in the third coordinate direction (often 0)
3674: . qstart - first index in the fourth coordinate direction (often 0)
3675: - a      - location of pointer to array obtained from `VecGetArray4dRead()`

3677:   Level: beginner

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

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

3687: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3688:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3689:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3690: @*/
3691: PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3692: {
3693:   void *dummy;

3695:   PetscFunctionBegin;
3697:   PetscAssertPointer(a, 10);
3699:   dummy = (void *)(*a + mstart);
3700:   PetscCall(PetscFree(dummy));
3701:   PetscCall(VecRestoreArrayRead(x, NULL));
3702:   *a = NULL;
3703:   PetscFunctionReturn(PETSC_SUCCESS);
3704: }

3706: /*@
3707:   VecLockGet - Get the current lock status of a vector

3709:   Logically Collective

3711:   Input Parameter:
3712: . x - the vector

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

3718:   Level: advanced

3720: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
3721: @*/
3722: PetscErrorCode VecLockGet(Vec x, PetscInt *state)
3723: {
3724:   PetscFunctionBegin;
3726:   PetscAssertPointer(state, 2);
3727:   *state = x->lock;
3728:   PetscFunctionReturn(PETSC_SUCCESS);
3729: }

3731: PetscErrorCode VecLockGetLocation(Vec x, const char *file[], const char *func[], int *line)
3732: {
3733:   PetscFunctionBegin;
3735:   PetscAssertPointer(file, 2);
3736:   PetscAssertPointer(func, 3);
3737:   PetscAssertPointer(line, 4);
3738: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3739:   {
3740:     const int index = x->lockstack.currentsize - 1;

3742:     *file = index < 0 ? NULL : x->lockstack.file[index];
3743:     *func = index < 0 ? NULL : x->lockstack.function[index];
3744:     *line = index < 0 ? 0 : x->lockstack.line[index];
3745:   }
3746: #else
3747:   *file = NULL;
3748:   *func = NULL;
3749:   *line = 0;
3750: #endif
3751:   PetscFunctionReturn(PETSC_SUCCESS);
3752: }

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

3757:   Logically Collective

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

3762:   Level: intermediate

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

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

3770: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPop()`, `VecLockGet()`
3771: @*/
3772: PetscErrorCode VecLockReadPush(Vec x)
3773: {
3774:   PetscFunctionBegin;
3776:   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");
3777: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3778:   {
3779:     const char *file, *func;
3780:     int         index, line;

3782:     if ((index = petscstack.currentsize - 2) < 0) {
3783:       // vec was locked "outside" of petsc, either in user-land or main. the error message will
3784:       // now show this function as the culprit, but it will include the stacktrace
3785:       file = "unknown user-file";
3786:       func = "unknown_user_function";
3787:       line = 0;
3788:     } else {
3789:       file = petscstack.file[index];
3790:       func = petscstack.function[index];
3791:       line = petscstack.line[index];
3792:     }
3793:     PetscStackPush_Private(x->lockstack, file, func, line, petscstack.petscroutine[index], PETSC_FALSE);
3794:   }
3795: #endif
3796:   PetscFunctionReturn(PETSC_SUCCESS);
3797: }

3799: /*@
3800:   VecLockReadPop - Pop a read-only lock from a vector

3802:   Logically Collective

3804:   Input Parameter:
3805: . x - the vector

3807:   Level: intermediate

3809: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockGet()`
3810: @*/
3811: PetscErrorCode VecLockReadPop(Vec x)
3812: {
3813:   PetscFunctionBegin;
3815:   PetscCheck(--x->lock >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector has been unlocked from read-only access too many times");
3816: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3817:   {
3818:     const char *previous = x->lockstack.function[x->lockstack.currentsize - 1];

3820:     PetscStackPop_Private(x->lockstack, previous);
3821:   }
3822: #endif
3823:   PetscFunctionReturn(PETSC_SUCCESS);
3824: }

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

3829:   Logically Collective

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

3835:   Level: intermediate

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

3843: .vb
3844:        VecGetArray(x,&xdata); // begin phase
3845:        VecLockWriteSet(v,PETSC_TRUE);

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

3849:        VecRestoreArray(x,&vdata); // end phase
3850:        VecLockWriteSet(v,PETSC_FALSE);
3851: .ve

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

3856: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
3857: @*/
3858: PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
3859: {
3860:   PetscFunctionBegin;
3862:   if (flg) {
3863:     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");
3864:     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");
3865:     x->lock = -1;
3866:   } else {
3867:     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");
3868:     x->lock = 0;
3869:   }
3870:   PetscFunctionReturn(PETSC_SUCCESS);
3871: }