1 #include <petscdmshell.h> /*I "petscdmshell.h" I*/ 2 #include <petscmat.h> 3 #include <petsc/private/dmimpl.h> 4 5 typedef struct { 6 Vec Xglobal; 7 Vec Xlocal; 8 Mat A; 9 VecScatter gtol; 10 VecScatter ltog; 11 VecScatter ltol; 12 } DM_Shell; 13 14 #undef __FUNCT__ 15 #define __FUNCT__ "DMGlobalToLocalBeginDefaultShell" 16 /*@ 17 DMGlobalToLocalBeginDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to begin a global to local scatter 18 Collective 19 20 Input Arguments: 21 + dm - shell DM 22 . g - global vector 23 . mode - InsertMode 24 - l - local vector 25 26 Level: advanced 27 28 Note: This is not normally called directly by user code, generally user code calls DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function. 29 30 .seealso: DMGlobalToLocalEndDefaultShell() 31 @*/ 32 PetscErrorCode DMGlobalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l) 33 { 34 PetscErrorCode ierr; 35 DM_Shell *shell = (DM_Shell*)dm->data; 36 37 PetscFunctionBegin; 38 if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()"); 39 ierr = VecScatterBegin(shell->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr); 40 PetscFunctionReturn(0); 41 } 42 43 #undef __FUNCT__ 44 #define __FUNCT__ "DMGlobalToLocalEndDefaultShell" 45 /*@ 46 DMGlobalToLocalEndDefaultShell - Uses the GlobalToLocal VecScatter context set by the user to end a global to local scatter 47 Collective 48 49 Input Arguments: 50 + dm - shell DM 51 . g - global vector 52 . mode - InsertMode 53 - l - local vector 54 55 Level: advanced 56 57 .seealso: DMGlobalToLocalBeginDefaultShell() 58 @*/ 59 PetscErrorCode DMGlobalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l) 60 { 61 PetscErrorCode ierr; 62 DM_Shell *shell = (DM_Shell*)dm->data; 63 64 PetscFunctionBegin; 65 if (!shell->gtol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()"); 66 ierr = VecScatterEnd(shell->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr); 67 PetscFunctionReturn(0); 68 } 69 70 #undef __FUNCT__ 71 #define __FUNCT__ "DMLocalToGlobalBeginDefaultShell" 72 /*@ 73 DMLocalToGlobalBeginDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to begin a local to global scatter 74 Collective 75 76 Input Arguments: 77 + dm - shell DM 78 . l - local vector 79 . mode - InsertMode 80 - g - global vector 81 82 Level: advanced 83 84 Note: This is not normally called directly by user code, generally user code calls DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). If the user provides their own custom routines to DMShellSetLocalToGlobal() then those routines might have reason to call this function. 85 86 .seealso: DMLocalToGlobalEndDefaultShell() 87 @*/ 88 PetscErrorCode DMLocalToGlobalBeginDefaultShell(DM dm,Vec l,InsertMode mode,Vec g) 89 { 90 PetscErrorCode ierr; 91 DM_Shell *shell = (DM_Shell*)dm->data; 92 93 PetscFunctionBegin; 94 if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()"); 95 ierr = VecScatterBegin(shell->ltog,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr); 96 PetscFunctionReturn(0); 97 } 98 99 #undef __FUNCT__ 100 #define __FUNCT__ "DMLocalToGlobalEndDefaultShell" 101 /*@ 102 DMLocalToGlobalEndDefaultShell - Uses the LocalToGlobal VecScatter context set by the user to end a local to global scatter 103 Collective 104 105 Input Arguments: 106 + dm - shell DM 107 . l - local vector 108 . mode - InsertMode 109 - g - global vector 110 111 Level: advanced 112 113 .seealso: DMLocalToGlobalBeginDefaultShell() 114 @*/ 115 PetscErrorCode DMLocalToGlobalEndDefaultShell(DM dm,Vec l,InsertMode mode,Vec g) 116 { 117 PetscErrorCode ierr; 118 DM_Shell *shell = (DM_Shell*)dm->data; 119 120 PetscFunctionBegin; 121 if (!shell->ltog) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToGlobalVecScatter()"); 122 ierr = VecScatterEnd(shell->ltog,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr); 123 PetscFunctionReturn(0); 124 } 125 126 #undef __FUNCT__ 127 #define __FUNCT__ "DMLocalToLocalBeginDefaultShell" 128 /*@ 129 DMLocalToLocalBeginDefaultShell - Uses the LocalToLocal VecScatter context set by the user to begin a local to local scatter 130 Collective 131 132 Input Arguments: 133 + dm - shell DM 134 . g - the original local vector 135 - mode - InsertMode 136 137 Output Parameter: 138 . l - the local vector with correct ghost values 139 140 Level: advanced 141 142 Note: This is not normally called directly by user code, generally user code calls DMLocalToLocalBegin() and DMLocalToLocalEnd(). If the user provides their own custom routines to DMShellSetLocalToLocal() then those routines might have reason to call this function. 143 144 .seealso: DMLocalToLocalEndDefaultShell() 145 @*/ 146 PetscErrorCode DMLocalToLocalBeginDefaultShell(DM dm,Vec g,InsertMode mode,Vec l) 147 { 148 PetscErrorCode ierr; 149 DM_Shell *shell = (DM_Shell*)dm->data; 150 151 PetscFunctionBegin; 152 if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetLocalToLocalVecScatter()"); 153 ierr = VecScatterBegin(shell->ltol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr); 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "DMLocalToLocalEndDefaultShell" 159 /*@ 160 DMLocalToLocalEndDefaultShell - Uses the LocalToLocal VecScatter context set by the user to end a local to local scatter 161 Collective 162 163 Input Arguments: 164 + dm - shell DM 165 . g - the original local vector 166 - mode - InsertMode 167 168 Output Parameter: 169 . l - the local vector with correct ghost values 170 171 Level: advanced 172 173 .seealso: DMLocalToLocalBeginDefaultShell() 174 @*/ 175 PetscErrorCode DMLocalToLocalEndDefaultShell(DM dm,Vec g,InsertMode mode,Vec l) 176 { 177 PetscErrorCode ierr; 178 DM_Shell *shell = (DM_Shell*)dm->data; 179 180 PetscFunctionBegin; 181 if (!shell->ltol) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE, "Cannot be used without first setting the scatter context via DMShellSetGlobalToLocalVecScatter()"); 182 ierr = VecScatterEnd(shell->ltol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr); 183 PetscFunctionReturn(0); 184 } 185 186 #undef __FUNCT__ 187 #define __FUNCT__ "DMCreateMatrix_Shell" 188 static PetscErrorCode DMCreateMatrix_Shell(DM dm,Mat *J) 189 { 190 PetscErrorCode ierr; 191 DM_Shell *shell = (DM_Shell*)dm->data; 192 Mat A; 193 194 PetscFunctionBegin; 195 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 196 PetscValidPointer(J,3); 197 if (!shell->A) { 198 if (shell->Xglobal) { 199 PetscInt m,M; 200 ierr = PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation\n");CHKERRQ(ierr); 201 ierr = VecGetSize(shell->Xglobal,&M);CHKERRQ(ierr); 202 ierr = VecGetLocalSize(shell->Xglobal,&m);CHKERRQ(ierr); 203 ierr = MatCreate(PetscObjectComm((PetscObject)dm),&shell->A);CHKERRQ(ierr); 204 ierr = MatSetSizes(shell->A,m,m,M,M);CHKERRQ(ierr); 205 ierr = MatSetType(shell->A,dm->mattype);CHKERRQ(ierr); 206 ierr = MatSetUp(shell->A);CHKERRQ(ierr); 207 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector"); 208 } 209 A = shell->A; 210 /* the check below is tacky and incomplete */ 211 if (dm->mattype) { 212 PetscBool flg,aij,seqaij,mpiaij; 213 ierr = PetscObjectTypeCompare((PetscObject)A,dm->mattype,&flg);CHKERRQ(ierr); 214 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr); 215 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);CHKERRQ(ierr); 216 ierr = PetscStrcmp(dm->mattype,MATAIJ,&aij);CHKERRQ(ierr); 217 if (!flg) { 218 if (!(aij && (seqaij || mpiaij))) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",dm->mattype,((PetscObject)A)->type_name); 219 } 220 } 221 if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */ 222 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 223 ierr = MatZeroEntries(A);CHKERRQ(ierr); 224 *J = A; 225 } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 226 ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr); 227 ierr = MatZeroEntries(*J);CHKERRQ(ierr); 228 } 229 PetscFunctionReturn(0); 230 } 231 232 #undef __FUNCT__ 233 #define __FUNCT__ "DMCreateGlobalVector_Shell" 234 PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec) 235 { 236 PetscErrorCode ierr; 237 DM_Shell *shell = (DM_Shell*)dm->data; 238 Vec X; 239 240 PetscFunctionBegin; 241 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 242 PetscValidPointer(gvec,2); 243 *gvec = 0; 244 X = shell->Xglobal; 245 if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()"); 246 if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */ 247 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 248 ierr = VecZeroEntries(X);CHKERRQ(ierr); 249 *gvec = X; 250 } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 251 ierr = VecDuplicate(X,gvec);CHKERRQ(ierr); 252 ierr = VecZeroEntries(*gvec);CHKERRQ(ierr); 253 } 254 ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr); 255 PetscFunctionReturn(0); 256 } 257 258 #undef __FUNCT__ 259 #define __FUNCT__ "DMCreateLocalVector_Shell" 260 PetscErrorCode DMCreateLocalVector_Shell(DM dm,Vec *gvec) 261 { 262 PetscErrorCode ierr; 263 DM_Shell *shell = (DM_Shell*)dm->data; 264 Vec X; 265 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 268 PetscValidPointer(gvec,2); 269 *gvec = 0; 270 X = shell->Xlocal; 271 if (!X) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMShellSetLocalVector() or DMShellSetCreateLocalVector()"); 272 if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */ 273 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 274 ierr = VecZeroEntries(X);CHKERRQ(ierr); 275 *gvec = X; 276 } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 277 ierr = VecDuplicate(X,gvec);CHKERRQ(ierr); 278 ierr = VecZeroEntries(*gvec);CHKERRQ(ierr); 279 } 280 ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr); 281 PetscFunctionReturn(0); 282 } 283 284 #undef __FUNCT__ 285 #define __FUNCT__ "DMShellSetMatrix" 286 /*@ 287 DMShellSetMatrix - sets a template matrix associated with the DMShell 288 289 Collective 290 291 Input Arguments: 292 + dm - shell DM 293 - J - template matrix 294 295 Level: advanced 296 297 .seealso: DMCreateMatrix(), DMShellSetCreateMatrix() 298 @*/ 299 PetscErrorCode DMShellSetMatrix(DM dm,Mat J) 300 { 301 DM_Shell *shell = (DM_Shell*)dm->data; 302 PetscErrorCode ierr; 303 PetscBool isshell; 304 305 PetscFunctionBegin; 306 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 307 PetscValidHeaderSpecific(J,MAT_CLASSID,2); 308 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 309 if (!isshell) PetscFunctionReturn(0); 310 ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 311 ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 312 shell->A = J; 313 PetscFunctionReturn(0); 314 } 315 316 #undef __FUNCT__ 317 #define __FUNCT__ "DMShellSetCreateMatrix" 318 /*@C 319 DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM 320 321 Logically Collective on DM 322 323 Input Arguments: 324 + dm - the shell DM 325 - func - the function to create a matrix 326 327 Level: advanced 328 329 .seealso: DMCreateMatrix(), DMShellSetMatrix() 330 @*/ 331 PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,Mat*)) 332 { 333 334 PetscFunctionBegin; 335 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 336 dm->ops->creatematrix = func; 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DMShellSetGlobalVector" 342 /*@ 343 DMShellSetGlobalVector - sets a template global vector associated with the DMShell 344 345 Logically Collective on DM 346 347 Input Arguments: 348 + dm - shell DM 349 - X - template vector 350 351 Level: advanced 352 353 .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector() 354 @*/ 355 PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X) 356 { 357 DM_Shell *shell = (DM_Shell*)dm->data; 358 PetscErrorCode ierr; 359 PetscBool isshell; 360 361 PetscFunctionBegin; 362 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 363 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 364 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 365 if (!isshell) PetscFunctionReturn(0); 366 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 367 ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 368 shell->Xglobal = X; 369 PetscFunctionReturn(0); 370 } 371 372 #undef __FUNCT__ 373 #define __FUNCT__ "DMShellSetCreateGlobalVector" 374 /*@C 375 DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM 376 377 Logically Collective 378 379 Input Arguments: 380 + dm - the shell DM 381 - func - the creation routine 382 383 Level: advanced 384 385 .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix() 386 @*/ 387 PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*)) 388 { 389 390 PetscFunctionBegin; 391 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 392 dm->ops->createglobalvector = func; 393 PetscFunctionReturn(0); 394 } 395 396 #undef __FUNCT__ 397 #define __FUNCT__ "DMShellSetLocalVector" 398 /*@ 399 DMShellSetLocalVector - sets a template local vector associated with the DMShell 400 401 Logically Collective on DM 402 403 Input Arguments: 404 + dm - shell DM 405 - X - template vector 406 407 Level: advanced 408 409 .seealso: DMCreateLocalVector(), DMShellSetMatrix(), DMShellSetCreateLocalVector() 410 @*/ 411 PetscErrorCode DMShellSetLocalVector(DM dm,Vec X) 412 { 413 DM_Shell *shell = (DM_Shell*)dm->data; 414 PetscErrorCode ierr; 415 PetscBool isshell; 416 417 PetscFunctionBegin; 418 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 419 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 420 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 421 if (!isshell) PetscFunctionReturn(0); 422 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 423 ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr); 424 shell->Xlocal = X; 425 PetscFunctionReturn(0); 426 } 427 428 #undef __FUNCT__ 429 #define __FUNCT__ "DMShellSetCreateLocalVector" 430 /*@C 431 DMShellSetCreateLocalVector - sets the routine to create a local vector associated with the shell DM 432 433 Logically Collective 434 435 Input Arguments: 436 + dm - the shell DM 437 - func - the creation routine 438 439 Level: advanced 440 441 .seealso: DMShellSetLocalVector(), DMShellSetCreateMatrix() 442 @*/ 443 PetscErrorCode DMShellSetCreateLocalVector(DM dm,PetscErrorCode (*func)(DM,Vec*)) 444 { 445 446 PetscFunctionBegin; 447 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 448 dm->ops->createlocalvector = func; 449 PetscFunctionReturn(0); 450 } 451 452 #undef __FUNCT__ 453 #define __FUNCT__ "DMShellSetGlobalToLocal" 454 /*@C 455 DMShellSetGlobalToLocal - Sets the routines used to perform a global to local scatter 456 457 Logically Collective on DM 458 459 Input Arguments 460 + dm - the shell DM 461 . begin - the routine that begins the global to local scatter 462 - end - the routine that ends the global to local scatter 463 464 Notes: If these functions are not provided but DMShellSetGlobalToLocalVecScatter() is called then 465 DMGlobalToLocalBeginDefaultShell()/DMGlobalToLocalEndDefaultShell() are used to to perform the transfers 466 467 Level: advanced 468 469 .seealso: DMShellSetLocalToGlobal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell() 470 @*/ 471 PetscErrorCode DMShellSetGlobalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) { 472 PetscFunctionBegin; 473 dm->ops->globaltolocalbegin = begin; 474 dm->ops->globaltolocalend = end; 475 PetscFunctionReturn(0); 476 } 477 478 #undef __FUNCT__ 479 #define __FUNCT__ "DMShellSetLocalToGlobal" 480 /*@C 481 DMShellSetLocalToGlobal - Sets the routines used to perform a local to global scatter 482 483 Logically Collective on DM 484 485 Input Arguments 486 + dm - the shell DM 487 . begin - the routine that begins the local to global scatter 488 - end - the routine that ends the local to global scatter 489 490 Notes: If these functions are not provided but DMShellSetLocalToGlobalVecScatter() is called then 491 DMLocalToGlobalBeginDefaultShell()/DMLocalToGlobalEndDefaultShell() are used to to perform the transfers 492 493 Level: advanced 494 495 .seealso: DMShellSetGlobalToLocal() 496 @*/ 497 PetscErrorCode DMShellSetLocalToGlobal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) { 498 PetscFunctionBegin; 499 dm->ops->localtoglobalbegin = begin; 500 dm->ops->localtoglobalend = end; 501 PetscFunctionReturn(0); 502 } 503 504 #undef __FUNCT__ 505 #define __FUNCT__ "DMShellSetLocalToLocal" 506 /*@C 507 DMShellSetLocalToLocal - Sets the routines used to perform a local to local scatter 508 509 Logically Collective on DM 510 511 Input Arguments 512 + dm - the shell DM 513 . begin - the routine that begins the local to local scatter 514 - end - the routine that ends the local to local scatter 515 516 Notes: If these functions are not provided but DMShellSetLocalToLocalVecScatter() is called then 517 DMLocalToLocalBeginDefaultShell()/DMLocalToLocalEndDefaultShell() are used to to perform the transfers 518 519 Level: advanced 520 521 .seealso: DMShellSetGlobalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell() 522 @*/ 523 PetscErrorCode DMShellSetLocalToLocal(DM dm,PetscErrorCode (*begin)(DM,Vec,InsertMode,Vec),PetscErrorCode (*end)(DM,Vec,InsertMode,Vec)) { 524 PetscFunctionBegin; 525 dm->ops->localtolocalbegin = begin; 526 dm->ops->localtolocalend = end; 527 PetscFunctionReturn(0); 528 } 529 530 #undef __FUNCT__ 531 #define __FUNCT__ "DMShellSetGlobalToLocalVecScatter" 532 /*@ 533 DMShellSetGlobalToLocalVecScatter - Sets a VecScatter context for global to local communication 534 535 Logically Collective on DM 536 537 Input Arguments 538 + dm - the shell DM 539 - gtol - the global to local VecScatter context 540 541 Level: advanced 542 543 .seealso: DMShellSetGlobalToLocal(), DMGlobalToLocalBeginDefaultShell(), DMGlobalToLocalEndDefaultShell() 544 @*/ 545 PetscErrorCode DMShellSetGlobalToLocalVecScatter(DM dm, VecScatter gtol) 546 { 547 DM_Shell *shell = (DM_Shell*)dm->data; 548 PetscErrorCode ierr; 549 550 PetscFunctionBegin; 551 ierr = PetscObjectReference((PetscObject)gtol);CHKERRQ(ierr); 552 /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */ 553 ierr = VecScatterDestroy(&shell->gtol);CHKERRQ(ierr); 554 shell->gtol = gtol; 555 PetscFunctionReturn(0); 556 } 557 558 #undef __FUNCT__ 559 #define __FUNCT__ "DMShellSetLocalToGlobalVecScatter" 560 /*@ 561 DMShellSetLocalToGlobalVecScatter - Sets a VecScatter context for local to global communication 562 563 Logically Collective on DM 564 565 Input Arguments 566 + dm - the shell DM 567 - ltog - the local to global VecScatter context 568 569 Level: advanced 570 571 .seealso: DMShellSetLocalToGlobal(), DMLocalToGlobalBeginDefaultShell(), DMLocalToGlobalEndDefaultShell() 572 @*/ 573 PetscErrorCode DMShellSetLocalToGlobalVecScatter(DM dm, VecScatter ltog) 574 { 575 DM_Shell *shell = (DM_Shell*)dm->data; 576 PetscErrorCode ierr; 577 578 PetscFunctionBegin; 579 ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr); 580 /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */ 581 ierr = VecScatterDestroy(&shell->ltog);CHKERRQ(ierr); 582 shell->ltog = ltog; 583 PetscFunctionReturn(0); 584 } 585 586 #undef __FUNCT__ 587 #define __FUNCT__ "DMShellSetLocalToLocalVecScatter" 588 /*@ 589 DMShellSetLocalToLocalVecScatter - Sets a VecScatter context for local to local communication 590 591 Logically Collective on DM 592 593 Input Arguments 594 + dm - the shell DM 595 - ltol - the local to local VecScatter context 596 597 Level: advanced 598 599 .seealso: DMShellSetLocalToLocal(), DMLocalToLocalBeginDefaultShell(), DMLocalToLocalEndDefaultShell() 600 @*/ 601 PetscErrorCode DMShellSetLocalToLocalVecScatter(DM dm, VecScatter ltol) 602 { 603 DM_Shell *shell = (DM_Shell*)dm->data; 604 PetscErrorCode ierr; 605 606 PetscFunctionBegin; 607 ierr = PetscObjectReference((PetscObject)ltol);CHKERRQ(ierr); 608 /* Call VecScatterDestroy() to avoid a memory leak in case of re-setting. */ 609 ierr = VecScatterDestroy(&shell->ltol);CHKERRQ(ierr); 610 shell->ltol = ltol; 611 PetscFunctionReturn(0); 612 } 613 614 #undef __FUNCT__ 615 #define __FUNCT__ "DMShellSetCoarsen" 616 /*@C 617 DMShellSetCoarsen - Set the routine used to coarsen the shell DM 618 619 Logically Collective on DM 620 621 Input Arguments 622 + dm - the shell DM 623 - coarsen - the routine that coarsens the DM 624 625 Level: advanced 626 627 .seealso: DMShellSetRefine(), DMCoarsen() 628 @*/ 629 PetscErrorCode DMShellSetCoarsen(DM dm, PetscErrorCode (*coarsen)(DM,MPI_Comm,DM*)) 630 { 631 PetscErrorCode ierr; 632 PetscBool isshell; 633 634 PetscFunctionBegin; 635 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 636 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 637 if (!isshell) PetscFunctionReturn(0); 638 dm->ops->coarsen = coarsen; 639 PetscFunctionReturn(0); 640 } 641 642 #undef __FUNCT__ 643 #define __FUNCT__ "DMShellSetRefine" 644 /*@C 645 DMShellSetRefine - Set the routine used to refine the shell DM 646 647 Logically Collective on DM 648 649 Input Arguments 650 + dm - the shell DM 651 - refine - the routine that refines the DM 652 653 Level: advanced 654 655 .seealso: DMShellSetCoarsen(), DMRefine() 656 @*/ 657 PetscErrorCode DMShellSetRefine(DM dm, PetscErrorCode (*refine)(DM,MPI_Comm,DM*)) 658 { 659 PetscErrorCode ierr; 660 PetscBool isshell; 661 662 PetscFunctionBegin; 663 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 664 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 665 if (!isshell) PetscFunctionReturn(0); 666 dm->ops->refine = refine; 667 PetscFunctionReturn(0); 668 } 669 670 #undef __FUNCT__ 671 #define __FUNCT__ "DMShellSetCreateInterpolation" 672 /*@C 673 DMShellSetCreateInterpolation - Set the routine used to create the interpolation operator 674 675 Logically Collective on DM 676 677 Input Arguments 678 + dm - the shell DM 679 - interp - the routine to create the interpolation 680 681 Level: advanced 682 683 .seealso: DMShellSetCreateInjection(), DMCreateInterpolation() 684 @*/ 685 PetscErrorCode DMShellSetCreateInterpolation(DM dm, PetscErrorCode (*interp)(DM,DM,Mat*,Vec*)) 686 { 687 PetscErrorCode ierr; 688 PetscBool isshell; 689 690 PetscFunctionBegin; 691 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 692 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 693 if (!isshell) PetscFunctionReturn(0); 694 dm->ops->createinterpolation = interp; 695 PetscFunctionReturn(0); 696 } 697 698 #undef __FUNCT__ 699 #define __FUNCT__ "DMShellSetCreateInjection" 700 /*@C 701 DMShellSetCreateInjection - Set the routine used to create the injection operator 702 703 Logically Collective on DM 704 705 Input Arguments 706 + dm - the shell DM 707 - inject - the routine to create the injection 708 709 Level: advanced 710 711 .seealso: DMShellSetCreateInterpolation(), DMCreateInjection() 712 @*/ 713 PetscErrorCode DMShellSetCreateInjection(DM dm, PetscErrorCode (*inject)(DM,DM,Mat*)) 714 { 715 PetscErrorCode ierr; 716 PetscBool isshell; 717 718 PetscFunctionBegin; 719 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 720 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 721 if (!isshell) PetscFunctionReturn(0); 722 dm->ops->getinjection = inject; 723 PetscFunctionReturn(0); 724 } 725 726 #undef __FUNCT__ 727 #define __FUNCT__ "DMShellSetCreateFieldDecomposition" 728 /*@C 729 DMShellSetCreateFieldDecomposition - Set the routine used to create a decomposition of fields for the shell DM 730 731 Logically Collective on DM 732 733 Input Arguments 734 + dm - the shell DM 735 - decomp - the routine to create the decomposition 736 737 Level: advanced 738 739 .seealso: DMCreateFieldDecomposition() 740 @*/ 741 PetscErrorCode DMShellSetCreateFieldDecomposition(DM dm, PetscErrorCode (*decomp)(DM,PetscInt*,char***, IS**,DM**)) 742 { 743 PetscErrorCode ierr; 744 PetscBool isshell; 745 746 PetscFunctionBegin; 747 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 748 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 749 if (!isshell) PetscFunctionReturn(0); 750 dm->ops->createfielddecomposition = decomp; 751 PetscFunctionReturn(0); 752 } 753 754 #undef __FUNCT__ 755 #define __FUNCT__ "DMDestroy_Shell" 756 static PetscErrorCode DMDestroy_Shell(DM dm) 757 { 758 PetscErrorCode ierr; 759 DM_Shell *shell = (DM_Shell*)dm->data; 760 761 PetscFunctionBegin; 762 ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 763 ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 764 ierr = VecDestroy(&shell->Xlocal);CHKERRQ(ierr); 765 ierr = VecScatterDestroy(&shell->gtol);CHKERRQ(ierr); 766 ierr = VecScatterDestroy(&shell->ltog);CHKERRQ(ierr); 767 ierr = VecScatterDestroy(&shell->ltol);CHKERRQ(ierr); 768 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 769 ierr = PetscFree(shell);CHKERRQ(ierr); 770 PetscFunctionReturn(0); 771 } 772 773 #undef __FUNCT__ 774 #define __FUNCT__ "DMView_Shell" 775 static PetscErrorCode DMView_Shell(DM dm,PetscViewer v) 776 { 777 PetscErrorCode ierr; 778 DM_Shell *shell = (DM_Shell*)dm->data; 779 780 PetscFunctionBegin; 781 ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr); 782 PetscFunctionReturn(0); 783 } 784 785 #undef __FUNCT__ 786 #define __FUNCT__ "DMLoad_Shell" 787 static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v) 788 { 789 PetscErrorCode ierr; 790 DM_Shell *shell = (DM_Shell*)dm->data; 791 792 PetscFunctionBegin; 793 ierr = VecCreate(PetscObjectComm((PetscObject)dm),&shell->Xglobal);CHKERRQ(ierr); 794 ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr); 795 PetscFunctionReturn(0); 796 } 797 798 #undef __FUNCT__ 799 #define __FUNCT__ "DMCreateSubDM_Shell" 800 PetscErrorCode DMCreateSubDM_Shell(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 801 { 802 PetscErrorCode ierr; 803 804 PetscFunctionBegin; 805 if (subdm) {ierr = DMShellCreate(PetscObjectComm((PetscObject) dm), subdm);CHKERRQ(ierr);} 806 ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 807 PetscFunctionReturn(0); 808 } 809 810 #undef __FUNCT__ 811 #define __FUNCT__ "DMCreate_Shell" 812 PETSC_EXTERN PetscErrorCode DMCreate_Shell(DM dm) 813 { 814 PetscErrorCode ierr; 815 DM_Shell *shell; 816 817 PetscFunctionBegin; 818 ierr = PetscNewLog(dm,&shell);CHKERRQ(ierr); 819 dm->data = shell; 820 821 ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr); 822 823 dm->ops->destroy = DMDestroy_Shell; 824 dm->ops->createglobalvector = DMCreateGlobalVector_Shell; 825 dm->ops->createlocalvector = DMCreateLocalVector_Shell; 826 dm->ops->creatematrix = DMCreateMatrix_Shell; 827 dm->ops->view = DMView_Shell; 828 dm->ops->load = DMLoad_Shell; 829 dm->ops->globaltolocalbegin = DMGlobalToLocalBeginDefaultShell; 830 dm->ops->globaltolocalend = DMGlobalToLocalEndDefaultShell; 831 dm->ops->localtoglobalbegin = DMLocalToGlobalBeginDefaultShell; 832 dm->ops->localtoglobalend = DMLocalToGlobalEndDefaultShell; 833 dm->ops->localtolocalbegin = DMLocalToLocalBeginDefaultShell; 834 dm->ops->localtolocalend = DMLocalToLocalEndDefaultShell; 835 dm->ops->createsubdm = DMCreateSubDM_Shell; 836 PetscFunctionReturn(0); 837 } 838 839 #undef __FUNCT__ 840 #define __FUNCT__ "DMShellCreate" 841 /*@ 842 DMShellCreate - Creates a shell DM object, used to manage user-defined problem data 843 844 Collective on MPI_Comm 845 846 Input Parameter: 847 . comm - the processors that will share the global vector 848 849 Output Parameters: 850 . shell - the shell DM 851 852 Level: advanced 853 854 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector() 855 @*/ 856 PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm) 857 { 858 PetscErrorCode ierr; 859 860 PetscFunctionBegin; 861 PetscValidPointer(dm,2); 862 ierr = DMCreate(comm,dm);CHKERRQ(ierr); 863 ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr); 864 ierr = DMSetUp(*dm);CHKERRQ(ierr); 865 PetscFunctionReturn(0); 866 } 867 868