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: `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`, `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`, `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 on dm 177 178 Input Parameter: 179 . dm - the dm 180 181 Level: developer 182 183 .seealso: `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 on dm 215 216 Input Parameter: 217 . dm - the dm 218 219 Level: developer 220 221 .seealso: `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: `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 Note: If a Vec with the given name does not exist, it is created. 311 312 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 313 @*/ 314 PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists) 315 { 316 DMNamedVecLink link; 317 318 PetscFunctionBegin; 319 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 320 PetscValidCharPointer(name, 2); 321 PetscValidBoolPointer(exists, 3); 322 *exists = PETSC_FALSE; 323 for (link = dm->namedglobal; link; link = link->next) { 324 PetscBool match; 325 PetscCall(PetscStrcmp(name, link->name, &match)); 326 if (match) { 327 *exists = PETSC_TRUE; 328 break; 329 } 330 } 331 PetscFunctionReturn(PETSC_SUCCESS); 332 } 333 334 /*@C 335 DMGetNamedGlobalVector - get access to a named, persistent global vector 336 337 Collective on dm 338 339 Input Parameters: 340 + dm - DM to hold named vectors 341 - name - unique name for Vec 342 343 Output Parameter: 344 . X - named Vec 345 346 Level: developer 347 348 Note: If a Vec with the given name does not exist, it is created. 349 350 .seealso: `DMRestoreNamedGlobalVector()` 351 @*/ 352 PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X) 353 { 354 DMNamedVecLink link; 355 356 PetscFunctionBegin; 357 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 358 PetscValidCharPointer(name, 2); 359 PetscValidPointer(X, 3); 360 for (link = dm->namedglobal; link; link = link->next) { 361 PetscBool match; 362 363 PetscCall(PetscStrcmp(name, link->name, &match)); 364 if (match) { 365 DM vdm; 366 367 PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); 368 PetscCall(VecGetDM(link->X, &vdm)); 369 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 370 PetscCall(VecSetDM(link->X, dm)); 371 goto found; 372 } 373 } 374 375 /* Create the Vec */ 376 PetscCall(PetscNew(&link)); 377 PetscCall(PetscStrallocpy(name, &link->name)); 378 PetscCall(DMCreateGlobalVector(dm, &link->X)); 379 link->next = dm->namedglobal; 380 dm->namedglobal = link; 381 382 found: 383 *X = link->X; 384 link->status = DMVEC_STATUS_OUT; 385 PetscFunctionReturn(PETSC_SUCCESS); 386 } 387 388 /*@C 389 DMRestoreNamedGlobalVector - restore access to a named, persistent global vector 390 391 Collective on dm 392 393 Input Parameters: 394 + dm - DM on which the vector was gotten 395 . name - name under which the vector was gotten 396 - X - Vec to restore 397 398 Level: developer 399 400 .seealso: `DMGetNamedGlobalVector()` 401 @*/ 402 PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X) 403 { 404 DMNamedVecLink link; 405 406 PetscFunctionBegin; 407 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 408 PetscValidCharPointer(name, 2); 409 PetscValidPointer(X, 3); 410 PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); 411 for (link = dm->namedglobal; link; link = link->next) { 412 PetscBool match; 413 414 PetscCall(PetscStrcmp(name, link->name, &match)); 415 if (match) { 416 DM vdm; 417 418 PetscCall(VecGetDM(*X, &vdm)); 419 PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); 420 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); 421 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 422 423 link->status = DMVEC_STATUS_IN; 424 PetscCall(VecSetDM(link->X, NULL)); 425 *X = NULL; 426 PetscFunctionReturn(PETSC_SUCCESS); 427 } 428 } 429 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); 430 } 431 432 /*@C 433 DMHasNamedLocalVector - check for a named, persistent local vector 434 435 Not Collective 436 437 Input Parameters: 438 + dm - DM to hold named vectors 439 - name - unique name for Vec 440 441 Output Parameter: 442 . exists - true if the vector was previously created 443 444 Level: developer 445 446 Note: If a Vec with the given name does not exist, it is created. 447 448 .seealso: `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: If a Vec with the given name does not exist, it is created. 485 486 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 487 @*/ 488 PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X) 489 { 490 DMNamedVecLink link; 491 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 494 PetscValidCharPointer(name, 2); 495 PetscValidPointer(X, 3); 496 for (link = dm->namedlocal; link; link = link->next) { 497 PetscBool match; 498 499 PetscCall(PetscStrcmp(name, link->name, &match)); 500 if (match) { 501 DM vdm; 502 503 PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); 504 PetscCall(VecGetDM(link->X, &vdm)); 505 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 506 PetscCall(VecSetDM(link->X, dm)); 507 goto found; 508 } 509 } 510 511 /* Create the Vec */ 512 PetscCall(PetscNew(&link)); 513 PetscCall(PetscStrallocpy(name, &link->name)); 514 PetscCall(DMCreateLocalVector(dm, &link->X)); 515 link->next = dm->namedlocal; 516 dm->namedlocal = link; 517 518 found: 519 *X = link->X; 520 link->status = DMVEC_STATUS_OUT; 521 PetscFunctionReturn(PETSC_SUCCESS); 522 } 523 524 /*@C 525 DMRestoreNamedLocalVector - restore access to a named, persistent local vector 526 527 Not Collective 528 529 Input Parameters: 530 + dm - DM on which the vector was gotten 531 . name - name under which the vector was gotten 532 - X - Vec to restore 533 534 Level: developer 535 536 .seealso: `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()` 537 @*/ 538 PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X) 539 { 540 DMNamedVecLink link; 541 542 PetscFunctionBegin; 543 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 544 PetscValidCharPointer(name, 2); 545 PetscValidPointer(X, 3); 546 PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); 547 for (link = dm->namedlocal; link; link = link->next) { 548 PetscBool match; 549 550 PetscCall(PetscStrcmp(name, link->name, &match)); 551 if (match) { 552 DM vdm; 553 554 PetscCall(VecGetDM(*X, &vdm)); 555 PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); 556 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); 557 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 558 559 link->status = DMVEC_STATUS_IN; 560 PetscCall(VecSetDM(link->X, NULL)); 561 *X = NULL; 562 PetscFunctionReturn(PETSC_SUCCESS); 563 } 564 } 565 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); 566 } 567