xref: /petsc/src/dm/interface/dmget.c (revision 0baf8eba40dbc839082666f9f7396a225d6f663c)
1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
2 
3 /*@
4   DMGetLocalVector - Gets a PETSc vector that may be used with the `DM` local routines. This vector has spaces for the ghost values.
5 
6   Not Collective
7 
8   Input Parameter:
9 . dm - the `DM`
10 
11   Output Parameter:
12 . g - the local vector
13 
14   Level: beginner
15 
16   Note:
17   The vector values are NOT initialized and may have garbage in them, so you may need
18   to zero them.
19 
20   The output parameter, `g`, is a regular PETSc vector that should be returned with
21   `DMRestoreLocalVector()` DO NOT call `VecDestroy()` on it.
22 
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()`.
26 
27   VecStride*() operations can be useful when using `DM` with dof > 1
28 
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;
37   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38   PetscAssertPointer(g, 2);
39   for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) {
40     if (dm->localin[i]) {
41       DM vdm;
42 
43       *g             = dm->localin[i];
44       dm->localin[i] = NULL;
45 
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));
53 
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 }
63 
64 /*@
65   DMRestoreLocalVector - Returns a PETSc vector that was
66   obtained from `DMGetLocalVector()`. Do not use with vector obtained via
67   `DMCreateLocalVector()`.
68 
69   Not Collective
70 
71   Input Parameters:
72 + dm - the `DM`
73 - g  - the local vector
74 
75   Level: beginner
76 
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;
84 
85   PetscFunctionBegin;
86   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87   PetscAssertPointer(g, 2);
88   for (j = 0; j < DM_MAX_WORK_VECTORS; j++) {
89     if (*g == dm->localout[j]) {
90       DM vdm;
91 
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 }
109 
110 /*@
111   DMGetGlobalVector - Gets a PETSc vector that may be used with the `DM` global routines.
112 
113   Collective
114 
115   Input Parameter:
116 . dm - the `DM`
117 
118   Output Parameter:
119 . g - the global vector
120 
121   Level: beginner
122 
123   Note:
124   The vector values are NOT initialized and may have garbage in them, so you may need
125   to zero them.
126 
127   The output parameter, `g`, is a regular PETSc vector that should be returned with
128   `DMRestoreGlobalVector()` DO NOT call `VecDestroy()` on it.
129 
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()`.
133 
134   VecStride*() operations can be useful when using `DM` with dof > 1
135 
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;
144 
145   PetscFunctionBegin;
146   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
147   PetscAssertPointer(g, 2);
148   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
149     if (dm->globalin[i]) {
150       DM vdm;
151 
152       *g              = dm->globalin[i];
153       dm->globalin[i] = NULL;
154 
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));
162 
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 }
172 
173 /*@
174   DMClearGlobalVectors - Destroys all the global vectors that have been created for `DMGetGlobalVector()` calls in this `DM`
175 
176   Collective
177 
178   Input Parameter:
179 . dm - the `DM`
180 
181   Level: developer
182 
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;
191 
192   PetscFunctionBegin;
193   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
194   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
195     Vec g;
196 
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;
202 
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 }
210 
211 /*@
212   DMClearLocalVectors - Destroys all the local vectors that have been created for `DMGetLocalVector()` calls in this `DM`
213 
214   Collective
215 
216   Input Parameter:
217 . dm - the `DM`
218 
219   Level: developer
220 
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;
229 
230   PetscFunctionBegin;
231   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
232   for (i = 0; i < DM_MAX_WORK_VECTORS; i++) {
233     Vec g;
234 
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;
240 
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 }
248 
249 /*@
250   DMRestoreGlobalVector - Returns a PETSc vector that
251   obtained from `DMGetGlobalVector()`. Do not use with vector obtained via
252   `DMCreateGlobalVector()`.
253 
254   Not Collective
255 
256   Input Parameters:
257 + dm - the `DM`
258 - g  - the global vector
259 
260   Level: beginner
261 
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;
269 
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
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;
277 
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 }
295 
296 /*@
297   DMClearNamedGlobalVectors - Destroys all the named global vectors that have been created with `DMGetNamedGlobalVector()` in this `DM`
298 
299   Collective
300 
301   Input Parameter:
302 . dm - the `DM`
303 
304   Level: developer
305 
306 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
307 @*/
308 PetscErrorCode DMClearNamedGlobalVectors(DM dm)
309 {
310   DMNamedVecLink nnext;
311 
312   PetscFunctionBegin;
313   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
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 }
325 
326 /*@
327   DMClearNamedLocalVectors - Destroys all the named local vectors that have been created with `DMGetNamedLocalVector()` in this `DM`
328 
329   Collective
330 
331   Input Parameter:
332 . dm - the `DM`
333 
334   Level: developer
335 
336 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedGlobalVectors()`
337 @*/
338 PetscErrorCode DMClearNamedLocalVectors(DM dm)
339 {
340   DMNamedVecLink nnext;
341 
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
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 }
355 
356 /*@
357   DMHasNamedGlobalVector - check for a named, persistent global vector created with `DMGetNamedGlobalVector()`
358 
359   Not Collective
360 
361   Input Parameters:
362 + dm   - `DM` to hold named vectors
363 - name - unique name for `Vec`
364 
365   Output Parameter:
366 . exists - true if the vector was previously created
367 
368   Level: developer
369 
370 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedGlobalVectors()`
371 @*/
372 PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists)
373 {
374   DMNamedVecLink link;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
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 }
391 
392 /*@
393   DMGetNamedGlobalVector - get access to a named, persistent global vector
394 
395   Collective
396 
397   Input Parameters:
398 + dm   - `DM` to hold named vectors
399 - name - unique name for `X`
400 
401   Output Parameter:
402 . X - named `Vec`
403 
404   Level: developer
405 
406   Note:
407   If a `Vec` with the given name does not exist, it is created.
408 
409 .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMHasNamedGlobalVector()`, `DMClearNamedGlobalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
410 @*/
411 PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X)
412 {
413   DMNamedVecLink link;
414 
415   PetscFunctionBegin;
416   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
417   PetscAssertPointer(name, 2);
418   PetscAssertPointer(X, 3);
419   for (link = dm->namedglobal; link; link = link->next) {
420     PetscBool match;
421 
422     PetscCall(PetscStrcmp(name, link->name, &match));
423     if (match) {
424       DM vdm;
425 
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   }
433 
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;
440 
441 found:
442   *X           = link->X;
443   link->status = DMVEC_STATUS_OUT;
444   PetscFunctionReturn(PETSC_SUCCESS);
445 }
446 
447 /*@
448   DMRestoreNamedGlobalVector - restore access to a named, persistent global vector
449 
450   Collective
451 
452   Input Parameters:
453 + dm   - `DM` on which `X` was gotten
454 . name - name under which `X` was gotten
455 - X    - `Vec` to restore
456 
457   Level: developer
458 
459 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMClearNamedGlobalVectors()`
460 @*/
461 PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X)
462 {
463   DMNamedVecLink link;
464 
465   PetscFunctionBegin;
466   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
467   PetscAssertPointer(name, 2);
468   PetscAssertPointer(X, 3);
469   PetscValidHeaderSpecific(*X, VEC_CLASSID, 3);
470   for (link = dm->namedglobal; link; link = link->next) {
471     PetscBool match;
472 
473     PetscCall(PetscStrcmp(name, link->name, &match));
474     if (match) {
475       DM vdm;
476 
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");
481 
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 }
490 
491 /*@
492   DMHasNamedLocalVector - check for a named, persistent local vector created with `DMGetNamedLocalVector()`
493 
494   Not Collective
495 
496   Input Parameters:
497 + dm   - `DM` to hold named vectors
498 - name - unique name for `Vec`
499 
500   Output Parameter:
501 . exists - true if the vector was previously created
502 
503   Level: developer
504 
505   Note:
506   If a `Vec` with the given name does not exist, it is created.
507 
508 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedLocalVectors()`
509 @*/
510 PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists)
511 {
512   DMNamedVecLink link;
513 
514   PetscFunctionBegin;
515   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
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 }
529 
530 /*@
531   DMGetNamedLocalVector - get access to a named, persistent local vector
532 
533   Not Collective
534 
535   Input Parameters:
536 + dm   - `DM` to hold named vectors
537 - name - unique name for `X`
538 
539   Output Parameter:
540 . X - named `Vec`
541 
542   Level: developer
543 
544   Note:
545   If a `Vec` with the given name does not exist, it is created.
546 
547 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMHasNamedLocalVector()`, `DMClearNamedLocalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()`
548 @*/
549 PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X)
550 {
551   DMNamedVecLink link;
552 
553   PetscFunctionBegin;
554   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
555   PetscAssertPointer(name, 2);
556   PetscAssertPointer(X, 3);
557   for (link = dm->namedlocal; link; link = link->next) {
558     PetscBool match;
559 
560     PetscCall(PetscStrcmp(name, link->name, &match));
561     if (match) {
562       DM vdm;
563 
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   }
571 
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;
578 
579 found:
580   *X           = link->X;
581   link->status = DMVEC_STATUS_OUT;
582   PetscFunctionReturn(PETSC_SUCCESS);
583 }
584 
585 /*@
586   DMRestoreNamedLocalVector - restore access to a named, persistent local vector obtained with `DMGetNamedLocalVector()`
587 
588   Not Collective
589 
590   Input Parameters:
591 + dm   - `DM` on which `X` was gotten
592 . name - name under which `X` was gotten
593 - X    - `Vec` to restore
594 
595   Level: developer
596 
597 .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()`
598 @*/
599 PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X)
600 {
601   DMNamedVecLink link;
602 
603   PetscFunctionBegin;
604   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
605   PetscAssertPointer(name, 2);
606   PetscAssertPointer(X, 3);
607   PetscValidHeaderSpecific(*X, VEC_CLASSID, 3);
608   for (link = dm->namedlocal; link; link = link->next) {
609     PetscBool match;
610 
611     PetscCall(PetscStrcmp(name, link->name, &match));
612     if (match) {
613       DM vdm;
614 
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");
619 
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 }
628