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()`, `DMClearLocalVectors()`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`
33: @*/
34: PetscErrorCode DMGetLocalVector(DM dm, Vec *g)
35: {
36: PetscFunctionBegin;
38: PetscAssertPointer(g, 2);
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()`, `DMClearLocalVectors()`
80: @*/
81: PetscErrorCode DMRestoreLocalVector(DM dm, Vec *g)
82: {
83: PetscInt i, j;
85: PetscFunctionBegin;
87: PetscAssertPointer(g, 2);
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
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()`, `DMClearGlobalVectors()`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`
140: @*/
141: PetscErrorCode DMGetGlobalVector(DM dm, Vec *g)
142: {
143: PetscInt i;
145: PetscFunctionBegin;
147: PetscAssertPointer(g, 2);
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 created for `DMGetGlobalVector()` calls 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()`, `DMClearLocalVectors()`
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 created for `DMGetLocalVector()` calls 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()`, `DMRestoreLocalVector()`,
224: `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearGlobalVectors()`
225: @*/
226: PetscErrorCode DMClearLocalVectors(DM dm)
227: {
228: PetscFunctionBegin;
230: for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
231: Vec g;
233: PetscCheck(!dm->localout[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of local vectors that has a local vector obtained with DMGetLocalVector()");
234: g = dm->localin[i];
235: dm->localin[i] = NULL;
236: if (g) {
237: DM vdm;
239: PetscCall(VecGetDM(g, &vdm));
240: PetscCheck(!vdm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Clearing local vector that has a DM attached");
241: }
242: PetscCall(VecDestroy(&g));
243: }
244: PetscFunctionReturn(PETSC_SUCCESS);
245: }
247: /*@
248: DMRestoreGlobalVector - Returns a PETSc vector that
249: obtained from `DMGetGlobalVector()`. Do not use with vector obtained via
250: `DMCreateGlobalVector()`.
252: Not Collective
254: Input Parameters:
255: + dm - the `DM`
256: - g - the global vector
258: Level: beginner
260: .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`,
261: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToGlobalBegin()`,
262: `DMGlobalToGlobalEnd()`, `DMGlobalToGlobal()`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMClearGlobalVectors()`
263: @*/
264: PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g)
265: {
266: PetscFunctionBegin;
268: PetscAssertPointer(g, 2);
269: PetscCall(VecSetErrorIfLocked(*g, 2));
270: for (PetscInt j = 0; j < DM_MAX_WORK_VECTORS; j++) {
271: if (*g == dm->globalout[j]) {
272: DM vdm;
274: PetscCall(VecGetDM(*g, &vdm));
275: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
276: PetscCall(VecSetDM(*g, NULL));
277: dm->globalout[j] = NULL;
278: for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
279: if (!dm->globalin[i]) {
280: dm->globalin[i] = *g;
281: goto alldone;
282: }
283: }
284: }
285: }
286: PetscCall(VecDestroy(g));
287: alldone:
288: *g = NULL;
289: PetscFunctionReturn(PETSC_SUCCESS);
290: }
292: /*@
293: DMClearNamedGlobalVectors - Destroys all the named global vectors that have been created with `DMGetNamedGlobalVector()` in this `DM`
295: Collective
297: Input Parameter:
298: . dm - the `DM`
300: Level: developer
302: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
303: @*/
304: PetscErrorCode DMClearNamedGlobalVectors(DM dm)
305: {
306: DMNamedVecLink nnext;
308: PetscFunctionBegin;
310: nnext = dm->namedglobal;
311: dm->namedglobal = NULL;
312: for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
313: nnext = nlink->next;
314: PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has global Vec named '%s' checked out", nlink->name);
315: PetscCall(PetscFree(nlink->name));
316: PetscCall(VecDestroy(&nlink->X));
317: PetscCall(PetscFree(nlink));
318: }
319: PetscFunctionReturn(PETSC_SUCCESS);
320: }
322: /*@
323: DMClearNamedLocalVectors - Destroys all the named local vectors that have been created with `DMGetNamedLocalVector()` in this `DM`
325: Collective
327: Input Parameter:
328: . dm - the `DM`
330: Level: developer
332: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedGlobalVectors()`
333: @*/
334: PetscErrorCode DMClearNamedLocalVectors(DM dm)
335: {
336: DMNamedVecLink nnext;
338: PetscFunctionBegin;
340: nnext = dm->namedlocal;
341: dm->namedlocal = NULL;
342: for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
343: nnext = nlink->next;
344: PetscCheck(nlink->status == DMVEC_STATUS_IN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM still has local Vec named '%s' checked out", nlink->name);
345: PetscCall(PetscFree(nlink->name));
346: PetscCall(VecDestroy(&nlink->X));
347: PetscCall(PetscFree(nlink));
348: }
349: PetscFunctionReturn(PETSC_SUCCESS);
350: }
352: /*@
353: DMHasNamedGlobalVector - check for a named, persistent global vector created with `DMGetNamedGlobalVector()`
355: Not Collective
357: Input Parameters:
358: + dm - `DM` to hold named vectors
359: - name - unique name for `Vec`
361: Output Parameter:
362: . exists - true if the vector was previously created
364: Level: developer
366: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedGlobalVectors()`
367: @*/
368: PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
369: {
370: DMNamedVecLink link;
372: PetscFunctionBegin;
374: PetscAssertPointer(name, 2);
375: PetscAssertPointer(exists, 3);
376: *exists = PETSC_FALSE;
377: for (link = dm->namedglobal; link; link = link->next) {
378: PetscBool match;
379: PetscCall(PetscStrcmp(name, link->name, &match));
380: if (match) {
381: *exists = PETSC_TRUE;
382: break;
383: }
384: }
385: PetscFunctionReturn(PETSC_SUCCESS);
386: }
388: /*@
389: DMGetNamedGlobalVector - get access to a named, persistent global vector
391: Collective
393: Input Parameters:
394: + dm - `DM` to hold named vectors
395: - name - unique name for `X`
397: Output Parameter:
398: . X - named `Vec`
400: Level: developer
402: Note:
403: If a `Vec` with the given name does not exist, it is created.
405: .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMHasNamedGlobalVector()`, `DMClearNamedGlobalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
406: @*/
407: PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
408: {
409: DMNamedVecLink link;
411: PetscFunctionBegin;
413: PetscAssertPointer(name, 2);
414: PetscAssertPointer(X, 3);
415: for (link = dm->namedglobal; link; link = link->next) {
416: PetscBool match;
418: PetscCall(PetscStrcmp(name, link->name, &match));
419: if (match) {
420: DM vdm;
422: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
423: PetscCall(VecGetDM(link->X, &vdm));
424: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
425: PetscCall(VecSetDM(link->X, dm));
426: goto found;
427: }
428: }
430: /* Create the Vec */
431: PetscCall(PetscNew(&link));
432: PetscCall(PetscStrallocpy(name, &link->name));
433: PetscCall(DMCreateGlobalVector(dm, &link->X));
434: link->next = dm->namedglobal;
435: dm->namedglobal = link;
437: found:
438: *X = link->X;
439: link->status = DMVEC_STATUS_OUT;
440: PetscFunctionReturn(PETSC_SUCCESS);
441: }
443: /*@
444: DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
446: Collective
448: Input Parameters:
449: + dm - `DM` on which `X` was gotten
450: . name - name under which `X` was gotten
451: - X - `Vec` to restore
453: Level: developer
455: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMClearNamedGlobalVectors()`
456: @*/
457: PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
458: {
459: DMNamedVecLink link;
461: PetscFunctionBegin;
463: PetscAssertPointer(name, 2);
464: PetscAssertPointer(X, 3);
466: for (link = dm->namedglobal; link; link = link->next) {
467: PetscBool match;
469: PetscCall(PetscStrcmp(name, link->name, &match));
470: if (match) {
471: DM vdm;
473: PetscCall(VecGetDM(*X, &vdm));
474: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
475: 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);
476: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
478: link->status = DMVEC_STATUS_IN;
479: PetscCall(VecSetDM(link->X, NULL));
480: *X = NULL;
481: PetscFunctionReturn(PETSC_SUCCESS);
482: }
483: }
484: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
485: }
487: /*@
488: DMHasNamedLocalVector - check for a named, persistent local vector created with `DMGetNamedLocalVector()`
490: Not Collective
492: Input Parameters:
493: + dm - `DM` to hold named vectors
494: - name - unique name for `Vec`
496: Output Parameter:
497: . exists - true if the vector was previously created
499: Level: developer
501: Note:
502: If a `Vec` with the given name does not exist, it is created.
504: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedLocalVectors()`
505: @*/
506: PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists)
507: {
508: DMNamedVecLink link;
510: PetscFunctionBegin;
512: PetscAssertPointer(name, 2);
513: PetscAssertPointer(exists, 3);
514: *exists = PETSC_FALSE;
515: for (link = dm->namedlocal; link; link = link->next) {
516: PetscBool match;
517: PetscCall(PetscStrcmp(name, link->name, &match));
518: if (match) {
519: *exists = PETSC_TRUE;
520: break;
521: }
522: }
523: PetscFunctionReturn(PETSC_SUCCESS);
524: }
526: /*@
527: DMGetNamedLocalVector - get access to a named, persistent local vector
529: Not Collective
531: Input Parameters:
532: + dm - `DM` to hold named vectors
533: - name - unique name for `X`
535: Output Parameter:
536: . X - named `Vec`
538: Level: developer
540: Note:
541: If a `Vec` with the given name does not exist, it is created.
543: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMHasNamedLocalVector()`, `DMClearNamedLocalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
544: @*/
545: PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
546: {
547: DMNamedVecLink link;
549: PetscFunctionBegin;
551: PetscAssertPointer(name, 2);
552: PetscAssertPointer(X, 3);
553: for (link = dm->namedlocal; link; link = link->next) {
554: PetscBool match;
556: PetscCall(PetscStrcmp(name, link->name, &match));
557: if (match) {
558: DM vdm;
560: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
561: PetscCall(VecGetDM(link->X, &vdm));
562: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
563: PetscCall(VecSetDM(link->X, dm));
564: goto found;
565: }
566: }
568: /* Create the Vec */
569: PetscCall(PetscNew(&link));
570: PetscCall(PetscStrallocpy(name, &link->name));
571: PetscCall(DMCreateLocalVector(dm, &link->X));
572: link->next = dm->namedlocal;
573: dm->namedlocal = link;
575: found:
576: *X = link->X;
577: link->status = DMVEC_STATUS_OUT;
578: PetscFunctionReturn(PETSC_SUCCESS);
579: }
581: /*@
582: DMRestoreNamedLocalVector - restore access to a named, persistent local vector obtained with `DMGetNamedLocalVector()`
584: Not Collective
586: Input Parameters:
587: + dm - `DM` on which `X` was gotten
588: . name - name under which `X` was gotten
589: - X - `Vec` to restore
591: Level: developer
593: .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
594: @*/
595: PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
596: {
597: DMNamedVecLink link;
599: PetscFunctionBegin;
601: PetscAssertPointer(name, 2);
602: PetscAssertPointer(X, 3);
604: for (link = dm->namedlocal; link; link = link->next) {
605: PetscBool match;
607: PetscCall(PetscStrcmp(name, link->name, &match));
608: if (match) {
609: DM vdm;
611: PetscCall(VecGetDM(*X, &vdm));
612: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
613: 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);
614: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
616: link->status = DMVEC_STATUS_IN;
617: PetscCall(VecSetDM(link->X, NULL));
618: *X = NULL;
619: PetscFunctionReturn(PETSC_SUCCESS);
620: }
621: }
622: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
623: }