Actual source code: dmget.c
1: #include <petsc/private/dmimpl.h>
3: /*@
4: DMGetLocalVector - Gets a PETSc vector that may be used with the `DM` local routines. This vector has spaces for the ghost values.
6: Not Collective
8: Input Parameter:
9: . dm - the `DM`
11: Output Parameter:
12: . g - the local vector
14: Level: beginner
16: Note:
17: The vector values are NOT initialized and may have garbage in them, so you may need
18: to zero them.
20: The output parameter, `g`, is a regular PETSc vector that should be returned with
21: `DMRestoreLocalVector()` DO NOT call `VecDestroy()` on it.
23: This is intended to be used for vectors you need for a short time, like within a single function call.
24: For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your
25: code you should use `DMCreateLocalVector()`.
27: VecStride*() operations can be useful when using DM with dof > 1
29: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
30: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
31: `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`,
32: `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`
33: @*/
34: PetscErrorCode DMGetLocalVector(DM dm, Vec *g)
35: {
36: PetscFunctionBegin;
39: for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
40: if (dm->localin[i]) {
41: DM vdm;
43: *g = dm->localin[i];
44: dm->localin[i] = NULL;
46: PetscCall(VecGetDM(*g, &vdm));
47: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
48: PetscCall(VecSetDM(*g, dm));
49: goto alldone;
50: }
51: }
52: PetscCall(DMCreateLocalVector(dm, g));
54: alldone:
55: for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
56: if (!dm->localout[i]) {
57: dm->localout[i] = *g;
58: break;
59: }
60: }
61: PetscFunctionReturn(PETSC_SUCCESS);
62: }
64: /*@
65: DMRestoreLocalVector - Returns a PETSc vector that was
66: obtained from `DMGetLocalVector()`. Do not use with vector obtained via
67: `DMCreateLocalVector()`.
69: Not Collective
71: Input Parameters:
72: + dm - the `DM`
73: - g - the local vector
75: Level: beginner
77: .seealso: `DM`, `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
78: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
79: `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMGetLocalVector()`
80: @*/
81: PetscErrorCode DMRestoreLocalVector(DM dm, Vec *g)
82: {
83: PetscInt i, j;
85: PetscFunctionBegin;
88: for (j = 0; j < DM_MAX_WORK_VECTORS; j++) {
89: if (*g == dm->localout[j]) {
90: DM vdm;
92: PetscCall(VecGetDM(*g, &vdm));
93: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
94: PetscCall(VecSetDM(*g, NULL));
95: dm->localout[j] = NULL;
96: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
97: if (!dm->localin[i]) {
98: dm->localin[i] = *g;
99: goto alldone;
100: }
101: }
102: }
103: }
104: PetscCall(VecDestroy(g));
105: alldone:
106: *g = NULL;
107: PetscFunctionReturn(PETSC_SUCCESS);
108: }
110: /*@
111: DMGetGlobalVector - Gets a PETSc vector that may be used with the `DM` global routines.
113: Collective on dm
115: Input Parameter:
116: . dm - the `DM`
118: Output Parameter:
119: . g - the global vector
121: Level: beginner
123: Note:
124: The vector values are NOT initialized and may have garbage in them, so you may need
125: to zero them.
127: The output parameter, `g`, is a regular PETSc vector that should be returned with
128: `DMRestoreGlobalVector()` DO NOT call `VecDestroy()` on it.
130: This is intended to be used for vectors you need for a short time, like within a single function call.
131: For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your
132: code you should use `DMCreateGlobalVector()`.
134: VecStride*() operations can be useful when using `DM` with dof > 1
136: .seealso: `DM`, `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
137: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
138: `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`
139: `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`
140: @*/
141: PetscErrorCode DMGetGlobalVector(DM dm, Vec *g)
142: {
143: PetscInt i;
145: PetscFunctionBegin;
148: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
149: if (dm->globalin[i]) {
150: DM vdm;
152: *g = dm->globalin[i];
153: dm->globalin[i] = NULL;
155: PetscCall(VecGetDM(*g, &vdm));
156: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
157: PetscCall(VecSetDM(*g, dm));
158: goto alldone;
159: }
160: }
161: PetscCall(DMCreateGlobalVector(dm, g));
163: alldone:
164: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
165: if (!dm->globalout[i]) {
166: dm->globalout[i] = *g;
167: break;
168: }
169: }
170: PetscFunctionReturn(PETSC_SUCCESS);
171: }
173: /*@
174: DMClearGlobalVectors - Destroys all the global vectors that have been stashed in this `DM`
176: Collective
178: Input Parameter:
179: . dm - the `DM`
181: Level: developer
183: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
184: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`,
185: `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`
186: `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`
187: @*/
188: PetscErrorCode DMClearGlobalVectors(DM dm)
189: {
190: PetscInt i;
192: PetscFunctionBegin;
194: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
195: Vec g;
197: PetscCheck(!dm->globalout[i], PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of global vectors that has a global vector obtained with DMGetGlobalVector()");
198: g = dm->globalin[i];
199: dm->globalin[i] = NULL;
200: if (g) {
201: DM vdm;
203: PetscCall(VecGetDM(g, &vdm));
204: PetscCheck(!vdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing global vector that has a DM attached");
205: }
206: PetscCall(VecDestroy(&g));
207: }
208: PetscFunctionReturn(PETSC_SUCCESS);
209: }
211: /*@
212: DMClearLocalVectors - Destroys all the local vectors that have been stashed in this `DM`
214: Collective
216: Input Parameter:
217: . dm - the `DM`
219: Level: developer
221: .seealso: `DM`, `DMCreateLocalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
222: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMLocalToLocalBegin()`,
223: `DMLocalToLocalEnd()`, `DMLocalToLocalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`
224: `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`
225: @*/
226: PetscErrorCode DMClearLocalVectors(DM dm)
227: {
228: PetscInt i;
230: PetscFunctionBegin;
232: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
233: Vec g;
235: PetscCheck(!dm->localout[i], PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of local vectors that has a local vector obtained with DMGetLocalVector()");
236: g = dm->localin[i];
237: dm->localin[i] = NULL;
238: if (g) {
239: DM vdm;
241: PetscCall(VecGetDM(g, &vdm));
242: PetscCheck(!vdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing local vector that has a DM attached");
243: }
244: PetscCall(VecDestroy(&g));
245: }
246: PetscFunctionReturn(PETSC_SUCCESS);
247: }
249: /*@
250: DMRestoreGlobalVector - Returns a PETSc vector that
251: obtained from `DMGetGlobalVector()`. Do not use with vector obtained via
252: `DMCreateGlobalVector()`.
254: Not Collective
256: Input Parameters:
257: + dm - the `DM`
258: - g - the global vector
260: Level: beginner
262: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
263: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToGlobalBegin()`,
264: `DMGlobalToGlobalEnd()`, `DMGlobalToGlobal()`, `DMCreateLocalVector()`, `DMGetGlobalVector()`
265: @*/
266: PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g)
267: {
268: PetscInt i, j;
270: PetscFunctionBegin;
273: PetscCall(VecSetErrorIfLocked(*g, 2));
274: for (j = 0; j < DM_MAX_WORK_VECTORS; j++) {
275: if (*g == dm->globalout[j]) {
276: DM vdm;
278: PetscCall(VecGetDM(*g, &vdm));
279: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
280: PetscCall(VecSetDM(*g, NULL));
281: dm->globalout[j] = NULL;
282: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
283: if (!dm->globalin[i]) {
284: dm->globalin[i] = *g;
285: goto alldone;
286: }
287: }
288: }
289: }
290: PetscCall(VecDestroy(g));
291: alldone:
292: *g = NULL;
293: PetscFunctionReturn(PETSC_SUCCESS);
294: }
296: /*@C
297: DMHasNamedGlobalVector - check for a named, persistent global vector
299: Not Collective
301: Input Parameters:
302: + dm - `DM` to hold named vectors
303: - name - unique name for `Vec`
305: Output Parameter:
306: . exists - true if the vector was previously created
308: Level: developer
310: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
311: @*/
312: PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
313: {
314: DMNamedVecLink link;
316: PetscFunctionBegin;
320: *exists = PETSC_FALSE;
321: for (link = dm->namedglobal; link; link = link->next) {
322: PetscBool match;
323: PetscCall(PetscStrcmp(name, link->name, &match));
324: if (match) {
325: *exists = PETSC_TRUE;
326: break;
327: }
328: }
329: PetscFunctionReturn(PETSC_SUCCESS);
330: }
332: /*@C
333: DMGetNamedGlobalVector - get access to a named, persistent global vector
335: Collective
337: Input Parameters:
338: + dm - `DM` to hold named vectors
339: - name - unique name for `Vec`
341: Output Parameter:
342: . X - named `Vec`
344: Level: developer
346: Note:
347: If a `Vec` with the given name does not exist, it is created.
349: .seealso: `DM`, `DMRestoreNamedGlobalVector()`
350: @*/
351: PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
352: {
353: DMNamedVecLink link;
355: PetscFunctionBegin;
359: for (link = dm->namedglobal; link; link = link->next) {
360: PetscBool match;
362: PetscCall(PetscStrcmp(name, link->name, &match));
363: if (match) {
364: DM vdm;
366: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
367: PetscCall(VecGetDM(link->X, &vdm));
368: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
369: PetscCall(VecSetDM(link->X, dm));
370: goto found;
371: }
372: }
374: /* Create the Vec */
375: PetscCall(PetscNew(&link));
376: PetscCall(PetscStrallocpy(name, &link->name));
377: PetscCall(DMCreateGlobalVector(dm, &link->X));
378: link->next = dm->namedglobal;
379: dm->namedglobal = link;
381: found:
382: *X = link->X;
383: link->status = DMVEC_STATUS_OUT;
384: PetscFunctionReturn(PETSC_SUCCESS);
385: }
387: /*@C
388: DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
390: Collective
392: Input Parameters:
393: + dm - `DM` on which the vector was gotten
394: . name - name under which the vector was gotten
395: - X - `Vec` to restore
397: Level: developer
399: .seealso: `DM`, `DMGetNamedGlobalVector()`
400: @*/
401: PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
402: {
403: DMNamedVecLink link;
405: PetscFunctionBegin;
410: for (link = dm->namedglobal; link; link = link->next) {
411: PetscBool match;
413: PetscCall(PetscStrcmp(name, link->name, &match));
414: if (match) {
415: DM vdm;
417: PetscCall(VecGetDM(*X, &vdm));
418: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
419: PetscCheck(link->X == *X, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Attempt to restore Vec name '%s', but Vec does not match the cache", name);
420: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
422: link->status = DMVEC_STATUS_IN;
423: PetscCall(VecSetDM(link->X, NULL));
424: *X = NULL;
425: PetscFunctionReturn(PETSC_SUCCESS);
426: }
427: }
428: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
429: }
431: /*@C
432: DMHasNamedLocalVector - check for a named, persistent local vector
434: Not Collective
436: Input Parameters:
437: + dm - `DM` to hold named vectors
438: - name - unique name for `Vec`
440: Output Parameter:
441: . exists - true if the vector was previously created
443: Level: developer
445: Note:
446: If a `Vec` with the given name does not exist, it is created.
448: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
449: @*/
450: PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists)
451: {
452: DMNamedVecLink link;
454: PetscFunctionBegin;
458: *exists = PETSC_FALSE;
459: for (link = dm->namedlocal; link; link = link->next) {
460: PetscBool match;
461: PetscCall(PetscStrcmp(name, link->name, &match));
462: if (match) {
463: *exists = PETSC_TRUE;
464: break;
465: }
466: }
467: PetscFunctionReturn(PETSC_SUCCESS);
468: }
470: /*@C
471: DMGetNamedLocalVector - get access to a named, persistent local vector
473: Not Collective
475: Input Parameters:
476: + dm - `DM` to hold named vectors
477: - name - unique name for `Vec`
479: Output Parameter:
480: . X - named `Vec`
482: Level: developer
484: Note:
485: If a `Vec` with the given name does not exist, it is created.
487: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
488: @*/
489: PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
490: {
491: DMNamedVecLink link;
493: PetscFunctionBegin;
497: for (link = dm->namedlocal; link; link = link->next) {
498: PetscBool match;
500: PetscCall(PetscStrcmp(name, link->name, &match));
501: if (match) {
502: DM vdm;
504: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
505: PetscCall(VecGetDM(link->X, &vdm));
506: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
507: PetscCall(VecSetDM(link->X, dm));
508: goto found;
509: }
510: }
512: /* Create the Vec */
513: PetscCall(PetscNew(&link));
514: PetscCall(PetscStrallocpy(name, &link->name));
515: PetscCall(DMCreateLocalVector(dm, &link->X));
516: link->next = dm->namedlocal;
517: dm->namedlocal = link;
519: found:
520: *X = link->X;
521: link->status = DMVEC_STATUS_OUT;
522: PetscFunctionReturn(PETSC_SUCCESS);
523: }
525: /*@C
526: DMRestoreNamedLocalVector - restore access to a named, persistent local vector
528: Not Collective
530: Input Parameters:
531: + dm - `DM` on which the vector was gotten
532: . name - name under which the vector was gotten
533: - X - `Vec` to restore
535: Level: developer
537: .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`
538: @*/
539: PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
540: {
541: DMNamedVecLink link;
543: PetscFunctionBegin;
548: for (link = dm->namedlocal; link; link = link->next) {
549: PetscBool match;
551: PetscCall(PetscStrcmp(name, link->name, &match));
552: if (match) {
553: DM vdm;
555: PetscCall(VecGetDM(*X, &vdm));
556: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
557: PetscCheck(link->X == *X, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Attempt to restore Vec name '%s', but Vec does not match the cache", name);
558: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
560: link->status = DMVEC_STATUS_IN;
561: PetscCall(VecSetDM(link->X, NULL));
562: *X = NULL;
563: PetscFunctionReturn(PETSC_SUCCESS);
564: }
565: }
566: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
567: }