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