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: `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`, `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`, `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 on dm
178: Input Parameter:
179: . dm - the dm
181: Level: developer
183: .seealso: `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 on dm
216: Input Parameter:
217: . dm - the dm
219: Level: developer
221: .seealso: `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: `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: Note: If a Vec with the given name does not exist, it is created.
312: .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
313: @*/
314: PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
315: {
316: DMNamedVecLink link;
318: PetscFunctionBegin;
322: *exists = PETSC_FALSE;
323: for (link = dm->namedglobal; link; link = link->next) {
324: PetscBool match;
325: PetscCall(PetscStrcmp(name, link->name, &match));
326: if (match) {
327: *exists = PETSC_TRUE;
328: break;
329: }
330: }
331: PetscFunctionReturn(PETSC_SUCCESS);
332: }
334: /*@C
335: DMGetNamedGlobalVector - get access to a named, persistent global vector
337: Collective on dm
339: Input Parameters:
340: + dm - DM to hold named vectors
341: - name - unique name for Vec
343: Output Parameter:
344: . X - named Vec
346: Level: developer
348: Note: If a Vec with the given name does not exist, it is created.
350: .seealso: `DMRestoreNamedGlobalVector()`
351: @*/
352: PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
353: {
354: DMNamedVecLink link;
356: PetscFunctionBegin;
360: for (link = dm->namedglobal; link; link = link->next) {
361: PetscBool match;
363: PetscCall(PetscStrcmp(name, link->name, &match));
364: if (match) {
365: DM vdm;
367: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
368: PetscCall(VecGetDM(link->X, &vdm));
369: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
370: PetscCall(VecSetDM(link->X, dm));
371: goto found;
372: }
373: }
375: /* Create the Vec */
376: PetscCall(PetscNew(&link));
377: PetscCall(PetscStrallocpy(name, &link->name));
378: PetscCall(DMCreateGlobalVector(dm, &link->X));
379: link->next = dm->namedglobal;
380: dm->namedglobal = link;
382: found:
383: *X = link->X;
384: link->status = DMVEC_STATUS_OUT;
385: PetscFunctionReturn(PETSC_SUCCESS);
386: }
388: /*@C
389: DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
391: Collective on dm
393: Input Parameters:
394: + dm - DM on which the vector was gotten
395: . name - name under which the vector was gotten
396: - X - Vec to restore
398: Level: developer
400: .seealso: `DMGetNamedGlobalVector()`
401: @*/
402: PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
403: {
404: DMNamedVecLink link;
406: PetscFunctionBegin;
411: for (link = dm->namedglobal; link; link = link->next) {
412: PetscBool match;
414: PetscCall(PetscStrcmp(name, link->name, &match));
415: if (match) {
416: DM vdm;
418: PetscCall(VecGetDM(*X, &vdm));
419: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
420: 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);
421: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
423: link->status = DMVEC_STATUS_IN;
424: PetscCall(VecSetDM(link->X, NULL));
425: *X = NULL;
426: PetscFunctionReturn(PETSC_SUCCESS);
427: }
428: }
429: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
430: }
432: /*@C
433: DMHasNamedLocalVector - check for a named, persistent local vector
435: Not Collective
437: Input Parameters:
438: + dm - DM to hold named vectors
439: - name - unique name for Vec
441: Output Parameter:
442: . exists - true if the vector was previously created
444: Level: developer
446: Note: If a Vec with the given name does not exist, it is created.
448: .seealso: `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: If a Vec with the given name does not exist, it is created.
486: .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`
487: @*/
488: PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
489: {
490: DMNamedVecLink link;
492: PetscFunctionBegin;
496: for (link = dm->namedlocal; link; link = link->next) {
497: PetscBool match;
499: PetscCall(PetscStrcmp(name, link->name, &match));
500: if (match) {
501: DM vdm;
503: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
504: PetscCall(VecGetDM(link->X, &vdm));
505: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
506: PetscCall(VecSetDM(link->X, dm));
507: goto found;
508: }
509: }
511: /* Create the Vec */
512: PetscCall(PetscNew(&link));
513: PetscCall(PetscStrallocpy(name, &link->name));
514: PetscCall(DMCreateLocalVector(dm, &link->X));
515: link->next = dm->namedlocal;
516: dm->namedlocal = link;
518: found:
519: *X = link->X;
520: link->status = DMVEC_STATUS_OUT;
521: PetscFunctionReturn(PETSC_SUCCESS);
522: }
524: /*@C
525: DMRestoreNamedLocalVector - restore access to a named, persistent local vector
527: Not Collective
529: Input Parameters:
530: + dm - DM on which the vector was gotten
531: . name - name under which the vector was gotten
532: - X - Vec to restore
534: Level: developer
536: .seealso: `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`
537: @*/
538: PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
539: {
540: DMNamedVecLink link;
542: PetscFunctionBegin;
547: for (link = dm->namedlocal; link; link = link->next) {
548: PetscBool match;
550: PetscCall(PetscStrcmp(name, link->name, &match));
551: if (match) {
552: DM vdm;
554: PetscCall(VecGetDM(*X, &vdm));
555: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
556: 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);
557: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
559: link->status = DMVEC_STATUS_IN;
560: PetscCall(VecSetDM(link->X, NULL));
561: *X = NULL;
562: PetscFunctionReturn(PETSC_SUCCESS);
563: }
564: }
565: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
566: }