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 @*/
DMGetLocalVector(DM dm,Vec * g)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 @*/
DMRestoreLocalVector(DM dm,Vec * g)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 @*/
DMGetGlobalVector(DM dm,Vec * g)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 @*/
DMClearGlobalVectors(DM dm)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 @*/
DMClearLocalVectors(DM dm)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 @*/
DMRestoreGlobalVector(DM dm,Vec * g)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 @*/
DMClearNamedGlobalVectors(DM dm)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 @*/
DMClearNamedLocalVectors(DM dm)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 @*/
DMHasNamedGlobalVector(DM dm,const char * name,PetscBool * exists)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 @*/
DMGetNamedGlobalVector(DM dm,const char * name,Vec * X)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 @*/
DMRestoreNamedGlobalVector(DM dm,const char * name,Vec * X)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 @*/
DMHasNamedLocalVector(DM dm,const char * name,PetscBool * exists)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 @*/
DMGetNamedLocalVector(DM dm,const char * name,Vec * X)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 @*/
DMRestoreNamedLocalVector(DM dm,const char * name,Vec * X)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