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> /*I "petscvec.h" I*/
6
7 PetscInt VecGetSubVectorSavedStateId = -1;
8
9 #if PetscDefined(USE_DEBUG)
10 // this is a no-op '0' macro in optimized builds
VecValidValues_Internal(Vec vec,PetscInt argnum,PetscBool begin)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;
18
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
35
36 /*@
37 VecMaxPointwiseDivide - Computes the maximum of the componentwise division `max = max_i abs(x[i]/y[i])`.
38
39 Logically Collective
40
41 Input Parameters:
42 + x - the numerators
43 - y - the denominators
44
45 Output Parameter:
46 . max - the result
47
48 Level: advanced
49
50 Notes:
51 `x` and `y` may be the same vector
52
53 if a particular `y[i]` is zero, it is treated as 1 in the above formula
54
55 .seealso: [](ch_vectors), `Vec`, `VecPointwiseDivide()`, `VecPointwiseMult()`, `VecPointwiseMax()`, `VecPointwiseMin()`, `VecPointwiseMaxAbs()`
56 @*/
VecMaxPointwiseDivide(Vec x,Vec y,PetscReal * max)57 PetscErrorCode VecMaxPointwiseDivide(Vec x, Vec y, PetscReal *max)
58 {
59 PetscFunctionBegin;
60 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
61 PetscValidHeaderSpecific(y, VEC_CLASSID, 2);
62 PetscAssertPointer(max, 3);
63 PetscValidType(x, 1);
64 PetscValidType(y, 2);
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 }
76
77 /*@
78 VecDot - Computes the vector dot product.
79
80 Collective
81
82 Input Parameters:
83 + x - first vector
84 - y - second vector
85
86 Output Parameter:
87 . val - the dot product
88
89 Level: intermediate
90
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.
99
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.
105
106 .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDotRealPart()`
107 @*/
VecDot(Vec x,Vec y,PetscScalar * val)108 PetscErrorCode VecDot(Vec x, Vec y, PetscScalar *val)
109 {
110 PetscFunctionBegin;
111 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
112 PetscValidHeaderSpecific(y, VEC_CLASSID, 2);
113 PetscAssertPointer(val, 3);
114 PetscValidType(x, 1);
115 PetscValidType(y, 2);
116 PetscCheckSameTypeAndComm(x, 1, y, 2);
117 VecCheckSameSize(x, 1, y, 2);
118 VecCheckAssembled(x);
119 VecCheckAssembled(y);
120
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 }
130
131 /*@
132 VecDotRealPart - Computes the real part of the vector dot product.
133
134 Collective
135
136 Input Parameters:
137 + x - first vector
138 - y - second vector
139
140 Output Parameter:
141 . val - the real part of the dot product;
142
143 Level: intermediate
144
145 Notes for Users of Complex Numbers:
146 See `VecDot()` for more details on the definition of the dot product for complex numbers
147
148 For real numbers this returns the same value as `VecDot()`
149
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)
152
153 Developer Notes:
154 This is not currently optimized to compute only the real part of the dot product.
155
156 .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDot()`, `VecDotNorm2()`
157 @*/
VecDotRealPart(Vec x,Vec y,PetscReal * val)158 PetscErrorCode VecDotRealPart(Vec x, Vec y, PetscReal *val)
159 {
160 PetscScalar fdot;
161
162 PetscFunctionBegin;
163 PetscCall(VecDot(x, y, &fdot));
164 *val = PetscRealPart(fdot);
165 PetscFunctionReturn(PETSC_SUCCESS);
166 }
167
168 /*@
169 VecNorm - Computes the vector norm.
170
171 Collective
172
173 Input Parameters:
174 + x - the vector
175 - type - the type of the norm requested
176
177 Output Parameter:
178 . val - the norm
179
180 Level: intermediate
181
182 Notes:
183 See `NormType` for descriptions of each norm.
184
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.
189
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.
195
196 .seealso: [](ch_vectors), `Vec`, `NormType`, `VecDot()`, `VecTDot()`, `VecDotBegin()`, `VecDotEnd()`, `VecNormAvailable()`,
197 `VecNormBegin()`, `VecNormEnd()`, `NormType()`
198 @*/
VecNorm(Vec x,NormType type,PetscReal * val)199 PetscErrorCode VecNorm(Vec x, NormType type, PetscReal *val)
200 {
201 PetscBool flg = PETSC_TRUE;
202
203 PetscFunctionBegin;
204 PetscCall(VecLockReadPush(x));
205 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
206 PetscValidType(x, 1);
207 VecCheckAssembled(x);
208 PetscValidLogicalCollectiveEnum(x, type, 2);
209 PetscAssertPointer(val, 3);
210
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));
231
232 if (type != NORM_1_AND_2) PetscCall(PetscObjectComposedDataSetReal((PetscObject)x, NormIds[type], *val));
233 }
234 PetscCall(VecLockReadPop(x));
235 PetscFunctionReturn(PETSC_SUCCESS);
236 }
237
238 /*@
239 VecNormAvailable - Returns the vector norm if it is already known. That is, it has been previously computed and cached in the vector
240
241 Not Collective
242
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.
248
249 Output Parameters:
250 + available - `PETSC_TRUE` if the val returned is valid
251 - val - the norm
252
253 Level: intermediate
254
255 .seealso: [](ch_vectors), `Vec`, `VecDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`,
256 `VecNormBegin()`, `VecNormEnd()`
257 @*/
VecNormAvailable(Vec x,NormType type,PetscBool * available,PetscReal * val)258 PetscErrorCode VecNormAvailable(Vec x, NormType type, PetscBool *available, PetscReal *val)
259 {
260 PetscFunctionBegin;
261 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
262 PetscValidType(x, 1);
263 PetscAssertPointer(available, 3);
264 PetscAssertPointer(val, 4);
265
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 }
273
274 /*@
275 VecNormalize - Normalizes a vector by its 2-norm.
276
277 Collective
278
279 Input Parameter:
280 . x - the vector
281
282 Output Parameter:
283 . val - the vector norm before normalization. May be `NULL` if the value is not needed.
284
285 Level: intermediate
286
287 .seealso: [](ch_vectors), `Vec`, `VecNorm()`, `NORM_2`, `NormType`
288 @*/
VecNormalize(Vec x,PetscReal * val)289 PetscErrorCode VecNormalize(Vec x, PetscReal *val)
290 {
291 PetscReal norm;
292
293 PetscFunctionBegin;
294 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
295 PetscValidType(x, 1);
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 infinity 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 }
310
311 /*@
312 VecMax - Determines the vector component with maximum real part and its location.
313
314 Collective
315
316 Input Parameter:
317 . x - the vector
318
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
322
323 Level: intermediate
324
325 Notes:
326 Returns the value `PETSC_MIN_REAL` and negative `p` if the vector is of length 0.
327
328 Returns the smallest index with the maximum value
329
330 Developer Note:
331 The Nag Fortran compiler does not like the symbol name VecMax
332
333 .seealso: [](ch_vectors), `Vec`, `VecNorm()`, `VecMin()`
334 @*/
VecMax(Vec x,PetscInt * p,PetscReal * val)335 PetscErrorCode VecMax(Vec x, PetscInt *p, PetscReal *val)
336 {
337 PetscFunctionBegin;
338 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
339 PetscValidType(x, 1);
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 }
350
351 /*@
352 VecMin - Determines the vector component with minimum real part and its location.
353
354 Collective
355
356 Input Parameter:
357 . x - the vector
358
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
362
363 Level: intermediate
364
365 Notes:
366 Returns the value `PETSC_MAX_REAL` and negative `p` if the vector is of length 0.
367
368 This returns the smallest index with the minimum value
369
370 Developer Note:
371 The Nag Fortran compiler does not like the symbol name VecMin
372
373 .seealso: [](ch_vectors), `Vec`, `VecMax()`
374 @*/
VecMin(Vec x,PetscInt * p,PetscReal * val)375 PetscErrorCode VecMin(Vec x, PetscInt *p, PetscReal *val)
376 {
377 PetscFunctionBegin;
378 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
379 PetscValidType(x, 1);
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 }
390
391 /*@
392 VecTDot - Computes an indefinite vector dot product. That is, this
393 routine does NOT use the complex conjugate.
394
395 Collective
396
397 Input Parameters:
398 + x - first vector
399 - y - second vector
400
401 Output Parameter:
402 . val - the dot product
403
404 Level: intermediate
405
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.
412
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.
418
419 .seealso: [](ch_vectors), `Vec`, `VecDot()`, `VecMTDot()`
420 @*/
VecTDot(Vec x,Vec y,PetscScalar * val)421 PetscErrorCode VecTDot(Vec x, Vec y, PetscScalar *val)
422 {
423 PetscFunctionBegin;
424 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
425 PetscValidHeaderSpecific(y, VEC_CLASSID, 2);
426 PetscAssertPointer(val, 3);
427 PetscValidType(x, 1);
428 PetscValidType(y, 2);
429 PetscCheckSameTypeAndComm(x, 1, y, 2);
430 VecCheckSameSize(x, 1, y, 2);
431 VecCheckAssembled(x);
432 VecCheckAssembled(y);
433
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 }
443
VecScaleAsync_Private(Vec x,PetscScalar alpha,PetscDeviceContext dctx)444 PetscErrorCode VecScaleAsync_Private(Vec x, PetscScalar alpha, PetscDeviceContext dctx)
445 {
446 PetscReal norms[4];
447 PetscBool flgs[4];
448 PetscScalar one = 1.0;
449
450 PetscFunctionBegin;
451 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
452 PetscValidType(x, 1);
453 VecCheckAssembled(x);
454 PetscCall(VecSetErrorIfLocked(x, 1));
455 PetscValidLogicalCollectiveScalar(x, alpha, 2);
456 if (alpha == one) PetscFunctionReturn(PETSC_SUCCESS);
457
458 /* get current stashed norms */
459 for (PetscInt i = 0; i < 4; i++) PetscCall(PetscObjectComposedDataGetReal((PetscObject)x, NormIds[i], norms[i], flgs[i]));
460
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));
464
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 }
473
474 /*@
475 VecScale - Scales a vector.
476
477 Logically Collective
478
479 Input Parameters:
480 + x - the vector
481 - alpha - the scalar
482
483 Level: intermediate
484
485 Note:
486 For a vector with n components, `VecScale()` computes x[i] = alpha * x[i], for i=1,...,n.
487
488 .seealso: [](ch_vectors), `Vec`, `VecSet()`
489 @*/
VecScale(Vec x,PetscScalar alpha)490 PetscErrorCode VecScale(Vec x, PetscScalar alpha)
491 {
492 PetscFunctionBegin;
493 PetscCall(VecScaleAsync_Private(x, alpha, NULL));
494 PetscFunctionReturn(PETSC_SUCCESS);
495 }
496
VecSetAsync_Private(Vec x,PetscScalar alpha,PetscDeviceContext dctx)497 PetscErrorCode VecSetAsync_Private(Vec x, PetscScalar alpha, PetscDeviceContext dctx)
498 {
499 PetscFunctionBegin;
500 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
501 PetscValidType(x, 1);
502 VecCheckAssembled(x);
503 PetscValidLogicalCollectiveScalar(x, alpha, 2);
504 PetscCall(VecSetErrorIfLocked(x, 1));
505
506 if (alpha == 0) {
507 PetscReal norm;
508 PetscBool set;
509
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));
517
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;
522
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 }
540
541 /*@
542 VecSet - Sets all components of a vector to a single scalar value.
543
544 Logically Collective
545
546 Input Parameters:
547 + x - the vector
548 - alpha - the scalar
549
550 Level: beginner
551
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.
557
558 You CANNOT call this after you have called `VecSetValues()` but before you call
559 `VecAssemblyBegin()`
560
561 If `alpha` is zero and the norm of the vector is known to be zero then this skips the unneeded zeroing process
562
563 .seealso: [](ch_vectors), `Vec`, `VecSetValues()`, `VecSetValuesBlocked()`, `VecSetRandom()`
564 @*/
VecSet(Vec x,PetscScalar alpha)565 PetscErrorCode VecSet(Vec x, PetscScalar alpha)
566 {
567 PetscFunctionBegin;
568 PetscCall(VecSetAsync_Private(x, alpha, NULL));
569 PetscFunctionReturn(PETSC_SUCCESS);
570 }
571
VecAXPYAsync_Private(Vec y,PetscScalar alpha,Vec x,PetscDeviceContext dctx)572 PetscErrorCode VecAXPYAsync_Private(Vec y, PetscScalar alpha, Vec x, PetscDeviceContext dctx)
573 {
574 PetscFunctionBegin;
575 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
576 PetscValidHeaderSpecific(y, VEC_CLASSID, 1);
577 PetscValidType(x, 3);
578 PetscValidType(y, 1);
579 PetscCheckSameTypeAndComm(x, 3, y, 1);
580 VecCheckSameSize(x, 3, y, 1);
581 VecCheckAssembled(x);
582 VecCheckAssembled(y);
583 PetscValidLogicalCollectiveScalar(y, alpha, 2);
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`.
600
601 Logically Collective
602
603 Input Parameters:
604 + alpha - the scalar
605 . x - vector scale by `alpha`
606 - y - vector accumulated into
607
608 Output Parameter:
609 . y - output vector
610
611 Level: intermediate
612
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
623
624 .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
625 @*/
VecAXPY(Vec y,PetscScalar alpha,Vec x)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 }
632
VecAYPXAsync_Private(Vec y,PetscScalar beta,Vec x,PetscDeviceContext dctx)633 PetscErrorCode VecAYPXAsync_Private(Vec y, PetscScalar beta, Vec x, PetscDeviceContext dctx)
634 {
635 PetscFunctionBegin;
636 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
637 PetscValidHeaderSpecific(y, VEC_CLASSID, 1);
638 PetscValidType(x, 3);
639 PetscValidType(y, 1);
640 PetscCheckSameTypeAndComm(x, 3, y, 1);
641 VecCheckSameSize(x, 1, y, 3);
642 VecCheckAssembled(x);
643 VecCheckAssembled(y);
644 PetscValidLogicalCollectiveScalar(y, beta, 2);
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 }
662
663 /*@
664 VecAYPX - Computes `y = x + beta y`.
665
666 Logically Collective
667
668 Input Parameters:
669 + beta - the scalar
670 . x - the unscaled vector
671 - y - the vector to be scaled
672
673 Output Parameter:
674 . y - output vector
675
676 Level: intermediate
677
678 Developer Notes:
679 The implementation is optimized for `beta` of -1.0, 0.0, and 1.0
680
681 .seealso: [](ch_vectors), `Vec`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
682 @*/
VecAYPX(Vec y,PetscScalar beta,Vec x)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 }
689
VecAXPBYAsync_Private(Vec y,PetscScalar alpha,PetscScalar beta,Vec x,PetscDeviceContext dctx)690 PetscErrorCode VecAXPBYAsync_Private(Vec y, PetscScalar alpha, PetscScalar beta, Vec x, PetscDeviceContext dctx)
691 {
692 PetscFunctionBegin;
693 PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
694 PetscValidHeaderSpecific(y, VEC_CLASSID, 1);
695 PetscValidType(x, 4);
696 PetscValidType(y, 1);
697 PetscCheckSameTypeAndComm(x, 4, y, 1);
698 VecCheckSameSize(y, 1, x, 4);
699 VecCheckAssembled(x);
700 VecCheckAssembled(y);
701 PetscValidLogicalCollectiveScalar(y, alpha, 2);
702 PetscValidLogicalCollectiveScalar(y, beta, 3);
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 }
708
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 }
718
719 /*@
720 VecAXPBY - Computes `y = alpha x + beta y`.
721
722 Logically Collective
723
724 Input Parameters:
725 + alpha - first scalar
726 . beta - second scalar
727 . x - the first scaled vector
728 - y - the second scaled vector
729
730 Output Parameter:
731 . y - output vector
732
733 Level: intermediate
734
735 Developer Notes:
736 The implementation is optimized for `alpha` and/or `beta` values of 0.0 and 1.0
737
738 .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`
739 @*/
VecAXPBY(Vec y,PetscScalar alpha,PetscScalar beta,Vec x)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 }
746
VecAXPBYPCZAsync_Private(Vec z,PetscScalar alpha,PetscScalar beta,PetscScalar gamma,Vec x,Vec y,PetscDeviceContext dctx)747 PetscErrorCode VecAXPBYPCZAsync_Private(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y, PetscDeviceContext dctx)
748 {
749 PetscFunctionBegin;
750 PetscValidHeaderSpecific(z, VEC_CLASSID, 1);
751 PetscValidHeaderSpecific(x, VEC_CLASSID, 5);
752 PetscValidHeaderSpecific(y, VEC_CLASSID, 6);
753 PetscValidType(z, 1);
754 PetscValidType(x, 5);
755 PetscValidType(y, 6);
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);
765 PetscValidLogicalCollectiveScalar(z, alpha, 2);
766 PetscValidLogicalCollectiveScalar(z, beta, 3);
767 PetscValidLogicalCollectiveScalar(z, gamma, 4);
768 if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) PetscFunctionReturn(PETSC_SUCCESS);
769
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`
783
784 Logically Collective
785
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
793
794 Output Parameter:
795 . z - output vector
796
797 Level: intermediate
798
799 Note:
800 `x`, `y` and `z` must be different vectors
801
802 Developer Notes:
803 The implementation is optimized for `alpha` of 1.0 and `gamma` of 1.0 or 0.0
804
805 .seealso: [](ch_vectors), `Vec`, `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBY()`
806 @*/
VecAXPBYPCZ(Vec z,PetscScalar alpha,PetscScalar beta,PetscScalar gamma,Vec x,Vec y)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 }
813
VecWAXPYAsync_Private(Vec w,PetscScalar alpha,Vec x,Vec y,PetscDeviceContext dctx)814 PetscErrorCode VecWAXPYAsync_Private(Vec w, PetscScalar alpha, Vec x, Vec y, PetscDeviceContext dctx)
815 {
816 PetscFunctionBegin;
817 PetscValidHeaderSpecific(w, VEC_CLASSID, 1);
818 PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
819 PetscValidHeaderSpecific(y, VEC_CLASSID, 4);
820 PetscValidType(w, 1);
821 PetscValidType(x, 3);
822 PetscValidType(y, 4);
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);
831 PetscValidLogicalCollectiveScalar(y, alpha, 2);
832 PetscCall(VecSetErrorIfLocked(w, 1));
833
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 }
848
849 /*@
850 VecWAXPY - Computes `w = alpha x + y`.
851
852 Logically Collective
853
854 Input Parameters:
855 + alpha - the scalar
856 . x - first vector, multiplied by `alpha`
857 - y - second vector
858
859 Output Parameter:
860 . w - the result
861
862 Level: intermediate
863
864 Note:
865 `w` cannot be either `x` or `y`, but `x` and `y` can be the same
866
867 Developer Notes:
868 The implementation is optimized for alpha of -1.0, 0.0, and 1.0
869
870 .seealso: [](ch_vectors), `Vec`, `VecAXPY()`, `VecAYPX()`, `VecAXPBY()`, `VecMAXPY()`, `VecAXPBYPCZ()`
871 @*/
VecWAXPY(Vec w,PetscScalar alpha,Vec x,Vec y)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 }
878
879 /*@
880 VecSetValues - Inserts or adds values into certain locations of a vector.
881
882 Not Collective
883
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. Pass `NULL` to set all zeroes.
889 - iora - either `INSERT_VALUES` to replace the current values or `ADD_VALUES` to add values to any existing entries
890
891 Level: beginner
892
893 Notes:
894 .vb
895 `VecSetValues()` sets x[ix[i]] = y[i], for i=0,...,ni-1.
896 .ve
897
898 Calls to `VecSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
899 options cannot be mixed without intervening calls to the assembly
900 routines.
901
902 These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
903 MUST be called after all calls to `VecSetValues()` have been completed.
904
905 VecSetValues() uses 0-based indices in Fortran as well as in C.
906
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.
912
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
918
919 .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesLocal()`,
920 `VecSetValue()`, `VecSetValuesBlocked()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `VecGetValues()`
921 @*/
VecSetValues(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)922 PetscErrorCode VecSetValues(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
923 {
924 PetscFunctionBeginHot;
925 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
926 if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
927 PetscAssertPointer(ix, 3);
928 if (y) PetscAssertPointer(y, 4);
929 PetscValidType(x, 1);
930
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 }
937
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
941
942 Not Collective
943
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)
948
949 Output Parameter:
950 . y - array of values, must be passed in with a length of `ni`
951
952 Level: beginner
953
954 Notes:
955 The user provides the allocated array y; it is NOT allocated in this routine
956
957 `VecGetValues()` gets y[i] = x[ix[i]], for i=0,...,ni-1.
958
959 `VecAssemblyBegin()` and `VecAssemblyEnd()` MUST be called before calling this if `VecSetValues()` or related routine has been called
960
961 VecGetValues() uses 0-based indices in Fortran as well as in C.
962
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.
966
967 .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`
968 @*/
VecGetValues(Vec x,PetscInt ni,const PetscInt ix[],PetscScalar y[])969 PetscErrorCode VecGetValues(Vec x, PetscInt ni, const PetscInt ix[], PetscScalar y[])
970 {
971 PetscFunctionBegin;
972 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
973 if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
974 PetscAssertPointer(ix, 3);
975 PetscAssertPointer(y, 4);
976 PetscValidType(x, 1);
977 VecCheckAssembled(x);
978 PetscUseTypeMethod(x, getvalues, ni, ix, y);
979 PetscFunctionReturn(PETSC_SUCCESS);
980 }
981
982 /*@
983 VecSetValuesBlocked - Inserts or adds blocks of values into certain locations of a vector.
984
985 Not Collective
986
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. Pass `NULL` to set all zeroes.
992 - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES`, adds values to any existing entries
993
994 Level: intermediate
995
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().
999
1000 Calls to `VecSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1001 options cannot be mixed without intervening calls to the assembly
1002 routines.
1003
1004 These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
1005 MUST be called after all calls to `VecSetValuesBlocked()` have been completed.
1006
1007 `VecSetValuesBlocked()` uses 0-based indices in Fortran as well as in C.
1008
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.
1013
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
1019
1020 .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesBlockedLocal()`,
1021 `VecSetValues()`
1022 @*/
VecSetValuesBlocked(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)1023 PetscErrorCode VecSetValuesBlocked(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1024 {
1025 PetscFunctionBeginHot;
1026 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
1027 if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1028 PetscAssertPointer(ix, 3);
1029 if (y) PetscAssertPointer(y, 4);
1030 PetscValidType(x, 1);
1031
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 }
1038
1039 /*@
1040 VecSetValuesLocal - Inserts or adds values into certain locations of a vector,
1041 using a local ordering of the nodes.
1042
1043 Not Collective
1044
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. Pass `NULL` to set all zeroes.
1050 - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries
1051
1052 Level: intermediate
1053
1054 Notes:
1055 `VecSetValuesLocal()` sets x[ix[i]] = y[i], for i=0,...,ni-1.
1056
1057 Calls to `VecSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1058 options cannot be mixed without intervening calls to the assembly
1059 routines.
1060
1061 These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
1062 MUST be called after all calls to `VecSetValuesLocal()` have been completed.
1063
1064 `VecSetValuesLocal()` uses 0-based indices in Fortran as well as in C.
1065
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
1071
1072 .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetLocalToGlobalMapping()`,
1073 `VecSetValuesBlockedLocal()`
1074 @*/
VecSetValuesLocal(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)1075 PetscErrorCode VecSetValuesLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1076 {
1077 PetscInt lixp[128], *lix = lixp;
1078
1079 PetscFunctionBeginHot;
1080 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
1081 if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1082 PetscAssertPointer(ix, 3);
1083 if (y) PetscAssertPointer(y, 4);
1084 PetscValidType(x, 1);
1085
1086 PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1087 if (PetscUnlikely(!x->map->mapping && x->ops->getlocaltoglobalmapping)) PetscUseTypeMethod(x, getlocaltoglobalmapping, &x->map->mapping);
1088 if (x->map->mapping) {
1089 if (ni > 128) PetscCall(PetscMalloc1(ni, &lix));
1090 PetscCall(ISLocalToGlobalMappingApply(x->map->mapping, ni, (PetscInt *)ix, lix));
1091 PetscUseTypeMethod(x, setvalues, ni, lix, y, iora);
1092 if (ni > 128) PetscCall(PetscFree(lix));
1093 } else PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
1094 PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1095 PetscCall(PetscObjectStateIncrease((PetscObject)x));
1096 PetscFunctionReturn(PETSC_SUCCESS);
1097 }
1098
1099 /*@
1100 VecSetValuesBlockedLocal - Inserts or adds values into certain locations of a vector,
1101 using a local ordering of the nodes.
1102
1103 Not Collective
1104
1105 Input Parameters:
1106 + x - vector to insert in
1107 . ni - number of blocks to add
1108 . ix - indices where to add in block count, not element count
1109 . y - array of values. Pass `NULL` to set all zeroes.
1110 - iora - either `INSERT_VALUES` replaces existing entries with new values, `ADD_VALUES` adds values to any existing entries
1111
1112 Level: intermediate
1113
1114 Notes:
1115 `VecSetValuesBlockedLocal()` sets x[bs*ix[i]+j] = y[bs*i+j],
1116 for j=0,..bs-1, for i=0,...,ni-1, where bs has been set with `VecSetBlockSize()`.
1117
1118 Calls to `VecSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
1119 options cannot be mixed without intervening calls to the assembly
1120 routines.
1121
1122 These values may be cached, so `VecAssemblyBegin()` and `VecAssemblyEnd()`
1123 MUST be called after all calls to `VecSetValuesBlockedLocal()` have been completed.
1124
1125 `VecSetValuesBlockedLocal()` uses 0-based indices in Fortran as well as in C.
1126
1127 Fortran Note:
1128 If any of `ix` and `y` are scalars pass them using, for example,
1129 .vb
1130 call VecSetValuesBlockedLocal(mat, one, [ix], [y], INSERT_VALUES, ierr)
1131 .ve
1132
1133 .seealso: [](ch_vectors), `Vec`, `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetValuesBlocked()`,
1134 `VecSetLocalToGlobalMapping()`
1135 @*/
VecSetValuesBlockedLocal(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)1136 PetscErrorCode VecSetValuesBlockedLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1137 {
1138 PetscInt lixp[128], *lix = lixp;
1139
1140 PetscFunctionBeginHot;
1141 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
1142 if (!ni) PetscFunctionReturn(PETSC_SUCCESS);
1143 PetscAssertPointer(ix, 3);
1144 if (y) PetscAssertPointer(y, 4);
1145 PetscValidType(x, 1);
1146 PetscCall(PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0));
1147 if (PetscUnlikely(!x->map->mapping && x->ops->getlocaltoglobalmapping)) PetscUseTypeMethod(x, getlocaltoglobalmapping, &x->map->mapping);
1148 if (x->map->mapping) {
1149 if (ni > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(lixp)) PetscCall(PetscMalloc1(ni, &lix));
1150 PetscCall(ISLocalToGlobalMappingApplyBlock(x->map->mapping, ni, (PetscInt *)ix, lix));
1151 PetscUseTypeMethod(x, setvaluesblocked, ni, lix, y, iora);
1152 if (ni > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(lixp)) PetscCall(PetscFree(lix));
1153 } else {
1154 PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1155 }
1156 PetscCall(PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0));
1157 PetscCall(PetscObjectStateIncrease((PetscObject)x));
1158 PetscFunctionReturn(PETSC_SUCCESS);
1159 }
1160
VecMXDot_Private(Vec x,PetscInt nv,const Vec y[],PetscScalar result[],PetscErrorCode (* mxdot)(Vec,PetscInt,const Vec[],PetscScalar[]),PetscLogEvent event)1161 static PetscErrorCode VecMXDot_Private(Vec x, PetscInt nv, const Vec y[], PetscScalar result[], PetscErrorCode (*mxdot)(Vec, PetscInt, const Vec[], PetscScalar[]), PetscLogEvent event)
1162 {
1163 PetscFunctionBegin;
1164 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
1165 PetscValidType(x, 1);
1166 VecCheckAssembled(x);
1167 PetscValidLogicalCollectiveInt(x, nv, 2);
1168 if (!nv) PetscFunctionReturn(PETSC_SUCCESS);
1169 PetscAssertPointer(y, 3);
1170 for (PetscInt i = 0; i < nv; ++i) {
1171 PetscValidHeaderSpecific(y[i], VEC_CLASSID, 3);
1172 PetscValidType(y[i], 3);
1173 PetscCheckSameTypeAndComm(x, 1, y[i], 3);
1174 VecCheckSameSize(x, 1, y[i], 3);
1175 VecCheckAssembled(y[i]);
1176 PetscCall(VecLockReadPush(y[i]));
1177 }
1178 PetscAssertPointer(result, 4);
1179 PetscValidFunction(mxdot, 5);
1180
1181 PetscCall(VecLockReadPush(x));
1182 PetscCall(PetscLogEventBegin(event, x, *y, 0, 0));
1183 PetscCall((*mxdot)(x, nv, y, result));
1184 PetscCall(PetscLogEventEnd(event, x, *y, 0, 0));
1185 PetscCall(VecLockReadPop(x));
1186 for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(y[i]));
1187 PetscFunctionReturn(PETSC_SUCCESS);
1188 }
1189
1190 /*@
1191 VecMTDot - Computes indefinite vector multiple dot products.
1192 That is, it does NOT use the complex conjugate.
1193
1194 Collective
1195
1196 Input Parameters:
1197 + x - one vector
1198 . nv - number of vectors
1199 - y - array of vectors. Note that vectors are pointers
1200
1201 Output Parameter:
1202 . val - array of the dot products
1203
1204 Level: intermediate
1205
1206 Notes for Users of Complex Numbers:
1207 For complex vectors, `VecMTDot()` computes the indefinite form
1208 .vb
1209 val = (x,y) = y^T x,
1210 .ve
1211 where y^T denotes the transpose of y.
1212
1213 Use `VecMDot()` for the inner product
1214 .vb
1215 val = (x,y) = y^H x,
1216 .ve
1217 where y^H denotes the conjugate transpose of y.
1218
1219 .seealso: [](ch_vectors), `Vec`, `VecMDot()`, `VecTDot()`
1220 @*/
VecMTDot(Vec x,PetscInt nv,const Vec y[],PetscScalar val[])1221 PetscErrorCode VecMTDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1222 {
1223 PetscFunctionBegin;
1224 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
1225 PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mtdot, VEC_MTDot));
1226 PetscFunctionReturn(PETSC_SUCCESS);
1227 }
1228
1229 /*@
1230 VecMDot - Computes multiple vector dot products.
1231
1232 Collective
1233
1234 Input Parameters:
1235 + x - one vector
1236 . nv - number of vectors
1237 - y - array of vectors.
1238
1239 Output Parameter:
1240 . val - array of the dot products (does not allocate the array)
1241
1242 Level: intermediate
1243
1244 Notes for Users of Complex Numbers:
1245 For complex vectors, `VecMDot()` computes
1246 .vb
1247 val = (x,y) = y^H x,
1248 .ve
1249 where y^H denotes the conjugate transpose of y.
1250
1251 Use `VecMTDot()` for the indefinite form
1252 .vb
1253 val = (x,y) = y^T x,
1254 .ve
1255 where y^T denotes the transpose of y.
1256
1257 Note:
1258 The implementation may use BLAS 2 operations when the vectors `y` have been obtained with `VecDuplicateVecs()`
1259
1260 .seealso: [](ch_vectors), `Vec`, `VecMTDot()`, `VecDot()`, `VecDuplicateVecs()`
1261 @*/
VecMDot(Vec x,PetscInt nv,const Vec y[],PetscScalar val[])1262 PetscErrorCode VecMDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1263 {
1264 PetscFunctionBegin;
1265 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
1266 PetscCall(VecMXDot_Private(x, nv, y, val, x->ops->mdot, VEC_MDot));
1267 PetscFunctionReturn(PETSC_SUCCESS);
1268 }
1269
VecMAXPYAsync_Private(Vec y,PetscInt nv,const PetscScalar alpha[],Vec x[],PetscDeviceContext dctx)1270 PetscErrorCode VecMAXPYAsync_Private(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[], PetscDeviceContext dctx)
1271 {
1272 PetscFunctionBegin;
1273 PetscValidHeaderSpecific(y, VEC_CLASSID, 1);
1274 VecCheckAssembled(y);
1275 PetscValidLogicalCollectiveInt(y, nv, 2);
1276 PetscCall(VecSetErrorIfLocked(y, 1));
1277 PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);
1278 if (nv) {
1279 PetscInt zeros = 0;
1280
1281 PetscAssertPointer(alpha, 3);
1282 PetscAssertPointer(x, 4);
1283 for (PetscInt i = 0; i < nv; ++i) {
1284 PetscValidLogicalCollectiveScalar(y, alpha[i], 3);
1285 PetscValidHeaderSpecific(x[i], VEC_CLASSID, 4);
1286 PetscValidType(x[i], 4);
1287 PetscCheckSameTypeAndComm(y, 1, x[i], 4);
1288 VecCheckSameSize(y, 1, x[i], 4);
1289 PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1290 VecCheckAssembled(x[i]);
1291 PetscCall(VecLockReadPush(x[i]));
1292 zeros += alpha[i] == (PetscScalar)0.0;
1293 }
1294
1295 if (zeros < nv) {
1296 PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1297 VecMethodDispatch(y, dctx, VecAsyncFnName(MAXPY), maxpy, (Vec, PetscInt, const PetscScalar[], Vec[], PetscDeviceContext), nv, alpha, x);
1298 PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1299 PetscCall(PetscObjectStateIncrease((PetscObject)y));
1300 }
1301
1302 for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1303 }
1304 PetscFunctionReturn(PETSC_SUCCESS);
1305 }
1306
1307 /*@
1308 VecMAXPY - Computes `y = y + sum alpha[i] x[i]`
1309
1310 Logically Collective
1311
1312 Input Parameters:
1313 + nv - number of scalars and `x` vectors
1314 . alpha - array of scalars
1315 . y - one vector
1316 - x - array of vectors
1317
1318 Level: intermediate
1319
1320 Notes:
1321 `y` cannot be any of the `x` vectors
1322
1323 The implementation may use BLAS 2 operations when the vectors `y` have been obtained with `VecDuplicateVecs()`
1324
1325 .seealso: [](ch_vectors), `Vec`, `VecMAXPBY()`,`VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`, `VecDuplicateVecs()`
1326 @*/
VecMAXPY(Vec y,PetscInt nv,const PetscScalar alpha[],Vec x[])1327 PetscErrorCode VecMAXPY(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[])
1328 {
1329 PetscFunctionBegin;
1330 PetscCall(VecMAXPYAsync_Private(y, nv, alpha, x, NULL));
1331 PetscFunctionReturn(PETSC_SUCCESS);
1332 }
1333
1334 /*@
1335 VecMAXPBY - Computes `y = beta y + sum alpha[i] x[i]`
1336
1337 Logically Collective
1338
1339 Input Parameters:
1340 + nv - number of scalars and `x` vectors
1341 . alpha - array of scalars
1342 . beta - scalar
1343 . y - one vector
1344 - x - array of vectors
1345
1346 Level: intermediate
1347
1348 Note:
1349 `y` cannot be any of the `x` vectors.
1350
1351 Developer Notes:
1352 This is a convenience routine, but implementations might be able to optimize it, for example, when `beta` is zero.
1353
1354 .seealso: [](ch_vectors), `Vec`, `VecMAXPY()`, `VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
1355 @*/
VecMAXPBY(Vec y,PetscInt nv,const PetscScalar alpha[],PetscScalar beta,Vec x[])1356 PetscErrorCode VecMAXPBY(Vec y, PetscInt nv, const PetscScalar alpha[], PetscScalar beta, Vec x[])
1357 {
1358 PetscFunctionBegin;
1359 PetscValidHeaderSpecific(y, VEC_CLASSID, 1);
1360 VecCheckAssembled(y);
1361 PetscValidLogicalCollectiveInt(y, nv, 2);
1362 PetscCall(VecSetErrorIfLocked(y, 1));
1363 PetscCheck(nv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vectors (given %" PetscInt_FMT ") cannot be negative", nv);
1364
1365 PetscValidLogicalCollectiveScalar(y, beta, 4);
1366 if (y->ops->maxpby) {
1367 PetscInt zeros = 0;
1368
1369 if (nv) {
1370 PetscAssertPointer(alpha, 3);
1371 PetscAssertPointer(x, 5);
1372 }
1373
1374 for (PetscInt i = 0; i < nv; ++i) { // scan all alpha[]
1375 PetscValidLogicalCollectiveScalar(y, alpha[i], 3);
1376 PetscValidHeaderSpecific(x[i], VEC_CLASSID, 5);
1377 PetscValidType(x[i], 5);
1378 PetscCheckSameTypeAndComm(y, 1, x[i], 5);
1379 VecCheckSameSize(y, 1, x[i], 5);
1380 PetscCheck(y != x[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Array of vectors 'x' cannot contain y, found x[%" PetscInt_FMT "] == y", i);
1381 VecCheckAssembled(x[i]);
1382 PetscCall(VecLockReadPush(x[i]));
1383 zeros += alpha[i] == (PetscScalar)0.0;
1384 }
1385
1386 if (zeros < nv) { // has nonzero alpha
1387 PetscCall(PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0));
1388 PetscUseTypeMethod(y, maxpby, nv, alpha, beta, x);
1389 PetscCall(PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0));
1390 PetscCall(PetscObjectStateIncrease((PetscObject)y));
1391 } else {
1392 PetscCall(VecScale(y, beta));
1393 }
1394
1395 for (PetscInt i = 0; i < nv; ++i) PetscCall(VecLockReadPop(x[i]));
1396 } else { // no maxpby
1397 if (beta == 0.0) PetscCall(VecSet(y, 0.0));
1398 else PetscCall(VecScale(y, beta));
1399 PetscCall(VecMAXPY(y, nv, alpha, x));
1400 }
1401 PetscFunctionReturn(PETSC_SUCCESS);
1402 }
1403
1404 /*@
1405 VecConcatenate - Creates a new vector that is a vertical concatenation of all the given array of vectors
1406 in the order they appear in the array. The concatenated vector resides on the same
1407 communicator and is the same type as the source vectors.
1408
1409 Collective
1410
1411 Input Parameters:
1412 + nx - number of vectors to be concatenated
1413 - X - array containing the vectors to be concatenated in the order of concatenation
1414
1415 Output Parameters:
1416 + Y - concatenated vector
1417 - x_is - array of index sets corresponding to the concatenated components of `Y` (pass `NULL` if not needed)
1418
1419 Level: advanced
1420
1421 Notes:
1422 Concatenation is similar to the functionality of a `VECNEST` object; they both represent combination of
1423 different vector spaces. However, concatenated vectors do not store any information about their
1424 sub-vectors and own their own data. Consequently, this function provides index sets to enable the
1425 manipulation of data in the concatenated vector that corresponds to the original components at creation.
1426
1427 This is a useful tool for outer loop algorithms, particularly constrained optimizers, where the solver
1428 has to operate on combined vector spaces and cannot utilize `VECNEST` objects due to incompatibility with
1429 bound projections.
1430
1431 .seealso: [](ch_vectors), `Vec`, `VECNEST`, `VECSCATTER`, `VecScatterCreate()`
1432 @*/
VecConcatenate(PetscInt nx,const Vec X[],Vec * Y,IS * x_is[])1433 PetscErrorCode VecConcatenate(PetscInt nx, const Vec X[], Vec *Y, IS *x_is[])
1434 {
1435 MPI_Comm comm;
1436 VecType vec_type;
1437 Vec Ytmp, Xtmp;
1438 IS *is_tmp;
1439 PetscInt i, shift = 0, Xnl, Xng, Xbegin;
1440
1441 PetscFunctionBegin;
1442 PetscValidLogicalCollectiveInt(*X, nx, 1);
1443 PetscValidHeaderSpecific(*X, VEC_CLASSID, 2);
1444 PetscValidType(*X, 2);
1445 PetscAssertPointer(Y, 3);
1446
1447 if ((*X)->ops->concatenate) {
1448 /* use the dedicated concatenation function if available */
1449 PetscCall((*(*X)->ops->concatenate)(nx, X, Y, x_is));
1450 } else {
1451 /* loop over vectors and start creating IS */
1452 comm = PetscObjectComm((PetscObject)*X);
1453 PetscCall(VecGetType(*X, &vec_type));
1454 PetscCall(PetscMalloc1(nx, &is_tmp));
1455 for (i = 0; i < nx; i++) {
1456 PetscCall(VecGetSize(X[i], &Xng));
1457 PetscCall(VecGetLocalSize(X[i], &Xnl));
1458 PetscCall(VecGetOwnershipRange(X[i], &Xbegin, NULL));
1459 PetscCall(ISCreateStride(comm, Xnl, shift + Xbegin, 1, &is_tmp[i]));
1460 shift += Xng;
1461 }
1462 /* create the concatenated vector */
1463 PetscCall(VecCreate(comm, &Ytmp));
1464 PetscCall(VecSetType(Ytmp, vec_type));
1465 PetscCall(VecSetSizes(Ytmp, PETSC_DECIDE, shift));
1466 PetscCall(VecSetUp(Ytmp));
1467 /* copy data from X array to Y and return */
1468 for (i = 0; i < nx; i++) {
1469 PetscCall(VecGetSubVector(Ytmp, is_tmp[i], &Xtmp));
1470 PetscCall(VecCopy(X[i], Xtmp));
1471 PetscCall(VecRestoreSubVector(Ytmp, is_tmp[i], &Xtmp));
1472 }
1473 *Y = Ytmp;
1474 if (x_is) {
1475 *x_is = is_tmp;
1476 } else {
1477 for (i = 0; i < nx; i++) PetscCall(ISDestroy(&is_tmp[i]));
1478 PetscCall(PetscFree(is_tmp));
1479 }
1480 }
1481 PetscFunctionReturn(PETSC_SUCCESS);
1482 }
1483
1484 /* A helper function for VecGetSubVector to check if we can implement it with no-copy (i.e. the subvector shares
1485 memory with the original vector), and the block size of the subvector.
1486
1487 Input Parameters:
1488 + X - the original vector
1489 - is - the index set of the subvector
1490
1491 Output Parameters:
1492 + contig - PETSC_TRUE if the index set refers to contiguous entries on this process, else PETSC_FALSE
1493 . start - start of contiguous block, as an offset from the start of the ownership range of the original vector
1494 - blocksize - the block size of the subvector
1495
1496 */
VecGetSubVectorContiguityAndBS_Private(Vec X,IS is,PetscBool * contig,PetscInt * start,PetscInt * blocksize)1497 PetscErrorCode VecGetSubVectorContiguityAndBS_Private(Vec X, IS is, PetscBool *contig, PetscInt *start, PetscInt *blocksize)
1498 {
1499 PetscInt gstart, gend, lstart;
1500 PetscBool red[2] = {PETSC_TRUE /*contiguous*/, PETSC_TRUE /*validVBS*/};
1501 PetscInt n, N, ibs, vbs, bs = 1;
1502
1503 PetscFunctionBegin;
1504 PetscCall(ISGetLocalSize(is, &n));
1505 PetscCall(ISGetSize(is, &N));
1506 PetscCall(ISGetBlockSize(is, &ibs));
1507 PetscCall(VecGetBlockSize(X, &vbs));
1508 PetscCall(VecGetOwnershipRange(X, &gstart, &gend));
1509 PetscCall(ISContiguousLocal(is, gstart, gend, &lstart, &red[0]));
1510 /* block size is given by IS if ibs > 1; otherwise, check the vector */
1511 if (ibs > 1) {
1512 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, red, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1513 bs = ibs;
1514 } else {
1515 if (n % vbs || vbs == 1) red[1] = PETSC_FALSE; /* this process invalidate the collectiveness of block size */
1516 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, red, 2, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is)));
1517 if (red[0] && red[1]) bs = vbs; /* all processes have a valid block size and the access will be contiguous */
1518 }
1519
1520 *contig = red[0];
1521 *start = lstart;
1522 *blocksize = bs;
1523 PetscFunctionReturn(PETSC_SUCCESS);
1524 }
1525
1526 /* A helper function for VecGetSubVector, to be used when we have to build a standalone subvector through VecScatter
1527
1528 Input Parameters:
1529 + X - the original vector
1530 . is - the index set of the subvector
1531 - bs - the block size of the subvector, gotten from VecGetSubVectorContiguityAndBS_Private()
1532
1533 Output Parameter:
1534 . Z - the subvector, which will compose the VecScatter context on output
1535 */
VecGetSubVectorThroughVecScatter_Private(Vec X,IS is,PetscInt bs,Vec * Z)1536 PetscErrorCode VecGetSubVectorThroughVecScatter_Private(Vec X, IS is, PetscInt bs, Vec *Z)
1537 {
1538 PetscInt n, N;
1539 VecScatter vscat;
1540 Vec Y;
1541
1542 PetscFunctionBegin;
1543 PetscCall(ISGetLocalSize(is, &n));
1544 PetscCall(ISGetSize(is, &N));
1545 PetscCall(VecCreate(PetscObjectComm((PetscObject)is), &Y));
1546 PetscCall(VecSetSizes(Y, n, N));
1547 PetscCall(VecSetBlockSize(Y, bs));
1548 PetscCall(VecSetType(Y, ((PetscObject)X)->type_name));
1549 PetscCall(VecScatterCreate(X, is, Y, NULL, &vscat));
1550 PetscCall(VecScatterBegin(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1551 PetscCall(VecScatterEnd(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD));
1552 PetscCall(PetscObjectCompose((PetscObject)Y, "VecGetSubVector_Scatter", (PetscObject)vscat));
1553 PetscCall(VecScatterDestroy(&vscat));
1554 *Z = Y;
1555 PetscFunctionReturn(PETSC_SUCCESS);
1556 }
1557
1558 /*@
1559 VecGetSubVector - Gets a vector representing part of another vector
1560
1561 Collective
1562
1563 Input Parameters:
1564 + X - vector from which to extract a subvector
1565 - is - index set representing portion of `X` to extract
1566
1567 Output Parameter:
1568 . Y - subvector corresponding to `is`
1569
1570 Level: advanced
1571
1572 Notes:
1573 The subvector `Y` should be returned with `VecRestoreSubVector()`.
1574 `X` and `is` must be defined on the same communicator
1575
1576 Changes to the subvector will be reflected in the `X` vector on the call to `VecRestoreSubVector()`.
1577
1578 This function may return a subvector without making a copy, therefore it is not safe to use the original vector while
1579 modifying the subvector. Other non-overlapping subvectors can still be obtained from `X` using this function.
1580
1581 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`.
1582
1583 .seealso: [](ch_vectors), `Vec`, `IS`, `VECNEST`, `MatCreateSubMatrix()`
1584 @*/
VecGetSubVector(Vec X,IS is,Vec * Y)1585 PetscErrorCode VecGetSubVector(Vec X, IS is, Vec *Y)
1586 {
1587 Vec Z;
1588
1589 PetscFunctionBegin;
1590 PetscValidHeaderSpecific(X, VEC_CLASSID, 1);
1591 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
1592 PetscCheckSameComm(X, 1, is, 2);
1593 PetscAssertPointer(Y, 3);
1594 if (X->ops->getsubvector) {
1595 PetscUseTypeMethod(X, getsubvector, is, &Z);
1596 } else { /* Default implementation currently does no caching */
1597 PetscBool contig;
1598 PetscInt n, N, start, bs;
1599
1600 PetscCall(ISGetLocalSize(is, &n));
1601 PetscCall(ISGetSize(is, &N));
1602 PetscCall(VecGetSubVectorContiguityAndBS_Private(X, is, &contig, &start, &bs));
1603 if (contig) { /* We can do a no-copy implementation */
1604 const PetscScalar *x;
1605 PetscInt state = 0;
1606 PetscBool isstd, iscuda, iship;
1607
1608 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &isstd, VECSEQ, VECMPI, VECSTANDARD, ""));
1609 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1610 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));
1611 if (iscuda) {
1612 #if defined(PETSC_HAVE_CUDA)
1613 const PetscScalar *x_d;
1614 PetscMPIInt size;
1615 PetscOffloadMask flg;
1616
1617 PetscCall(VecCUDAGetArrays_Private(X, &x, &x_d, &flg));
1618 PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1619 PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1620 if (x) x += start;
1621 if (x_d) x_d += start;
1622 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1623 if (size == 1) {
1624 PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1625 } else {
1626 PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1627 }
1628 Z->offloadmask = flg;
1629 #endif
1630 } else if (iship) {
1631 #if defined(PETSC_HAVE_HIP)
1632 const PetscScalar *x_d;
1633 PetscMPIInt size;
1634 PetscOffloadMask flg;
1635
1636 PetscCall(VecHIPGetArrays_Private(X, &x, &x_d, &flg));
1637 PetscCheck(flg != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for PETSC_OFFLOAD_UNALLOCATED");
1638 PetscCheck(!n || x || x_d, PETSC_COMM_SELF, PETSC_ERR_SUP, "Missing vector data");
1639 if (x) x += start;
1640 if (x_d) x_d += start;
1641 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1642 if (size == 1) {
1643 PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z));
1644 } else {
1645 PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z));
1646 }
1647 Z->offloadmask = flg;
1648 #endif
1649 } else if (isstd) {
1650 PetscMPIInt size;
1651
1652 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)X), &size));
1653 PetscCall(VecGetArrayRead(X, &x));
1654 if (x) x += start;
1655 if (size == 1) {
1656 PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)X), bs, n, x, &Z));
1657 } else {
1658 PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)X), bs, n, N, x, &Z));
1659 }
1660 PetscCall(VecRestoreArrayRead(X, &x));
1661 } else { /* default implementation: use place array */
1662 PetscCall(VecGetArrayRead(X, &x));
1663 PetscCall(VecCreate(PetscObjectComm((PetscObject)X), &Z));
1664 PetscCall(VecSetType(Z, ((PetscObject)X)->type_name));
1665 PetscCall(VecSetSizes(Z, n, N));
1666 PetscCall(VecSetBlockSize(Z, bs));
1667 PetscCall(VecPlaceArray(Z, PetscSafePointerPlusOffset(x, start)));
1668 PetscCall(VecRestoreArrayRead(X, &x));
1669 }
1670
1671 /* this is relevant only in debug mode */
1672 PetscCall(VecLockGet(X, &state));
1673 if (state) PetscCall(VecLockReadPush(Z));
1674 Z->ops->placearray = NULL;
1675 Z->ops->replacearray = NULL;
1676 } else { /* Have to create a scatter and do a copy */
1677 PetscCall(VecGetSubVectorThroughVecScatter_Private(X, is, bs, &Z));
1678 }
1679 }
1680 /* Record the state when the subvector was gotten so we know whether its values need to be put back */
1681 if (VecGetSubVectorSavedStateId < 0) PetscCall(PetscObjectComposedDataRegister(&VecGetSubVectorSavedStateId));
1682 PetscCall(PetscObjectComposedDataSetInt((PetscObject)Z, VecGetSubVectorSavedStateId, 1));
1683 *Y = Z;
1684 PetscFunctionReturn(PETSC_SUCCESS);
1685 }
1686
1687 /*@
1688 VecRestoreSubVector - Restores a subvector extracted using `VecGetSubVector()`
1689
1690 Collective
1691
1692 Input Parameters:
1693 + X - vector from which subvector was obtained
1694 . is - index set representing the subset of `X`
1695 - Y - subvector being restored
1696
1697 Level: advanced
1698
1699 .seealso: [](ch_vectors), `Vec`, `IS`, `VecGetSubVector()`
1700 @*/
VecRestoreSubVector(Vec X,IS is,Vec * Y)1701 PetscErrorCode VecRestoreSubVector(Vec X, IS is, Vec *Y)
1702 {
1703 PETSC_UNUSED PetscObjectState dummystate = 0;
1704 PetscBool unchanged;
1705
1706 PetscFunctionBegin;
1707 PetscValidHeaderSpecific(X, VEC_CLASSID, 1);
1708 PetscValidHeaderSpecific(is, IS_CLASSID, 2);
1709 PetscCheckSameComm(X, 1, is, 2);
1710 PetscAssertPointer(Y, 3);
1711 PetscValidHeaderSpecific(*Y, VEC_CLASSID, 3);
1712
1713 if (X->ops->restoresubvector) PetscUseTypeMethod(X, restoresubvector, is, Y);
1714 else {
1715 PetscCall(PetscObjectComposedDataGetInt((PetscObject)*Y, VecGetSubVectorSavedStateId, dummystate, unchanged));
1716 if (!unchanged) { /* If Y's state has not changed since VecGetSubVector(), we only need to destroy Y */
1717 VecScatter scatter;
1718 PetscInt state;
1719
1720 PetscCall(VecLockGet(X, &state));
1721 PetscCheck(state == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vec X is locked for read-only or read/write access");
1722
1723 PetscCall(PetscObjectQuery((PetscObject)*Y, "VecGetSubVector_Scatter", (PetscObject *)&scatter));
1724 if (scatter) {
1725 PetscCall(VecScatterBegin(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1726 PetscCall(VecScatterEnd(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE));
1727 } else {
1728 PetscBool iscuda, iship;
1729 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, ""));
1730 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, ""));
1731
1732 if (iscuda) {
1733 #if defined(PETSC_HAVE_CUDA)
1734 PetscOffloadMask ymask = (*Y)->offloadmask;
1735
1736 /* The offloadmask of X dictates where to move memory
1737 If X GPU data is valid, then move Y data on GPU if needed
1738 Otherwise, move back to the CPU */
1739 switch (X->offloadmask) {
1740 case PETSC_OFFLOAD_BOTH:
1741 if (ymask == PETSC_OFFLOAD_CPU) {
1742 PetscCall(VecCUDAResetArray(*Y));
1743 } else if (ymask == PETSC_OFFLOAD_GPU) {
1744 X->offloadmask = PETSC_OFFLOAD_GPU;
1745 }
1746 break;
1747 case PETSC_OFFLOAD_GPU:
1748 if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecCUDAResetArray(*Y));
1749 break;
1750 case PETSC_OFFLOAD_CPU:
1751 if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1752 break;
1753 case PETSC_OFFLOAD_UNALLOCATED:
1754 case PETSC_OFFLOAD_KOKKOS:
1755 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1756 }
1757 #endif
1758 } else if (iship) {
1759 #if defined(PETSC_HAVE_HIP)
1760 PetscOffloadMask ymask = (*Y)->offloadmask;
1761
1762 /* The offloadmask of X dictates where to move memory
1763 If X GPU data is valid, then move Y data on GPU if needed
1764 Otherwise, move back to the CPU */
1765 switch (X->offloadmask) {
1766 case PETSC_OFFLOAD_BOTH:
1767 if (ymask == PETSC_OFFLOAD_CPU) {
1768 PetscCall(VecHIPResetArray(*Y));
1769 } else if (ymask == PETSC_OFFLOAD_GPU) {
1770 X->offloadmask = PETSC_OFFLOAD_GPU;
1771 }
1772 break;
1773 case PETSC_OFFLOAD_GPU:
1774 if (ymask == PETSC_OFFLOAD_CPU) PetscCall(VecHIPResetArray(*Y));
1775 break;
1776 case PETSC_OFFLOAD_CPU:
1777 if (ymask == PETSC_OFFLOAD_GPU) PetscCall(VecResetArray(*Y));
1778 break;
1779 case PETSC_OFFLOAD_UNALLOCATED:
1780 case PETSC_OFFLOAD_KOKKOS:
1781 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1782 }
1783 #endif
1784 } else {
1785 /* If OpenCL vecs updated the device memory, this triggers a copy on the CPU */
1786 PetscCall(VecResetArray(*Y));
1787 }
1788 PetscCall(PetscObjectStateIncrease((PetscObject)X));
1789 }
1790 }
1791 }
1792 PetscCall(VecDestroy(Y));
1793 PetscFunctionReturn(PETSC_SUCCESS);
1794 }
1795
1796 /*@
1797 VecCreateLocalVector - Creates a vector object suitable for use with `VecGetLocalVector()` and friends. You must call `VecDestroy()` when the
1798 vector is no longer needed.
1799
1800 Not Collective.
1801
1802 Input Parameter:
1803 . v - The vector for which the local vector is desired.
1804
1805 Output Parameter:
1806 . w - Upon exit this contains the local vector.
1807
1808 Level: beginner
1809
1810 .seealso: [](ch_vectors), `Vec`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecRestoreLocalVector()`
1811 @*/
VecCreateLocalVector(Vec v,Vec * w)1812 PetscErrorCode VecCreateLocalVector(Vec v, Vec *w)
1813 {
1814 VecType roottype;
1815 PetscInt n;
1816
1817 PetscFunctionBegin;
1818 PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
1819 PetscAssertPointer(w, 2);
1820 if (v->ops->createlocalvector) {
1821 PetscUseTypeMethod(v, createlocalvector, w);
1822 PetscFunctionReturn(PETSC_SUCCESS);
1823 }
1824 PetscCall(VecGetRootType_Private(v, &roottype));
1825 PetscCall(VecCreate(PETSC_COMM_SELF, w));
1826 PetscCall(VecGetLocalSize(v, &n));
1827 PetscCall(VecSetSizes(*w, n, n));
1828 PetscCall(VecGetBlockSize(v, &n));
1829 PetscCall(VecSetBlockSize(*w, n));
1830 PetscCall(VecSetType(*w, roottype));
1831 PetscFunctionReturn(PETSC_SUCCESS);
1832 }
1833
1834 /*@
1835 VecGetLocalVectorRead - Maps the local portion of a vector into a
1836 vector.
1837
1838 Not Collective.
1839
1840 Input Parameter:
1841 . v - The vector for which the local vector is desired.
1842
1843 Output Parameter:
1844 . w - Upon exit this contains the local vector.
1845
1846 Level: beginner
1847
1848 Notes:
1849 You must call `VecRestoreLocalVectorRead()` when the local
1850 vector is no longer needed.
1851
1852 This function is similar to `VecGetArrayRead()` which maps the local
1853 portion into a raw pointer. `VecGetLocalVectorRead()` is usually
1854 almost as efficient as `VecGetArrayRead()` but in certain circumstances
1855 `VecGetLocalVectorRead()` can be much more efficient than
1856 `VecGetArrayRead()`. This is because the construction of a contiguous
1857 array representing the vector data required by `VecGetArrayRead()` can
1858 be an expensive operation for certain vector types. For example, for
1859 GPU vectors `VecGetArrayRead()` requires that the data between device
1860 and host is synchronized.
1861
1862 Unlike `VecGetLocalVector()`, this routine is not collective and
1863 preserves cached information.
1864
1865 .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1866 @*/
VecGetLocalVectorRead(Vec v,Vec w)1867 PetscErrorCode VecGetLocalVectorRead(Vec v, Vec w)
1868 {
1869 PetscFunctionBegin;
1870 PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
1871 PetscValidHeaderSpecific(w, VEC_CLASSID, 2);
1872 VecCheckSameLocalSize(v, 1, w, 2);
1873 if (v->ops->getlocalvectorread) {
1874 PetscUseTypeMethod(v, getlocalvectorread, w);
1875 } else {
1876 PetscScalar *a;
1877
1878 PetscCall(VecGetArrayRead(v, (const PetscScalar **)&a));
1879 PetscCall(VecPlaceArray(w, a));
1880 }
1881 PetscCall(PetscObjectStateIncrease((PetscObject)w));
1882 PetscCall(VecLockReadPush(v));
1883 PetscCall(VecLockReadPush(w));
1884 PetscFunctionReturn(PETSC_SUCCESS);
1885 }
1886
1887 /*@
1888 VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1889 previously mapped into a vector using `VecGetLocalVectorRead()`.
1890
1891 Not Collective.
1892
1893 Input Parameters:
1894 + v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVectorRead()`.
1895 - w - The vector into which the local portion of `v` was mapped.
1896
1897 Level: beginner
1898
1899 .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1900 @*/
VecRestoreLocalVectorRead(Vec v,Vec w)1901 PetscErrorCode VecRestoreLocalVectorRead(Vec v, Vec w)
1902 {
1903 PetscFunctionBegin;
1904 PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
1905 PetscValidHeaderSpecific(w, VEC_CLASSID, 2);
1906 if (v->ops->restorelocalvectorread) {
1907 PetscUseTypeMethod(v, restorelocalvectorread, w);
1908 } else {
1909 const PetscScalar *a;
1910
1911 PetscCall(VecGetArrayRead(w, &a));
1912 PetscCall(VecRestoreArrayRead(v, &a));
1913 PetscCall(VecResetArray(w));
1914 }
1915 PetscCall(VecLockReadPop(v));
1916 PetscCall(VecLockReadPop(w));
1917 PetscCall(PetscObjectStateIncrease((PetscObject)w));
1918 PetscFunctionReturn(PETSC_SUCCESS);
1919 }
1920
1921 /*@
1922 VecGetLocalVector - Maps the local portion of a vector into a
1923 vector.
1924
1925 Collective
1926
1927 Input Parameter:
1928 . v - The vector for which the local vector is desired.
1929
1930 Output Parameter:
1931 . w - Upon exit this contains the local vector.
1932
1933 Level: beginner
1934
1935 Notes:
1936 You must call `VecRestoreLocalVector()` when the local
1937 vector is no longer needed.
1938
1939 This function is similar to `VecGetArray()` which maps the local
1940 portion into a raw pointer. `VecGetLocalVector()` is usually about as
1941 efficient as `VecGetArray()` but in certain circumstances
1942 `VecGetLocalVector()` can be much more efficient than `VecGetArray()`.
1943 This is because the construction of a contiguous array representing
1944 the vector data required by `VecGetArray()` can be an expensive
1945 operation for certain vector types. For example, for GPU vectors
1946 `VecGetArray()` requires that the data between device and host is
1947 synchronized.
1948
1949 .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecRestoreLocalVector()`, `VecGetLocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1950 @*/
VecGetLocalVector(Vec v,Vec w)1951 PetscErrorCode VecGetLocalVector(Vec v, Vec w)
1952 {
1953 PetscFunctionBegin;
1954 PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
1955 PetscValidHeaderSpecific(w, VEC_CLASSID, 2);
1956 VecCheckSameLocalSize(v, 1, w, 2);
1957 if (v->ops->getlocalvector) {
1958 PetscUseTypeMethod(v, getlocalvector, w);
1959 } else {
1960 PetscScalar *a;
1961
1962 PetscCall(VecGetArray(v, &a));
1963 PetscCall(VecPlaceArray(w, a));
1964 }
1965 PetscCall(PetscObjectStateIncrease((PetscObject)w));
1966 PetscFunctionReturn(PETSC_SUCCESS);
1967 }
1968
1969 /*@
1970 VecRestoreLocalVector - Unmaps the local portion of a vector
1971 previously mapped into a vector using `VecGetLocalVector()`.
1972
1973 Logically Collective.
1974
1975 Input Parameters:
1976 + v - The local portion of this vector was previously mapped into `w` using `VecGetLocalVector()`.
1977 - w - The vector into which the local portion of `v` was mapped.
1978
1979 Level: beginner
1980
1981 .seealso: [](ch_vectors), `Vec`, `VecCreateLocalVector()`, `VecGetLocalVector()`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `LocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1982 @*/
VecRestoreLocalVector(Vec v,Vec w)1983 PetscErrorCode VecRestoreLocalVector(Vec v, Vec w)
1984 {
1985 PetscFunctionBegin;
1986 PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
1987 PetscValidHeaderSpecific(w, VEC_CLASSID, 2);
1988 if (v->ops->restorelocalvector) {
1989 PetscUseTypeMethod(v, restorelocalvector, w);
1990 } else {
1991 PetscScalar *a;
1992 PetscCall(VecGetArray(w, &a));
1993 PetscCall(VecRestoreArray(v, &a));
1994 PetscCall(VecResetArray(w));
1995 }
1996 PetscCall(PetscObjectStateIncrease((PetscObject)w));
1997 PetscCall(PetscObjectStateIncrease((PetscObject)v));
1998 PetscFunctionReturn(PETSC_SUCCESS);
1999 }
2000
2001 /*@C
2002 VecGetArray - Returns a pointer to a contiguous array that contains this
2003 MPI processes's portion of the vector data
2004
2005 Logically Collective
2006
2007 Input Parameter:
2008 . x - the vector
2009
2010 Output Parameter:
2011 . a - location to put pointer to the array
2012
2013 Level: beginner
2014
2015 Notes:
2016 For the standard PETSc vectors, `VecGetArray()` returns a pointer to the local data array and
2017 does not use any copies. If the underlying vector data is not stored in a contiguous array
2018 this routine will copy the data to a contiguous array and return a pointer to that. You MUST
2019 call `VecRestoreArray()` when you no longer need access to the array.
2020
2021 For vectors that may also have the array data in GPU memory, for example, `VECCUDA`, this call ensures the CPU array has the
2022 most recent array values by copying the data from the GPU memory if needed.
2023
2024 Fortran Note:
2025 .vb
2026 PetscScalar, pointer :: a(:)
2027 .ve
2028
2029 .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecPlaceArray()`, `VecGetArray2d()`,
2030 `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`, `VecGetArrayAndMemType()`
2031 @*/
VecGetArray(Vec x,PetscScalar * a[])2032 PetscErrorCode VecGetArray(Vec x, PetscScalar *a[])
2033 {
2034 PetscFunctionBegin;
2035 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2036 PetscCall(VecSetErrorIfLocked(x, 1));
2037 if (x->ops->getarray) { /* The if-else order matters! VECNEST, VECCUDA etc should have ops->getarray while VECCUDA etc are petscnative */
2038 PetscUseTypeMethod(x, getarray, a);
2039 } else if (x->petscnative) { /* VECSTANDARD */
2040 *a = *((PetscScalar **)x->data);
2041 } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array for vector type \"%s\"", ((PetscObject)x)->type_name);
2042 PetscFunctionReturn(PETSC_SUCCESS);
2043 }
2044
2045 /*@C
2046 VecRestoreArray - Restores a vector after `VecGetArray()` has been called and the array is no longer needed
2047
2048 Logically Collective
2049
2050 Input Parameters:
2051 + x - the vector
2052 - a - location of pointer to array obtained from `VecGetArray()`
2053
2054 Level: beginner
2055
2056 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2057 `VecGetArrayPair()`, `VecRestoreArrayPair()`
2058 @*/
VecRestoreArray(Vec x,PetscScalar * a[])2059 PetscErrorCode VecRestoreArray(Vec x, PetscScalar *a[])
2060 {
2061 PetscFunctionBegin;
2062 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2063 if (a) PetscAssertPointer(a, 2);
2064 if (x->ops->restorearray) {
2065 PetscUseTypeMethod(x, restorearray, a);
2066 } else PetscCheck(x->petscnative, PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot restore array for vector type \"%s\"", ((PetscObject)x)->type_name);
2067 if (a) *a = NULL;
2068 PetscCall(PetscObjectStateIncrease((PetscObject)x));
2069 PetscFunctionReturn(PETSC_SUCCESS);
2070 }
2071 /*@C
2072 VecGetArrayRead - Get read-only pointer to contiguous array containing this processor's portion of the vector data.
2073
2074 Not Collective
2075
2076 Input Parameter:
2077 . x - the vector
2078
2079 Output Parameter:
2080 . a - the array
2081
2082 Level: beginner
2083
2084 Notes:
2085 The array must be returned using a matching call to `VecRestoreArrayRead()`.
2086
2087 Unlike `VecGetArray()`, preserves cached information like vector norms.
2088
2089 Standard PETSc vectors use contiguous storage so that this routine does not perform a copy. Other vector
2090 implementations may require a copy, but such implementations should cache the contiguous representation so that
2091 only one copy is performed when this routine is called multiple times in sequence.
2092
2093 For vectors that may also have the array data in GPU memory, for example, `VECCUDA`, this call ensures the CPU array has the
2094 most recent array values by copying the data from the GPU memory if needed.
2095
2096 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2097 `VecGetArrayAndMemType()`
2098 @*/
VecGetArrayRead(Vec x,const PetscScalar * a[])2099 PetscErrorCode VecGetArrayRead(Vec x, const PetscScalar *a[])
2100 {
2101 PetscFunctionBegin;
2102 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2103 PetscAssertPointer(a, 2);
2104 if (x->ops->getarrayread) {
2105 PetscUseTypeMethod(x, getarrayread, a);
2106 } else if (x->ops->getarray) {
2107 PetscObjectState state;
2108
2109 /* VECNEST, VECCUDA, VECKOKKOS etc */
2110 // x->ops->getarray may bump the object state, but since we know this is a read-only get
2111 // we can just undo that
2112 PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2113 PetscUseTypeMethod(x, getarray, (PetscScalar **)a);
2114 PetscCall(PetscObjectStateSet((PetscObject)x, state));
2115 } else if (x->petscnative) {
2116 /* VECSTANDARD */
2117 *a = *((PetscScalar **)x->data);
2118 } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array read for vector type \"%s\"", ((PetscObject)x)->type_name);
2119 PetscFunctionReturn(PETSC_SUCCESS);
2120 }
2121
2122 /*@C
2123 VecRestoreArrayRead - Restore array obtained with `VecGetArrayRead()`
2124
2125 Not Collective
2126
2127 Input Parameters:
2128 + x - the vector
2129 - a - the array
2130
2131 Level: beginner
2132
2133 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2134 @*/
VecRestoreArrayRead(Vec x,const PetscScalar * a[])2135 PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar *a[])
2136 {
2137 PetscFunctionBegin;
2138 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2139 if (a) PetscAssertPointer(a, 2);
2140 if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
2141 /* nothing */
2142 } else if (x->ops->restorearrayread) { /* VECNEST */
2143 PetscUseTypeMethod(x, restorearrayread, a);
2144 } else { /* No one? */
2145 PetscObjectState state;
2146
2147 // x->ops->restorearray may bump the object state, but since we know this is a read-restore
2148 // we can just undo that
2149 PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2150 PetscUseTypeMethod(x, restorearray, (PetscScalar **)a);
2151 PetscCall(PetscObjectStateSet((PetscObject)x, state));
2152 }
2153 if (a) *a = NULL;
2154 PetscFunctionReturn(PETSC_SUCCESS);
2155 }
2156
2157 /*@C
2158 VecGetArrayWrite - Returns a pointer to a contiguous array that WILL contain this
2159 MPI processes's portion of the vector data.
2160
2161 Logically Collective
2162
2163 Input Parameter:
2164 . x - the vector
2165
2166 Output Parameter:
2167 . a - location to put pointer to the array
2168
2169 Level: intermediate
2170
2171 Note:
2172 The values in this array are NOT valid, the caller of this routine is responsible for putting
2173 values into the array; any values it does not set will be invalid.
2174
2175 The array must be returned using a matching call to `VecRestoreArrayWrite()`.
2176
2177 For vectors associated with GPUs, the host and device vectors are not synchronized before
2178 giving access. If you need correct values in the array use `VecGetArray()`
2179
2180 .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecPlaceArray()`, `VecGetArray2d()`,
2181 `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArray()`, `VecRestoreArrayWrite()`, `VecGetArrayAndMemType()`
2182 @*/
VecGetArrayWrite(Vec x,PetscScalar * a[])2183 PetscErrorCode VecGetArrayWrite(Vec x, PetscScalar *a[])
2184 {
2185 PetscFunctionBegin;
2186 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2187 PetscAssertPointer(a, 2);
2188 PetscCall(VecSetErrorIfLocked(x, 1));
2189 if (x->ops->getarraywrite) {
2190 PetscUseTypeMethod(x, getarraywrite, a);
2191 } else {
2192 PetscCall(VecGetArray(x, a));
2193 }
2194 PetscFunctionReturn(PETSC_SUCCESS);
2195 }
2196
2197 /*@C
2198 VecRestoreArrayWrite - Restores a vector after `VecGetArrayWrite()` has been called.
2199
2200 Logically Collective
2201
2202 Input Parameters:
2203 + x - the vector
2204 - a - location of pointer to array obtained from `VecGetArray()`
2205
2206 Level: beginner
2207
2208 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
2209 `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`
2210 @*/
VecRestoreArrayWrite(Vec x,PetscScalar * a[])2211 PetscErrorCode VecRestoreArrayWrite(Vec x, PetscScalar *a[])
2212 {
2213 PetscFunctionBegin;
2214 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2215 if (a) PetscAssertPointer(a, 2);
2216 if (x->ops->restorearraywrite) {
2217 PetscUseTypeMethod(x, restorearraywrite, a);
2218 } else if (x->ops->restorearray) {
2219 PetscUseTypeMethod(x, restorearray, a);
2220 }
2221 if (a) *a = NULL;
2222 PetscCall(PetscObjectStateIncrease((PetscObject)x));
2223 PetscFunctionReturn(PETSC_SUCCESS);
2224 }
2225
2226 /*@C
2227 VecGetArrays - Returns a pointer to the arrays in a set of vectors
2228 that were created by a call to `VecDuplicateVecs()`.
2229
2230 Logically Collective; No Fortran Support
2231
2232 Input Parameters:
2233 + x - the vectors
2234 - n - the number of vectors
2235
2236 Output Parameter:
2237 . a - location to put pointer to the array
2238
2239 Level: intermediate
2240
2241 Note:
2242 You MUST call `VecRestoreArrays()` when you no longer need access to the arrays.
2243
2244 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArrays()`
2245 @*/
VecGetArrays(const Vec x[],PetscInt n,PetscScalar ** a[])2246 PetscErrorCode VecGetArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2247 {
2248 PetscInt i;
2249 PetscScalar **q;
2250
2251 PetscFunctionBegin;
2252 PetscAssertPointer(x, 1);
2253 PetscValidHeaderSpecific(*x, VEC_CLASSID, 1);
2254 PetscAssertPointer(a, 3);
2255 PetscCheck(n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must get at least one array n = %" PetscInt_FMT, n);
2256 PetscCall(PetscMalloc1(n, &q));
2257 for (i = 0; i < n; ++i) PetscCall(VecGetArray(x[i], &q[i]));
2258 *a = q;
2259 PetscFunctionReturn(PETSC_SUCCESS);
2260 }
2261
2262 /*@C
2263 VecRestoreArrays - Restores a group of vectors after `VecGetArrays()`
2264 has been called.
2265
2266 Logically Collective; No Fortran Support
2267
2268 Input Parameters:
2269 + x - the vector
2270 . n - the number of vectors
2271 - a - location of pointer to arrays obtained from `VecGetArrays()`
2272
2273 Notes:
2274 For regular PETSc vectors this routine does not involve any copies. For
2275 any special vectors that do not store local vector data in a contiguous
2276 array, this routine will copy the data back into the underlying
2277 vector data structure from the arrays obtained with `VecGetArrays()`.
2278
2279 Level: intermediate
2280
2281 .seealso: [](ch_vectors), `Vec`, `VecGetArrays()`, `VecRestoreArray()`
2282 @*/
VecRestoreArrays(const Vec x[],PetscInt n,PetscScalar ** a[])2283 PetscErrorCode VecRestoreArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2284 {
2285 PetscInt i;
2286 PetscScalar **q = *a;
2287
2288 PetscFunctionBegin;
2289 PetscAssertPointer(x, 1);
2290 PetscValidHeaderSpecific(*x, VEC_CLASSID, 1);
2291 PetscAssertPointer(a, 3);
2292
2293 for (i = 0; i < n; ++i) PetscCall(VecRestoreArray(x[i], &q[i]));
2294 PetscCall(PetscFree(q));
2295 PetscFunctionReturn(PETSC_SUCCESS);
2296 }
2297
2298 /*@C
2299 VecGetArrayAndMemType - Like `VecGetArray()`, but if this is a standard device vector (e.g.,
2300 `VECCUDA`), the returned pointer will be a device pointer to the device memory that contains
2301 this MPI processes's portion of the vector data.
2302
2303 Logically Collective; No Fortran Support
2304
2305 Input Parameter:
2306 . x - the vector
2307
2308 Output Parameters:
2309 + a - location to put pointer to the array
2310 - mtype - memory type of the array
2311
2312 Level: beginner
2313
2314 Note:
2315 Device data is guaranteed to have the latest value. Otherwise, when this is a host vector
2316 (e.g., `VECMPI`), this routine functions the same as `VecGetArray()` and returns a host
2317 pointer.
2318
2319 For `VECKOKKOS`, if Kokkos is configured without device (e.g., use serial or openmp), per
2320 this function, the vector works like `VECSEQ`/`VECMPI`; otherwise, it works like `VECCUDA` or
2321 `VECHIP` etc.
2322
2323 Use `VecRestoreArrayAndMemType()` when the array access is no longer needed.
2324
2325 .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`,
2326 `VecPlaceArray()`, `VecGetArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2327 @*/
VecGetArrayAndMemType(Vec x,PetscScalar * a[],PetscMemType * mtype)2328 PetscErrorCode VecGetArrayAndMemType(Vec x, PetscScalar *a[], PetscMemType *mtype)
2329 {
2330 PetscFunctionBegin;
2331 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2332 PetscValidType(x, 1);
2333 if (a) PetscAssertPointer(a, 2);
2334 if (mtype) PetscAssertPointer(mtype, 3);
2335 PetscCall(VecSetErrorIfLocked(x, 1));
2336 if (x->ops->getarrayandmemtype) {
2337 /* VECCUDA, VECKOKKOS etc */
2338 PetscUseTypeMethod(x, getarrayandmemtype, a, mtype);
2339 } else {
2340 /* VECSTANDARD, VECNEST, VECVIENNACL */
2341 PetscCall(VecGetArray(x, a));
2342 if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2343 }
2344 PetscFunctionReturn(PETSC_SUCCESS);
2345 }
2346
2347 /*@C
2348 VecRestoreArrayAndMemType - Restores a vector after `VecGetArrayAndMemType()` has been called.
2349
2350 Logically Collective; No Fortran Support
2351
2352 Input Parameters:
2353 + x - the vector
2354 - a - location of pointer to array obtained from `VecGetArrayAndMemType()`
2355
2356 Level: beginner
2357
2358 .seealso: [](ch_vectors), `Vec`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`,
2359 `VecPlaceArray()`, `VecRestoreArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2360 @*/
VecRestoreArrayAndMemType(Vec x,PetscScalar * a[])2361 PetscErrorCode VecRestoreArrayAndMemType(Vec x, PetscScalar *a[])
2362 {
2363 PetscFunctionBegin;
2364 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2365 PetscValidType(x, 1);
2366 if (a) PetscAssertPointer(a, 2);
2367 if (x->ops->restorearrayandmemtype) {
2368 /* VECCUDA, VECKOKKOS etc */
2369 PetscUseTypeMethod(x, restorearrayandmemtype, a);
2370 } else {
2371 /* VECNEST, VECVIENNACL */
2372 PetscCall(VecRestoreArray(x, a));
2373 } /* VECSTANDARD does nothing */
2374 if (a) *a = NULL;
2375 PetscCall(PetscObjectStateIncrease((PetscObject)x));
2376 PetscFunctionReturn(PETSC_SUCCESS);
2377 }
2378
2379 /*@C
2380 VecGetArrayReadAndMemType - Like `VecGetArrayRead()`, but if the input vector is a device vector, it will return a read-only device pointer.
2381 The returned pointer is guaranteed to point to up-to-date data. For host vectors, it functions as `VecGetArrayRead()`.
2382
2383 Not Collective; No Fortran Support
2384
2385 Input Parameter:
2386 . x - the vector
2387
2388 Output Parameters:
2389 + a - the array
2390 - mtype - memory type of the array
2391
2392 Level: beginner
2393
2394 Notes:
2395 The array must be returned using a matching call to `VecRestoreArrayReadAndMemType()`.
2396
2397 .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2398 @*/
VecGetArrayReadAndMemType(Vec x,const PetscScalar * a[],PetscMemType * mtype)2399 PetscErrorCode VecGetArrayReadAndMemType(Vec x, const PetscScalar *a[], PetscMemType *mtype)
2400 {
2401 PetscFunctionBegin;
2402 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2403 PetscValidType(x, 1);
2404 PetscAssertPointer(a, 2);
2405 if (mtype) PetscAssertPointer(mtype, 3);
2406 if (x->ops->getarrayreadandmemtype) {
2407 /* VECCUDA/VECHIP though they are also petscnative */
2408 PetscUseTypeMethod(x, getarrayreadandmemtype, a, mtype);
2409 } else if (x->ops->getarrayandmemtype) {
2410 /* VECKOKKOS */
2411 PetscObjectState state;
2412
2413 // see VecGetArrayRead() for why
2414 PetscCall(PetscObjectStateGet((PetscObject)x, &state));
2415 PetscUseTypeMethod(x, getarrayandmemtype, (PetscScalar **)a, mtype);
2416 PetscCall(PetscObjectStateSet((PetscObject)x, state));
2417 } else {
2418 PetscCall(VecGetArrayRead(x, a));
2419 if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2420 }
2421 PetscFunctionReturn(PETSC_SUCCESS);
2422 }
2423
2424 /*@C
2425 VecRestoreArrayReadAndMemType - Restore array obtained with `VecGetArrayReadAndMemType()`
2426
2427 Not Collective; No Fortran Support
2428
2429 Input Parameters:
2430 + x - the vector
2431 - a - the array
2432
2433 Level: beginner
2434
2435 .seealso: [](ch_vectors), `Vec`, `VecGetArrayReadAndMemType()`, `VecRestoreArrayAndMemType()`, `VecRestoreArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2436 @*/
VecRestoreArrayReadAndMemType(Vec x,const PetscScalar * a[])2437 PetscErrorCode VecRestoreArrayReadAndMemType(Vec x, const PetscScalar *a[])
2438 {
2439 PetscFunctionBegin;
2440 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2441 PetscValidType(x, 1);
2442 if (a) PetscAssertPointer(a, 2);
2443 if (x->ops->restorearrayreadandmemtype) {
2444 /* VECCUDA/VECHIP */
2445 PetscUseTypeMethod(x, restorearrayreadandmemtype, a);
2446 } else if (!x->petscnative) {
2447 /* VECNEST */
2448 PetscCall(VecRestoreArrayRead(x, a));
2449 }
2450 if (a) *a = NULL;
2451 PetscFunctionReturn(PETSC_SUCCESS);
2452 }
2453
2454 /*@C
2455 VecGetArrayWriteAndMemType - Like `VecGetArrayWrite()`, but if this is a device vector it will always return
2456 a device pointer to the device memory that contains this processor's portion of the vector data.
2457
2458 Logically Collective; No Fortran Support
2459
2460 Input Parameter:
2461 . x - the vector
2462
2463 Output Parameters:
2464 + a - the array
2465 - mtype - memory type of the array
2466
2467 Level: beginner
2468
2469 Note:
2470 The array must be returned using a matching call to `VecRestoreArrayWriteAndMemType()`, where it will label the device memory as most recent.
2471
2472 .seealso: [](ch_vectors), `Vec`, `VecRestoreArrayWriteAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2473 @*/
VecGetArrayWriteAndMemType(Vec x,PetscScalar * a[],PetscMemType * mtype)2474 PetscErrorCode VecGetArrayWriteAndMemType(Vec x, PetscScalar *a[], PetscMemType *mtype)
2475 {
2476 PetscFunctionBegin;
2477 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2478 PetscValidType(x, 1);
2479 PetscCall(VecSetErrorIfLocked(x, 1));
2480 PetscAssertPointer(a, 2);
2481 if (mtype) PetscAssertPointer(mtype, 3);
2482 if (x->ops->getarraywriteandmemtype) {
2483 /* VECCUDA, VECHIP, VECKOKKOS etc, though they are also petscnative */
2484 PetscUseTypeMethod(x, getarraywriteandmemtype, a, mtype);
2485 } else if (x->ops->getarrayandmemtype) {
2486 PetscCall(VecGetArrayAndMemType(x, a, mtype));
2487 } else {
2488 /* VECNEST, VECVIENNACL */
2489 PetscCall(VecGetArrayWrite(x, a));
2490 if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2491 }
2492 PetscFunctionReturn(PETSC_SUCCESS);
2493 }
2494
2495 /*@C
2496 VecRestoreArrayWriteAndMemType - Restore array obtained with `VecGetArrayWriteAndMemType()`
2497
2498 Logically Collective; No Fortran Support
2499
2500 Input Parameters:
2501 + x - the vector
2502 - a - the array
2503
2504 Level: beginner
2505
2506 .seealso: [](ch_vectors), `Vec`, `VecGetArrayWriteAndMemType()`, `VecRestoreArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2507 @*/
VecRestoreArrayWriteAndMemType(Vec x,PetscScalar * a[])2508 PetscErrorCode VecRestoreArrayWriteAndMemType(Vec x, PetscScalar *a[])
2509 {
2510 PetscFunctionBegin;
2511 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2512 PetscValidType(x, 1);
2513 PetscCall(VecSetErrorIfLocked(x, 1));
2514 if (a) PetscAssertPointer(a, 2);
2515 if (x->ops->restorearraywriteandmemtype) {
2516 /* VECCUDA/VECHIP */
2517 PetscMemType PETSC_UNUSED mtype; // since this function doesn't accept a memtype?
2518 PetscUseTypeMethod(x, restorearraywriteandmemtype, a, &mtype);
2519 } else if (x->ops->restorearrayandmemtype) {
2520 PetscCall(VecRestoreArrayAndMemType(x, a));
2521 } else {
2522 PetscCall(VecRestoreArray(x, a));
2523 }
2524 if (a) *a = NULL;
2525 PetscFunctionReturn(PETSC_SUCCESS);
2526 }
2527
2528 /*@
2529 VecPlaceArray - Allows one to replace the array in a vector with an
2530 array provided by the user. This is useful to avoid copying an array
2531 into a vector.
2532
2533 Logically Collective
2534
2535 Input Parameters:
2536 + vec - the vector
2537 - array - the array
2538
2539 Level: developer
2540
2541 Notes:
2542 Adding `const` to `array` was an oversight, as subsequent operations on `vec` would
2543 likely modify the data in `array`. However, we have kept it to avoid breaking APIs.
2544
2545 Use `VecReplaceArray()` instead to permanently replace the array
2546
2547 You can return to the original array with a call to `VecResetArray()`. `vec` does not take
2548 ownership of `array` in any way.
2549
2550 The user must free `array` themselves but be careful not to
2551 do so before the vector has either been destroyed, had its original array restored with
2552 `VecResetArray()` or permanently replaced with `VecReplaceArray()`.
2553
2554 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`
2555 @*/
VecPlaceArray(Vec vec,const PetscScalar array[])2556 PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2557 {
2558 PetscFunctionBegin;
2559 PetscValidHeaderSpecific(vec, VEC_CLASSID, 1);
2560 PetscValidType(vec, 1);
2561 if (array) PetscAssertPointer(array, 2);
2562 PetscUseTypeMethod(vec, placearray, array);
2563 PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2564 PetscFunctionReturn(PETSC_SUCCESS);
2565 }
2566
2567 /*@C
2568 VecReplaceArray - Allows one to replace the array in a vector with an
2569 array provided by the user. This is useful to avoid copying an array
2570 into a vector.
2571
2572 Logically Collective; No Fortran Support
2573
2574 Input Parameters:
2575 + vec - the vector
2576 - array - the array
2577
2578 Level: developer
2579
2580 Notes:
2581 Adding `const` to `array` was an oversight, as subsequent operations on `vec` would
2582 likely modify the data in `array`. However, we have kept it to avoid breaking APIs.
2583
2584 This permanently replaces the array and frees the memory associated
2585 with the old array. Use `VecPlaceArray()` to temporarily replace the array.
2586
2587 The memory passed in MUST be obtained with `PetscMalloc()` and CANNOT be
2588 freed by the user. It will be freed when the vector is destroyed.
2589
2590 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`
2591 @*/
VecReplaceArray(Vec vec,const PetscScalar array[])2592 PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2593 {
2594 PetscFunctionBegin;
2595 PetscValidHeaderSpecific(vec, VEC_CLASSID, 1);
2596 PetscValidType(vec, 1);
2597 PetscUseTypeMethod(vec, replacearray, array);
2598 PetscCall(PetscObjectStateIncrease((PetscObject)vec));
2599 PetscFunctionReturn(PETSC_SUCCESS);
2600 }
2601
2602 /*@C
2603 VecGetArray2d - Returns a pointer to a 2d contiguous array that contains this
2604 processor's portion of the vector data. You MUST call `VecRestoreArray2d()`
2605 when you no longer need access to the array.
2606
2607 Logically Collective
2608
2609 Input Parameters:
2610 + x - the vector
2611 . m - first dimension of two dimensional array
2612 . n - second dimension of two dimensional array
2613 . mstart - first index you will use in first coordinate direction (often 0)
2614 - nstart - first index in the second coordinate direction (often 0)
2615
2616 Output Parameter:
2617 . a - location to put pointer to the array
2618
2619 Level: developer
2620
2621 Notes:
2622 For a vector obtained from `DMCreateLocalVector()` `mstart` and `nstart` are likely
2623 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2624 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2625 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.
2626
2627 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2628
2629 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2630 `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2631 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2632 @*/
VecGetArray2d(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar ** a[])2633 PetscErrorCode VecGetArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2634 {
2635 PetscInt i, N;
2636 PetscScalar *aa;
2637
2638 PetscFunctionBegin;
2639 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2640 PetscAssertPointer(a, 6);
2641 PetscValidType(x, 1);
2642 PetscCall(VecGetLocalSize(x, &N));
2643 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);
2644 PetscCall(VecGetArray(x, &aa));
2645
2646 PetscCall(PetscMalloc1(m, a));
2647 for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2648 *a -= mstart;
2649 PetscFunctionReturn(PETSC_SUCCESS);
2650 }
2651
2652 /*@C
2653 VecGetArray2dWrite - Returns a pointer to a 2d contiguous array that will contain this
2654 processor's portion of the vector data. You MUST call `VecRestoreArray2dWrite()`
2655 when you no longer need access to the array.
2656
2657 Logically Collective
2658
2659 Input Parameters:
2660 + x - the vector
2661 . m - first dimension of two dimensional array
2662 . n - second dimension of two dimensional array
2663 . mstart - first index you will use in first coordinate direction (often 0)
2664 - nstart - first index in the second coordinate direction (often 0)
2665
2666 Output Parameter:
2667 . a - location to put pointer to the array
2668
2669 Level: developer
2670
2671 Notes:
2672 For a vector obtained from `DMCreateLocalVector()` `mstart` and `nstart` are likely
2673 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2674 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2675 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.
2676
2677 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2678
2679 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2680 `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2681 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2682 @*/
VecGetArray2dWrite(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar ** a[])2683 PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2684 {
2685 PetscInt i, N;
2686 PetscScalar *aa;
2687
2688 PetscFunctionBegin;
2689 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2690 PetscAssertPointer(a, 6);
2691 PetscValidType(x, 1);
2692 PetscCall(VecGetLocalSize(x, &N));
2693 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);
2694 PetscCall(VecGetArrayWrite(x, &aa));
2695
2696 PetscCall(PetscMalloc1(m, a));
2697 for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
2698 *a -= mstart;
2699 PetscFunctionReturn(PETSC_SUCCESS);
2700 }
2701
2702 /*@C
2703 VecRestoreArray2d - Restores a vector after `VecGetArray2d()` has been called.
2704
2705 Logically Collective
2706
2707 Input Parameters:
2708 + x - the vector
2709 . m - first dimension of two dimensional array
2710 . n - second dimension of the two dimensional array
2711 . mstart - first index you will use in first coordinate direction (often 0)
2712 . nstart - first index in the second coordinate direction (often 0)
2713 - a - location of pointer to array obtained from `VecGetArray2d()`
2714
2715 Level: developer
2716
2717 Notes:
2718 For regular PETSc vectors this routine does not involve any copies. For
2719 any special vectors that do not store local vector data in a contiguous
2720 array, this routine will copy the data back into the underlying
2721 vector data structure from the array obtained with `VecGetArray()`.
2722
2723 This routine actually zeros out the `a` pointer.
2724
2725 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2726 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2727 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2728 @*/
VecRestoreArray2d(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar ** a[])2729 PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2730 {
2731 void *dummy;
2732
2733 PetscFunctionBegin;
2734 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2735 PetscAssertPointer(a, 6);
2736 PetscValidType(x, 1);
2737 dummy = (void *)(*a + mstart);
2738 PetscCall(PetscFree(dummy));
2739 PetscCall(VecRestoreArray(x, NULL));
2740 *a = NULL;
2741 PetscFunctionReturn(PETSC_SUCCESS);
2742 }
2743
2744 /*@C
2745 VecRestoreArray2dWrite - Restores a vector after `VecGetArray2dWrite()` has been called.
2746
2747 Logically Collective
2748
2749 Input Parameters:
2750 + x - the vector
2751 . m - first dimension of two dimensional array
2752 . n - second dimension of the two dimensional array
2753 . mstart - first index you will use in first coordinate direction (often 0)
2754 . nstart - first index in the second coordinate direction (often 0)
2755 - a - location of pointer to array obtained from `VecGetArray2d()`
2756
2757 Level: developer
2758
2759 Notes:
2760 For regular PETSc vectors this routine does not involve any copies. For
2761 any special vectors that do not store local vector data in a contiguous
2762 array, this routine will copy the data back into the underlying
2763 vector data structure from the array obtained with `VecGetArray()`.
2764
2765 This routine actually zeros out the `a` pointer.
2766
2767 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2768 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2769 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2770 @*/
VecRestoreArray2dWrite(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar ** a[])2771 PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
2772 {
2773 void *dummy;
2774
2775 PetscFunctionBegin;
2776 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2777 PetscAssertPointer(a, 6);
2778 PetscValidType(x, 1);
2779 dummy = (void *)(*a + mstart);
2780 PetscCall(PetscFree(dummy));
2781 PetscCall(VecRestoreArrayWrite(x, NULL));
2782 PetscFunctionReturn(PETSC_SUCCESS);
2783 }
2784
2785 /*@C
2786 VecGetArray1d - Returns a pointer to a 1d contiguous array that contains this
2787 processor's portion of the vector data. You MUST call `VecRestoreArray1d()`
2788 when you no longer need access to the array.
2789
2790 Logically Collective
2791
2792 Input Parameters:
2793 + x - the vector
2794 . m - first dimension of two dimensional array
2795 - mstart - first index you will use in first coordinate direction (often 0)
2796
2797 Output Parameter:
2798 . a - location to put pointer to the array
2799
2800 Level: developer
2801
2802 Notes:
2803 For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
2804 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2805 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.
2806
2807 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2808
2809 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2810 `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2811 `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2812 @*/
VecGetArray1d(Vec x,PetscInt m,PetscInt mstart,PetscScalar * a[])2813 PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2814 {
2815 PetscInt N;
2816
2817 PetscFunctionBegin;
2818 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2819 PetscAssertPointer(a, 4);
2820 PetscValidType(x, 1);
2821 PetscCall(VecGetLocalSize(x, &N));
2822 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);
2823 PetscCall(VecGetArray(x, a));
2824 *a -= mstart;
2825 PetscFunctionReturn(PETSC_SUCCESS);
2826 }
2827
2828 /*@C
2829 VecGetArray1dWrite - Returns a pointer to a 1d contiguous array that will contain this
2830 processor's portion of the vector data. You MUST call `VecRestoreArray1dWrite()`
2831 when you no longer need access to the array.
2832
2833 Logically Collective
2834
2835 Input Parameters:
2836 + x - the vector
2837 . m - first dimension of two dimensional array
2838 - mstart - first index you will use in first coordinate direction (often 0)
2839
2840 Output Parameter:
2841 . a - location to put pointer to the array
2842
2843 Level: developer
2844
2845 Notes:
2846 For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
2847 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2848 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.
2849
2850 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2851
2852 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2853 `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
2854 `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2855 @*/
VecGetArray1dWrite(Vec x,PetscInt m,PetscInt mstart,PetscScalar * a[])2856 PetscErrorCode VecGetArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2857 {
2858 PetscInt N;
2859
2860 PetscFunctionBegin;
2861 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2862 PetscAssertPointer(a, 4);
2863 PetscValidType(x, 1);
2864 PetscCall(VecGetLocalSize(x, &N));
2865 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);
2866 PetscCall(VecGetArrayWrite(x, a));
2867 *a -= mstart;
2868 PetscFunctionReturn(PETSC_SUCCESS);
2869 }
2870
2871 /*@C
2872 VecRestoreArray1d - Restores a vector after `VecGetArray1d()` has been called.
2873
2874 Logically Collective
2875
2876 Input Parameters:
2877 + x - the vector
2878 . m - first dimension of two dimensional array
2879 . mstart - first index you will use in first coordinate direction (often 0)
2880 - a - location of pointer to array obtained from `VecGetArray1d()`
2881
2882 Level: developer
2883
2884 Notes:
2885 For regular PETSc vectors this routine does not involve any copies. For
2886 any special vectors that do not store local vector data in a contiguous
2887 array, this routine will copy the data back into the underlying
2888 vector data structure from the array obtained with `VecGetArray1d()`.
2889
2890 This routine actually zeros out the `a` pointer.
2891
2892 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2893 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2894 `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2895 @*/
VecRestoreArray1d(Vec x,PetscInt m,PetscInt mstart,PetscScalar * a[])2896 PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2897 {
2898 PetscFunctionBegin;
2899 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2900 PetscValidType(x, 1);
2901 PetscCall(VecRestoreArray(x, NULL));
2902 *a = NULL;
2903 PetscFunctionReturn(PETSC_SUCCESS);
2904 }
2905
2906 /*@C
2907 VecRestoreArray1dWrite - Restores a vector after `VecGetArray1dWrite()` has been called.
2908
2909 Logically Collective
2910
2911 Input Parameters:
2912 + x - the vector
2913 . m - first dimension of two dimensional array
2914 . mstart - first index you will use in first coordinate direction (often 0)
2915 - a - location of pointer to array obtained from `VecGetArray1d()`
2916
2917 Level: developer
2918
2919 Notes:
2920 For regular PETSc vectors this routine does not involve any copies. For
2921 any special vectors that do not store local vector data in a contiguous
2922 array, this routine will copy the data back into the underlying
2923 vector data structure from the array obtained with `VecGetArray1d()`.
2924
2925 This routine actually zeros out the `a` pointer.
2926
2927 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
2928 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
2929 `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2930 @*/
VecRestoreArray1dWrite(Vec x,PetscInt m,PetscInt mstart,PetscScalar * a[])2931 PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
2932 {
2933 PetscFunctionBegin;
2934 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2935 PetscValidType(x, 1);
2936 PetscCall(VecRestoreArrayWrite(x, NULL));
2937 *a = NULL;
2938 PetscFunctionReturn(PETSC_SUCCESS);
2939 }
2940
2941 /*@C
2942 VecGetArray3d - Returns a pointer to a 3d contiguous array that contains this
2943 processor's portion of the vector data. You MUST call `VecRestoreArray3d()`
2944 when you no longer need access to the array.
2945
2946 Logically Collective
2947
2948 Input Parameters:
2949 + x - the vector
2950 . m - first dimension of three dimensional array
2951 . n - second dimension of three dimensional array
2952 . p - third dimension of three dimensional array
2953 . mstart - first index you will use in first coordinate direction (often 0)
2954 . nstart - first index in the second coordinate direction (often 0)
2955 - pstart - first index in the third coordinate direction (often 0)
2956
2957 Output Parameter:
2958 . a - location to put pointer to the array
2959
2960 Level: developer
2961
2962 Notes:
2963 For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
2964 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
2965 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
2966 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
2967
2968 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2969
2970 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
2971 `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecRestoreArray3d()`,
2972 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
2973 @*/
VecGetArray3d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar *** a[])2974 PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
2975 {
2976 PetscInt i, N, j;
2977 PetscScalar *aa, **b;
2978
2979 PetscFunctionBegin;
2980 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
2981 PetscAssertPointer(a, 8);
2982 PetscValidType(x, 1);
2983 PetscCall(VecGetLocalSize(x, &N));
2984 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);
2985 PetscCall(VecGetArray(x, &aa));
2986
2987 PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
2988 b = (PetscScalar **)((*a) + m);
2989 for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
2990 for (i = 0; i < m; i++)
2991 for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset(aa, i * n * p + j * p - pstart);
2992 *a -= mstart;
2993 PetscFunctionReturn(PETSC_SUCCESS);
2994 }
2995
2996 /*@C
2997 VecGetArray3dWrite - Returns a pointer to a 3d contiguous array that will contain this
2998 processor's portion of the vector data. You MUST call `VecRestoreArray3dWrite()`
2999 when you no longer need access to the array.
3000
3001 Logically Collective
3002
3003 Input Parameters:
3004 + x - the vector
3005 . m - first dimension of three dimensional array
3006 . n - second dimension of three dimensional array
3007 . p - third dimension of three dimensional array
3008 . mstart - first index you will use in first coordinate direction (often 0)
3009 . nstart - first index in the second coordinate direction (often 0)
3010 - pstart - first index in the third coordinate direction (often 0)
3011
3012 Output Parameter:
3013 . a - location to put pointer to the array
3014
3015 Level: developer
3016
3017 Notes:
3018 For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3019 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3020 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3021 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3022
3023 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3024
3025 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3026 `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3027 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3028 @*/
VecGetArray3dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar *** a[])3029 PetscErrorCode VecGetArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3030 {
3031 PetscInt i, N, j;
3032 PetscScalar *aa, **b;
3033
3034 PetscFunctionBegin;
3035 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3036 PetscAssertPointer(a, 8);
3037 PetscValidType(x, 1);
3038 PetscCall(VecGetLocalSize(x, &N));
3039 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);
3040 PetscCall(VecGetArrayWrite(x, &aa));
3041
3042 PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3043 b = (PetscScalar **)((*a) + m);
3044 for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3045 for (i = 0; i < m; i++)
3046 for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;
3047
3048 *a -= mstart;
3049 PetscFunctionReturn(PETSC_SUCCESS);
3050 }
3051
3052 /*@C
3053 VecRestoreArray3d - Restores a vector after `VecGetArray3d()` has been called.
3054
3055 Logically Collective
3056
3057 Input Parameters:
3058 + x - the vector
3059 . m - first dimension of three dimensional array
3060 . n - second dimension of the three dimensional array
3061 . p - third dimension of the three dimensional array
3062 . mstart - first index you will use in first coordinate direction (often 0)
3063 . nstart - first index in the second coordinate direction (often 0)
3064 . pstart - first index in the third coordinate direction (often 0)
3065 - a - location of pointer to array obtained from VecGetArray3d()
3066
3067 Level: developer
3068
3069 Notes:
3070 For regular PETSc vectors this routine does not involve any copies. For
3071 any special vectors that do not store local vector data in a contiguous
3072 array, this routine will copy the data back into the underlying
3073 vector data structure from the array obtained with `VecGetArray()`.
3074
3075 This routine actually zeros out the `a` pointer.
3076
3077 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3078 `VecGetArray2d()`, `VecGetArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3079 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3080 @*/
VecRestoreArray3d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar *** a[])3081 PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3082 {
3083 void *dummy;
3084
3085 PetscFunctionBegin;
3086 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3087 PetscAssertPointer(a, 8);
3088 PetscValidType(x, 1);
3089 dummy = (void *)(*a + mstart);
3090 PetscCall(PetscFree(dummy));
3091 PetscCall(VecRestoreArray(x, NULL));
3092 *a = NULL;
3093 PetscFunctionReturn(PETSC_SUCCESS);
3094 }
3095
3096 /*@C
3097 VecRestoreArray3dWrite - Restores a vector after `VecGetArray3dWrite()` has been called.
3098
3099 Logically Collective
3100
3101 Input Parameters:
3102 + x - the vector
3103 . m - first dimension of three dimensional array
3104 . n - second dimension of the three dimensional array
3105 . p - third dimension of the three dimensional array
3106 . mstart - first index you will use in first coordinate direction (often 0)
3107 . nstart - first index in the second coordinate direction (often 0)
3108 . pstart - first index in the third coordinate direction (often 0)
3109 - a - location of pointer to array obtained from VecGetArray3d()
3110
3111 Level: developer
3112
3113 Notes:
3114 For regular PETSc vectors this routine does not involve any copies. For
3115 any special vectors that do not store local vector data in a contiguous
3116 array, this routine will copy the data back into the underlying
3117 vector data structure from the array obtained with `VecGetArray()`.
3118
3119 This routine actually zeros out the `a` pointer.
3120
3121 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3122 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3123 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3124 @*/
VecRestoreArray3dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar *** a[])3125 PetscErrorCode VecRestoreArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3126 {
3127 void *dummy;
3128
3129 PetscFunctionBegin;
3130 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3131 PetscAssertPointer(a, 8);
3132 PetscValidType(x, 1);
3133 dummy = (void *)(*a + mstart);
3134 PetscCall(PetscFree(dummy));
3135 PetscCall(VecRestoreArrayWrite(x, NULL));
3136 *a = NULL;
3137 PetscFunctionReturn(PETSC_SUCCESS);
3138 }
3139
3140 /*@C
3141 VecGetArray4d - Returns a pointer to a 4d contiguous array that contains this
3142 processor's portion of the vector data. You MUST call `VecRestoreArray4d()`
3143 when you no longer need access to the array.
3144
3145 Logically Collective
3146
3147 Input Parameters:
3148 + x - the vector
3149 . m - first dimension of four dimensional array
3150 . n - second dimension of four dimensional array
3151 . p - third dimension of four dimensional array
3152 . q - fourth dimension of four dimensional array
3153 . mstart - first index you will use in first coordinate direction (often 0)
3154 . nstart - first index in the second coordinate direction (often 0)
3155 . pstart - first index in the third coordinate direction (often 0)
3156 - qstart - first index in the fourth coordinate direction (often 0)
3157
3158 Output Parameter:
3159 . a - location to put pointer to the array
3160
3161 Level: developer
3162
3163 Notes:
3164 For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3165 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3166 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3167 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3168
3169 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3170
3171 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3172 `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3173 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecRestoreArray4d()`
3174 @*/
VecGetArray4d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar **** a[])3175 PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3176 {
3177 PetscInt i, N, j, k;
3178 PetscScalar *aa, ***b, **c;
3179
3180 PetscFunctionBegin;
3181 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3182 PetscAssertPointer(a, 10);
3183 PetscValidType(x, 1);
3184 PetscCall(VecGetLocalSize(x, &N));
3185 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);
3186 PetscCall(VecGetArray(x, &aa));
3187
3188 PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3189 b = (PetscScalar ***)((*a) + m);
3190 c = (PetscScalar **)(b + m * n);
3191 for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3192 for (i = 0; i < m; i++)
3193 for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3194 for (i = 0; i < m; i++)
3195 for (j = 0; j < n; j++)
3196 for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3197 *a -= mstart;
3198 PetscFunctionReturn(PETSC_SUCCESS);
3199 }
3200
3201 /*@C
3202 VecGetArray4dWrite - Returns a pointer to a 4d contiguous array that will contain this
3203 processor's portion of the vector data. You MUST call `VecRestoreArray4dWrite()`
3204 when you no longer need access to the array.
3205
3206 Logically Collective
3207
3208 Input Parameters:
3209 + x - the vector
3210 . m - first dimension of four dimensional array
3211 . n - second dimension of four dimensional array
3212 . p - third dimension of four dimensional array
3213 . q - fourth dimension of four dimensional array
3214 . mstart - first index you will use in first coordinate direction (often 0)
3215 . nstart - first index in the second coordinate direction (often 0)
3216 . pstart - first index in the third coordinate direction (often 0)
3217 - qstart - first index in the fourth coordinate direction (often 0)
3218
3219 Output Parameter:
3220 . a - location to put pointer to the array
3221
3222 Level: developer
3223
3224 Notes:
3225 For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3226 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3227 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3228 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3229
3230 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3231
3232 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3233 `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3234 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3235 @*/
VecGetArray4dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar **** a[])3236 PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3237 {
3238 PetscInt i, N, j, k;
3239 PetscScalar *aa, ***b, **c;
3240
3241 PetscFunctionBegin;
3242 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3243 PetscAssertPointer(a, 10);
3244 PetscValidType(x, 1);
3245 PetscCall(VecGetLocalSize(x, &N));
3246 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);
3247 PetscCall(VecGetArrayWrite(x, &aa));
3248
3249 PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3250 b = (PetscScalar ***)((*a) + m);
3251 c = (PetscScalar **)(b + m * n);
3252 for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3253 for (i = 0; i < m; i++)
3254 for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3255 for (i = 0; i < m; i++)
3256 for (j = 0; j < n; j++)
3257 for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3258 *a -= mstart;
3259 PetscFunctionReturn(PETSC_SUCCESS);
3260 }
3261
3262 /*@C
3263 VecRestoreArray4d - Restores a vector after `VecGetArray4d()` has been called.
3264
3265 Logically Collective
3266
3267 Input Parameters:
3268 + x - the vector
3269 . m - first dimension of four dimensional array
3270 . n - second dimension of the four dimensional array
3271 . p - third dimension of the four dimensional array
3272 . q - fourth dimension of the four dimensional array
3273 . mstart - first index you will use in first coordinate direction (often 0)
3274 . nstart - first index in the second coordinate direction (often 0)
3275 . pstart - first index in the third coordinate direction (often 0)
3276 . qstart - first index in the fourth coordinate direction (often 0)
3277 - a - location of pointer to array obtained from VecGetArray4d()
3278
3279 Level: developer
3280
3281 Notes:
3282 For regular PETSc vectors this routine does not involve any copies. For
3283 any special vectors that do not store local vector data in a contiguous
3284 array, this routine will copy the data back into the underlying
3285 vector data structure from the array obtained with `VecGetArray()`.
3286
3287 This routine actually zeros out the `a` pointer.
3288
3289 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3290 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3291 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`
3292 @*/
VecRestoreArray4d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar **** a[])3293 PetscErrorCode VecRestoreArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3294 {
3295 void *dummy;
3296
3297 PetscFunctionBegin;
3298 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3299 PetscAssertPointer(a, 10);
3300 PetscValidType(x, 1);
3301 dummy = (void *)(*a + mstart);
3302 PetscCall(PetscFree(dummy));
3303 PetscCall(VecRestoreArray(x, NULL));
3304 *a = NULL;
3305 PetscFunctionReturn(PETSC_SUCCESS);
3306 }
3307
3308 /*@C
3309 VecRestoreArray4dWrite - Restores a vector after `VecGetArray4dWrite()` has been called.
3310
3311 Logically Collective
3312
3313 Input Parameters:
3314 + x - the vector
3315 . m - first dimension of four dimensional array
3316 . n - second dimension of the four dimensional array
3317 . p - third dimension of the four dimensional array
3318 . q - fourth dimension of the four dimensional array
3319 . mstart - first index you will use in first coordinate direction (often 0)
3320 . nstart - first index in the second coordinate direction (often 0)
3321 . pstart - first index in the third coordinate direction (often 0)
3322 . qstart - first index in the fourth coordinate direction (often 0)
3323 - a - location of pointer to array obtained from `VecGetArray4d()`
3324
3325 Level: developer
3326
3327 Notes:
3328 For regular PETSc vectors this routine does not involve any copies. For
3329 any special vectors that do not store local vector data in a contiguous
3330 array, this routine will copy the data back into the underlying
3331 vector data structure from the array obtained with `VecGetArray()`.
3332
3333 This routine actually zeros out the `a` pointer.
3334
3335 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3336 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3337 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3338 @*/
VecRestoreArray4dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar **** a[])3339 PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3340 {
3341 void *dummy;
3342
3343 PetscFunctionBegin;
3344 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3345 PetscAssertPointer(a, 10);
3346 PetscValidType(x, 1);
3347 dummy = (void *)(*a + mstart);
3348 PetscCall(PetscFree(dummy));
3349 PetscCall(VecRestoreArrayWrite(x, NULL));
3350 *a = NULL;
3351 PetscFunctionReturn(PETSC_SUCCESS);
3352 }
3353
3354 /*@C
3355 VecGetArray2dRead - Returns a pointer to a 2d contiguous array that contains this
3356 processor's portion of the vector data. You MUST call `VecRestoreArray2dRead()`
3357 when you no longer need access to the array.
3358
3359 Logically Collective
3360
3361 Input Parameters:
3362 + x - the vector
3363 . m - first dimension of two dimensional array
3364 . n - second dimension of two dimensional array
3365 . mstart - first index you will use in first coordinate direction (often 0)
3366 - nstart - first index in the second coordinate direction (often 0)
3367
3368 Output Parameter:
3369 . a - location to put pointer to the array
3370
3371 Level: developer
3372
3373 Notes:
3374 For a vector obtained from `DMCreateLocalVector()` `mstart` and `nstart` are likely
3375 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3376 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3377 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray2d()`.
3378
3379 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3380
3381 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3382 `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3383 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3384 @*/
VecGetArray2dRead(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar ** a[])3385 PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3386 {
3387 PetscInt i, N;
3388 const PetscScalar *aa;
3389
3390 PetscFunctionBegin;
3391 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3392 PetscAssertPointer(a, 6);
3393 PetscValidType(x, 1);
3394 PetscCall(VecGetLocalSize(x, &N));
3395 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);
3396 PetscCall(VecGetArrayRead(x, &aa));
3397
3398 PetscCall(PetscMalloc1(m, a));
3399 for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3400 *a -= mstart;
3401 PetscFunctionReturn(PETSC_SUCCESS);
3402 }
3403
3404 /*@C
3405 VecRestoreArray2dRead - Restores a vector after `VecGetArray2dRead()` has been called.
3406
3407 Logically Collective
3408
3409 Input Parameters:
3410 + x - the vector
3411 . m - first dimension of two dimensional array
3412 . n - second dimension of the two dimensional array
3413 . mstart - first index you will use in first coordinate direction (often 0)
3414 . nstart - first index in the second coordinate direction (often 0)
3415 - a - location of pointer to array obtained from VecGetArray2d()
3416
3417 Level: developer
3418
3419 Notes:
3420 For regular PETSc vectors this routine does not involve any copies. For
3421 any special vectors that do not store local vector data in a contiguous
3422 array, this routine will copy the data back into the underlying
3423 vector data structure from the array obtained with `VecGetArray()`.
3424
3425 This routine actually zeros out the `a` pointer.
3426
3427 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3428 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3429 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3430 @*/
VecRestoreArray2dRead(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar ** a[])3431 PetscErrorCode VecRestoreArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3432 {
3433 void *dummy;
3434
3435 PetscFunctionBegin;
3436 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3437 PetscAssertPointer(a, 6);
3438 PetscValidType(x, 1);
3439 dummy = (void *)(*a + mstart);
3440 PetscCall(PetscFree(dummy));
3441 PetscCall(VecRestoreArrayRead(x, NULL));
3442 *a = NULL;
3443 PetscFunctionReturn(PETSC_SUCCESS);
3444 }
3445
3446 /*@C
3447 VecGetArray1dRead - Returns a pointer to a 1d contiguous array that contains this
3448 processor's portion of the vector data. You MUST call `VecRestoreArray1dRead()`
3449 when you no longer need access to the array.
3450
3451 Logically Collective
3452
3453 Input Parameters:
3454 + x - the vector
3455 . m - first dimension of two dimensional array
3456 - mstart - first index you will use in first coordinate direction (often 0)
3457
3458 Output Parameter:
3459 . a - location to put pointer to the array
3460
3461 Level: developer
3462
3463 Notes:
3464 For a vector obtained from `DMCreateLocalVector()` `mstart` is likely
3465 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3466 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`.
3467
3468 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3469
3470 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3471 `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3472 `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3473 @*/
VecGetArray1dRead(Vec x,PetscInt m,PetscInt mstart,PetscScalar * a[])3474 PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3475 {
3476 PetscInt N;
3477
3478 PetscFunctionBegin;
3479 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3480 PetscAssertPointer(a, 4);
3481 PetscValidType(x, 1);
3482 PetscCall(VecGetLocalSize(x, &N));
3483 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);
3484 PetscCall(VecGetArrayRead(x, (const PetscScalar **)a));
3485 *a -= mstart;
3486 PetscFunctionReturn(PETSC_SUCCESS);
3487 }
3488
3489 /*@C
3490 VecRestoreArray1dRead - Restores a vector after `VecGetArray1dRead()` has been called.
3491
3492 Logically Collective
3493
3494 Input Parameters:
3495 + x - the vector
3496 . m - first dimension of two dimensional array
3497 . mstart - first index you will use in first coordinate direction (often 0)
3498 - a - location of pointer to array obtained from `VecGetArray1dRead()`
3499
3500 Level: developer
3501
3502 Notes:
3503 For regular PETSc vectors this routine does not involve any copies. For
3504 any special vectors that do not store local vector data in a contiguous
3505 array, this routine will copy the data back into the underlying
3506 vector data structure from the array obtained with `VecGetArray1dRead()`.
3507
3508 This routine actually zeros out the `a` pointer.
3509
3510 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3511 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3512 `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3513 @*/
VecRestoreArray1dRead(Vec x,PetscInt m,PetscInt mstart,PetscScalar * a[])3514 PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3515 {
3516 PetscFunctionBegin;
3517 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3518 PetscValidType(x, 1);
3519 PetscCall(VecRestoreArrayRead(x, NULL));
3520 *a = NULL;
3521 PetscFunctionReturn(PETSC_SUCCESS);
3522 }
3523
3524 /*@C
3525 VecGetArray3dRead - Returns a pointer to a 3d contiguous array that contains this
3526 processor's portion of the vector data. You MUST call `VecRestoreArray3dRead()`
3527 when you no longer need access to the array.
3528
3529 Logically Collective
3530
3531 Input Parameters:
3532 + x - the vector
3533 . m - first dimension of three dimensional array
3534 . n - second dimension of three dimensional array
3535 . p - third dimension of three dimensional array
3536 . mstart - first index you will use in first coordinate direction (often 0)
3537 . nstart - first index in the second coordinate direction (often 0)
3538 - pstart - first index in the third coordinate direction (often 0)
3539
3540 Output Parameter:
3541 . a - location to put pointer to the array
3542
3543 Level: developer
3544
3545 Notes:
3546 For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3547 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3548 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3549 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3dRead()`.
3550
3551 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3552
3553 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3554 `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3555 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3556 @*/
VecGetArray3dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar *** a[])3557 PetscErrorCode VecGetArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3558 {
3559 PetscInt i, N, j;
3560 const PetscScalar *aa;
3561 PetscScalar **b;
3562
3563 PetscFunctionBegin;
3564 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3565 PetscAssertPointer(a, 8);
3566 PetscValidType(x, 1);
3567 PetscCall(VecGetLocalSize(x, &N));
3568 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);
3569 PetscCall(VecGetArrayRead(x, &aa));
3570
3571 PetscCall(PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a));
3572 b = (PetscScalar **)((*a) + m);
3573 for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3574 for (i = 0; i < m; i++)
3575 for (j = 0; j < n; j++) b[i * n + j] = PetscSafePointerPlusOffset((PetscScalar *)aa, i * n * p + j * p - pstart);
3576 *a -= mstart;
3577 PetscFunctionReturn(PETSC_SUCCESS);
3578 }
3579
3580 /*@C
3581 VecRestoreArray3dRead - Restores a vector after `VecGetArray3dRead()` has been called.
3582
3583 Logically Collective
3584
3585 Input Parameters:
3586 + x - the vector
3587 . m - first dimension of three dimensional array
3588 . n - second dimension of the three dimensional array
3589 . p - third dimension of the three dimensional array
3590 . mstart - first index you will use in first coordinate direction (often 0)
3591 . nstart - first index in the second coordinate direction (often 0)
3592 . pstart - first index in the third coordinate direction (often 0)
3593 - a - location of pointer to array obtained from `VecGetArray3dRead()`
3594
3595 Level: developer
3596
3597 Notes:
3598 For regular PETSc vectors this routine does not involve any copies. For
3599 any special vectors that do not store local vector data in a contiguous
3600 array, this routine will copy the data back into the underlying
3601 vector data structure from the array obtained with `VecGetArray()`.
3602
3603 This routine actually zeros out the `a` pointer.
3604
3605 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3606 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3607 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3608 @*/
VecRestoreArray3dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar *** a[])3609 PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3610 {
3611 void *dummy;
3612
3613 PetscFunctionBegin;
3614 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3615 PetscAssertPointer(a, 8);
3616 PetscValidType(x, 1);
3617 dummy = (void *)(*a + mstart);
3618 PetscCall(PetscFree(dummy));
3619 PetscCall(VecRestoreArrayRead(x, NULL));
3620 *a = NULL;
3621 PetscFunctionReturn(PETSC_SUCCESS);
3622 }
3623
3624 /*@C
3625 VecGetArray4dRead - Returns a pointer to a 4d contiguous array that contains this
3626 processor's portion of the vector data. You MUST call `VecRestoreArray4dRead()`
3627 when you no longer need access to the array.
3628
3629 Logically Collective
3630
3631 Input Parameters:
3632 + x - the vector
3633 . m - first dimension of four dimensional array
3634 . n - second dimension of four dimensional array
3635 . p - third dimension of four dimensional array
3636 . q - fourth dimension of four dimensional array
3637 . mstart - first index you will use in first coordinate direction (often 0)
3638 . nstart - first index in the second coordinate direction (often 0)
3639 . pstart - first index in the third coordinate direction (often 0)
3640 - qstart - first index in the fourth coordinate direction (often 0)
3641
3642 Output Parameter:
3643 . a - location to put pointer to the array
3644
3645 Level: beginner
3646
3647 Notes:
3648 For a vector obtained from `DMCreateLocalVector()` `mstart`, `nstart`, and `pstart` are likely
3649 obtained from the corner indices obtained from `DMDAGetGhostCorners()` while for
3650 `DMCreateGlobalVector()` they are the corner indices from `DMDAGetCorners()`. In both cases
3651 the arguments from `DMDAGet[Ghost]Corners()` are reversed in the call to `VecGetArray3d()`.
3652
3653 For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3654
3655 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecPlaceArray()`,
3656 `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3657 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3658 @*/
VecGetArray4dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar **** a[])3659 PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3660 {
3661 PetscInt i, N, j, k;
3662 const PetscScalar *aa;
3663 PetscScalar ***b, **c;
3664
3665 PetscFunctionBegin;
3666 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3667 PetscAssertPointer(a, 10);
3668 PetscValidType(x, 1);
3669 PetscCall(VecGetLocalSize(x, &N));
3670 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);
3671 PetscCall(VecGetArrayRead(x, &aa));
3672
3673 PetscCall(PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a));
3674 b = (PetscScalar ***)((*a) + m);
3675 c = (PetscScalar **)(b + m * n);
3676 for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3677 for (i = 0; i < m; i++)
3678 for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3679 for (i = 0; i < m; i++)
3680 for (j = 0; j < n; j++)
3681 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;
3682 *a -= mstart;
3683 PetscFunctionReturn(PETSC_SUCCESS);
3684 }
3685
3686 /*@C
3687 VecRestoreArray4dRead - Restores a vector after `VecGetArray4d()` has been called.
3688
3689 Logically Collective
3690
3691 Input Parameters:
3692 + x - the vector
3693 . m - first dimension of four dimensional array
3694 . n - second dimension of the four dimensional array
3695 . p - third dimension of the four dimensional array
3696 . q - fourth dimension of the four dimensional array
3697 . mstart - first index you will use in first coordinate direction (often 0)
3698 . nstart - first index in the second coordinate direction (often 0)
3699 . pstart - first index in the third coordinate direction (often 0)
3700 . qstart - first index in the fourth coordinate direction (often 0)
3701 - a - location of pointer to array obtained from `VecGetArray4dRead()`
3702
3703 Level: beginner
3704
3705 Notes:
3706 For regular PETSc vectors this routine does not involve any copies. For
3707 any special vectors that do not store local vector data in a contiguous
3708 array, this routine will copy the data back into the underlying
3709 vector data structure from the array obtained with `VecGetArray()`.
3710
3711 This routine actually zeros out the `a` pointer.
3712
3713 .seealso: [](ch_vectors), `Vec`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecPlaceArray()`,
3714 `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3715 `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3716 @*/
VecRestoreArray4dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar **** a[])3717 PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3718 {
3719 void *dummy;
3720
3721 PetscFunctionBegin;
3722 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3723 PetscAssertPointer(a, 10);
3724 PetscValidType(x, 1);
3725 dummy = (void *)(*a + mstart);
3726 PetscCall(PetscFree(dummy));
3727 PetscCall(VecRestoreArrayRead(x, NULL));
3728 *a = NULL;
3729 PetscFunctionReturn(PETSC_SUCCESS);
3730 }
3731
3732 /*@
3733 VecLockGet - Get the current lock status of a vector
3734
3735 Logically Collective
3736
3737 Input Parameter:
3738 . x - the vector
3739
3740 Output Parameter:
3741 . state - greater than zero indicates the vector is locked for read; less than zero indicates the vector is
3742 locked for write; equal to zero means the vector is unlocked, that is, it is free to read or write.
3743
3744 Level: advanced
3745
3746 .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
3747 @*/
VecLockGet(Vec x,PetscInt * state)3748 PetscErrorCode VecLockGet(Vec x, PetscInt *state)
3749 {
3750 PetscFunctionBegin;
3751 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3752 PetscAssertPointer(state, 2);
3753 *state = x->lock;
3754 PetscFunctionReturn(PETSC_SUCCESS);
3755 }
3756
VecLockGetLocation(Vec x,const char * file[],const char * func[],int * line)3757 PetscErrorCode VecLockGetLocation(Vec x, const char *file[], const char *func[], int *line)
3758 {
3759 PetscFunctionBegin;
3760 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3761 PetscAssertPointer(file, 2);
3762 PetscAssertPointer(func, 3);
3763 PetscAssertPointer(line, 4);
3764 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3765 {
3766 const int index = x->lockstack.currentsize - 1;
3767
3768 *file = index < 0 ? NULL : x->lockstack.file[index];
3769 *func = index < 0 ? NULL : x->lockstack.function[index];
3770 *line = index < 0 ? 0 : x->lockstack.line[index];
3771 }
3772 #else
3773 *file = NULL;
3774 *func = NULL;
3775 *line = 0;
3776 #endif
3777 PetscFunctionReturn(PETSC_SUCCESS);
3778 }
3779
3780 /*@
3781 VecLockReadPush - Push a read-only lock on a vector to prevent it from being written to
3782
3783 Logically Collective
3784
3785 Input Parameter:
3786 . x - the vector
3787
3788 Level: intermediate
3789
3790 Notes:
3791 If this is set then calls to `VecGetArray()` or `VecSetValues()` or any other routines that change the vectors values will generate an error.
3792
3793 The call can be nested, i.e., called multiple times on the same vector, but each `VecLockReadPush()` has to have one matching
3794 `VecLockReadPop()`, which removes the latest read-only lock.
3795
3796 .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPop()`, `VecLockGet()`
3797 @*/
VecLockReadPush(Vec x)3798 PetscErrorCode VecLockReadPush(Vec x)
3799 {
3800 PetscFunctionBegin;
3801 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3802 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");
3803 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3804 {
3805 const char *file, *func;
3806 int index, line;
3807
3808 if ((index = petscstack.currentsize - 2) < 0) {
3809 // vec was locked "outside" of petsc, either in user-land or main. the error message will
3810 // now show this function as the culprit, but it will include the stacktrace
3811 file = "unknown user-file";
3812 func = "unknown_user_function";
3813 line = 0;
3814 } else {
3815 file = petscstack.file[index];
3816 func = petscstack.function[index];
3817 line = petscstack.line[index];
3818 }
3819 PetscStackPush_Private(x->lockstack, file, func, line, petscstack.petscroutine[index], PETSC_FALSE);
3820 }
3821 #endif
3822 PetscFunctionReturn(PETSC_SUCCESS);
3823 }
3824
3825 /*@
3826 VecLockReadPop - Pop a read-only lock from a vector
3827
3828 Logically Collective
3829
3830 Input Parameter:
3831 . x - the vector
3832
3833 Level: intermediate
3834
3835 .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockGet()`
3836 @*/
VecLockReadPop(Vec x)3837 PetscErrorCode VecLockReadPop(Vec x)
3838 {
3839 PetscFunctionBegin;
3840 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3841 PetscCheck(--x->lock >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector has been unlocked from read-only access too many times");
3842 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
3843 {
3844 const char *previous = x->lockstack.function[x->lockstack.currentsize - 1];
3845
3846 PetscStackPop_Private(x->lockstack, previous);
3847 }
3848 #endif
3849 PetscFunctionReturn(PETSC_SUCCESS);
3850 }
3851
3852 /*@
3853 VecLockWriteSet - Lock or unlock a vector for exclusive read/write access
3854
3855 Logically Collective
3856
3857 Input Parameters:
3858 + x - the vector
3859 - flg - `PETSC_TRUE` to lock the vector for exclusive read/write access; `PETSC_FALSE` to unlock it.
3860
3861 Level: intermediate
3862
3863 Notes:
3864 The function is useful in split-phase computations, which usually have a begin phase and an end phase.
3865 One can call `VecLockWriteSet`(x,`PETSC_TRUE`) in the begin phase to lock a vector for exclusive
3866 access, and call `VecLockWriteSet`(x,`PETSC_FALSE`) in the end phase to unlock the vector from exclusive
3867 access. In this way, one is ensured no other operations can access the vector in between. The code may like
3868
3869 .vb
3870 VecGetArray(x,&xdata); // begin phase
3871 VecLockWriteSet(v,PETSC_TRUE);
3872
3873 Other operations, which can not access x anymore (they can access xdata, of course)
3874
3875 VecRestoreArray(x,&vdata); // end phase
3876 VecLockWriteSet(v,PETSC_FALSE);
3877 .ve
3878
3879 The call can not be nested on the same vector, in other words, one can not call `VecLockWriteSet`(x,`PETSC_TRUE`)
3880 again before calling `VecLockWriteSet`(v,`PETSC_FALSE`).
3881
3882 .seealso: [](ch_vectors), `Vec`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
3883 @*/
VecLockWriteSet(Vec x,PetscBool flg)3884 PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
3885 {
3886 PetscFunctionBegin;
3887 PetscValidHeaderSpecific(x, VEC_CLASSID, 1);
3888 if (flg) {
3889 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");
3890 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");
3891 x->lock = -1;
3892 } else {
3893 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");
3894 x->lock = 0;
3895 }
3896 PetscFunctionReturn(PETSC_SUCCESS);
3897 }
3898