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