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