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()` 33 @*/ 34 PetscErrorCode DMGetLocalVector(DM dm, Vec *g) 35 { 36 PetscFunctionBegin; 37 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38 PetscValidPointer(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`, `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, 78 `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, 79 `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMGetLocalVector()` 80 @*/ 81 PetscErrorCode DMRestoreLocalVector(DM dm, Vec *g) 82 { 83 PetscInt i, j; 84 85 PetscFunctionBegin; 86 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87 PetscValidPointer(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 on dm 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`, `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, 137 `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, 138 `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()` 139 `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()` 140 @*/ 141 PetscErrorCode DMGetGlobalVector(DM dm, Vec *g) 142 { 143 PetscInt i; 144 145 PetscFunctionBegin; 146 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 147 PetscValidPointer(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 stashed 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()` 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 stashed 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()`, `DMLocalToLocalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()` 224 `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()` 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], PetscObjectComm((PetscObject)dm), 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, PetscObjectComm((PetscObject)dm), 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()` 265 @*/ 266 PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g) 267 { 268 PetscInt i, j; 269 270 PetscFunctionBegin; 271 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 272 PetscValidPointer(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 /*@C 297 DMHasNamedGlobalVector - check for a named, persistent global vector 298 299 Not Collective 300 301 Input Parameters: 302 + dm - `DM` to hold named vectors 303 - name - unique name for `Vec` 304 305 Output Parameter: 306 . exists - true if the vector was previously created 307 308 Level: developer 309 310 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 311 @*/ 312 PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists) 313 { 314 DMNamedVecLink link; 315 316 PetscFunctionBegin; 317 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 318 PetscValidCharPointer(name, 2); 319 PetscValidBoolPointer(exists, 3); 320 *exists = PETSC_FALSE; 321 for (link = dm->namedglobal; link; link = link->next) { 322 PetscBool match; 323 PetscCall(PetscStrcmp(name, link->name, &match)); 324 if (match) { 325 *exists = PETSC_TRUE; 326 break; 327 } 328 } 329 PetscFunctionReturn(PETSC_SUCCESS); 330 } 331 332 /*@C 333 DMGetNamedGlobalVector - get access to a named, persistent global vector 334 335 Collective 336 337 Input Parameters: 338 + dm - `DM` to hold named vectors 339 - name - unique name for `Vec` 340 341 Output Parameter: 342 . X - named `Vec` 343 344 Level: developer 345 346 Note: 347 If a `Vec` with the given name does not exist, it is created. 348 349 .seealso: `DM`, `DMRestoreNamedGlobalVector()` 350 @*/ 351 PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X) 352 { 353 DMNamedVecLink link; 354 355 PetscFunctionBegin; 356 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 357 PetscValidCharPointer(name, 2); 358 PetscValidPointer(X, 3); 359 for (link = dm->namedglobal; link; link = link->next) { 360 PetscBool match; 361 362 PetscCall(PetscStrcmp(name, link->name, &match)); 363 if (match) { 364 DM vdm; 365 366 PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); 367 PetscCall(VecGetDM(link->X, &vdm)); 368 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 369 PetscCall(VecSetDM(link->X, dm)); 370 goto found; 371 } 372 } 373 374 /* Create the Vec */ 375 PetscCall(PetscNew(&link)); 376 PetscCall(PetscStrallocpy(name, &link->name)); 377 PetscCall(DMCreateGlobalVector(dm, &link->X)); 378 link->next = dm->namedglobal; 379 dm->namedglobal = link; 380 381 found: 382 *X = link->X; 383 link->status = DMVEC_STATUS_OUT; 384 PetscFunctionReturn(PETSC_SUCCESS); 385 } 386 387 /*@C 388 DMRestoreNamedGlobalVector - restore access to a named, persistent global vector 389 390 Collective 391 392 Input Parameters: 393 + dm - `DM` on which the vector was gotten 394 . name - name under which the vector was gotten 395 - X - `Vec` to restore 396 397 Level: developer 398 399 .seealso: `DM`, `DMGetNamedGlobalVector()` 400 @*/ 401 PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X) 402 { 403 DMNamedVecLink link; 404 405 PetscFunctionBegin; 406 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 407 PetscValidCharPointer(name, 2); 408 PetscValidPointer(X, 3); 409 PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); 410 for (link = dm->namedglobal; link; link = link->next) { 411 PetscBool match; 412 413 PetscCall(PetscStrcmp(name, link->name, &match)); 414 if (match) { 415 DM vdm; 416 417 PetscCall(VecGetDM(*X, &vdm)); 418 PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); 419 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); 420 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 421 422 link->status = DMVEC_STATUS_IN; 423 PetscCall(VecSetDM(link->X, NULL)); 424 *X = NULL; 425 PetscFunctionReturn(PETSC_SUCCESS); 426 } 427 } 428 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); 429 } 430 431 /*@C 432 DMHasNamedLocalVector - check for a named, persistent local vector 433 434 Not Collective 435 436 Input Parameters: 437 + dm - `DM` to hold named vectors 438 - name - unique name for `Vec` 439 440 Output Parameter: 441 . exists - true if the vector was previously created 442 443 Level: developer 444 445 Note: 446 If a `Vec` with the given name does not exist, it is created. 447 448 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 449 @*/ 450 PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists) 451 { 452 DMNamedVecLink link; 453 454 PetscFunctionBegin; 455 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 456 PetscValidCharPointer(name, 2); 457 PetscValidBoolPointer(exists, 3); 458 *exists = PETSC_FALSE; 459 for (link = dm->namedlocal; link; link = link->next) { 460 PetscBool match; 461 PetscCall(PetscStrcmp(name, link->name, &match)); 462 if (match) { 463 *exists = PETSC_TRUE; 464 break; 465 } 466 } 467 PetscFunctionReturn(PETSC_SUCCESS); 468 } 469 470 /*@C 471 DMGetNamedLocalVector - get access to a named, persistent local vector 472 473 Not Collective 474 475 Input Parameters: 476 + dm - `DM` to hold named vectors 477 - name - unique name for `Vec` 478 479 Output Parameter: 480 . X - named `Vec` 481 482 Level: developer 483 484 Note: 485 If a `Vec` with the given name does not exist, it is created. 486 487 .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 488 @*/ 489 PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X) 490 { 491 DMNamedVecLink link; 492 493 PetscFunctionBegin; 494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 495 PetscValidCharPointer(name, 2); 496 PetscValidPointer(X, 3); 497 for (link = dm->namedlocal; link; link = link->next) { 498 PetscBool match; 499 500 PetscCall(PetscStrcmp(name, link->name, &match)); 501 if (match) { 502 DM vdm; 503 504 PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); 505 PetscCall(VecGetDM(link->X, &vdm)); 506 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 507 PetscCall(VecSetDM(link->X, dm)); 508 goto found; 509 } 510 } 511 512 /* Create the Vec */ 513 PetscCall(PetscNew(&link)); 514 PetscCall(PetscStrallocpy(name, &link->name)); 515 PetscCall(DMCreateLocalVector(dm, &link->X)); 516 link->next = dm->namedlocal; 517 dm->namedlocal = link; 518 519 found: 520 *X = link->X; 521 link->status = DMVEC_STATUS_OUT; 522 PetscFunctionReturn(PETSC_SUCCESS); 523 } 524 525 /*@C 526 DMRestoreNamedLocalVector - restore access to a named, persistent local vector 527 528 Not Collective 529 530 Input Parameters: 531 + dm - `DM` on which the vector was gotten 532 . name - name under which the vector was gotten 533 - X - `Vec` to restore 534 535 Level: developer 536 537 .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()` 538 @*/ 539 PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X) 540 { 541 DMNamedVecLink link; 542 543 PetscFunctionBegin; 544 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 545 PetscValidCharPointer(name, 2); 546 PetscValidPointer(X, 3); 547 PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); 548 for (link = dm->namedlocal; link; link = link->next) { 549 PetscBool match; 550 551 PetscCall(PetscStrcmp(name, link->name, &match)); 552 if (match) { 553 DM vdm; 554 555 PetscCall(VecGetDM(*X, &vdm)); 556 PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); 557 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); 558 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 559 560 link->status = DMVEC_STATUS_IN; 561 PetscCall(VecSetDM(link->X, NULL)); 562 *X = NULL; 563 PetscFunctionReturn(PETSC_SUCCESS); 564 } 565 } 566 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); 567 } 568