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: .vb
94: val = (x,y) = y^H x,
95: .ve
96: where y^H denotes the conjugate transpose of y. Note that this corresponds to the usual "mathematicians" complex
97: inner product where the SECOND argument gets the complex conjugate. Since the `BLASdot()` complex conjugates the first
98: first argument we call the `BLASdot()` with the arguments reversed.
100: Use `VecTDot()` for the indefinite form
101: .vb
102: val = (x,y) = y^T x,
103: .ve
104: where y^T denotes the transpose of y.
106: .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDotRealPart()`
107: @*/
108: PetscErrorCode VecDot(Vec x, Vec y, PetscScalar *val)
109: {
110: PetscFunctionBegin;
113: PetscAssertPointer(val, 3);
116: PetscCheckSameTypeAndComm(x, 1, y, 2);
117: VecCheckSameSize(x, 1, y, 2);
118: VecCheckAssembled(x);
119: VecCheckAssembled(y);
121: PetscCall(VecLockReadPush(x));
122: PetscCall(VecLockReadPush(y));
123: PetscCall(PetscLogEventBegin(VEC_Dot, x, y, 0, 0));
124: PetscUseTypeMethod(x, dot, y, val);
125: PetscCall(PetscLogEventEnd(VEC_Dot, x, y, 0, 0));
126: PetscCall(VecLockReadPop(x));
127: PetscCall(VecLockReadPop(y));
128: PetscFunctionReturn(PETSC_SUCCESS);
129: }
131: /*@
132: VecDotRealPart - Computes the real part of the vector dot product.
134: Collective
136: Input Parameters:
137: + x - first vector
138: - y - second vector
140: Output Parameter:
141: . val - the real part of the dot product;
143: Level: intermediate
145: Notes for Users of Complex Numbers:
146: See `VecDot()` for more details on the definition of the dot product for complex numbers
148: For real numbers this returns the same value as `VecDot()`
150: 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
151: the space R^{2n} (that is a vector of 2n components with the real or imaginary part of the complex numbers for components)
153: Developer Notes:
154: This is not currently optimized to compute only the real part of the dot product.
156: .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDot()`, `VecDotNorm2()`
157: @*/
158: PetscErrorCode VecDotRealPart(Vec x, Vec y, PetscReal *val)
159: {
160: PetscScalar fdot;
162: PetscFunctionBegin;
163: PetscCall(VecDot(x, y, &fdot));
164: *val = PetscRealPart(fdot);
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: /*@
169: VecNorm - Computes the vector norm.
171: Collective
173: Input Parameters:
174: + x - the vector
175: - type - the type of the norm requested
177: Output Parameter:
178: . val - the norm
180: Level: intermediate
182: Notes:
183: See `NormType` for descriptions of each norm.
185: For complex numbers `NORM_1` will return the traditional 1 norm of the 2 norm of the complex
186: numbers; that is the 1 norm of the absolute values of the complex entries. In PETSc 3.6 and
187: earlier releases it returned the 1 norm of the 1 norm of the complex entries (what is
188: returned by the BLAS routine `asum()`). Both are valid norms but most people expect the former.
190: This routine stashes the computed norm value, repeated calls before the vector entries are
191: changed are then rapid since the precomputed value is immediately available. Certain vector
192: operations such as `VecSet()` store the norms so the value is immediately available and does
193: not need to be explicitly computed. `VecScale()` updates any stashed norm values, thus calls
194: after `VecScale()` do not need to explicitly recompute the norm.
196: .seealso: [](ch_vectors), `Vec`, `NormType`, `VecDot()`, `VecTDot()`, `VecDotBegin()`, `VecDotEnd()`, `VecNormAvailable()`,
197: `VecNormBegin()`, `VecNormEnd()`, `NormType()`
198: @*/
199: PetscErrorCode VecNorm(Vec x, NormType type, PetscReal *val)
200: {
201: PetscBool flg = PETSC_TRUE;
203: PetscFunctionBegin;
204: PetscCall(VecLockReadPush(x));
207: VecCheckAssembled(x);
209: PetscAssertPointer(val, 3);
211: PetscCall(VecNormAvailable(x, type, &flg, val));
212: // check that all MPI processes call this routine together and have same availability
213: if (PetscDefined(USE_DEBUG)) {
214: PetscMPIInt b0 = (PetscMPIInt)flg, b1[2], b2[2];
215: b1[0] = -b0;
216: b1[1] = b0;
217: PetscCallMPI(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, PetscObjectComm((PetscObject)x)));
218: 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]);
219: if (flg) {
220: PetscReal b1[2], b2[2];
221: b1[0] = -(*val);
222: b1[1] = *val;
223: PetscCallMPI(MPIU_Allreduce(b1, b2, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)x)));
224: 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);
225: }
226: }
227: if (!flg) {
228: PetscCall(PetscLogEventBegin(VEC_Norm, x, 0, 0, 0));
229: PetscUseTypeMethod(x, norm, type, val);
230: PetscCall(PetscLogEventEnd(VEC_Norm, x, 0, 0, 0));
232: if (type != NORM_1_AND_2) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[type], *val));
233: }
234: PetscCall(VecLockReadPop(x));
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: /*@
239: VecNormAvailable - Returns the vector norm if it is already known. That is, it has been previously computed and cached in the vector
241: Not Collective
243: Input Parameters:
244: + x - the vector
245: - 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
246: `NORM_1_AND_2`, which computes both norms and stores them
247: in a two element array.
249: Output Parameters:
250: + available - `PETSC_TRUE` if the val returned is valid
251: - val - the norm
253: Level: intermediate
255: .seealso: [](ch_vectors), `Vec`, `VecDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`,
256: `VecNormBegin()`, `VecNormEnd()`
257: @*/
258: PetscErrorCode VecNormAvailable(Vec x, NormType type, PetscBool *available, PetscReal *val)
259: {
260: PetscFunctionBegin;
263: PetscAssertPointer(available, 3);
264: PetscAssertPointer(val, 4);
266: if (type == NORM_1_AND_2) {
267: *available = PETSC_FALSE;
268: } else {
269: PetscCall(PetscObjectComposedDataGetReal((PetscObject)x, NormIds[type], *val, *available));
270: }
271: PetscFunctionReturn(PETSC_SUCCESS);
272: }
274: /*@
275: VecNormalize - Normalizes a vector by its 2-norm.
277: Collective
279: Input Parameter:
280: . x - the vector
282: Output Parameter:
283: . val - the vector norm before normalization. May be `NULL` if the value is not needed.
285: Level: intermediate
287: .seealso: [](ch_vectors), `Vec`, `VecNorm()`, `NORM_2`, `NormType`
288: @*/
289: PetscErrorCode VecNormalize(Vec x, PetscReal *val)
290: {
291: PetscReal norm;
293: PetscFunctionBegin;
296: PetscCall(VecSetErrorIfLocked(x, 1));
297: if (val) PetscAssertPointer(val, 2);
298: PetscCall(PetscLogEventBegin(VEC_Normalize, x, 0, 0, 0));
299: PetscCall(VecNorm(x, NORM_2, &norm));
300: if (norm == 0.0) PetscCall(PetscInfo(x, "Vector of zero norm can not be normalized; Returning only the zero norm\n"));
301: else if (PetscIsInfOrNanReal(norm)) PetscCall(PetscInfo(x, "Vector with Inf or Nan norm can not be normalized; Returning only the norm\n"));
302: else {
303: PetscScalar s = 1.0 / norm;
304: PetscCall(VecScale(x, s));
305: }
306: PetscCall(PetscLogEventEnd(VEC_Normalize, x, 0, 0, 0));
307: if (val) *val = norm;
308: PetscFunctionReturn(PETSC_SUCCESS);
309: }
311: /*@
312: VecMax - Determines the vector component with maximum real part and its location.
314: Collective
316: Input Parameter:
317: . x - the vector
319: Output Parameters:
320: + p - the index of `val` (pass `NULL` if you don't want this) in the vector
321: - val - the maximum component
323: Level: intermediate
325: Notes:
326: Returns the value `PETSC_MIN_REAL` and negative `p` if the vector is of length 0.
328: Returns the smallest index with the maximum value
330: Developer Note:
331: The Nag Fortran compiler does not like the symbol name VecMax
333: .seealso: [](ch_vectors), `Vec`, `VecNorm()`, `VecMin()`
334: @*/
335: PetscErrorCode VecMax(Vec x, PetscInt *p, PetscReal *val)
336: {
337: PetscFunctionBegin;
340: VecCheckAssembled(x);
341: if (p) PetscAssertPointer(p, 2);
342: PetscAssertPointer(val, 3);
343: PetscCall(VecLockReadPush(x));
344: PetscCall(PetscLogEventBegin(VEC_Max, x, 0, 0, 0));
345: PetscUseTypeMethod(x, max, p, val);
346: PetscCall(PetscLogEventEnd(VEC_Max, x, 0, 0, 0));
347: PetscCall(VecLockReadPop(x));
348: PetscFunctionReturn(PETSC_SUCCESS);
349: }
351: /*@
352: VecMin - Determines the vector component with minimum real part and its location.
354: Collective
356: Input Parameter:
357: . x - the vector
359: Output Parameters:
360: + p - the index of `val` (pass `NULL` if you don't want this location) in the vector
361: - val - the minimum component
363: Level: intermediate
365: Notes:
366: Returns the value `PETSC_MAX_REAL` and negative `p` if the vector is of length 0.
368: This returns the smallest index with the minimum value
370: Developer Note:
371: The Nag Fortran compiler does not like the symbol name VecMin
373: .seealso: [](ch_vectors), `Vec`, `VecMax()`
374: @*/
375: PetscErrorCode VecMin(Vec x, PetscInt *p, PetscReal *val)
376: {
377: PetscFunctionBegin;
380: VecCheckAssembled(x);
381: if (p) PetscAssertPointer(p, 2);
382: PetscAssertPointer(val, 3);
383: PetscCall(VecLockReadPush(x));
384: PetscCall(PetscLogEventBegin(VEC_Min, x, 0, 0, 0));
385: PetscUseTypeMethod(x, min, p, val);
386: PetscCall(PetscLogEventEnd(VEC_Min, x, 0, 0, 0));
387: PetscCall(VecLockReadPop(x));
388: PetscFunctionReturn(PETSC_SUCCESS);
389: }
391: /*@
392: VecTDot - Computes an indefinite vector dot product. That is, this
393: routine does NOT use the complex conjugate.
395: Collective
397: Input Parameters:
398: + x - first vector
399: - y - second vector
401: Output Parameter:
402: . val - the dot product
404: Level: intermediate
406: Notes for Users of Complex Numbers:
407: For complex vectors, `VecTDot()` computes the indefinite form
408: .vb
409: val = (x,y) = y^T x,
410: .ve
411: where y^T denotes the transpose of y.
413: Use `VecDot()` for the inner product
414: .vb
415: val = (x,y) = y^H x,
416: .ve
417: where y^H denotes the conjugate transpose of y.
419: .seealso: [](ch_vectors), `Vec`, `VecDot()`, `VecMTDot()`
420: @*/
421: PetscErrorCode VecTDot(Vec x, Vec y, PetscScalar *val)
422: {
423: PetscFunctionBegin;
426: PetscAssertPointer(val, 3);
429: PetscCheckSameTypeAndComm(x, 1, y, 2);
430: VecCheckSameSize(x, 1, y, 2);
431: VecCheckAssembled(x);
432: VecCheckAssembled(y);
434: PetscCall(VecLockReadPush(x));
435: PetscCall(VecLockReadPush(y));
436: PetscCall(PetscLogEventBegin(VEC_TDot, x, y, 0, 0));
437: PetscUseTypeMethod(x, tdot, y, val);
438: PetscCall(PetscLogEventEnd(VEC_TDot, x, y, 0, 0));
439: PetscCall(VecLockReadPop(x));
440: PetscCall(VecLockReadPop(y));
441: PetscFunctionReturn(PETSC_SUCCESS);
442: }
444: PetscErrorCode VecScaleAsync_Private(Vec x, PetscScalar alpha, PetscDeviceContext dctx)
445: {
446: PetscReal norms[4];
447: PetscBool flgs[4];
448: PetscScalar one = 1.0;
450: PetscFunctionBegin;
453: VecCheckAssembled(x);
454: PetscCall(VecSetErrorIfLocked(x, 1));
456: if (alpha == one) PetscFunctionReturn(PETSC_SUCCESS);
458: /* get current stashed norms */
459: for (PetscInt i = 0; i < 4; i++) PetscCall(PetscObjectComposedDataGetReal((PetscObject)x, NormIds[i], norms[i], flgs[i]));
461: PetscCall(PetscLogEventBegin(VEC_Scale, x, 0, 0, 0));
462: VecMethodDispatch(x, dctx, VecAsyncFnName(Scale), scale, (Vec, PetscScalar, PetscDeviceContext), alpha);
463: PetscCall(PetscLogEventEnd(VEC_Scale, x, 0, 0, 0));
465: PetscCall(PetscObjectStateIncrease((PetscObject)x));
466: /* put the scaled stashed norms back into the Vec */
467: for (PetscInt i = 0; i < 4; i++) {
468: PetscReal ar = PetscAbsScalar(alpha);
469: if (flgs[i]) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[i], ar * norms[i]));
470: }
471: PetscFunctionReturn(PETSC_SUCCESS);
472: }
474: /*@
475: VecScale - Scales a vector.
477: Logically Collective
479: Input Parameters:
480: + x - the vector
481: - alpha - the scalar
483: Level: intermediate
485: Note:
486: For a vector with n components, `VecScale()` computes x[i] = alpha * x[i], for i=1,...,n.
488: .seealso: [](ch_vectors), `Vec`, `VecSet()`
489: @*/
490: PetscErrorCode VecScale(Vec x, PetscScalar alpha)
491: {
492: PetscFunctionBegin;
493: PetscCall(VecScaleAsync_Private(x, alpha, NULL));
494: PetscFunctionReturn(PETSC_SUCCESS);
495: }
497: PetscErrorCode VecSetAsync_Private(Vec x, PetscScalar alpha, PetscDeviceContext dctx)
498: {
499: PetscFunctionBegin;
502: VecCheckAssembled(x);
504: PetscCall(VecSetErrorIfLocked(x, 1));
506: if (alpha == 0) {
507: PetscReal norm;
508: PetscBool set;
510: PetscCall(VecNormAvailable(x, NORM_2, &set, &norm));
511: if (set == PETSC_TRUE && norm == 0) PetscFunctionReturn(PETSC_SUCCESS);
512: }
513: PetscCall(PetscLogEventBegin(VEC_Set, x, 0, 0, 0));
514: VecMethodDispatch(x, dctx, VecAsyncFnName(Set), set, (Vec, PetscScalar, PetscDeviceContext), alpha);
515: PetscCall(PetscLogEventEnd(VEC_Set, x, 0, 0, 0));
516: PetscCall(PetscObjectStateIncrease((PetscObject)x));
518: /* norms can be simply set (if |alpha|*N not too large) */
519: {
520: PetscReal val = PetscAbsScalar(alpha);
521: const PetscInt N = x->map->N;
523: if (N == 0) {
524: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_1], 0.0));
525: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], 0.0));
526: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_2], 0.0));
527: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_FROBENIUS], 0.0));
528: } else if (val > PETSC_MAX_REAL / N) {
529: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], val));
530: } else {
531: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_1], N * val));
532: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], val));
533: val *= PetscSqrtReal((PetscReal)N);
534: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_2], val));
535: PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_FROBENIUS], val));
536: }
537: }
538: PetscFunctionReturn(PETSC_SUCCESS);
539: }
541: /*@
542: VecSet - Sets all components of a vector to a single scalar value.
544: Logically Collective
546: Input Parameters:
547: + x - the vector
548: - alpha - the scalar
550: Level: beginner
552: Notes:
553: For a vector of dimension n, `VecSet()` sets x[i] = alpha, for i=1,...,n,
554: so that all vector entries then equal the identical
555: scalar value, `alpha`. Use the more general routine
556: `VecSetValues()` to set different vector entries.
558: You CANNOT call this after you have called `VecSetValues()` but before you call
559: `VecAssemblyBegin()`
561: If `alpha` is zero and the norm of the vector is known to be zero then this skips the unneeded zeroing process
563: .seealso: [](ch_vectors), `Vec`, `VecSetValues()`, `VecSetValuesBlocked()`, `VecSetRandom()`
564: @*/
565: PetscErrorCode VecSet(Vec x, PetscScalar alpha)
566: {
567: PetscFunctionBegin;
568: PetscCall(VecSetAsync_Private(x, alpha, NULL));
569: PetscFunctionReturn(PETSC_SUCCESS);
570: }
572: PetscErrorCode VecAXPYAsync_Private(Vec y, PetscScalar alpha, Vec x, PetscDeviceContext dctx)
573: {
574: PetscFunctionBegin;
579: PetscCheckSameTypeAndComm(x, 3, y, 1);
580: VecCheckSameSize(x, 3, y, 1);
581: VecCheckAssembled(x);
582: VecCheckAssembled(y);
584: if (alpha == (PetscScalar)0.0) PetscFunctionReturn(PETSC_SUCCESS);
585: PetscCall(VecSetErrorIfLocked(y, 1));
586: if (x == y) {
587: PetscCall(VecScale(y, alpha + 1.0));
588: PetscFunctionReturn(PETSC_SUCCESS);
589: }
590: PetscCall(VecLockReadPush(x));
591: PetscCall(PetscLogEventBegin(VEC_AXPY, x, y, 0, 0));
592: VecMethodDispatch(y, dctx, VecAsyncFnName(AXPY), axpy, (Vec, PetscScalar, Vec, PetscDeviceContext), alpha, x);
593: PetscCall(PetscLogEventEnd(VEC_AXPY, x, y, 0, 0));
594: PetscCall(VecLockReadPop(x));
595: PetscCall(PetscObjectStateIncrease((PetscObject)y));
596: PetscFunctionReturn(PETSC_SUCCESS);
597: }
598: /*@
599: VecAXPY - Computes `y = alpha x + y`.
601: Logically Collective
603: Input Parameters:
604: + alpha - the scalar
605: . x - vector scale by `alpha`
606: - y - vector accumulated into
608: Output Parameter:
609: . y - output vector
611: Level: intermediate
613: Notes:
614: This routine is optimized for alpha of 0.0, otherwise it calls the BLAS routine
615: .vb
616: VecAXPY(y,alpha,x) y = alpha x + y
617: VecAYPX(y,beta,x) y = x + beta y
618: VecAXPBY(y,alpha,beta,x) y = alpha x + beta y
619: VecWAXPY(w,alpha,x,y) w = alpha x + y
620: VecAXPBYPCZ(z,alpha,beta,gamma,x,y) z = alpha x + beta y + gamma z
621: VecMAXPY(y,nv,alpha[],x[]) y = sum alpha[i] x[i] + y
622: .ve
624: .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
625: @*/
626: PetscErrorCode VecAXPY(Vec y, PetscScalar alpha, Vec x)
627: {
628: PetscFunctionBegin;
629: PetscCall(VecAXPYAsync_Private(y, alpha, x, NULL));
630: PetscFunctionReturn(PETSC_SUCCESS);
631: }
633: PetscErrorCode VecAYPXAsync_Private(Vec y, PetscScalar beta, Vec x, PetscDeviceContext dctx)
634: {
635: PetscFunctionBegin;
640: PetscCheckSameTypeAndComm(x, 3, y, 1);
641: VecCheckSameSize(x, 1, y, 3);
642: VecCheckAssembled(x);
643: VecCheckAssembled(y);
645: PetscCall(VecSetErrorIfLocked(y, 1));
646: if (x == y) {
647: PetscCall(VecScale(y, beta + 1.0));
648: PetscFunctionReturn(PETSC_SUCCESS);
649: }
650: PetscCall(VecLockReadPush(x));
651: if (beta == (PetscScalar)0.0) {
652: PetscCall(VecCopy(x, y));
653: } else {
654: PetscCall(PetscLogEventBegin(VEC_AYPX, x, y, 0, 0));
655: VecMethodDispatch(y, dctx, VecAsyncFnName(AYPX), aypx, (Vec, PetscScalar, Vec, PetscDeviceContext), beta, x);
656: PetscCall(PetscLogEventEnd(VEC_AYPX, x, y, 0, 0));
657: PetscCall(PetscObjectStateIncrease((PetscObject)y));
658: }
659: PetscCall(VecLockReadPop(x));
660: PetscFunctionReturn(PETSC_SUCCESS);
661: }
663: /*@
664: VecAYPX - Computes `y = x + beta y`.
666: Logically Collective
668: Input Parameters:
669: + beta - the scalar
670: . x - the unscaled vector
671: - y - the vector to be scaled
673: Output Parameter:
674: . y - output vector
676: Level: intermediate
678: Developer Notes:
679: The implementation is optimized for `beta` of -1.0, 0.0, and 1.0
681: .seealso: [](ch_vectors), `Vec`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
682: @*/
683: PetscErrorCode VecAYPX(Vec y, PetscScalar beta, Vec x)
684: {
685: PetscFunctionBegin;
686: PetscCall(VecAYPXAsync_Private(y, beta, x, NULL));
687: PetscFunctionReturn(PETSC_SUCCESS);
688: }
690: PetscErrorCode VecAXPBYAsync_Private(Vec y, PetscScalar alpha, PetscScalar beta, Vec x, PetscDeviceContext dctx)
691: {
692: PetscFunctionBegin;
697: PetscCheckSameTypeAndComm(x, 4, y, 1);
698: VecCheckSameSize(y, 1, x, 4);
699: VecCheckAssembled(x);
700: VecCheckAssembled(y);
703: if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);
704: if (x == y) {
705: PetscCall(VecScale(y, alpha + beta));
706: PetscFunctionReturn(PETSC_SUCCESS);
707: }
709: PetscCall(VecSetErrorIfLocked(y, 1));
710: PetscCall(VecLockReadPush(x));
711: PetscCall(PetscLogEventBegin(VEC_AXPY, y, x, 0, 0));
712: VecMethodDispatch(y, dctx, VecAsyncFnName(AXPBY), axpby, (Vec, PetscScalar, PetscScalar, Vec, PetscDeviceContext), alpha, beta, x);
713: PetscCall(PetscLogEventEnd(VEC_AXPY, y, x, 0, 0));
714: PetscCall(PetscObjectStateIncrease((PetscObject)y));
715: PetscCall(VecLockReadPop(x));
716: PetscFunctionReturn(PETSC_SUCCESS);
717: }
719: /*@
720: VecAXPBY - Computes `y = alpha x + beta y`.
722: Logically Collective
724: Input Parameters:
725: + alpha - first scalar
726: . beta - second scalar
727: . x - the first scaled vector
728: - y - the second scaled vector
730: Output Parameter:
731: . y - output vector
733: Level: intermediate
735: Developer Notes:
736: The implementation is optimized for `alpha` and/or `beta` values of 0.0 and 1.0
738: .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`
739: @*/
740: PetscErrorCode VecAXPBY(Vec y, PetscScalar alpha, PetscScalar beta, Vec x)
741: {
742: PetscFunctionBegin;
743: PetscCall(VecAXPBYAsync_Private(y, alpha, beta, x, NULL));
744: PetscFunctionReturn(PETSC_SUCCESS);
745: }
747: PetscErrorCode VecAXPBYPCZAsync_Private(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y, PetscDeviceContext dctx)
748: {
749: PetscFunctionBegin;
756: PetscCheckSameTypeAndComm(x, 5, y, 6);
757: PetscCheckSameTypeAndComm(x, 5, z, 1);
758: VecCheckSameSize(x, 5, y, 6);
759: VecCheckSameSize(x, 5, z, 1);
760: PetscCheck(x != y && x != z, PetscObjectComm((PetscObject)x), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
761: PetscCheck(y != z, PetscObjectComm((PetscObject)y), PETSC_ERR_ARG_IDN, "x, y, and z must be different vectors");
762: VecCheckAssembled(x);
763: VecCheckAssembled(y);
764: VecCheckAssembled(z);
768: if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);
770: PetscCall(VecSetErrorIfLocked(z, 1));
771: PetscCall(VecLockReadPush(x));
772: PetscCall(VecLockReadPush(y));
773: PetscCall(PetscLogEventBegin(VEC_AXPBYPCZ, x, y, z, 0));
774: VecMethodDispatch(z, dctx, VecAsyncFnName(AXPBYPCZ), axpbypcz, (Vec, PetscScalar, PetscScalar, PetscScalar, Vec, Vec, PetscDeviceContext), alpha, beta, gamma, x, y);
775: PetscCall(PetscLogEventEnd(VEC_AXPBYPCZ, x, y, z, 0));
776: PetscCall(PetscObjectStateIncrease((PetscObject)z));
777: PetscCall(VecLockReadPop(x));
778: PetscCall(VecLockReadPop(y));
779: PetscFunctionReturn(PETSC_SUCCESS);
780: }
781: /*@
782: VecAXPBYPCZ - Computes `z = alpha x + beta y + gamma z`
784: Logically Collective
786: Input Parameters:
787: + alpha - first scalar
788: . beta - second scalar
789: . gamma - third scalar
790: . x - first vector
791: . y - second vector
792: - z - third vector
794: Output Parameter:
795: . z - output vector
797: Level: intermediate
799: Note:
800: `x`, `y` and `z` must be different vectors
802: Developer Notes:
803: The implementation is optimized for `alpha` of 1.0 and `gamma` of 1.0 or 0.0
805: .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBY()`
806: @*/
807: PetscErrorCode VecAXPBYPCZ(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y)
808: {
809: PetscFunctionBegin;
810: PetscCall(VecAXPBYPCZAsync_Private(z, alpha, beta, gamma, x, y, NULL));
811: PetscFunctionReturn(PETSC_SUCCESS);
812: }
814: PetscErrorCode VecWAXPYAsync_Private(Vec w, PetscScalar alpha, Vec x, Vec y, PetscDeviceContext dctx)
815: {
816: PetscFunctionBegin;
823: PetscCheckSameTypeAndComm(x, 3, y, 4);
824: PetscCheckSameTypeAndComm(y, 4, w, 1);
825: VecCheckSameSize(x, 3, y, 4);
826: VecCheckSameSize(x, 3, w, 1);
827: PetscCheck(w != y, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector y, suggest VecAXPY()");
828: PetscCheck(w != x, PETSC_COMM_SELF, PETSC_ERR_SUP, "Result vector w cannot be same as input vector x, suggest VecAYPX()");
829: VecCheckAssembled(x);
830: VecCheckAssembled(y);
832: PetscCall(VecSetErrorIfLocked(w, 1));
834: PetscCall(VecLockReadPush(x));
835: PetscCall(VecLockReadPush(y));
836: if (alpha == (PetscScalar)0.0) {
837: PetscCall(VecCopyAsync_Private(y, w, dctx));
838: } else {
839: PetscCall(PetscLogEventBegin(VEC_WAXPY, x, y, w, 0));
840: VecMethodDispatch(w, dctx, VecAsyncFnName(WAXPY), waxpy, (Vec, PetscScalar, Vec, Vec, PetscDeviceContext), alpha, x, y);
841: PetscCall(PetscLogEventEnd(VEC_WAXPY, x, y, w, 0));
842: PetscCall(PetscObjectStateIncrease((PetscObject)w));
843: }
844: PetscCall(VecLockReadPop(x));
845: PetscCall(VecLockReadPop(y));
846: PetscFunctionReturn(PETSC_SUCCESS);
847: }
849: /*@
850: VecWAXPY - Computes `w = alpha x + y`.
852: Logically Collective
854: Input Parameters:
855: + alpha - the scalar
856: . x - first vector, multiplied by `alpha`
857: - y - second vector
859: Output Parameter:
860: . w - the result
862: Level: intermediate
864: Note:
865: `w` cannot be either `x` or `y`, but `x` and `y` can be the same
867: Developer Notes:
868: The implementation is optimized for alpha of -1.0, 0.0, and 1.0
870: .seealso: [](ch_vectors), `Vec`, `VecAXPY()`, `VecAYPX()`, `VecAXPBY()`, `VecMAXPY()`, `VecAXPBYPCZ()`
871: @*/
872: PetscErrorCode VecWAXPY(Vec w, PetscScalar alpha, Vec x, Vec y)
873: {
874: PetscFunctionBegin;
875: PetscCall(VecWAXPYAsync_Private(w, alpha, x, y, NULL));
876: PetscFunctionReturn(PETSC_SUCCESS);
877: }
879: /*@
880: VecSetValues - Inserts or adds values into certain locations of a vector.
882: Not Collective
884: Input Parameters:
885: + x - vector to insert in
886: . ni - number of elements to add
887: . ix - indices where to add
888: . y - array of values
889: - iora - either `INSERT_VALUES` to replace the current values or `ADD_VALUES` to add values to any existing entries
891: Level: beginner
893: Notes:
894: .vb
895: `VecSetValues()` sets x[ix[i]] = y[i], for i=0,...,ni-1.
896: .ve
898: Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
899: options cannot be mixed without intervening calls to the assembly
900: routines.
902: These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
903: MUST be called after all calls to `VecSetValues()` have been completed.
905: VecSetValues() uses 0-based indices in Fortran as well as in C.
907: If you call `VecSetOption`(x, `VEC_IGNORE_NEGATIVE_INDICES`,`PETSC_TRUE`),
908: negative indices may be passed in ix. These rows are
909: simply ignored. This allows easily inserting element load matrices
910: with homogeneous Dirichlet boundary conditions that you don't want represented
911: in the vector.
913: Fortran Note:
914: If any of `ix` and `y` are scalars pass them using, for example,
915: .vb
916: call VecSetValues(mat, one, [ix], [y], INSERT_VALUES, ierr)
917: .ve
919: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesLocal()`,
920: `VecSetValue()`, `VecSetValuesBlocked()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `VecGetValues()`
921: @*/
922: PetscErrorCode VecSetValues(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
923: {
924: PetscFunctionBeginHot;
926: if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
927: PetscAssertPointer(ix, 3);
928: PetscAssertPointer(y, 4);
931: PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
932: PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
933: PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
934: PetscCall(PetscObjectStateIncrease((PetscObject)x));
935: PetscFunctionReturn(PETSC_SUCCESS);
936: }
938: /*@
939: VecGetValues - Gets values from certain locations of a vector. Currently
940: can only get values on the same processor on which they are owned
942: Not Collective
944: Input Parameters:
945: + x - vector to get values from
946: . ni - number of elements to get
947: - ix - indices where to get them from (in global 1d numbering)
949: Output Parameter:
950: . y - array of values, must be passed in with a length of `ni`
952: Level: beginner
954: Notes:
955: The user provides the allocated array y; it is NOT allocated in this routine
957: `VecGetValues()` gets y[i] = x[ix[i]], for i=0,...,ni-1.
959: `VecAssemblyBegin()` and `VecAssemblyEnd()` MUST be called before calling this if `VecSetValues()` or related routine has been called
961: VecGetValues() uses 0-based indices in Fortran as well as in C.
963: If you call `VecSetOption`(x, `VEC_IGNORE_NEGATIVE_INDICES`,`PETSC_TRUE`),
964: negative indices may be passed in ix. These rows are
965: simply ignored.
967: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`
968: @*/
969: PetscErrorCode VecGetValues(Vec x, PetscInt ni, const PetscInt ix[], PetscScalar y[])
970: {
971: PetscFunctionBegin;
973: if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
974: PetscAssertPointer(ix, 3);
975: PetscAssertPointer(y, 4);
977: VecCheckAssembled(x);
978: PetscUseTypeMethod(x, getvalues, ni, ix, y);
979: PetscFunctionReturn(PETSC_SUCCESS);
980: }
982: /*@
983: VecSetValuesBlocked - Inserts or adds blocks of values into certain locations of a vector.
985: Not Collective
987: Input Parameters:
988: + x - vector to insert in
989: . ni - number of blocks to add
990: . ix - indices where to add in block count, rather than element count
991: . y - array of values
992: - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES`, adds values to any existing entries
994: Level: intermediate
996: Notes:
997: `VecSetValuesBlocked()` sets x[bs*ix[i]+j] = y[bs*i+j],
998: for j=0,...,bs-1, for i=0,...,ni-1. where bs was set with VecSetBlockSize().
1000: Calls to `VecSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1001: options cannot be mixed without intervening calls to the assembly
1002: routines.
1004: These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
1005: MUST be called after all calls to `VecSetValuesBlocked()` have been completed.
1007: `VecSetValuesBlocked()` uses 0-based indices in Fortran as well as in C.
1009: Negative indices may be passed in ix, these rows are
1010: simply ignored. This allows easily inserting element load matrices
1011: with homogeneous Dirichlet boundary conditions that you don't want represented
1012: in the vector.
1014: Fortran Note:
1015: If any of `ix` and `y` are scalars pass them using, for example,
1016: .vb
1017: call VecSetValuesBlocked(mat, one, [ix], [y], INSERT_VALUES, ierr)
1018: .ve
1020: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesBlockedLocal()`,
1021: `VecSetValues()`
1022: @*/
1023: PetscErrorCode VecSetValuesBlocked(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1024: {
1025: PetscFunctionBeginHot;
1027: if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1028: PetscAssertPointer(ix, 3);
1029: PetscAssertPointer(y, 4);
1032: PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1033: PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1034: PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1035: PetscCall(PetscObjectStateIncrease((PetscObject)x));
1036: PetscFunctionReturn(PETSC_SUCCESS);
1037: }
1039: /*@
1040: VecSetValuesLocal - Inserts or adds values into certain locations of a vector,
1041: using a local ordering of the nodes.
1043: Not Collective
1045: Input Parameters:
1046: + x - vector to insert in
1047: . ni - number of elements to add
1048: . ix - indices where to add
1049: . y - array of values
1050: - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries
1052: Level: intermediate
1054: Notes:
1055: `VecSetValuesLocal()` sets x[ix[i]] = y[i], for i=0,...,ni-1.
1057: Calls to `VecSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1058: options cannot be mixed without intervening calls to the assembly
1059: routines.
1061: These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
1062: MUST be called after all calls to `VecSetValuesLocal()` have been completed.
1064: `VecSetValuesLocal()` uses 0-based indices in Fortran as well as in C.
1066: Fortran Note:
1067: If any of `ix` and `y` are scalars pass them using, for example,
1068: .vb
1069: call VecSetValuesLocal(mat, one, [ix], [y], INSERT_VALUES, ierr)
1070: .ve
1072: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetLocalToGlobalMapping()`,
1073: `VecSetValuesBlockedLocal()`
1074: @*/
1075: PetscErrorCode VecSetValuesLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1076: {
1077: PetscInt lixp[128], *lix = lixp;
1079: PetscFunctionBeginHot;
1081: if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1082: PetscAssertPointer(ix, 3);
1083: PetscAssertPointer(y, 4);
1086: PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1087: if (!x->ops->setvalueslocal) {
1088: if (PetscUnlikely(!x->map->mapping && x->ops->getlocaltoglobalmapping)) PetscUseTypeMethod(x, getlocaltoglobalmapping, &x->map->mapping);
1089: if (x->map->mapping) {
1090: if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1091: PetscCall(ISLocalToGlobalMappingApply(x->map->mapping, ni, (PetscInt *)ix, lix));
1092: PetscUseTypeMethod(x, setvalues, ni, lix, y, iora);
1093: if (ni > 128) PetscCall(PetscFree(lix));
1094: } else PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
1095: } else PetscUseTypeMethod(x, setvalueslocal, ni, ix, y, iora);
1096: PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1097: PetscCall(PetscObjectStateIncrease((PetscObject)x));
1098: PetscFunctionReturn(PETSC_SUCCESS);
1099: }
1101: /*@
1102: VecSetValuesBlockedLocal - Inserts or adds values into certain locations of a vector,
1103: using a local ordering of the nodes.
1105: Not Collective
1107: Input Parameters:
1108: + x - vector to insert in
1109: . ni - number of blocks to add
1110: . ix - indices where to add in block count, not element count
1111: . y - array of values
1112: - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries
1114: Level: intermediate
1116: Notes:
1117: `VecSetValuesBlockedLocal()` sets x[bs*ix[i]+j] = y[bs*i+j],
1118: for j=0,..bs-1, for i=0,...,ni-1, where bs has been set with `VecSetBlockSize()`.
1120: Calls to `VecSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1121: options cannot be mixed without intervening calls to the assembly
1122: routines.
1124: These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
1125: MUST be called after all calls to `VecSetValuesBlockedLocal()` have been completed.
1127: `VecSetValuesBlockedLocal()` uses 0-based indices in Fortran as well as in C.
1129: Fortran Note:
1130: If any of `ix` and `y` are scalars pass them using, for example,
1131: .vb
1132: call VecSetValuesBlockedLocal(mat, one, [ix], [y], INSERT_VALUES, ierr)
1133: .ve
1135: .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetValuesBlocked()`,
1136: `VecSetLocalToGlobalMapping()`
1137: @*/
1138: PetscErrorCode VecSetValuesBlockedLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1139: {
1140: PetscInt lixp[128], *lix = lixp;
1142: PetscFunctionBeginHot;
1144: if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1145: PetscAssertPointer(ix, 3);
1146: PetscAssertPointer(y, 4);
1148: PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1149: if (PetscUnlikely(!x->map->mapping && x->ops->getlocaltoglobalmapping)) PetscUseTypeMethod(x, getlocaltoglobalmapping, &x->map->mapping);
1150: if (x->map->mapping) {
1151: if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1152: PetscCall(ISLocalToGlobalMappingApplyBlock(x->map->mapping, ni, (PetscInt *)ix, lix));
1153: PetscUseTypeMethod(x, setvaluesblocked, ni, lix, y, iora);
1154: if (ni > 128) PetscCall(PetscFree(lix));
1155: } else {
1156: PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1157: }
1158: PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1159: PetscCall(PetscObjectStateIncrease((PetscObject)x));
1160: PetscFunctionReturn(PETSC_SUCCESS);
1161: }
1163: static PetscErrorCode VecMXDot_Private(Vec x, PetscInt nv, const Vec y[], PetscScalar result[], PetscErrorCode (*mxdot)(Vec, PetscInt, const Vec[], PetscScalar[]), PetscLogEvent event)
1164: {
1165: PetscFunctionBegin;
1168: VecCheckAssembled(x);
1170: if (!nv) PetscFunctionReturn(PETSC_SUCCESS);
1171: PetscAssertPointer(y, 3);
1172: for (PetscInt i = 0; i < nv; ++i) {
1175: PetscCheckSameTypeAndComm(x, 1, y[i], 3);
1176: VecCheckSameSize(x, 1, y[i], 3);
1177: VecCheckAssembled(y[i]);
1178: PetscCall(VecLockReadPush(y[i]));
1179: }
1180: PetscAssertPointer(result, 4);
1183: PetscCall(VecLockReadPush(x));
1184: PetscCall(PetscLogEventBegin(event, x, *y, 0, 0));
1185: PetscCall((*mxdot)(x, nv, y, result));
1186: PetscCall(PetscLogEventEnd(event, x, *y, 0, 0));
1187: PetscCall(VecLockReadPop(x));
1188: for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(y[i]));
1189: PetscFunctionReturn(PETSC_SUCCESS);
1190: }
1192: /*@
1193: VecMTDot - Computes indefinite vector multiple dot products.
1194: That is, it does NOT use the complex conjugate.
1196: Collective
1198: Input Parameters:
1199: + x - one vector
1200: . nv - number of vectors
1201: - y - array of vectors. Note that vectors are pointers
1203: Output Parameter:
1204: . val - array of the dot products
1206: Level: intermediate
1208: Notes for Users of Complex Numbers:
1209: For complex vectors, `VecMTDot()` computes the indefinite form
1210: .vb
1211: val = (x,y) = y^T x,
1212: .ve
1213: where y^T denotes the transpose of y.
1215: Use `VecMDot()` for the inner product
1216: .vb
1217: val = (x,y) = y^H x,
1218: .ve
1219: where y^H denotes the conjugate transpose of y.
1221: .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`
1222: @*/
1223: PetscErrorCode VecMTDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1224: {
1225: PetscFunctionBegin;
1227: PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mtdot, VEC_MTDot));
1228: PetscFunctionReturn(PETSC_SUCCESS);
1229: }
1231: /*@
1232: VecMDot - Computes multiple vector dot products.
1234: Collective
1236: Input Parameters:
1237: + x - one vector
1238: . nv - number of vectors
1239: - y - array of vectors.
1241: Output Parameter:
1242: . val - array of the dot products (does not allocate the array)
1244: Level: intermediate
1246: Notes for Users of Complex Numbers:
1247: For complex vectors, `VecMDot()` computes
1248: .vb
1249: val = (x,y) = y^H x,
1250: .ve
1251: where y^H denotes the conjugate transpose of y.
1253: Use `VecMTDot()` for the indefinite form
1254: .vb
1255: val = (x,y) = y^T x,
1256: .ve
1257: where y^T denotes the transpose of y.
1259: Note:
1260: The implementation may use BLAS 2 operations when the vectors `y` have been obtained with `VecDuplicateVecs()`
1262: .seealso: [](ch_vectors), `Vec`, `VecMTDot()`, `VecDot()`, `VecDuplicateVecs()`
1263: @*/
1264: PetscErrorCode VecMDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1265: {
1266: PetscFunctionBegin;
1268: PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mdot, VEC_MDot));
1269: PetscFunctionReturn(PETSC_SUCCESS);
1270: }
1272: PetscErrorCode VecMAXPYAsync_Private(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[], PetscDeviceContext dctx)
1273: {
1274: PetscFunctionBegin;
1276: VecCheckAssembled(y);
1278: PetscCall(VecSetErrorIfLocked(y, 1));
1279: PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);
1280: if (nv) {
1281: PetscInt zeros = 0;
1283: PetscAssertPointer(alpha, 3);
1284: PetscAssertPointer(x, 4);
1285: for (PetscInt i = 0; i < nv; ++i) {
1289: PetscCheckSameTypeAndComm(y, 1, x[i], 4);
1290: VecCheckSameSize(y, 1, x[i], 4);
1291: PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1292: VecCheckAssembled(x[i]);
1293: PetscCall(VecLockReadPush(x[i]));
1294: zeros += alpha[i] == (PetscScalar)0.0;
1295: }
1297: if (zeros < nv) {
1298: PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1299: VecMethodDispatch(y, dctx, VecAsyncFnName(MAXPY), maxpy, (Vec, PetscInt, const PetscScalar[], Vec[], PetscDeviceContext), nv, alpha, x);
1300: PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1301: PetscCall(PetscObjectStateIncrease((PetscObject)y));
1302: }
1304: for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1305: }
1306: PetscFunctionReturn(PETSC_SUCCESS);
1307: }
1309: /*@
1310: VecMAXPY - Computes `y = y + sum alpha[i] x[i]`
1312: Logically Collective
1314: Input Parameters:
1315: + nv - number of scalars and `x` vectors
1316: . alpha - array of scalars
1317: . y - one vector
1318: - x - array of vectors
1320: Level: intermediate
1322: Notes:
1323: `y` cannot be any of the `x` vectors
1325: The implementation may use BLAS 2 operations when the vectors `y` have been obtained with `VecDuplicateVecs()`
1327: .seealso: [](ch_vectors), `Vec`, `VecMAXPBY()`,`VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`, `VecDuplicateVecs()`
1328: @*/
1329: PetscErrorCode VecMAXPY(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[])
1330: {
1331: PetscFunctionBegin;
1332: PetscCall(VecMAXPYAsync_Private(y, nv, alpha, x, NULL));
1333: PetscFunctionReturn(PETSC_SUCCESS);
1334: }
1336: /*@
1337: VecMAXPBY - Computes `y = beta y + sum alpha[i] x[i]`
1339: Logically Collective
1341: Input Parameters:
1342: + nv - number of scalars and `x` vectors
1343: . alpha - array of scalars
1344: . beta - scalar
1345: . y - one vector
1346: - x - array of vectors
1348: Level: intermediate
1350: Note:
1351: `y` cannot be any of the `x` vectors.
1353: Developer Notes:
1354: This is a convenience routine, but implementations might be able to optimize it, for example, when `beta` is zero.
1356: .seealso: [](ch_vectors), `Vec`, `VecMAXPY()`, `VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
1357: @*/
1358: PetscErrorCode VecMAXPBY(Vec y, PetscInt nv, const PetscScalar alpha[], PetscScalar beta, Vec x[])
1359: {
1360: PetscFunctionBegin;
1362: VecCheckAssembled(y);
1364: PetscCall(VecSetErrorIfLocked(y, 1));
1365: PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);
1368: if (y->ops->maxpby) {
1369: PetscInt zeros = 0;
1371: if (nv) {
1372: PetscAssertPointer(alpha, 3);
1373: PetscAssertPointer(x, 5);
1374: }
1376: for (PetscInt i = 0; i < nv; ++i) { // scan all alpha[]
1380: PetscCheckSameTypeAndComm(y, 1, x[i], 5);
1381: VecCheckSameSize(y, 1, x[i], 5);
1382: PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1383: VecCheckAssembled(x[i]);
1384: PetscCall(VecLockReadPush(x[i]));
1385: zeros += alpha[i] == (PetscScalar)0.0;
1386: }
1388: if (zeros < nv) { // has nonzero alpha
1389: PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1390: PetscUseTypeMethod(y, maxpby, nv, alpha, beta, x);
1391: PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1392: PetscCall(PetscObjectStateIncrease((PetscObject)y));
1393: } else {
1394: PetscCall(VecScale(y, beta));
1395: }
1397: for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1398: } else { // no maxpby
1399: if (beta == 0.0) PetscCall(VecSet(y, 0.0));
1400: else PetscCall(VecScale(y, beta));
1401: PetscCall(VecMAXPY(y, nv, alpha, x));
1402: }
1403: PetscFunctionReturn(PETSC_SUCCESS);
1404: }
1406: /*@
1407: VecConcatenate - Creates a new vector that is a vertical concatenation of all the given array of vectors
1408: in the order they appear in the array. The concatenated vector resides on the same
1409: communicator and is the same type as the source vectors.
1411: Collective
1413: Input Parameters:
1414: + nx - number of vectors to be concatenated
1415: - X - array containing the vectors to be concatenated in the order of concatenation
1417: Output Parameters:
1418: + Y - concatenated vector
1419: - x_is - array of index sets corresponding to the concatenated components of `Y` (pass `NULL` if not needed)
1421: Level: advanced
1423: Notes:
1424: Concatenation is similar to the functionality of a `VECNEST` object; they both represent combination of
1425: different vector spaces. However, concatenated vectors do not store any information about their
1426: sub-vectors and own their own data. Consequently, this function provides index sets to enable the
1427: manipulation of data in the concatenated vector that corresponds to the original components at creation.
1429: This is a useful tool for outer loop algorithms, particularly constrained optimizers, where the solver
1430: has to operate on combined vector spaces and cannot utilize `VECNEST` objects due to incompatibility with
1431: bound projections.
1433: .seealso: [](ch_vectors), `Vec`, `VECNEST`, `VECSCATTER`, `VecScatterCreate()`
1434: @*/
1435: PetscErrorCode VecConcatenate(PetscInt nx, const Vec X[], Vec *Y, IS *x_is[])
1436: {
1437: MPI_Comm comm;
1438: VecType vec_type;
1439: Vec Ytmp, Xtmp;
1440: IS *is_tmp;
1441: PetscInt i, shift = 0, Xnl, Xng, Xbegin;
1443: PetscFunctionBegin;
1447: PetscAssertPointer(Y, 3);
1449: if ((*X)->ops->concatenate) {
1450: /* use the dedicated concatenation function if available */
1451: PetscCall((*(*X)->ops->concatenate)(nx, X, Y, x_is));
1452: } else {
1453: /* loop over vectors and start creating IS */
1454: comm = PetscObjectComm((PetscObject)*X);
1455: PetscCall(VecGetType(*X, &vec_type));
1456: PetscCall(PetscMalloc1(nx, &is_tmp));
1457: for (i = 0; i < nx; i++) {
1458: PetscCall(VecGetSize(X[i], &Xng));
1459: PetscCall(VecGetLocalSize(X[i], &Xnl));
1460: PetscCall(VecGetOwnershipRange(X[i], &Xbegin, NULL));
1461: PetscCall(ISCreateStride(comm, Xnl, shift + Xbegin, 1, &is_tmp[i]));
1462: shift += Xng;
1463: }
1464: /* create the concatenated vector */
1465: PetscCall(VecCreate(comm, &Ytmp));
1466: PetscCall(VecSetType(Ytmp, vec_type));
1467: PetscCall(VecSetSizes(Ytmp, PETSC_DECIDE, shift));
1468: PetscCall(VecSetUp(Ytmp));
1469: /* copy data from X array to Y and return */
1470: for (i = 0; i < nx; i++) {
1471: PetscCall(VecGetSubVector(Ytmp, is_tmp[i], &Xtmp));
1472: PetscCall(VecCopy(X[i], Xtmp));
1473: PetscCall(VecRestoreSubVector(Ytmp, is_tmp[i], &Xtmp));
1474: }
1475: *Y = Ytmp;
1476: if (x_is) {
1477: *x_is = is_tmp;
1478: } else {
1479: for (i = 0; i < nx; i++) PetscCall(ISDestroy(&is_tmp[i]));
1480: PetscCall(PetscFree(is_tmp));
1481: }
1482: }
1483: PetscFunctionReturn(PETSC_SUCCESS);
1484: }
1486: /* A helper function for VecGetSubVector to check if we can implement it with no-copy (i.e. the subvector shares
1487: memory with the original vector), and the block size of the subvector.
1489: Input Parameters:
1490: + X - the original vector
1491: - is - the index set of the subvector
1493: Output Parameters:
1494: + contig - PETSC_TRUE if the index set refers to contiguous entries on this process, else PETSC_FALSE
1495: . start - start of contiguous block, as an offset from the start of the ownership range of the original vector
1496: - blocksize - the block size of the subvector
1498: */
1499: PetscErrorCode VecGetSubVectorContiguityAndBS_Private(Vec X, IS is, PetscBool *contig, PetscInt *start, PetscInt *blocksize)
1500: {
1501: PetscInt gstart, gend, lstart;
1502: PetscBool red[2] = {PETSC_TRUE /*contiguous*/, PETSC_TRUE /*validVBS*/};
1503: PetscInt n, N, ibs, vbs, bs = 1;
1505: PetscFunctionBegin;
1506: PetscCall(ISGetLocalSize(is, &n));
1507: PetscCall(ISGetSize(is, &N));
1508: PetscCall(ISGetBlockSize(is, &ibs));
1509: PetscCall(VecGetBlockSize(X, &vbs));
1510: PetscCall(VecGetOwnershipRange(X, &gstart, &gend));
1511: PetscCall(ISContiguousLocal(is, gstart, gend, &lstart, &red[0]));
1512: /* block size is given by IS if ibs > 1; otherwise, check the vector */
1513: if (ibs > 1) {
1514: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, red, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1515: bs = ibs;
1516: } else {
1517: if (n % vbs || vbs == 1) red[1] = PETSC_FALSE; /* this process invalidate the collectiveness of block size */
1518: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, red, 2, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1519: if (red[0] && red[1]) bs = vbs; /* all processes have a valid block size and the access will be contiguous */
1520: }
1522: *contig = red[0];
1523: *start = lstart;
1524: *blocksize = bs;
1525: PetscFunctionReturn(PETSC_SUCCESS);
1526: }
1528: /* A helper function for VecGetSubVector, to be used when we have to build a standalone subvector through VecScatter
1530: Input Parameters:
1531: + X - the original vector
1532: . is - the index set of the subvector
1533: - bs - the block size of the subvector, gotten from VecGetSubVectorContiguityAndBS_Private()
1535: Output Parameter:
1536: . Z - the subvector, which will compose the VecScatter context on output
1537: */
1538: PetscErrorCode VecGetSubVectorThroughVecScatter_Private(Vec X, IS is, PetscInt bs, Vec *Z)
1539: {
1540: PetscInt n, N;
1541: VecScatter vscat;
1542: Vec Y;
1544: PetscFunctionBegin;
1545: PetscCall(ISGetLocalSize(is, &n));
1546: PetscCall(ISGetSize(is, &N));
1547: PetscCall(VecCreate(PetscObjectComm((PetscObject)is), &Y));
1548: PetscCall(VecSetSizes(Y, n, N));
1549: PetscCall(VecSetBlockSize(Y, bs));
1550: PetscCall(VecSetType(Y, ((PetscObject)X)->type_name));
1551: PetscCall(VecScatterCreate(X, is, Y, NULL, &vscat));
1552: PetscCall(VecScatterBegin(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1553: PetscCall(VecScatterEnd(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1554: PetscCall(PetscObjectCompose((PetscObject)Y, "VecGetSubVector_Scatter", (PetscObject)vscat));
1555: PetscCall(VecScatterDestroy(&vscat));
1556: *Z = Y;
1557: PetscFunctionReturn(PETSC_SUCCESS);
1558: }
1560: /*@
1561: VecGetSubVector - Gets a vector representing part of another vector
1563: Collective
1565: Input Parameters:
1566: + X - vector from which to extract a subvector
1567: - is - index set representing portion of `X` to extract
1569: Output Parameter:
1570: . Y - subvector corresponding to `is`
1572: Level: advanced
1574: Notes:
1575: The subvector `Y` should be returned with `VecRestoreSubVector()`.
1576: `X` and `is` must be defined on the same communicator
1578: Changes to the subvector will be reflected in the `X` vector on the call to `VecRestoreSubVector()`.
1580: This function may return a subvector without making a copy, therefore it is not safe to use the original vector while
1581: modifying the subvector. Other non-overlapping subvectors can still be obtained from `X` using this function.
1583: 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`.
1585: .seealso: [](ch_vectors), `Vec`, `IS`, `VECNEST`, `MatCreateSubMatrix()`
1586: @*/
1587: PetscErrorCode VecGetSubVector(Vec X, IS is, Vec *Y)
1588: {
1589: Vec Z;
1591: PetscFunctionBegin;
1594: PetscCheckSameComm(X, 1, is, 2);
1595: PetscAssertPointer(Y, 3);
1596: if (X->ops->getsubvector) {
1597: PetscUseTypeMethod(X, getsubvector, is, &Z);
1598: } else { /* Default implementation currently does no caching */
1599: PetscBool contig;
1600: PetscInt n, N, start, bs;
1602: PetscCall(ISGetLocalSize(is, &n));
1603: PetscCall(ISGetSize(is, &N));
1604: PetscCall(VecGetSubVectorContiguityAndBS_Private(X, is, &contig, &start, &bs));
1605: if (contig) { /* We can do a no-copy implementation */
1606: const PetscScalar *x;
1607: PetscInt state = 0;
1608: PetscBool isstd, iscuda, iship;
1610: PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &isstd, VECSEQ, VECMPI, VECSTANDARD, ""));
1611: PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1612: PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));
1613: if (iscuda) {
1614: #if defined(PETSC_HAVE_CUDA)
1615: const PetscScalar *x_d;
1616: PetscMPIInt size;
1617: PetscOffloadMask flg;
1619: PetscCall(VecCUDAGetArrays_Private(X, &x, &x_d, &flg));
1620: PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1621: PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1622: if (x) x += start;
1623: if (x_d) x_d += start;
1624: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1625: if (size == 1) {
1626: PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1627: } else {
1628: PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1629: }
1630: Z->offloadmask = flg;
1631: #endif
1632: } else if (iship) {
1633: #if defined(PETSC_HAVE_HIP)
1634: const PetscScalar *x_d;
1635: PetscMPIInt size;
1636: PetscOffloadMask flg;
1638: PetscCall(VecHIPGetArrays_Private(X, &x, &x_d, &flg));
1639: PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1640: PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1641: if (x) x += start;
1642: if (x_d) x_d += start;
1643: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1644: if (size == 1) {
1645: PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1646: } else {
1647: PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1648: }
1649: Z->offloadmask = flg;
1650: #endif
1651: } else if (isstd) {
1652: PetscMPIInt size;
1654: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1655: PetscCall(VecGetArrayRead(X, &x));
1656: if (x) x += start;
1657: if (size == 1) {
1658: PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)X), bs, n, x, &Z));
1659: } else {
1660: PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)X), bs, n, N, x, &Z));
1661: }
1662: PetscCall(VecRestoreArrayRead(X, &x));
1663: } else { /* default implementation: use place array */
1664: PetscCall(VecGetArrayRead(X, &x));
1665: PetscCall(VecCreate(PetscObjectComm((PetscObject)X), &Z));
1666: PetscCall(VecSetType(Z, ((PetscObject)X)->type_name));
1667: PetscCall(VecSetSizes(Z, n, N));
1668: PetscCall(VecSetBlockSize(Z, bs));
1669: PetscCall(VecPlaceArray(Z, PetscSafePointerPlusOffset(x, start)));
1670: PetscCall(VecRestoreArrayRead(X, &x));
1671: }
1673: /* this is relevant only in debug mode */
1674: PetscCall(VecLockGet(X, &state));
1675: if (state) PetscCall(VecLockReadPush(Z));
1676: Z->ops->placearray = NULL;
1677: Z->ops->replacearray = NULL;
1678: } else { /* Have to create a scatter and do a copy */
1679: PetscCall(VecGetSubVectorThroughVecScatter_Private(X, is, bs, &Z));
1680: }
1681: }
1682: /* Record the state when the subvector was gotten so we know whether its values need to be put back */
1683: if (VecGetSubVectorSavedStateId < 0) PetscCall(PetscObjectComposedDataRegister(&VecGetSubVectorSavedStateId));
1684: PetscCall(PetscObjectComposedDataSetInt((PetscObject)Z, VecGetSubVectorSavedStateId, 1));
1685: *Y = Z;
1686: PetscFunctionReturn(PETSC_SUCCESS);
1687: }
1689: /*@
1690: VecRestoreSubVector - Restores a subvector extracted using `VecGetSubVector()`
1692: Collective
1694: Input Parameters:
1695: + X - vector from which subvector was obtained
1696: . is - index set representing the subset of `X`
1697: - Y - subvector being restored
1699: Level: advanced
1701: .seealso: [](ch_vectors), `Vec`, `IS`, `VecGetSubVector()`
1702: @*/
1703: PetscErrorCode VecRestoreSubVector(Vec X, IS is, Vec *Y)
1704: {
1705: PETSC_UNUSED PetscObjectState dummystate = 0;
1706: PetscBool unchanged;
1708: PetscFunctionBegin;
1711: PetscCheckSameComm(X, 1, is, 2);
1712: PetscAssertPointer(Y, 3);
1715: if (X->ops->restoresubvector) PetscUseTypeMethod(X, restoresubvector, is, Y);
1716: else {
1717: PetscCall(PetscObjectComposedDataGetInt((PetscObject)*Y, VecGetSubVectorSavedStateId, dummystate, unchanged));
1718: if (!unchanged) { /* If Y's state has not changed since VecGetSubVector(), we only need to destroy Y */
1719: VecScatter scatter;
1720: PetscInt state;
1722: PetscCall(VecLockGet(X, &state));
1723: PetscCheck(state == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vec X is locked for read-only or read/write access");
1725: PetscCall(PetscObjectQuery((PetscObject)*Y, "VecGetSubVector_Scatter", (PetscObject *)&scatter));
1726: if (scatter) {
1727: PetscCall(VecScatterBegin(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1728: PetscCall(VecScatterEnd(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1729: } else {
1730: PetscBool iscuda, iship;
1731: PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1732: PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));
1734: if (iscuda) {
1735: #if defined(PETSC_HAVE_CUDA)
1736: PetscOffloadMask ymask = (*Y)->offloadmask;
1738: /* The offloadmask of X dictates where to move memory
1739: If X GPU data is valid, then move Y data on GPU if needed
1740: Otherwise, move back to the CPU */
1741: switch (X->offloadmask) {
1742: case PETSC_OFFLOAD_BOTH:
1743: if (ymask == PETSC_OFFLOAD_CPU) {
1744: PetscCall(VecCUDAResetArray(*Y));
1745: } else if (ymask == PETSC_OFFLOAD_GPU) {
1746: X->offloadmask = PETSC_OFFLOAD_GPU;
1747: }
1748: break;
1749: case PETSC_OFFLOAD_GPU:
1750: if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecCUDAResetArray(*Y));
1751: break;
1752: case PETSC_OFFLOAD_CPU:
1753: if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1754: break;
1755: case PETSC_OFFLOAD_UNALLOCATED:
1756: case PETSC_OFFLOAD_KOKKOS:
1757: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1758: }
1759: #endif
1760: } else if (iship) {
1761: #if defined(PETSC_HAVE_HIP)
1762: PetscOffloadMask ymask = (*Y)->offloadmask;
1764: /* The offloadmask of X dictates where to move memory
1765: If X GPU data is valid, then move Y data on GPU if needed
1766: Otherwise, move back to the CPU */
1767: switch (X->offloadmask) {
1768: case PETSC_OFFLOAD_BOTH:
1769: if (ymask == PETSC_OFFLOAD_CPU) {
1770: PetscCall(VecHIPResetArray(*Y));
1771: } else if (ymask == PETSC_OFFLOAD_GPU) {
1772: X->offloadmask = PETSC_OFFLOAD_GPU;
1773: }
1774: break;
1775: case PETSC_OFFLOAD_GPU:
1776: if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecHIPResetArray(*Y));
1777: break;
1778: case PETSC_OFFLOAD_CPU:
1779: if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1780: break;
1781: case PETSC_OFFLOAD_UNALLOCATED:
1782: case PETSC_OFFLOAD_KOKKOS:
1783: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1784: }
1785: #endif
1786: } else {
1787: /* If OpenCL vecs updated the device memory, this triggers a copy on the CPU */
1788: PetscCall(VecResetArray(*Y));
1789: }
1790: PetscCall(PetscObjectStateIncrease((PetscObject)X));
1791: }
1792: }
1793: }
1794: PetscCall(VecDestroy(Y));
1795: PetscFunctionReturn(PETSC_SUCCESS);
1796: }
1798: /*@
1799: VecCreateLocalVector - Creates a vector object suitable for use with `VecGetLocalVector()` and friends. You must call `VecDestroy()` when the
1800: vector is no longer needed.
1802: Not Collective.
1804: Input Parameter:
1805: . v - The vector for which the local vector is desired.
1807: Output Parameter:
1808: . w - Upon exit this contains the local vector.
1810: Level: beginner
1812: .seealso: [](ch_vectors), `Vec`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecRestoreLocalVector()`
1813: @*/
1814: PetscErrorCode VecCreateLocalVector(Vec v, Vec *w)
1815: {
1816: VecType roottype;
1817: PetscInt n;
1819: PetscFunctionBegin;
1821: PetscAssertPointer(w, 2);
1822: if (v->ops->createlocalvector) {
1823: PetscUseTypeMethod(v, createlocalvector, w);
1824: PetscFunctionReturn(PETSC_SUCCESS);
1825: }
1826: PetscCall(VecGetRootType_Private(v, &roottype));
1827: PetscCall(VecCreate(PETSC_COMM_SELF, w));
1828: PetscCall(VecGetLocalSize(v, &n));
1829: PetscCall(VecSetSizes(*w, n, n));
1830: PetscCall(VecGetBlockSize(v, &n));
1831: PetscCall(VecSetBlockSize(*w, n));
1832: PetscCall(VecSetType(*w, roottype));
1833: PetscFunctionReturn(PETSC_SUCCESS);
1834: }
1836: /*@
1837: VecGetLocalVectorRead - Maps the local portion of a vector into a
1838: vector.
1840: Not Collective.
1842: Input Parameter:
1843: . v - The vector for which the local vector is desired.
1845: Output Parameter:
1846: . w - Upon exit this contains the local vector.
1848: Level: beginner
1850: Notes:
1851: You must call `VecRestoreLocalVectorRead()` when the local
1852: vector is no longer needed.
1854: This function is similar to `VecGetArrayRead()` which maps the local
1855: portion into a raw pointer. `VecGetLocalVectorRead()` is usually
1856: almost as efficient as `VecGetArrayRead()` but in certain circumstances
1857: `VecGetLocalVectorRead()` can be much more efficient than
1858: `VecGetArrayRead()`. This is because the construction of a contiguous
1859: array representing the vector data required by `VecGetArrayRead()` can
1860: be an expensive operation for certain vector types. For example, for
1861: GPU vectors `VecGetArrayRead()` requires that the data between device
1862: and host is synchronized.
1864: Unlike `VecGetLocalVector()`, this routine is not collective and
1865: preserves cached information.
1867: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1868: @*/
1869: PetscErrorCode VecGetLocalVectorRead(Vec v, Vec w)
1870: {
1871: PetscFunctionBegin;
1874: VecCheckSameLocalSize(v, 1, w, 2);
1875: if (v->ops->getlocalvectorread) {
1876: PetscUseTypeMethod(v, getlocalvectorread, w);
1877: } else {
1878: PetscScalar *a;
1880: PetscCall(VecGetArrayRead(v, (const PetscScalar **)&a));
1881: PetscCall(VecPlaceArray(w, a));
1882: }
1883: PetscCall(PetscObjectStateIncrease((PetscObject)w));
1884: PetscCall(VecLockReadPush(v));
1885: PetscCall(VecLockReadPush(w));
1886: PetscFunctionReturn(PETSC_SUCCESS);
1887: }
1889: /*@
1890: VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1891: previously mapped into a vector using `VecGetLocalVectorRead()`.
1893: Not Collective.
1895: Input Parameters:
1896: + v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVectorRead()`.
1897: - w - The vector into which the local portion of `v` was mapped.
1899: Level: beginner
1901: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1902: @*/
1903: PetscErrorCode VecRestoreLocalVectorRead(Vec v, Vec w)
1904: {
1905: PetscFunctionBegin;
1908: if (v->ops->restorelocalvectorread) {
1909: PetscUseTypeMethod(v, restorelocalvectorread, w);
1910: } else {
1911: const PetscScalar *a;
1913: PetscCall(VecGetArrayRead(w, &a));
1914: PetscCall(VecRestoreArrayRead(v, &a));
1915: PetscCall(VecResetArray(w));
1916: }
1917: PetscCall(VecLockReadPop(v));
1918: PetscCall(VecLockReadPop(w));
1919: PetscCall(PetscObjectStateIncrease((PetscObject)w));
1920: PetscFunctionReturn(PETSC_SUCCESS);
1921: }
1923: /*@
1924: VecGetLocalVector - Maps the local portion of a vector into a
1925: vector.
1927: Collective
1929: Input Parameter:
1930: . v - The vector for which the local vector is desired.
1932: Output Parameter:
1933: . w - Upon exit this contains the local vector.
1935: Level: beginner
1937: Notes:
1938: You must call `VecRestoreLocalVector()` when the local
1939: vector is no longer needed.
1941: This function is similar to `VecGetArray()` which maps the local
1942: portion into a raw pointer. `VecGetLocalVector()` is usually about as
1943: efficient as `VecGetArray()` but in certain circumstances
1944: `VecGetLocalVector()` can be much more efficient than `VecGetArray()`.
1945: This is because the construction of a contiguous array representing
1946: the vector data required by `VecGetArray()` can be an expensive
1947: operation for certain vector types. For example, for GPU vectors
1948: `VecGetArray()` requires that the data between device and host is
1949: synchronized.
1951: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVector()`, `VecGetLocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1952: @*/
1953: PetscErrorCode VecGetLocalVector(Vec v, Vec w)
1954: {
1955: PetscFunctionBegin;
1958: VecCheckSameLocalSize(v, 1, w, 2);
1959: if (v->ops->getlocalvector) {
1960: PetscUseTypeMethod(v, getlocalvector, w);
1961: } else {
1962: PetscScalar *a;
1964: PetscCall(VecGetArray(v, &a));
1965: PetscCall(VecPlaceArray(w, a));
1966: }
1967: PetscCall(PetscObjectStateIncrease((PetscObject)w));
1968: PetscFunctionReturn(PETSC_SUCCESS);
1969: }
1971: /*@
1972: VecRestoreLocalVector - Unmaps the local portion of a vector
1973: previously mapped into a vector using `VecGetLocalVector()`.
1975: Logically Collective.
1977: Input Parameters:
1978: + v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVector()`.
1979: - w - The vector into which the local portion of `v` was mapped.
1981: Level: beginner
1983: .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVector()`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `LocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1984: @*/
1985: PetscErrorCode VecRestoreLocalVector(Vec v, Vec w)
1986: {
1987: PetscFunctionBegin;
1990: if (v->ops->restorelocalvector) {
1991: PetscUseTypeMethod(v, restorelocalvector, w);
1992: } else {
1993: PetscScalar *a;
1994: PetscCall(VecGetArray(w, &a));
1995: PetscCall(VecRestoreArray(v, &a));
1996: PetscCall(VecResetArray(w));
1997: }
1998: PetscCall(PetscObjectStateIncrease((PetscObject)w));
1999: PetscCall(PetscObjectStateIncrease((PetscObject)v));
2000: PetscFunctionReturn(PETSC_SUCCESS);
2001: }
2003: /*@C
2004: VecGetArray - Returns a pointer to a contiguous array that contains this
2005: MPI processes's portion of the vector data
2007: Logically Collective
2009: Input Parameter:
2010: . x - the vector
2012: Output Parameter:
2013: . a - location to put pointer to the array
2015: Level: beginner
2017: Notes:
2018: For the standard PETSc vectors, `VecGetArray()` returns a pointer to the local data array and
2019: does not use any copies. If the underlying vector data is not stored in a contiguous array
2020: this routine will copy the data to a contiguous array and return a pointer to that. You MUST
2021: call `VecRestoreArray()` when you no longer need access to the array.
2023: For vectors that may also have the array data in GPU memory, for example, `VECCUDA`, this call ensures the CPU array has the
2024: most recent array values by copying the data from the GPU memory if needed.
2026: Fortran Note:
2027: .vb
2028: PetscScalar, pointer :: a(:)
2029: .ve
2031: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecPlaceArray()`, `VecGetArray2d()`,
2032: `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`, `VecGetArrayAndMemType()`
2033: @*/
2034: PetscErrorCode VecGetArray(Vec x, PetscScalar *a[])
2035: {
2036: PetscFunctionBegin;
2038: PetscCall(VecSetErrorIfLocked(x, 1));
2039: if (x->ops->getarray) { /* The if-else order matters! VECNEST, VECCUDA etc should have ops->getarray while VECCUDA etc are petscnative */
2040: PetscUseTypeMethod(x, getarray, a);
2041: } else if (x->petscnative) { /* VECSTANDARD */
2042: *a = *((PetscScalar **)x->data);
2043: } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array for vector type \"%s\"", ((PetscObject)x)->type_name);
2044: PetscFunctionReturn(PETSC_SUCCESS);
2045: }
2047: /*@C
2048: VecRestoreArray - Restores a vector after `VecGetArray()` has been called and the array is no longer needed
2050: Logically Collective
2052: Input Parameters:
2053: + x - the vector
2054: - a - location of pointer to array obtained from `VecGetArray()`
2056: Level: beginner
2058: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2059: `VecGetArrayPair()`, `VecRestoreArrayPair()`
2060: @*/
2061: PetscErrorCode VecRestoreArray(Vec x, PetscScalar *a[])
2062: {
2063: PetscFunctionBegin;
2065: if (a) PetscAssertPointer(a, 2);
2066: if (x->ops->restorearray) {
2067: PetscUseTypeMethod(x, restorearray, a);
2068: } else PetscCheck(x->petscnative, PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot restore array for vector type \"%s\"", ((PetscObject)x)->type_name);
2069: if (a) *a = NULL;
2070: PetscCall(PetscObjectStateIncrease((PetscObject)x));
2071: PetscFunctionReturn(PETSC_SUCCESS);
2072: }
2073: /*@C
2074: VecGetArrayRead - Get read-only pointer to contiguous array containing this processor's portion of the vector data.
2076: Not Collective
2078: Input Parameter:
2079: . x - the vector
2081: Output Parameter:
2082: . a - the array
2084: Level: beginner
2086: Notes:
2087: The array must be returned using a matching call to `VecRestoreArrayRead()`.
2089: Unlike `VecGetArray()`, preserves cached information like vector norms.
2091: Standard PETSc vectors use contiguous storage so that this routine does not perform a copy. Other vector
2092: implementations may require a copy, but such implementations should cache the contiguous representation so that
2093: only one copy is performed when this routine is called multiple times in sequence.
2095: For vectors that may also have the array data in GPU memory, for example, `VECCUDA`, this call ensures the CPU array has the
2096: most recent array values by copying the data from the GPU memory if needed.
2098: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2099: `VecGetArrayAndMemType()`
2100: @*/
2101: PetscErrorCode VecGetArrayRead(Vec x, const PetscScalar *a[])
2102: {
2103: PetscFunctionBegin;
2105: PetscAssertPointer(a, 2);
2106: if (x->ops->getarrayread) {
2107: PetscUseTypeMethod(x, getarrayread, a);
2108: } else if (x->ops->getarray) {
2109: PetscObjectState state;
2111: /* VECNEST, VECCUDA, VECKOKKOS etc */
2112: // x->ops->getarray may bump the object state, but since we know this is a read-only get
2113: // we can just undo that
2114: PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2115: PetscUseTypeMethod(x, getarray, (PetscScalar **)a);
2116: PetscCall(PetscObjectStateSet((PetscObject)x, state));
2117: } else if (x->petscnative) {
2118: /* VECSTANDARD */
2119: *a = *((PetscScalar **)x->data);
2120: } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array read for vector type \"%s\"", ((PetscObject)x)->type_name);
2121: PetscFunctionReturn(PETSC_SUCCESS);
2122: }
2124: /*@C
2125: VecRestoreArrayRead - Restore array obtained with `VecGetArrayRead()`
2127: Not Collective
2129: Input Parameters:
2130: + x - the vector
2131: - a - the array
2133: Level: beginner
2135: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2136: @*/
2137: PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar *a[])
2138: {
2139: PetscFunctionBegin;
2141: if (a) PetscAssertPointer(a, 2);
2142: if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
2143: /* nothing */
2144: } else if (x->ops->restorearrayread) { /* VECNEST */
2145: PetscUseTypeMethod(x, restorearrayread, a);
2146: } else { /* No one? */
2147: PetscObjectState state;
2149: // x->ops->restorearray may bump the object state, but since we know this is a read-restore
2150: // we can just undo that
2151: PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2152: PetscUseTypeMethod(x, restorearray, (PetscScalar **)a);
2153: PetscCall(PetscObjectStateSet((PetscObject)x, state));
2154: }
2155: if (a) *a = NULL;
2156: PetscFunctionReturn(PETSC_SUCCESS);
2157: }
2159: /*@C
2160: VecGetArrayWrite - Returns a pointer to a contiguous array that WILL contain this
2161: MPI processes's portion of the vector data.
2163: Logically Collective
2165: Input Parameter:
2166: . x - the vector
2168: Output Parameter:
2169: . a - location to put pointer to the array
2171: Level: intermediate
2173: Note:
2174: The values in this array are NOT valid, the caller of this routine is responsible for putting
2175: values into the array; any values it does not set will be invalid.
2177: The array must be returned using a matching call to `VecRestoreArrayWrite()`.
2179: For vectors associated with GPUs, the host and device vectors are not synchronized before
2180: giving access. If you need correct values in the array use `VecGetArray()`
2182: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecPlaceArray()`, `VecGetArray2d()`,
2183: `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArray()`, `VecRestoreArrayWrite()`, `VecGetArrayAndMemType()`
2184: @*/
2185: PetscErrorCode VecGetArrayWrite(Vec x, PetscScalar *a[])
2186: {
2187: PetscFunctionBegin;
2189: PetscAssertPointer(a, 2);
2190: PetscCall(VecSetErrorIfLocked(x, 1));
2191: if (x->ops->getarraywrite) {
2192: PetscUseTypeMethod(x, getarraywrite, a);
2193: } else {
2194: PetscCall(VecGetArray(x, a));
2195: }
2196: PetscFunctionReturn(PETSC_SUCCESS);
2197: }
2199: /*@C
2200: VecRestoreArrayWrite - Restores a vector after `VecGetArrayWrite()` has been called.
2202: Logically Collective
2204: Input Parameters:
2205: + x - the vector
2206: - a - location of pointer to array obtained from `VecGetArray()`
2208: Level: beginner
2210: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2211: `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`
2212: @*/
2213: PetscErrorCode VecRestoreArrayWrite(Vec x, PetscScalar *a[])
2214: {
2215: PetscFunctionBegin;
2217: if (a) PetscAssertPointer(a, 2);
2218: if (x->ops->restorearraywrite) {
2219: PetscUseTypeMethod(x, restorearraywrite, a);
2220: } else if (x->ops->restorearray) {
2221: PetscUseTypeMethod(x, restorearray, a);
2222: }
2223: if (a) *a = NULL;
2224: PetscCall(PetscObjectStateIncrease((PetscObject)x));
2225: PetscFunctionReturn(PETSC_SUCCESS);
2226: }
2228: /*@C
2229: VecGetArrays - Returns a pointer to the arrays in a set of vectors
2230: that were created by a call to `VecDuplicateVecs()`.
2232: Logically Collective; No Fortran Support
2234: Input Parameters:
2235: + x - the vectors
2236: - n - the number of vectors
2238: Output Parameter:
2239: . a - location to put pointer to the array
2241: Level: intermediate
2243: Note:
2244: You MUST call `VecRestoreArrays()` when you no longer need access to the arrays.
2246: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrays()`
2247: @*/
2248: PetscErrorCode VecGetArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2249: {
2250: PetscInt i;
2251: PetscScalar **q;
2253: PetscFunctionBegin;
2254: PetscAssertPointer(x, 1);
2256: PetscAssertPointer(a, 3);
2257: PetscCheck(n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must get at least one array n = %" PetscInt_FMT, n);
2258: PetscCall(PetscMalloc1(n, &q));
2259: for (i = 0; i < n; ++i) PetscCall(VecGetArray(x[i], &q[i]));
2260: *a = q;
2261: PetscFunctionReturn(PETSC_SUCCESS);
2262: }
2264: /*@C
2265: VecRestoreArrays - Restores a group of vectors after `VecGetArrays()`
2266: has been called.
2268: Logically Collective; No Fortran Support
2270: Input Parameters:
2271: + x - the vector
2272: . n - the number of vectors
2273: - a - location of pointer to arrays obtained from `VecGetArrays()`
2275: Notes:
2276: For regular PETSc vectors this routine does not involve any copies. For
2277: any special vectors that do not store local vector data in a contiguous
2278: array, this routine will copy the data back into the underlying
2279: vector data structure from the arrays obtained with `VecGetArrays()`.
2281: Level: intermediate
2283: .seealso: [](ch_vectors), `Vec`, `VecGetArrays()`, `VecRestoreArray()`
2284: @*/
2285: PetscErrorCode VecRestoreArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2286: {
2287: PetscInt i;
2288: PetscScalar **q = *a;
2290: PetscFunctionBegin;
2291: PetscAssertPointer(x, 1);
2293: PetscAssertPointer(a, 3);
2295: for (i = 0; i < n; ++i) PetscCall(VecRestoreArray(x[i], &q[i]));
2296: PetscCall(PetscFree(q));
2297: PetscFunctionReturn(PETSC_SUCCESS);
2298: }
2300: /*@C
2301: VecGetArrayAndMemType - Like `VecGetArray()`, but if this is a standard device vector (e.g.,
2302: `VECCUDA`), the returned pointer will be a device pointer to the device memory that contains
2303: this MPI processes's portion of the vector data.
2305: Logically Collective; No Fortran Support
2307: Input Parameter:
2308: . x - the vector
2310: Output Parameters:
2311: + a - location to put pointer to the array
2312: - mtype - memory type of the array
2314: Level: beginner
2316: Note:
2317: Device data is guaranteed to have the latest value. Otherwise, when this is a host vector
2318: (e.g., `VECMPI`), this routine functions the same as `VecGetArray()` and returns a host
2319: pointer.
2321: For `VECKOKKOS`, if Kokkos is configured without device (e.g., use serial or openmp), per
2322: this function, the vector works like `VECSEQ`/`VECMPI`; otherwise, it works like `VECCUDA` or
2323: `VECHIP` etc.
2325: Use `VecRestoreArrayAndMemType()` when the array access is no longer needed.
2327: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`,
2328: `VecPlaceArray()`, `VecGetArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2329: @*/
2330: PetscErrorCode VecGetArrayAndMemType(Vec x, PetscScalar *a[], PetscMemType *mtype)
2331: {
2332: PetscFunctionBegin;
2335: PetscAssertPointer(a, 2);
2336: if (mtype) PetscAssertPointer(mtype, 3);
2337: PetscCall(VecSetErrorIfLocked(x, 1));
2338: if (x->ops->getarrayandmemtype) {
2339: /* VECCUDA, VECKOKKOS etc */
2340: PetscUseTypeMethod(x, getarrayandmemtype, a, mtype);
2341: } else {
2342: /* VECSTANDARD, VECNEST, VECVIENNACL */
2343: PetscCall(VecGetArray(x, a));
2344: if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2345: }
2346: PetscFunctionReturn(PETSC_SUCCESS);
2347: }
2349: /*@C
2350: VecRestoreArrayAndMemType - Restores a vector after `VecGetArrayAndMemType()` has been called.
2352: Logically Collective; No Fortran Support
2354: Input Parameters:
2355: + x - the vector
2356: - a - location of pointer to array obtained from `VecGetArrayAndMemType()`
2358: Level: beginner
2360: .seealso: [](ch_vectors), `Vec`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`,
2361: `VecPlaceArray()`, `VecRestoreArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2362: @*/
2363: PetscErrorCode VecRestoreArrayAndMemType(Vec x, PetscScalar *a[])
2364: {
2365: PetscFunctionBegin;
2368: if (a) PetscAssertPointer(a, 2);
2369: if (x->ops->restorearrayandmemtype) {
2370: /* VECCUDA, VECKOKKOS etc */
2371: PetscUseTypeMethod(x, restorearrayandmemtype, a);
2372: } else {
2373: /* VECNEST, VECVIENNACL */
2374: PetscCall(VecRestoreArray(x, a));
2375: } /* VECSTANDARD does nothing */
2376: if (a) *a = NULL;
2377: PetscCall(PetscObjectStateIncrease((PetscObject)x));
2378: PetscFunctionReturn(PETSC_SUCCESS);
2379: }
2381: /*@C
2382: VecGetArrayReadAndMemType - Like `VecGetArrayRead()`, but if the input vector is a device vector, it will return a read-only device pointer.
2383: The returned pointer is guaranteed to point to up-to-date data. For host vectors, it functions as `VecGetArrayRead()`.
2385: Not Collective; No Fortran Support
2387: Input Parameter:
2388: . x - the vector
2390: Output Parameters:
2391: + a - the array
2392: - mtype - memory type of the array
2394: Level: beginner
2396: Notes:
2397: The array must be returned using a matching call to `VecRestoreArrayReadAndMemType()`.
2399: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2400: @*/
2401: PetscErrorCode VecGetArrayReadAndMemType(Vec x, const PetscScalar *a[], PetscMemType *mtype)
2402: {
2403: PetscFunctionBegin;
2406: PetscAssertPointer(a, 2);
2407: if (mtype) PetscAssertPointer(mtype, 3);
2408: if (x->ops->getarrayreadandmemtype) {
2409: /* VECCUDA/VECHIP though they are also petscnative */
2410: PetscUseTypeMethod(x, getarrayreadandmemtype, a, mtype);
2411: } else if (x->ops->getarrayandmemtype) {
2412: /* VECKOKKOS */
2413: PetscObjectState state;
2415: // see VecGetArrayRead() for why
2416: PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2417: PetscUseTypeMethod(x, getarrayandmemtype, (PetscScalar **)a, mtype);
2418: PetscCall(PetscObjectStateSet((PetscObject)x, state));
2419: } else {
2420: PetscCall(VecGetArrayRead(x, a));
2421: if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2422: }
2423: PetscFunctionReturn(PETSC_SUCCESS);
2424: }
2426: /*@C
2427: VecRestoreArrayReadAndMemType - Restore array obtained with `VecGetArrayReadAndMemType()`
2429: Not Collective; No Fortran Support
2431: Input Parameters:
2432: + x - the vector
2433: - a - the array
2435: Level: beginner
2437: .seealso: [](ch_vectors), `Vec`, `VecGetArrayReadAndMemType()`, `VecRestoreArrayAndMemType()`, `VecRestoreArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2438: @*/
2439: PetscErrorCode VecRestoreArrayReadAndMemType(Vec x, const PetscScalar *a[])
2440: {
2441: PetscFunctionBegin;
2444: if (a) PetscAssertPointer(a, 2);
2445: if (x->ops->restorearrayreadandmemtype) {
2446: /* VECCUDA/VECHIP */
2447: PetscUseTypeMethod(x, restorearrayreadandmemtype, a);
2448: } else if (!x->petscnative) {
2449: /* VECNEST */
2450: PetscCall(VecRestoreArrayRead(x, a));
2451: }
2452: if (a) *a = NULL;
2453: PetscFunctionReturn(PETSC_SUCCESS);
2454: }
2456: /*@C
2457: VecGetArrayWriteAndMemType - Like `VecGetArrayWrite()`, but if this is a device vector it will always return
2458: a device pointer to the device memory that contains this processor's portion of the vector data.
2460: Logically Collective; No Fortran Support
2462: Input Parameter:
2463: . x - the vector
2465: Output Parameters:
2466: + a - the array
2467: - mtype - memory type of the array
2469: Level: beginner
2471: Note:
2472: The array must be returned using a matching call to `VecRestoreArrayWriteAndMemType()`, where it will label the device memory as most recent.
2474: .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayWriteAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2475: @*/
2476: PetscErrorCode VecGetArrayWriteAndMemType(Vec x, PetscScalar *a[], PetscMemType *mtype)
2477: {
2478: PetscFunctionBegin;
2481: PetscCall(VecSetErrorIfLocked(x, 1));
2482: PetscAssertPointer(a, 2);
2483: if (mtype) PetscAssertPointer(mtype, 3);
2484: if (x->ops->getarraywriteandmemtype) {
2485: /* VECCUDA, VECHIP, VECKOKKOS etc, though they are also petscnative */
2486: PetscUseTypeMethod(x, getarraywriteandmemtype, a, mtype);
2487: } else if (x->ops->getarrayandmemtype) {
2488: PetscCall(VecGetArrayAndMemType(x, a, mtype));
2489: } else {
2490: /* VECNEST, VECVIENNACL */
2491: PetscCall(VecGetArrayWrite(x, a));
2492: if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2493: }
2494: PetscFunctionReturn(PETSC_SUCCESS);
2495: }
2497: /*@C
2498: VecRestoreArrayWriteAndMemType - Restore array obtained with `VecGetArrayWriteAndMemType()`
2500: Logically Collective; No Fortran Support
2502: Input Parameters:
2503: + x - the vector
2504: - a - the array
2506: Level: beginner
2508: .seealso: [](ch_vectors), `Vec`, `VecGetArrayWriteAndMemType()`, `VecRestoreArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2509: @*/
2510: PetscErrorCode VecRestoreArrayWriteAndMemType(Vec x, PetscScalar *a[])
2511: {
2512: PetscFunctionBegin;
2515: PetscCall(VecSetErrorIfLocked(x, 1));
2516: if (a) PetscAssertPointer(a, 2);
2517: if (x->ops->restorearraywriteandmemtype) {
2518: /* VECCUDA/VECHIP */
2519: PetscMemType PETSC_UNUSED mtype; // since this function doesn't accept a memtype?
2520: PetscUseTypeMethod(x, restorearraywriteandmemtype, a, &mtype);
2521: } else if (x->ops->restorearrayandmemtype) {
2522: PetscCall(VecRestoreArrayAndMemType(x, a));
2523: } else {
2524: PetscCall(VecRestoreArray(x, a));
2525: }
2526: if (a) *a = NULL;
2527: PetscFunctionReturn(PETSC_SUCCESS);
2528: }
2530: /*@
2531: VecPlaceArray - Allows one to replace the array in a vector with an
2532: array provided by the user. This is useful to avoid copying an array
2533: into a vector.
2535: Logically Collective; No Fortran Support
2537: Input Parameters:
2538: + vec - the vector
2539: - array - the array
2541: Level: developer
2543: Notes:
2544: Adding `const` to `array` was an oversight, as subsequent operations on `vec` would
2545: likely modify the data in `array`. However, we have kept it to avoid breaking APIs.
2547: Use `VecReplaceArray()` instead to permanently replace the array
2549: You can return to the original array with a call to `VecResetArray()`. `vec` does not take
2550: ownership of `array` in any way.
2552: The user must free `array` themselves but be careful not to
2553: do so before the vector has either been destroyed, had its original array restored with
2554: `VecResetArray()` or permanently replaced with `VecReplaceArray()`.
2556: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`
2557: @*/
2558: PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2559: {
2560: PetscFunctionBegin;
2563: if (array) PetscAssertPointer(array, 2);
2564: PetscUseTypeMethod(vec, placearray, array);
2565: PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2566: PetscFunctionReturn(PETSC_SUCCESS);
2567: }
2569: /*@C
2570: VecReplaceArray - Allows one to replace the array in a vector with an
2571: array provided by the user. This is useful to avoid copying an array
2572: into a vector.
2574: Logically Collective; No Fortran Support
2576: Input Parameters:
2577: + vec - the vector
2578: - array - the array
2580: Level: developer
2582: Notes:
2583: Adding `const` to `array` was an oversight, as subsequent operations on `vec` would
2584: likely modify the data in `array`. However, we have kept it to avoid breaking APIs.
2586: This permanently replaces the array and frees the memory associated
2587: with the old array. Use `VecPlaceArray()` to temporarily replace the array.
2589: The memory passed in MUST be obtained with `PetscMalloc()` and CANNOT be
2590: freed by the user. It will be freed when the vector is destroyed.
2592: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`
2593: @*/
2594: PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2595: {
2596: PetscFunctionBegin;
2599: PetscUseTypeMethod(vec, replacearray, array);
2600: PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2601: PetscFunctionReturn(PETSC_SUCCESS);
2602: }
2604: /*@C
2605: VecGetArray2d - Returns a pointer to a 2d contiguous array that contains this
2606: processor's portion of the vector data. You MUST call `VecRestoreArray2d()`
2607: when you no longer need access to the array.
2609: Logically Collective
2611: Input Parameters:
2612: + x - the vector
2613: . m - first dimension of two dimensional array
2614: . n - second dimension of two dimensional array
2615: . mstart - first index you will use in first coordinate direction (often 0)
2616: - nstart - first index in the second coordinate direction (often 0)
2618: Output Parameter:
2619: . a - location to put pointer to the array
2621: Level: developer
2623: Notes:
2624: For a vector obtained from `DMCreateLocalVector()` `mstart` and `nstart` are likely
2625: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2626: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2627: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.
2629: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2631: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2632: `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2633: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2634: @*/
2635: PetscErrorCode VecGetArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2636: {
2637: PetscInt i, N;
2638: PetscScalar *aa;
2640: PetscFunctionBegin;
2642: PetscAssertPointer(a, 6);
2644: PetscCall(VecGetLocalSize(x, &N));
2645: 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);
2646: PetscCall(VecGetArray(x, &aa));
2648: PetscCall(PetscMalloc1(m, a));
2649: for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2650: *a -= mstart;
2651: PetscFunctionReturn(PETSC_SUCCESS);
2652: }
2654: /*@C
2655: VecGetArray2dWrite - Returns a pointer to a 2d contiguous array that will contain this
2656: processor's portion of the vector data. You MUST call `VecRestoreArray2dWrite()`
2657: when you no longer need access to the array.
2659: Logically Collective
2661: Input Parameters:
2662: + x - the vector
2663: . m - first dimension of two dimensional array
2664: . n - second dimension of two dimensional array
2665: . mstart - first index you will use in first coordinate direction (often 0)
2666: - nstart - first index in the second coordinate direction (often 0)
2668: Output Parameter:
2669: . a - location to put pointer to the array
2671: Level: developer
2673: Notes:
2674: For a vector obtained from `DMCreateLocalVector()` `mstart` and `nstart` are likely
2675: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2676: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2677: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.
2679: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2681: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2682: `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2683: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2684: @*/
2685: PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2686: {
2687: PetscInt i, N;
2688: PetscScalar *aa;
2690: PetscFunctionBegin;
2692: PetscAssertPointer(a, 6);
2694: PetscCall(VecGetLocalSize(x, &N));
2695: 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);
2696: PetscCall(VecGetArrayWrite(x, &aa));
2698: PetscCall(PetscMalloc1(m, a));
2699: for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2700: *a -= mstart;
2701: PetscFunctionReturn(PETSC_SUCCESS);
2702: }
2704: /*@C
2705: VecRestoreArray2d - Restores a vector after `VecGetArray2d()` has been called.
2707: Logically Collective
2709: Input Parameters:
2710: + x - the vector
2711: . m - first dimension of two dimensional array
2712: . n - second dimension of the two dimensional array
2713: . mstart - first index you will use in first coordinate direction (often 0)
2714: . nstart - first index in the second coordinate direction (often 0)
2715: - a - location of pointer to array obtained from `VecGetArray2d()`
2717: Level: developer
2719: Notes:
2720: For regular PETSc vectors this routine does not involve any copies. For
2721: any special vectors that do not store local vector data in a contiguous
2722: array, this routine will copy the data back into the underlying
2723: vector data structure from the array obtained with `VecGetArray()`.
2725: This routine actually zeros out the `a` pointer.
2727: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2728: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2729: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2730: @*/
2731: PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2732: {
2733: void *dummy;
2735: PetscFunctionBegin;
2737: PetscAssertPointer(a, 6);
2739: dummy = (void *)(*a + mstart);
2740: PetscCall(PetscFree(dummy));
2741: PetscCall(VecRestoreArray(x, NULL));
2742: *a = NULL;
2743: PetscFunctionReturn(PETSC_SUCCESS);
2744: }
2746: /*@C
2747: VecRestoreArray2dWrite - Restores a vector after `VecGetArray2dWrite()` has been called.
2749: Logically Collective
2751: Input Parameters:
2752: + x - the vector
2753: . m - first dimension of two dimensional array
2754: . n - second dimension of the two dimensional array
2755: . mstart - first index you will use in first coordinate direction (often 0)
2756: . nstart - first index in the second coordinate direction (often 0)
2757: - a - location of pointer to array obtained from `VecGetArray2d()`
2759: Level: developer
2761: Notes:
2762: For regular PETSc vectors this routine does not involve any copies. For
2763: any special vectors that do not store local vector data in a contiguous
2764: array, this routine will copy the data back into the underlying
2765: vector data structure from the array obtained with `VecGetArray()`.
2767: This routine actually zeros out the `a` pointer.
2769: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2770: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2771: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2772: @*/
2773: PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2774: {
2775: void *dummy;
2777: PetscFunctionBegin;
2779: PetscAssertPointer(a, 6);
2781: dummy = (void *)(*a + mstart);
2782: PetscCall(PetscFree(dummy));
2783: PetscCall(VecRestoreArrayWrite(x, NULL));
2784: PetscFunctionReturn(PETSC_SUCCESS);
2785: }
2787: /*@C
2788: VecGetArray1d - Returns a pointer to a 1d contiguous array that contains this
2789: processor's portion of the vector data. You MUST call `VecRestoreArray1d()`
2790: when you no longer need access to the array.
2792: Logically Collective
2794: Input Parameters:
2795: + x - the vector
2796: . m - first dimension of two dimensional array
2797: - mstart - first index you will use in first coordinate direction (often 0)
2799: Output Parameter:
2800: . a - location to put pointer to the array
2802: Level: developer
2804: Notes:
2805: For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
2806: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2807: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.
2809: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2811: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2812: `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2813: `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2814: @*/
2815: PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2816: {
2817: PetscInt N;
2819: PetscFunctionBegin;
2821: PetscAssertPointer(a, 4);
2823: PetscCall(VecGetLocalSize(x, &N));
2824: 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);
2825: PetscCall(VecGetArray(x, a));
2826: *a -= mstart;
2827: PetscFunctionReturn(PETSC_SUCCESS);
2828: }
2830: /*@C
2831: VecGetArray1dWrite - Returns a pointer to a 1d contiguous array that will contain this
2832: processor's portion of the vector data. You MUST call `VecRestoreArray1dWrite()`
2833: when you no longer need access to the array.
2835: Logically Collective
2837: Input Parameters:
2838: + x - the vector
2839: . m - first dimension of two dimensional array
2840: - mstart - first index you will use in first coordinate direction (often 0)
2842: Output Parameter:
2843: . a - location to put pointer to the array
2845: Level: developer
2847: Notes:
2848: For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
2849: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2850: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.
2852: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2854: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2855: `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2856: `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2857: @*/
2858: PetscErrorCode VecGetArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2859: {
2860: PetscInt N;
2862: PetscFunctionBegin;
2864: PetscAssertPointer(a, 4);
2866: PetscCall(VecGetLocalSize(x, &N));
2867: 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);
2868: PetscCall(VecGetArrayWrite(x, a));
2869: *a -= mstart;
2870: PetscFunctionReturn(PETSC_SUCCESS);
2871: }
2873: /*@C
2874: VecRestoreArray1d - Restores a vector after `VecGetArray1d()` has been called.
2876: Logically Collective
2878: Input Parameters:
2879: + x - the vector
2880: . m - first dimension of two dimensional array
2881: . mstart - first index you will use in first coordinate direction (often 0)
2882: - a - location of pointer to array obtained from `VecGetArray1d()`
2884: Level: developer
2886: Notes:
2887: For regular PETSc vectors this routine does not involve any copies. For
2888: any special vectors that do not store local vector data in a contiguous
2889: array, this routine will copy the data back into the underlying
2890: vector data structure from the array obtained with `VecGetArray1d()`.
2892: This routine actually zeros out the `a` pointer.
2894: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2895: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2896: `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2897: @*/
2898: PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2899: {
2900: PetscFunctionBegin;
2903: PetscCall(VecRestoreArray(x, NULL));
2904: *a = NULL;
2905: PetscFunctionReturn(PETSC_SUCCESS);
2906: }
2908: /*@C
2909: VecRestoreArray1dWrite - Restores a vector after `VecGetArray1dWrite()` has been called.
2911: Logically Collective
2913: Input Parameters:
2914: + x - the vector
2915: . m - first dimension of two dimensional array
2916: . mstart - first index you will use in first coordinate direction (often 0)
2917: - a - location of pointer to array obtained from `VecGetArray1d()`
2919: Level: developer
2921: Notes:
2922: For regular PETSc vectors this routine does not involve any copies. For
2923: any special vectors that do not store local vector data in a contiguous
2924: array, this routine will copy the data back into the underlying
2925: vector data structure from the array obtained with `VecGetArray1d()`.
2927: This routine actually zeros out the `a` pointer.
2929: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2930: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2931: `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2932: @*/
2933: PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2934: {
2935: PetscFunctionBegin;
2938: PetscCall(VecRestoreArrayWrite(x, NULL));
2939: *a = NULL;
2940: PetscFunctionReturn(PETSC_SUCCESS);
2941: }
2943: /*@C
2944: VecGetArray3d - Returns a pointer to a 3d contiguous array that contains this
2945: processor's portion of the vector data. You MUST call `VecRestoreArray3d()`
2946: when you no longer need access to the array.
2948: Logically Collective
2950: Input Parameters:
2951: + x - the vector
2952: . m - first dimension of three dimensional array
2953: . n - second dimension of three dimensional array
2954: . p - third dimension of three dimensional array
2955: . mstart - first index you will use in first coordinate direction (often 0)
2956: . nstart - first index in the second coordinate direction (often 0)
2957: - pstart - first index in the third coordinate direction (often 0)
2959: Output Parameter:
2960: . a - location to put pointer to the array
2962: Level: developer
2964: Notes:
2965: For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
2966: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2967: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2968: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
2970: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2972: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2973: `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecRestoreArray3d()`,
2974: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2975: @*/
2976: PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
2977: {
2978: PetscInt i, N, j;
2979: PetscScalar *aa, **b;
2981: PetscFunctionBegin;
2983: PetscAssertPointer(a, 8);
2985: PetscCall(VecGetLocalSize(x, &N));
2986: 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);
2987: PetscCall(VecGetArray(x, &aa));
2989: PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
2990: b = (PetscScalar **)((*a) + m);
2991: for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
2992: for (i = 0; i < m; i++)
2993: for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset(aa, i * n * p + j * p - pstart);
2994: *a -= mstart;
2995: PetscFunctionReturn(PETSC_SUCCESS);
2996: }
2998: /*@C
2999: VecGetArray3dWrite - Returns a pointer to a 3d contiguous array that will contain this
3000: processor's portion of the vector data. You MUST call `VecRestoreArray3dWrite()`
3001: when you no longer need access to the array.
3003: Logically Collective
3005: Input Parameters:
3006: + x - the vector
3007: . m - first dimension of three dimensional array
3008: . n - second dimension of three dimensional array
3009: . p - third dimension of three dimensional array
3010: . mstart - first index you will use in first coordinate direction (often 0)
3011: . nstart - first index in the second coordinate direction (often 0)
3012: - pstart - first index in the third coordinate direction (often 0)
3014: Output Parameter:
3015: . a - location to put pointer to the array
3017: Level: developer
3019: Notes:
3020: For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3021: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3022: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3023: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3025: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3027: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3028: `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3029: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3030: @*/
3031: PetscErrorCode VecGetArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3032: {
3033: PetscInt i, N, j;
3034: PetscScalar *aa, **b;
3036: PetscFunctionBegin;
3038: PetscAssertPointer(a, 8);
3040: PetscCall(VecGetLocalSize(x, &N));
3041: 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);
3042: PetscCall(VecGetArrayWrite(x, &aa));
3044: PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3045: b = (PetscScalar **)((*a) + m);
3046: for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3047: for (i = 0; i < m; i++)
3048: for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;
3050: *a -= mstart;
3051: PetscFunctionReturn(PETSC_SUCCESS);
3052: }
3054: /*@C
3055: VecRestoreArray3d - Restores a vector after `VecGetArray3d()` has been called.
3057: Logically Collective
3059: Input Parameters:
3060: + x - the vector
3061: . m - first dimension of three dimensional array
3062: . n - second dimension of the three dimensional array
3063: . p - third dimension of the three dimensional array
3064: . mstart - first index you will use in first coordinate direction (often 0)
3065: . nstart - first index in the second coordinate direction (often 0)
3066: . pstart - first index in the third coordinate direction (often 0)
3067: - a - location of pointer to array obtained from VecGetArray3d()
3069: Level: developer
3071: Notes:
3072: For regular PETSc vectors this routine does not involve any copies. For
3073: any special vectors that do not store local vector data in a contiguous
3074: array, this routine will copy the data back into the underlying
3075: vector data structure from the array obtained with `VecGetArray()`.
3077: This routine actually zeros out the `a` pointer.
3079: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3080: `VecGetArray2d()`, `VecGetArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3081: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3082: @*/
3083: PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3084: {
3085: void *dummy;
3087: PetscFunctionBegin;
3089: PetscAssertPointer(a, 8);
3091: dummy = (void *)(*a + mstart);
3092: PetscCall(PetscFree(dummy));
3093: PetscCall(VecRestoreArray(x, NULL));
3094: *a = NULL;
3095: PetscFunctionReturn(PETSC_SUCCESS);
3096: }
3098: /*@C
3099: VecRestoreArray3dWrite - Restores a vector after `VecGetArray3dWrite()` has been called.
3101: Logically Collective
3103: Input Parameters:
3104: + x - the vector
3105: . m - first dimension of three dimensional array
3106: . n - second dimension of the three dimensional array
3107: . p - third dimension of the three dimensional array
3108: . mstart - first index you will use in first coordinate direction (often 0)
3109: . nstart - first index in the second coordinate direction (often 0)
3110: . pstart - first index in the third coordinate direction (often 0)
3111: - a - location of pointer to array obtained from VecGetArray3d()
3113: Level: developer
3115: Notes:
3116: For regular PETSc vectors this routine does not involve any copies. For
3117: any special vectors that do not store local vector data in a contiguous
3118: array, this routine will copy the data back into the underlying
3119: vector data structure from the array obtained with `VecGetArray()`.
3121: This routine actually zeros out the `a` pointer.
3123: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3124: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3125: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3126: @*/
3127: PetscErrorCode VecRestoreArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3128: {
3129: void *dummy;
3131: PetscFunctionBegin;
3133: PetscAssertPointer(a, 8);
3135: dummy = (void *)(*a + mstart);
3136: PetscCall(PetscFree(dummy));
3137: PetscCall(VecRestoreArrayWrite(x, NULL));
3138: *a = NULL;
3139: PetscFunctionReturn(PETSC_SUCCESS);
3140: }
3142: /*@C
3143: VecGetArray4d - Returns a pointer to a 4d contiguous array that contains this
3144: processor's portion of the vector data. You MUST call `VecRestoreArray4d()`
3145: when you no longer need access to the array.
3147: Logically Collective
3149: Input Parameters:
3150: + x - the vector
3151: . m - first dimension of four dimensional array
3152: . n - second dimension of four dimensional array
3153: . p - third dimension of four dimensional array
3154: . q - fourth dimension of four dimensional array
3155: . mstart - first index you will use in first coordinate direction (often 0)
3156: . nstart - first index in the second coordinate direction (often 0)
3157: . pstart - first index in the third coordinate direction (often 0)
3158: - qstart - first index in the fourth coordinate direction (often 0)
3160: Output Parameter:
3161: . a - location to put pointer to the array
3163: Level: developer
3165: Notes:
3166: For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3167: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3168: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3169: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3171: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3173: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3174: `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3175: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecRestoreArray4d()`
3176: @*/
3177: PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3178: {
3179: PetscInt i, N, j, k;
3180: PetscScalar *aa, ***b, **c;
3182: PetscFunctionBegin;
3184: PetscAssertPointer(a, 10);
3186: PetscCall(VecGetLocalSize(x, &N));
3187: 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);
3188: PetscCall(VecGetArray(x, &aa));
3190: PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3191: b = (PetscScalar ***)((*a) + m);
3192: c = (PetscScalar **)(b + m * n);
3193: for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3194: for (i = 0; i < m; i++)
3195: for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3196: for (i = 0; i < m; i++)
3197: for (j = 0; j < n; j++)
3198: for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3199: *a -= mstart;
3200: PetscFunctionReturn(PETSC_SUCCESS);
3201: }
3203: /*@C
3204: VecGetArray4dWrite - Returns a pointer to a 4d contiguous array that will contain this
3205: processor's portion of the vector data. You MUST call `VecRestoreArray4dWrite()`
3206: when you no longer need access to the array.
3208: Logically Collective
3210: Input Parameters:
3211: + x - the vector
3212: . m - first dimension of four dimensional array
3213: . n - second dimension of four dimensional array
3214: . p - third dimension of four dimensional array
3215: . q - fourth dimension of four dimensional array
3216: . mstart - first index you will use in first coordinate direction (often 0)
3217: . nstart - first index in the second coordinate direction (often 0)
3218: . pstart - first index in the third coordinate direction (often 0)
3219: - qstart - first index in the fourth coordinate direction (often 0)
3221: Output Parameter:
3222: . a - location to put pointer to the array
3224: Level: developer
3226: Notes:
3227: For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3228: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3229: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3230: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3232: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3234: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3235: `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3236: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3237: @*/
3238: PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3239: {
3240: PetscInt i, N, j, k;
3241: PetscScalar *aa, ***b, **c;
3243: PetscFunctionBegin;
3245: PetscAssertPointer(a, 10);
3247: PetscCall(VecGetLocalSize(x, &N));
3248: 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);
3249: PetscCall(VecGetArrayWrite(x, &aa));
3251: PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3252: b = (PetscScalar ***)((*a) + m);
3253: c = (PetscScalar **)(b + m * n);
3254: for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3255: for (i = 0; i < m; i++)
3256: for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3257: for (i = 0; i < m; i++)
3258: for (j = 0; j < n; j++)
3259: for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3260: *a -= mstart;
3261: PetscFunctionReturn(PETSC_SUCCESS);
3262: }
3264: /*@C
3265: VecRestoreArray4d - Restores a vector after `VecGetArray4d()` has been called.
3267: Logically Collective
3269: Input Parameters:
3270: + x - the vector
3271: . m - first dimension of four dimensional array
3272: . n - second dimension of the four dimensional array
3273: . p - third dimension of the four dimensional array
3274: . q - fourth dimension of the four dimensional array
3275: . mstart - first index you will use in first coordinate direction (often 0)
3276: . nstart - first index in the second coordinate direction (often 0)
3277: . pstart - first index in the third coordinate direction (often 0)
3278: . qstart - first index in the fourth coordinate direction (often 0)
3279: - a - location of pointer to array obtained from VecGetArray4d()
3281: Level: developer
3283: Notes:
3284: For regular PETSc vectors this routine does not involve any copies. For
3285: any special vectors that do not store local vector data in a contiguous
3286: array, this routine will copy the data back into the underlying
3287: vector data structure from the array obtained with `VecGetArray()`.
3289: This routine actually zeros out the `a` pointer.
3291: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3292: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3293: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`
3294: @*/
3295: PetscErrorCode VecRestoreArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3296: {
3297: void *dummy;
3299: PetscFunctionBegin;
3301: PetscAssertPointer(a, 10);
3303: dummy = (void *)(*a + mstart);
3304: PetscCall(PetscFree(dummy));
3305: PetscCall(VecRestoreArray(x, NULL));
3306: *a = NULL;
3307: PetscFunctionReturn(PETSC_SUCCESS);
3308: }
3310: /*@C
3311: VecRestoreArray4dWrite - Restores a vector after `VecGetArray4dWrite()` has been called.
3313: Logically Collective
3315: Input Parameters:
3316: + x - the vector
3317: . m - first dimension of four dimensional array
3318: . n - second dimension of the four dimensional array
3319: . p - third dimension of the four dimensional array
3320: . q - fourth dimension of the four dimensional array
3321: . mstart - first index you will use in first coordinate direction (often 0)
3322: . nstart - first index in the second coordinate direction (often 0)
3323: . pstart - first index in the third coordinate direction (often 0)
3324: . qstart - first index in the fourth coordinate direction (often 0)
3325: - a - location of pointer to array obtained from `VecGetArray4d()`
3327: Level: developer
3329: Notes:
3330: For regular PETSc vectors this routine does not involve any copies. For
3331: any special vectors that do not store local vector data in a contiguous
3332: array, this routine will copy the data back into the underlying
3333: vector data structure from the array obtained with `VecGetArray()`.
3335: This routine actually zeros out the `a` pointer.
3337: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3338: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3339: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3340: @*/
3341: PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3342: {
3343: void *dummy;
3345: PetscFunctionBegin;
3347: PetscAssertPointer(a, 10);
3349: dummy = (void *)(*a + mstart);
3350: PetscCall(PetscFree(dummy));
3351: PetscCall(VecRestoreArrayWrite(x, NULL));
3352: *a = NULL;
3353: PetscFunctionReturn(PETSC_SUCCESS);
3354: }
3356: /*@C
3357: VecGetArray2dRead - Returns a pointer to a 2d contiguous array that contains this
3358: processor's portion of the vector data. You MUST call `VecRestoreArray2dRead()`
3359: when you no longer need access to the array.
3361: Logically Collective
3363: Input Parameters:
3364: + x - the vector
3365: . m - first dimension of two dimensional array
3366: . n - second dimension of two dimensional array
3367: . mstart - first index you will use in first coordinate direction (often 0)
3368: - nstart - first index in the second coordinate direction (often 0)
3370: Output Parameter:
3371: . a - location to put pointer to the array
3373: Level: developer
3375: Notes:
3376: For a vector obtained from `DMCreateLocalVector()` `mstart` and `nstart` are likely
3377: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3378: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3379: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.
3381: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3383: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3384: `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3385: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3386: @*/
3387: PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3388: {
3389: PetscInt i, N;
3390: const PetscScalar *aa;
3392: PetscFunctionBegin;
3394: PetscAssertPointer(a, 6);
3396: PetscCall(VecGetLocalSize(x, &N));
3397: 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);
3398: PetscCall(VecGetArrayRead(x, &aa));
3400: PetscCall(PetscMalloc1(m, a));
3401: for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3402: *a -= mstart;
3403: PetscFunctionReturn(PETSC_SUCCESS);
3404: }
3406: /*@C
3407: VecRestoreArray2dRead - Restores a vector after `VecGetArray2dRead()` has been called.
3409: Logically Collective
3411: Input Parameters:
3412: + x - the vector
3413: . m - first dimension of two dimensional array
3414: . n - second dimension of the two dimensional array
3415: . mstart - first index you will use in first coordinate direction (often 0)
3416: . nstart - first index in the second coordinate direction (often 0)
3417: - a - location of pointer to array obtained from VecGetArray2d()
3419: Level: developer
3421: Notes:
3422: For regular PETSc vectors this routine does not involve any copies. For
3423: any special vectors that do not store local vector data in a contiguous
3424: array, this routine will copy the data back into the underlying
3425: vector data structure from the array obtained with `VecGetArray()`.
3427: This routine actually zeros out the `a` pointer.
3429: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3430: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3431: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3432: @*/
3433: PetscErrorCode VecRestoreArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3434: {
3435: void *dummy;
3437: PetscFunctionBegin;
3439: PetscAssertPointer(a, 6);
3441: dummy = (void *)(*a + mstart);
3442: PetscCall(PetscFree(dummy));
3443: PetscCall(VecRestoreArrayRead(x, NULL));
3444: *a = NULL;
3445: PetscFunctionReturn(PETSC_SUCCESS);
3446: }
3448: /*@C
3449: VecGetArray1dRead - Returns a pointer to a 1d contiguous array that contains this
3450: processor's portion of the vector data. You MUST call `VecRestoreArray1dRead()`
3451: when you no longer need access to the array.
3453: Logically Collective
3455: Input Parameters:
3456: + x - the vector
3457: . m - first dimension of two dimensional array
3458: - mstart - first index you will use in first coordinate direction (often 0)
3460: Output Parameter:
3461: . a - location to put pointer to the array
3463: Level: developer
3465: Notes:
3466: For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
3467: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3468: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.
3470: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3472: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3473: `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3474: `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3475: @*/
3476: PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3477: {
3478: PetscInt N;
3480: PetscFunctionBegin;
3482: PetscAssertPointer(a, 4);
3484: PetscCall(VecGetLocalSize(x, &N));
3485: 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);
3486: PetscCall(VecGetArrayRead(x, (const PetscScalar **)a));
3487: *a -= mstart;
3488: PetscFunctionReturn(PETSC_SUCCESS);
3489: }
3491: /*@C
3492: VecRestoreArray1dRead - Restores a vector after `VecGetArray1dRead()` has been called.
3494: Logically Collective
3496: Input Parameters:
3497: + x - the vector
3498: . m - first dimension of two dimensional array
3499: . mstart - first index you will use in first coordinate direction (often 0)
3500: - a - location of pointer to array obtained from `VecGetArray1dRead()`
3502: Level: developer
3504: Notes:
3505: For regular PETSc vectors this routine does not involve any copies. For
3506: any special vectors that do not store local vector data in a contiguous
3507: array, this routine will copy the data back into the underlying
3508: vector data structure from the array obtained with `VecGetArray1dRead()`.
3510: This routine actually zeros out the `a` pointer.
3512: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3513: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3514: `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3515: @*/
3516: PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3517: {
3518: PetscFunctionBegin;
3521: PetscCall(VecRestoreArrayRead(x, NULL));
3522: *a = NULL;
3523: PetscFunctionReturn(PETSC_SUCCESS);
3524: }
3526: /*@C
3527: VecGetArray3dRead - Returns a pointer to a 3d contiguous array that contains this
3528: processor's portion of the vector data. You MUST call `VecRestoreArray3dRead()`
3529: when you no longer need access to the array.
3531: Logically Collective
3533: Input Parameters:
3534: + x - the vector
3535: . m - first dimension of three dimensional array
3536: . n - second dimension of three dimensional array
3537: . p - third dimension of three dimensional array
3538: . mstart - first index you will use in first coordinate direction (often 0)
3539: . nstart - first index in the second coordinate direction (often 0)
3540: - pstart - first index in the third coordinate direction (often 0)
3542: Output Parameter:
3543: . a - location to put pointer to the array
3545: Level: developer
3547: Notes:
3548: For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3549: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3550: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3551: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3dRead()`.
3553: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3555: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3556: `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3557: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3558: @*/
3559: PetscErrorCode VecGetArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3560: {
3561: PetscInt i, N, j;
3562: const PetscScalar *aa;
3563: PetscScalar **b;
3565: PetscFunctionBegin;
3567: PetscAssertPointer(a, 8);
3569: PetscCall(VecGetLocalSize(x, &N));
3570: 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);
3571: PetscCall(VecGetArrayRead(x, &aa));
3573: PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3574: b = (PetscScalar **)((*a) + m);
3575: for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3576: for (i = 0; i < m; i++)
3577: for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset((PetscScalar *)aa, i * n * p + j * p - pstart);
3578: *a -= mstart;
3579: PetscFunctionReturn(PETSC_SUCCESS);
3580: }
3582: /*@C
3583: VecRestoreArray3dRead - Restores a vector after `VecGetArray3dRead()` has been called.
3585: Logically Collective
3587: Input Parameters:
3588: + x - the vector
3589: . m - first dimension of three dimensional array
3590: . n - second dimension of the three dimensional array
3591: . p - third dimension of the three dimensional array
3592: . mstart - first index you will use in first coordinate direction (often 0)
3593: . nstart - first index in the second coordinate direction (often 0)
3594: . pstart - first index in the third coordinate direction (often 0)
3595: - a - location of pointer to array obtained from `VecGetArray3dRead()`
3597: Level: developer
3599: Notes:
3600: For regular PETSc vectors this routine does not involve any copies. For
3601: any special vectors that do not store local vector data in a contiguous
3602: array, this routine will copy the data back into the underlying
3603: vector data structure from the array obtained with `VecGetArray()`.
3605: This routine actually zeros out the `a` pointer.
3607: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3608: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3609: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3610: @*/
3611: PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3612: {
3613: void *dummy;
3615: PetscFunctionBegin;
3617: PetscAssertPointer(a, 8);
3619: dummy = (void *)(*a + mstart);
3620: PetscCall(PetscFree(dummy));
3621: PetscCall(VecRestoreArrayRead(x, NULL));
3622: *a = NULL;
3623: PetscFunctionReturn(PETSC_SUCCESS);
3624: }
3626: /*@C
3627: VecGetArray4dRead - Returns a pointer to a 4d contiguous array that contains this
3628: processor's portion of the vector data. You MUST call `VecRestoreArray4dRead()`
3629: when you no longer need access to the array.
3631: Logically Collective
3633: Input Parameters:
3634: + x - the vector
3635: . m - first dimension of four dimensional array
3636: . n - second dimension of four dimensional array
3637: . p - third dimension of four dimensional array
3638: . q - fourth dimension of four dimensional array
3639: . mstart - first index you will use in first coordinate direction (often 0)
3640: . nstart - first index in the second coordinate direction (often 0)
3641: . pstart - first index in the third coordinate direction (often 0)
3642: - qstart - first index in the fourth coordinate direction (often 0)
3644: Output Parameter:
3645: . a - location to put pointer to the array
3647: Level: beginner
3649: Notes:
3650: For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3651: obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3652: `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3653: the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3655: For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3657: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3658: `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3659: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3660: @*/
3661: PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3662: {
3663: PetscInt i, N, j, k;
3664: const PetscScalar *aa;
3665: PetscScalar ***b, **c;
3667: PetscFunctionBegin;
3669: PetscAssertPointer(a, 10);
3671: PetscCall(VecGetLocalSize(x, &N));
3672: 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);
3673: PetscCall(VecGetArrayRead(x, &aa));
3675: PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3676: b = (PetscScalar ***)((*a) + m);
3677: c = (PetscScalar **)(b + m * n);
3678: for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3679: for (i = 0; i < m; i++)
3680: for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3681: for (i = 0; i < m; i++)
3682: for (j = 0; j < n; j++)
3683: 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;
3684: *a -= mstart;
3685: PetscFunctionReturn(PETSC_SUCCESS);
3686: }
3688: /*@C
3689: VecRestoreArray4dRead - Restores a vector after `VecGetArray4d()` has been called.
3691: Logically Collective
3693: Input Parameters:
3694: + x - the vector
3695: . m - first dimension of four dimensional array
3696: . n - second dimension of the four dimensional array
3697: . p - third dimension of the four dimensional array
3698: . q - fourth dimension of the four dimensional array
3699: . mstart - first index you will use in first coordinate direction (often 0)
3700: . nstart - first index in the second coordinate direction (often 0)
3701: . pstart - first index in the third coordinate direction (often 0)
3702: . qstart - first index in the fourth coordinate direction (often 0)
3703: - a - location of pointer to array obtained from `VecGetArray4dRead()`
3705: Level: beginner
3707: Notes:
3708: For regular PETSc vectors this routine does not involve any copies. For
3709: any special vectors that do not store local vector data in a contiguous
3710: array, this routine will copy the data back into the underlying
3711: vector data structure from the array obtained with `VecGetArray()`.
3713: This routine actually zeros out the `a` pointer.
3715: .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3716: `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3717: `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3718: @*/
3719: PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3720: {
3721: void *dummy;
3723: PetscFunctionBegin;
3725: PetscAssertPointer(a, 10);
3727: dummy = (void *)(*a + mstart);
3728: PetscCall(PetscFree(dummy));
3729: PetscCall(VecRestoreArrayRead(x, NULL));
3730: *a = NULL;
3731: PetscFunctionReturn(PETSC_SUCCESS);
3732: }
3734: /*@
3735: VecLockGet - Get the current lock status of a vector
3737: Logically Collective
3739: Input Parameter:
3740: . x - the vector
3742: Output Parameter:
3743: . state - greater than zero indicates the vector is locked for read; less than zero indicates the vector is
3744: locked for write; equal to zero means the vector is unlocked, that is, it is free to read or write.
3746: Level: advanced
3748: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
3749: @*/
3750: PetscErrorCode VecLockGet(Vec x, PetscInt *state)
3751: {
3752: PetscFunctionBegin;
3754: PetscAssertPointer(state, 2);
3755: *state = x->lock;
3756: PetscFunctionReturn(PETSC_SUCCESS);
3757: }
3759: PetscErrorCode VecLockGetLocation(Vec x, const char *file[], const char *func[], int *line)
3760: {
3761: PetscFunctionBegin;
3763: PetscAssertPointer(file, 2);
3764: PetscAssertPointer(func, 3);
3765: PetscAssertPointer(line, 4);
3766: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3767: {
3768: const int index = x->lockstack.currentsize - 1;
3770: *file = index < 0 ? NULL : x->lockstack.file[index];
3771: *func = index < 0 ? NULL : x->lockstack.function[index];
3772: *line = index < 0 ? 0 : x->lockstack.line[index];
3773: }
3774: #else
3775: *file = NULL;
3776: *func = NULL;
3777: *line = 0;
3778: #endif
3779: PetscFunctionReturn(PETSC_SUCCESS);
3780: }
3782: /*@
3783: VecLockReadPush - Push a read-only lock on a vector to prevent it from being written to
3785: Logically Collective
3787: Input Parameter:
3788: . x - the vector
3790: Level: intermediate
3792: Notes:
3793: If this is set then calls to `VecGetArray()` or `VecSetValues()` or any other routines that change the vectors values will generate an error.
3795: The call can be nested, i.e., called multiple times on the same vector, but each `VecLockReadPush()` has to have one matching
3796: `VecLockReadPop()`, which removes the latest read-only lock.
3798: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPop()`, `VecLockGet()`
3799: @*/
3800: PetscErrorCode VecLockReadPush(Vec x)
3801: {
3802: PetscFunctionBegin;
3804: 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");
3805: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3806: {
3807: const char *file, *func;
3808: int index, line;
3810: if ((index = petscstack.currentsize - 2) < 0) {
3811: // vec was locked "outside" of petsc, either in user-land or main. the error message will
3812: // now show this function as the culprit, but it will include the stacktrace
3813: file = "unknown user-file";
3814: func = "unknown_user_function";
3815: line = 0;
3816: } else {
3817: file = petscstack.file[index];
3818: func = petscstack.function[index];
3819: line = petscstack.line[index];
3820: }
3821: PetscStackPush_Private(x->lockstack, file, func, line, petscstack.petscroutine[index], PETSC_FALSE);
3822: }
3823: #endif
3824: PetscFunctionReturn(PETSC_SUCCESS);
3825: }
3827: /*@
3828: VecLockReadPop - Pop a read-only lock from a vector
3830: Logically Collective
3832: Input Parameter:
3833: . x - the vector
3835: Level: intermediate
3837: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockGet()`
3838: @*/
3839: PetscErrorCode VecLockReadPop(Vec x)
3840: {
3841: PetscFunctionBegin;
3843: PetscCheck(--x->lock >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector has been unlocked from read-only access too many times");
3844: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3845: {
3846: const char *previous = x->lockstack.function[x->lockstack.currentsize - 1];
3848: PetscStackPop_Private(x->lockstack, previous);
3849: }
3850: #endif
3851: PetscFunctionReturn(PETSC_SUCCESS);
3852: }
3854: /*@
3855: VecLockWriteSet - Lock or unlock a vector for exclusive read/write access
3857: Logically Collective
3859: Input Parameters:
3860: + x - the vector
3861: - flg - `PETSC_TRUE` to lock the vector for exclusive read/write access; `PETSC_FALSE` to unlock it.
3863: Level: intermediate
3865: Notes:
3866: The function is useful in split-phase computations, which usually have a begin phase and an end phase.
3867: One can call `VecLockWriteSet`(x,`PETSC_TRUE`) in the begin phase to lock a vector for exclusive
3868: access, and call `VecLockWriteSet`(x,`PETSC_FALSE`) in the end phase to unlock the vector from exclusive
3869: access. In this way, one is ensured no other operations can access the vector in between. The code may like
3871: .vb
3872: VecGetArray(x,&xdata); // begin phase
3873: VecLockWriteSet(v,PETSC_TRUE);
3875: Other operations, which can not access x anymore (they can access xdata, of course)
3877: VecRestoreArray(x,&vdata); // end phase
3878: VecLockWriteSet(v,PETSC_FALSE);
3879: .ve
3881: The call can not be nested on the same vector, in other words, one can not call `VecLockWriteSet`(x,`PETSC_TRUE`)
3882: again before calling `VecLockWriteSet`(v,`PETSC_FALSE`).
3884: .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
3885: @*/
3886: PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
3887: {
3888: PetscFunctionBegin;
3890: if (flg) {
3891: 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");
3892: 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");
3893: x->lock = -1;
3894: } else {
3895: 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");
3896: x->lock = 0;
3897: }
3898: PetscFunctionReturn(PETSC_SUCCESS);
3899: }