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: PetscInt i;
230: PetscFunctionBegin;
232: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
233: Vec g;
235: PetscCheck(!dm->localout[i], PETSC_COMM_SELF, 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, PETSC_COMM_SELF, 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()`, `DMClearGlobalVectors()`
265: @*/
266: PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g)
267: {
268: PetscInt i, j;
270: PetscFunctionBegin;
272: PetscAssertPointer(g, 2);
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: /*@
297: DMClearNamedGlobalVectors - Destroys all the named global vectors that have been created with `DMGetNamedGlobalVector()` in this `DM`
299: Collective
301: Input Parameter:
302: . dm - the `DM`
304: Level: developer
306: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
307: @*/
308: PetscErrorCode DMClearNamedGlobalVectors(DM dm)
309: {
310: DMNamedVecLink nnext;
312: PetscFunctionBegin;
314: nnext = dm->namedglobal;
315: dm->namedglobal = NULL;
316: for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
317: nnext = nlink->next;
318: PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has global Vec named '%s' checked out", nlink->name);
319: PetscCall(PetscFree(nlink->name));
320: PetscCall(VecDestroy(&nlink->X));
321: PetscCall(PetscFree(nlink));
322: }
323: PetscFunctionReturn(PETSC_SUCCESS);
324: }
326: /*@
327: DMClearNamedLocalVectors - Destroys all the named local vectors that have been created with `DMGetNamedLocalVector()` in this `DM`
329: Collective
331: Input Parameter:
332: . dm - the `DM`
334: Level: developer
336: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedGlobalVectors()`
337: @*/
338: PetscErrorCode DMClearNamedLocalVectors(DM dm)
339: {
340: DMNamedVecLink nnext;
342: PetscFunctionBegin;
344: nnext = dm->namedlocal;
345: dm->namedlocal = NULL;
346: for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
347: nnext = nlink->next;
348: PetscCheck(nlink->status == DMVEC_STATUS_IN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM still has local Vec named '%s' checked out", nlink->name);
349: PetscCall(PetscFree(nlink->name));
350: PetscCall(VecDestroy(&nlink->X));
351: PetscCall(PetscFree(nlink));
352: }
353: PetscFunctionReturn(PETSC_SUCCESS);
354: }
356: /*@
357: DMHasNamedGlobalVector - check for a named, persistent global vector created with `DMGetNamedGlobalVector()`
359: Not Collective
361: Input Parameters:
362: + dm - `DM` to hold named vectors
363: - name - unique name for `Vec`
365: Output Parameter:
366: . exists - true if the vector was previously created
368: Level: developer
370: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedGlobalVectors()`
371: @*/
372: PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
373: {
374: DMNamedVecLink link;
376: PetscFunctionBegin;
378: PetscAssertPointer(name, 2);
379: PetscAssertPointer(exists, 3);
380: *exists = PETSC_FALSE;
381: for (link = dm->namedglobal; link; link = link->next) {
382: PetscBool match;
383: PetscCall(PetscStrcmp(name, link->name, &match));
384: if (match) {
385: *exists = PETSC_TRUE;
386: break;
387: }
388: }
389: PetscFunctionReturn(PETSC_SUCCESS);
390: }
392: /*@
393: DMGetNamedGlobalVector - get access to a named, persistent global vector
395: Collective
397: Input Parameters:
398: + dm - `DM` to hold named vectors
399: - name - unique name for `X`
401: Output Parameter:
402: . X - named `Vec`
404: Level: developer
406: Note:
407: If a `Vec` with the given name does not exist, it is created.
409: .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMHasNamedGlobalVector()`, `DMClearNamedGlobalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
410: @*/
411: PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
412: {
413: DMNamedVecLink link;
415: PetscFunctionBegin;
417: PetscAssertPointer(name, 2);
418: PetscAssertPointer(X, 3);
419: for (link = dm->namedglobal; link; link = link->next) {
420: PetscBool match;
422: PetscCall(PetscStrcmp(name, link->name, &match));
423: if (match) {
424: DM vdm;
426: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
427: PetscCall(VecGetDM(link->X, &vdm));
428: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
429: PetscCall(VecSetDM(link->X, dm));
430: goto found;
431: }
432: }
434: /* Create the Vec */
435: PetscCall(PetscNew(&link));
436: PetscCall(PetscStrallocpy(name, &link->name));
437: PetscCall(DMCreateGlobalVector(dm, &link->X));
438: link->next = dm->namedglobal;
439: dm->namedglobal = link;
441: found:
442: *X = link->X;
443: link->status = DMVEC_STATUS_OUT;
444: PetscFunctionReturn(PETSC_SUCCESS);
445: }
447: /*@
448: DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
450: Collective
452: Input Parameters:
453: + dm - `DM` on which `X` was gotten
454: . name - name under which `X` was gotten
455: - X - `Vec` to restore
457: Level: developer
459: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMClearNamedGlobalVectors()`
460: @*/
461: PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
462: {
463: DMNamedVecLink link;
465: PetscFunctionBegin;
467: PetscAssertPointer(name, 2);
468: PetscAssertPointer(X, 3);
470: for (link = dm->namedglobal; link; link = link->next) {
471: PetscBool match;
473: PetscCall(PetscStrcmp(name, link->name, &match));
474: if (match) {
475: DM vdm;
477: PetscCall(VecGetDM(*X, &vdm));
478: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
479: 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);
480: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
482: link->status = DMVEC_STATUS_IN;
483: PetscCall(VecSetDM(link->X, NULL));
484: *X = NULL;
485: PetscFunctionReturn(PETSC_SUCCESS);
486: }
487: }
488: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
489: }
491: /*@
492: DMHasNamedLocalVector - check for a named, persistent local vector created with `DMGetNamedLocalVector()`
494: Not Collective
496: Input Parameters:
497: + dm - `DM` to hold named vectors
498: - name - unique name for `Vec`
500: Output Parameter:
501: . exists - true if the vector was previously created
503: Level: developer
505: Note:
506: If a `Vec` with the given name does not exist, it is created.
508: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedLocalVectors()`
509: @*/
510: PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists)
511: {
512: DMNamedVecLink link;
514: PetscFunctionBegin;
516: PetscAssertPointer(name, 2);
517: PetscAssertPointer(exists, 3);
518: *exists = PETSC_FALSE;
519: for (link = dm->namedlocal; link; link = link->next) {
520: PetscBool match;
521: PetscCall(PetscStrcmp(name, link->name, &match));
522: if (match) {
523: *exists = PETSC_TRUE;
524: break;
525: }
526: }
527: PetscFunctionReturn(PETSC_SUCCESS);
528: }
530: /*@
531: DMGetNamedLocalVector - get access to a named, persistent local vector
533: Not Collective
535: Input Parameters:
536: + dm - `DM` to hold named vectors
537: - name - unique name for `X`
539: Output Parameter:
540: . X - named `Vec`
542: Level: developer
544: Note:
545: If a `Vec` with the given name does not exist, it is created.
547: .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMHasNamedLocalVector()`, `DMClearNamedLocalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
548: @*/
549: PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
550: {
551: DMNamedVecLink link;
553: PetscFunctionBegin;
555: PetscAssertPointer(name, 2);
556: PetscAssertPointer(X, 3);
557: for (link = dm->namedlocal; link; link = link->next) {
558: PetscBool match;
560: PetscCall(PetscStrcmp(name, link->name, &match));
561: if (match) {
562: DM vdm;
564: PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name);
565: PetscCall(VecGetDM(link->X, &vdm));
566: PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector");
567: PetscCall(VecSetDM(link->X, dm));
568: goto found;
569: }
570: }
572: /* Create the Vec */
573: PetscCall(PetscNew(&link));
574: PetscCall(PetscStrallocpy(name, &link->name));
575: PetscCall(DMCreateLocalVector(dm, &link->X));
576: link->next = dm->namedlocal;
577: dm->namedlocal = link;
579: found:
580: *X = link->X;
581: link->status = DMVEC_STATUS_OUT;
582: PetscFunctionReturn(PETSC_SUCCESS);
583: }
585: /*@
586: DMRestoreNamedLocalVector - restore access to a named, persistent local vector obtained with `DMGetNamedLocalVector()`
588: Not Collective
590: Input Parameters:
591: + dm - `DM` on which `X` was gotten
592: . name - name under which `X` was gotten
593: - X - `Vec` to restore
595: Level: developer
597: .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
598: @*/
599: PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
600: {
601: DMNamedVecLink link;
603: PetscFunctionBegin;
605: PetscAssertPointer(name, 2);
606: PetscAssertPointer(X, 3);
608: for (link = dm->namedlocal; link; link = link->next) {
609: PetscBool match;
611: PetscCall(PetscStrcmp(name, link->name, &match));
612: if (match) {
613: DM vdm;
615: PetscCall(VecGetDM(*X, &vdm));
616: PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name);
617: 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);
618: PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector");
620: link->status = DMVEC_STATUS_IN;
621: PetscCall(VecSetDM(link->X, NULL));
622: *X = NULL;
623: PetscFunctionReturn(PETSC_SUCCESS);
624: }
625: }
626: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name);
627: }