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 PetscFunctionBegin; 36 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37 PetscValidPointer(g, 2); 38 for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) { 39 if (dm->localin[i]) { 40 DM vdm; 41 42 *g = dm->localin[i]; 43 dm->localin[i] = NULL; 44 45 PetscCall(VecGetDM(*g, &vdm)); 46 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 47 PetscCall(VecSetDM(*g, dm)); 48 goto alldone; 49 } 50 } 51 PetscCall(DMCreateLocalVector(dm, g)); 52 53 alldone: 54 for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) { 55 if (!dm->localout[i]) { 56 dm->localout[i] = *g; 57 break; 58 } 59 } 60 PetscFunctionReturn(0); 61 } 62 63 /*@ 64 DMRestoreLocalVector - Returns a PETSc vector that was 65 obtained from DMGetLocalVector(). Do not use with vector obtained via 66 DMCreateLocalVector(). 67 68 Not Collective 69 70 Input Parameters: 71 + dm - the dm 72 - g - the local vector 73 74 Level: beginner 75 76 .seealso: `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, 77 `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, 78 `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMGetLocalVector()` 79 @*/ 80 PetscErrorCode DMRestoreLocalVector(DM dm, Vec *g) { 81 PetscInt i, j; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85 PetscValidPointer(g, 2); 86 for (j = 0; j < DM_MAX_WORK_VECTORS; j++) { 87 if (*g == dm->localout[j]) { 88 DM vdm; 89 90 PetscCall(VecGetDM(*g, &vdm)); 91 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 92 PetscCall(VecSetDM(*g, NULL)); 93 dm->localout[j] = NULL; 94 for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { 95 if (!dm->localin[i]) { 96 dm->localin[i] = *g; 97 goto alldone; 98 } 99 } 100 } 101 } 102 PetscCall(VecDestroy(g)); 103 alldone: 104 *g = NULL; 105 PetscFunctionReturn(0); 106 } 107 108 /*@ 109 DMGetGlobalVector - Gets a PETSc vector that may be used with the DM global routines. 110 111 Collective on dm 112 113 Input Parameter: 114 . dm - the dm 115 116 Output Parameter: 117 . g - the global vector 118 119 Level: beginner 120 121 Note: 122 The vector values are NOT initialized and may have garbage in them, so you may need 123 to zero them. 124 125 The output parameter, g, is a regular PETSc vector that should be returned with 126 DMRestoreGlobalVector() DO NOT call VecDestroy() on it. 127 128 This is intended to be used for vectors you need for a short time, like within a single function call. 129 For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your 130 code you should use DMCreateGlobalVector(). 131 132 VecStride*() operations can be useful when using DM with dof > 1 133 134 .seealso: `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, 135 `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, 136 `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()` 137 `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()` 138 @*/ 139 PetscErrorCode DMGetGlobalVector(DM dm, Vec *g) { 140 PetscInt i; 141 142 PetscFunctionBegin; 143 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 144 PetscValidPointer(g, 2); 145 for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { 146 if (dm->globalin[i]) { 147 DM vdm; 148 149 *g = dm->globalin[i]; 150 dm->globalin[i] = NULL; 151 152 PetscCall(VecGetDM(*g, &vdm)); 153 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 154 PetscCall(VecSetDM(*g, dm)); 155 goto alldone; 156 } 157 } 158 PetscCall(DMCreateGlobalVector(dm, g)); 159 160 alldone: 161 for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { 162 if (!dm->globalout[i]) { 163 dm->globalout[i] = *g; 164 break; 165 } 166 } 167 PetscFunctionReturn(0); 168 } 169 170 /*@ 171 DMClearGlobalVectors - Destroys all the global vectors that have been stashed in this DM 172 173 Collective on dm 174 175 Input Parameter: 176 . dm - the dm 177 178 Level: developer 179 180 .seealso: `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, 181 `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, 182 `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()` 183 `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()` 184 @*/ 185 PetscErrorCode DMClearGlobalVectors(DM dm) { 186 PetscInt i; 187 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 190 for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { 191 Vec g; 192 193 PetscCheck(!dm->globalout[i], PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of global vectors that has a global vector obtained with DMGetGlobalVector()"); 194 g = dm->globalin[i]; 195 dm->globalin[i] = NULL; 196 if (g) { 197 DM vdm; 198 199 PetscCall(VecGetDM(g, &vdm)); 200 PetscCheck(!vdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing global vector that has a DM attached"); 201 } 202 PetscCall(VecDestroy(&g)); 203 } 204 PetscFunctionReturn(0); 205 } 206 207 /*@ 208 DMClearLocalVectors - Destroys all the local vectors that have been stashed in this DM 209 210 Collective on dm 211 212 Input Parameter: 213 . dm - the dm 214 215 Level: developer 216 217 .seealso: `DMCreateLocalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, 218 `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMLocalToLocalBegin()`, 219 `DMLocalToLocalEnd()`, `DMLocalToLocalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()` 220 `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()` 221 @*/ 222 PetscErrorCode DMClearLocalVectors(DM dm) { 223 PetscInt i; 224 225 PetscFunctionBegin; 226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 227 for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { 228 Vec g; 229 230 PetscCheck(!dm->localout[i], PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of local vectors that has a local vector obtained with DMGetLocalVector()"); 231 g = dm->localin[i]; 232 dm->localin[i] = NULL; 233 if (g) { 234 DM vdm; 235 236 PetscCall(VecGetDM(g, &vdm)); 237 PetscCheck(!vdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing local vector that has a DM attached"); 238 } 239 PetscCall(VecDestroy(&g)); 240 } 241 PetscFunctionReturn(0); 242 } 243 244 /*@ 245 DMRestoreGlobalVector - Returns a PETSc vector that 246 obtained from DMGetGlobalVector(). Do not use with vector obtained via 247 DMCreateGlobalVector(). 248 249 Not Collective 250 251 Input Parameters: 252 + dm - the dm 253 - g - the global vector 254 255 Level: beginner 256 257 .seealso: `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, 258 `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToGlobalBegin()`, 259 `DMGlobalToGlobalEnd()`, `DMGlobalToGlobal()`, `DMCreateLocalVector()`, `DMGetGlobalVector()` 260 @*/ 261 PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g) { 262 PetscInt i, j; 263 264 PetscFunctionBegin; 265 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 266 PetscValidPointer(g, 2); 267 PetscCall(VecSetErrorIfLocked(*g, 2)); 268 for (j = 0; j < DM_MAX_WORK_VECTORS; j++) { 269 if (*g == dm->globalout[j]) { 270 DM vdm; 271 272 PetscCall(VecGetDM(*g, &vdm)); 273 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 274 PetscCall(VecSetDM(*g, NULL)); 275 dm->globalout[j] = NULL; 276 for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { 277 if (!dm->globalin[i]) { 278 dm->globalin[i] = *g; 279 goto alldone; 280 } 281 } 282 } 283 } 284 PetscCall(VecDestroy(g)); 285 alldone: 286 *g = NULL; 287 PetscFunctionReturn(0); 288 } 289 290 /*@C 291 DMHasNamedGlobalVector - check for a named, persistent global vector 292 293 Not Collective 294 295 Input Parameters: 296 + dm - DM to hold named vectors 297 - name - unique name for Vec 298 299 Output Parameter: 300 . exists - true if the vector was previously created 301 302 Level: developer 303 304 Note: If a Vec with the given name does not exist, it is created. 305 306 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 307 @*/ 308 PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists) { 309 DMNamedVecLink link; 310 311 PetscFunctionBegin; 312 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 313 PetscValidCharPointer(name, 2); 314 PetscValidBoolPointer(exists, 3); 315 *exists = PETSC_FALSE; 316 for (link = dm->namedglobal; link; link = link->next) { 317 PetscBool match; 318 PetscCall(PetscStrcmp(name, link->name, &match)); 319 if (match) { 320 *exists = PETSC_TRUE; 321 break; 322 } 323 } 324 PetscFunctionReturn(0); 325 } 326 327 /*@C 328 DMGetNamedGlobalVector - get access to a named, persistent global vector 329 330 Collective on dm 331 332 Input Parameters: 333 + dm - DM to hold named vectors 334 - name - unique name for Vec 335 336 Output Parameter: 337 . X - named Vec 338 339 Level: developer 340 341 Note: If a Vec with the given name does not exist, it is created. 342 343 .seealso: `DMRestoreNamedGlobalVector()` 344 @*/ 345 PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X) { 346 DMNamedVecLink link; 347 348 PetscFunctionBegin; 349 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 350 PetscValidCharPointer(name, 2); 351 PetscValidPointer(X, 3); 352 for (link = dm->namedglobal; link; link = link->next) { 353 PetscBool match; 354 355 PetscCall(PetscStrcmp(name, link->name, &match)); 356 if (match) { 357 DM vdm; 358 359 PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); 360 PetscCall(VecGetDM(link->X, &vdm)); 361 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 362 PetscCall(VecSetDM(link->X, dm)); 363 goto found; 364 } 365 } 366 367 /* Create the Vec */ 368 PetscCall(PetscNew(&link)); 369 PetscCall(PetscStrallocpy(name, &link->name)); 370 PetscCall(DMCreateGlobalVector(dm, &link->X)); 371 link->next = dm->namedglobal; 372 dm->namedglobal = link; 373 374 found: 375 *X = link->X; 376 link->status = DMVEC_STATUS_OUT; 377 PetscFunctionReturn(0); 378 } 379 380 /*@C 381 DMRestoreNamedGlobalVector - restore access to a named, persistent global vector 382 383 Collective on dm 384 385 Input Parameters: 386 + dm - DM on which the vector was gotten 387 . name - name under which the vector was gotten 388 - X - Vec to restore 389 390 Level: developer 391 392 .seealso: `DMGetNamedGlobalVector()` 393 @*/ 394 PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X) { 395 DMNamedVecLink link; 396 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 399 PetscValidCharPointer(name, 2); 400 PetscValidPointer(X, 3); 401 PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); 402 for (link = dm->namedglobal; link; link = link->next) { 403 PetscBool match; 404 405 PetscCall(PetscStrcmp(name, link->name, &match)); 406 if (match) { 407 DM vdm; 408 409 PetscCall(VecGetDM(*X, &vdm)); 410 PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); 411 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); 412 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 413 414 link->status = DMVEC_STATUS_IN; 415 PetscCall(VecSetDM(link->X, NULL)); 416 *X = NULL; 417 PetscFunctionReturn(0); 418 } 419 } 420 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); 421 } 422 423 /*@C 424 DMHasNamedLocalVector - check for a named, persistent local vector 425 426 Not Collective 427 428 Input Parameters: 429 + dm - DM to hold named vectors 430 - name - unique name for Vec 431 432 Output Parameter: 433 . exists - true if the vector was previously created 434 435 Level: developer 436 437 Note: If a Vec with the given name does not exist, it is created. 438 439 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 440 @*/ 441 PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists) { 442 DMNamedVecLink link; 443 444 PetscFunctionBegin; 445 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 446 PetscValidCharPointer(name, 2); 447 PetscValidBoolPointer(exists, 3); 448 *exists = PETSC_FALSE; 449 for (link = dm->namedlocal; link; link = link->next) { 450 PetscBool match; 451 PetscCall(PetscStrcmp(name, link->name, &match)); 452 if (match) { 453 *exists = PETSC_TRUE; 454 break; 455 } 456 } 457 PetscFunctionReturn(0); 458 } 459 460 /*@C 461 DMGetNamedLocalVector - get access to a named, persistent local vector 462 463 Not Collective 464 465 Input Parameters: 466 + dm - DM to hold named vectors 467 - name - unique name for Vec 468 469 Output Parameter: 470 . X - named Vec 471 472 Level: developer 473 474 Note: If a Vec with the given name does not exist, it is created. 475 476 .seealso: `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()` 477 @*/ 478 PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X) { 479 DMNamedVecLink link; 480 481 PetscFunctionBegin; 482 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 483 PetscValidCharPointer(name, 2); 484 PetscValidPointer(X, 3); 485 for (link = dm->namedlocal; link; link = link->next) { 486 PetscBool match; 487 488 PetscCall(PetscStrcmp(name, link->name, &match)); 489 if (match) { 490 DM vdm; 491 492 PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); 493 PetscCall(VecGetDM(link->X, &vdm)); 494 PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); 495 PetscCall(VecSetDM(link->X, dm)); 496 goto found; 497 } 498 } 499 500 /* Create the Vec */ 501 PetscCall(PetscNew(&link)); 502 PetscCall(PetscStrallocpy(name, &link->name)); 503 PetscCall(DMCreateLocalVector(dm, &link->X)); 504 link->next = dm->namedlocal; 505 dm->namedlocal = link; 506 507 found: 508 *X = link->X; 509 link->status = DMVEC_STATUS_OUT; 510 PetscFunctionReturn(0); 511 } 512 513 /*@C 514 DMRestoreNamedLocalVector - restore access to a named, persistent local vector 515 516 Not Collective 517 518 Input Parameters: 519 + dm - DM on which the vector was gotten 520 . name - name under which the vector was gotten 521 - X - Vec to restore 522 523 Level: developer 524 525 .seealso: `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()` 526 @*/ 527 PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X) { 528 DMNamedVecLink link; 529 530 PetscFunctionBegin; 531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 532 PetscValidCharPointer(name, 2); 533 PetscValidPointer(X, 3); 534 PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); 535 for (link = dm->namedlocal; link; link = link->next) { 536 PetscBool match; 537 538 PetscCall(PetscStrcmp(name, link->name, &match)); 539 if (match) { 540 DM vdm; 541 542 PetscCall(VecGetDM(*X, &vdm)); 543 PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); 544 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); 545 PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); 546 547 link->status = DMVEC_STATUS_IN; 548 PetscCall(VecSetDM(link->X, NULL)); 549 *X = NULL; 550 PetscFunctionReturn(0); 551 } 552 } 553 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); 554 } 555