1 #include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/ 2 3 PetscClassId DM_CLASSID; 4 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal; 5 6 #undef __FUNCT__ 7 #define __FUNCT__ "DMViewFromOptions" 8 /* 9 Processes command line options to determine if/how a dm 10 is to be viewed. 11 12 */ 13 PetscErrorCode DMViewFromOptions(DM dm,const char optionname[]) 14 { 15 PetscErrorCode ierr; 16 PetscBool flg; 17 PetscViewer viewer; 18 PetscViewerFormat format; 19 20 PetscFunctionBegin; 21 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)dm),((PetscObject)dm)->prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr); 22 if (flg) { 23 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 24 ierr = DMView(dm,viewer);CHKERRQ(ierr); 25 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 26 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 27 } 28 PetscFunctionReturn(0); 29 } 30 31 32 #undef __FUNCT__ 33 #define __FUNCT__ "DMCreate" 34 /*@ 35 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 36 37 If you never call DMSetType() it will generate an 38 error when you try to use the vector. 39 40 Collective on MPI_Comm 41 42 Input Parameter: 43 . comm - The communicator for the DM object 44 45 Output Parameter: 46 . dm - The DM object 47 48 Level: beginner 49 50 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE 51 @*/ 52 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 53 { 54 DM v; 55 PetscErrorCode ierr; 56 57 PetscFunctionBegin; 58 PetscValidPointer(dm,2); 59 *dm = NULL; 60 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 61 ierr = VecInitializePackage();CHKERRQ(ierr); 62 ierr = MatInitializePackage();CHKERRQ(ierr); 63 ierr = DMInitializePackage();CHKERRQ(ierr); 64 #endif 65 66 ierr = PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 67 ierr = PetscMemzero(v->ops, sizeof(struct _DMOps));CHKERRQ(ierr); 68 69 70 v->ltogmap = NULL; 71 v->ltogmapb = NULL; 72 v->bs = 1; 73 v->coloringtype = IS_COLORING_GLOBAL; 74 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 75 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 76 v->defaultSection = NULL; 77 v->defaultGlobalSection = NULL; 78 { 79 PetscInt i; 80 for (i = 0; i < 10; ++i) { 81 v->nullspaceConstructors[i] = NULL; 82 } 83 } 84 v->numFields = 0; 85 v->fields = NULL; 86 87 *dm = v; 88 PetscFunctionReturn(0); 89 } 90 91 #undef __FUNCT__ 92 #define __FUNCT__ "DMSetVecType" 93 /*@C 94 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 95 96 Logically Collective on DMDA 97 98 Input Parameter: 99 + da - initial distributed array 100 . ctype - the vector type, currently either VECSTANDARD or VECCUSP 101 102 Options Database: 103 . -dm_vec_type ctype 104 105 Level: intermediate 106 107 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType 108 @*/ 109 PetscErrorCode DMSetVecType(DM da,VecType ctype) 110 { 111 PetscErrorCode ierr; 112 113 PetscFunctionBegin; 114 PetscValidHeaderSpecific(da,DM_CLASSID,1); 115 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 116 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 117 PetscFunctionReturn(0); 118 } 119 120 #undef __FUNCT__ 121 #define __FUNCT__ "VecGetDM" 122 /*@ 123 VecGetDM - Gets the DM defining the data layout of the vector 124 125 Not collective 126 127 Input Parameter: 128 . v - The Vec 129 130 Output Parameter: 131 . dm - The DM 132 133 Level: intermediate 134 135 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 136 @*/ 137 PetscErrorCode VecGetDM(Vec v, DM *dm) 138 { 139 PetscErrorCode ierr; 140 141 PetscFunctionBegin; 142 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 143 PetscValidPointer(dm,2); 144 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 145 PetscFunctionReturn(0); 146 } 147 148 #undef __FUNCT__ 149 #define __FUNCT__ "VecSetDM" 150 /*@ 151 VecSetDM - Sets the DM defining the data layout of the vector 152 153 Not collective 154 155 Input Parameters: 156 + v - The Vec 157 - dm - The DM 158 159 Level: intermediate 160 161 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 162 @*/ 163 PetscErrorCode VecSetDM(Vec v, DM dm) 164 { 165 PetscErrorCode ierr; 166 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 169 PetscValidHeaderSpecific(dm,DM_CLASSID,2); 170 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 171 PetscFunctionReturn(0); 172 } 173 174 #undef __FUNCT__ 175 #define __FUNCT__ "DMSetMatType" 176 /*@C 177 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 178 179 Logically Collective on DM 180 181 Input Parameter: 182 + dm - the DM context 183 . ctype - the matrix type 184 185 Options Database: 186 . -dm_mat_type ctype 187 188 Level: intermediate 189 190 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType 191 @*/ 192 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 193 { 194 PetscErrorCode ierr; 195 196 PetscFunctionBegin; 197 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 198 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 199 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 200 PetscFunctionReturn(0); 201 } 202 203 #undef __FUNCT__ 204 #define __FUNCT__ "MatGetDM" 205 /*@ 206 MatGetDM - Gets the DM defining the data layout of the matrix 207 208 Not collective 209 210 Input Parameter: 211 . A - The Mat 212 213 Output Parameter: 214 . dm - The DM 215 216 Level: intermediate 217 218 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 219 @*/ 220 PetscErrorCode MatGetDM(Mat A, DM *dm) 221 { 222 PetscErrorCode ierr; 223 224 PetscFunctionBegin; 225 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 226 PetscValidPointer(dm,2); 227 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 228 PetscFunctionReturn(0); 229 } 230 231 #undef __FUNCT__ 232 #define __FUNCT__ "MatSetDM" 233 /*@ 234 MatSetDM - Sets the DM defining the data layout of the matrix 235 236 Not collective 237 238 Input Parameters: 239 + A - The Mat 240 - dm - The DM 241 242 Level: intermediate 243 244 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 245 @*/ 246 PetscErrorCode MatSetDM(Mat A, DM dm) 247 { 248 PetscErrorCode ierr; 249 250 PetscFunctionBegin; 251 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 252 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 253 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 254 PetscFunctionReturn(0); 255 } 256 257 #undef __FUNCT__ 258 #define __FUNCT__ "DMSetOptionsPrefix" 259 /*@C 260 DMSetOptionsPrefix - Sets the prefix used for searching for all 261 DMDA options in the database. 262 263 Logically Collective on DMDA 264 265 Input Parameter: 266 + da - the DMDA context 267 - prefix - the prefix to prepend to all option names 268 269 Notes: 270 A hyphen (-) must NOT be given at the beginning of the prefix name. 271 The first character of all runtime options is AUTOMATICALLY the hyphen. 272 273 Level: advanced 274 275 .keywords: DMDA, set, options, prefix, database 276 277 .seealso: DMSetFromOptions() 278 @*/ 279 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 280 { 281 PetscErrorCode ierr; 282 283 PetscFunctionBegin; 284 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 285 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 286 PetscFunctionReturn(0); 287 } 288 289 #undef __FUNCT__ 290 #define __FUNCT__ "DMDestroy" 291 /*@ 292 DMDestroy - Destroys a vector packer or DMDA. 293 294 Collective on DM 295 296 Input Parameter: 297 . dm - the DM object to destroy 298 299 Level: developer 300 301 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 302 303 @*/ 304 PetscErrorCode DMDestroy(DM *dm) 305 { 306 PetscInt i, cnt = 0, f; 307 DMNamedVecLink nlink,nnext; 308 PetscErrorCode ierr; 309 310 PetscFunctionBegin; 311 if (!*dm) PetscFunctionReturn(0); 312 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 313 314 /* count all the circular references of DM and its contained Vecs */ 315 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 316 if ((*dm)->localin[i]) cnt++; 317 if ((*dm)->globalin[i]) cnt++; 318 } 319 for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++; 320 if ((*dm)->x) { 321 DM obj; 322 ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr); 323 if (obj == *dm) cnt++; 324 } 325 for (nlink=(*dm)->namedlocal; nlink; nlink=nlink->next) cnt++; 326 if ((*dm)->x) { 327 DM obj; 328 ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr); 329 if (obj == *dm) cnt++; 330 } 331 332 if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 333 /* 334 Need this test because the dm references the vectors that 335 reference the dm, so destroying the dm calls destroy on the 336 vectors that cause another destroy on the dm 337 */ 338 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 339 ((PetscObject) (*dm))->refct = 0; 340 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 341 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 342 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 343 } 344 for (nlink=(*dm)->namedglobal; nlink; nlink=nnext) { /* Destroy the named vectors */ 345 nnext = nlink->next; 346 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 347 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 348 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 349 ierr = PetscFree(nlink);CHKERRQ(ierr); 350 } 351 (*dm)->namedglobal = NULL; 352 353 for (nlink=(*dm)->namedlocal; nlink; nlink=nnext) { /* Destroy the named local vectors */ 354 nnext = nlink->next; 355 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 356 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 357 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 358 ierr = PetscFree(nlink);CHKERRQ(ierr); 359 } 360 (*dm)->namedlocal = NULL; 361 362 /* Destroy the list of hooks */ 363 { 364 DMCoarsenHookLink link,next; 365 for (link=(*dm)->coarsenhook; link; link=next) { 366 next = link->next; 367 ierr = PetscFree(link);CHKERRQ(ierr); 368 } 369 (*dm)->coarsenhook = NULL; 370 } 371 { 372 DMRefineHookLink link,next; 373 for (link=(*dm)->refinehook; link; link=next) { 374 next = link->next; 375 ierr = PetscFree(link);CHKERRQ(ierr); 376 } 377 (*dm)->refinehook = NULL; 378 } 379 { 380 DMSubDomainHookLink link,next; 381 for (link=(*dm)->subdomainhook; link; link=next) { 382 next = link->next; 383 ierr = PetscFree(link);CHKERRQ(ierr); 384 } 385 (*dm)->subdomainhook = NULL; 386 } 387 { 388 DMGlobalToLocalHookLink link,next; 389 for (link=(*dm)->gtolhook; link; link=next) { 390 next = link->next; 391 ierr = PetscFree(link);CHKERRQ(ierr); 392 } 393 (*dm)->gtolhook = NULL; 394 } 395 /* Destroy the work arrays */ 396 { 397 DMWorkLink link,next; 398 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 399 for (link=(*dm)->workin; link; link=next) { 400 next = link->next; 401 ierr = PetscFree(link->mem);CHKERRQ(ierr); 402 ierr = PetscFree(link);CHKERRQ(ierr); 403 } 404 (*dm)->workin = NULL; 405 } 406 407 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 408 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 409 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 410 411 if ((*dm)->ctx && (*dm)->ctxdestroy) { 412 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 413 } 414 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 415 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 416 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 417 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 418 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmapb);CHKERRQ(ierr); 419 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 420 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 421 422 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 423 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 424 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 425 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 426 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 427 428 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 429 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 430 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 431 432 for (f = 0; f < (*dm)->numFields; ++f) { 433 ierr = PetscObjectDestroy(&(*dm)->fields[f]);CHKERRQ(ierr); 434 } 435 ierr = PetscFree((*dm)->fields);CHKERRQ(ierr); 436 /* if memory was published with AMS then destroy it */ 437 ierr = PetscObjectAMSViewOff((PetscObject)*dm);CHKERRQ(ierr); 438 439 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 440 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 441 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 442 PetscFunctionReturn(0); 443 } 444 445 #undef __FUNCT__ 446 #define __FUNCT__ "DMSetUp" 447 /*@ 448 DMSetUp - sets up the data structures inside a DM object 449 450 Collective on DM 451 452 Input Parameter: 453 . dm - the DM object to setup 454 455 Level: developer 456 457 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 458 459 @*/ 460 PetscErrorCode DMSetUp(DM dm) 461 { 462 PetscErrorCode ierr; 463 464 PetscFunctionBegin; 465 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 466 if (dm->setupcalled) PetscFunctionReturn(0); 467 if (dm->ops->setup) { 468 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 469 } 470 dm->setupcalled = PETSC_TRUE; 471 PetscFunctionReturn(0); 472 } 473 474 #undef __FUNCT__ 475 #define __FUNCT__ "DMSetFromOptions" 476 /*@ 477 DMSetFromOptions - sets parameters in a DM from the options database 478 479 Collective on DM 480 481 Input Parameter: 482 . dm - the DM object to set options for 483 484 Options Database: 485 + -dm_preallocate_only: Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 486 . -dm_vec_type <type> type of vector to create inside DM 487 . -dm_mat_type <type> type of matrix to create inside DM 488 - -dm_coloring_type <global or ghosted> 489 490 Level: developer 491 492 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 493 494 @*/ 495 PetscErrorCode DMSetFromOptions(DM dm) 496 { 497 char typeName[256] = MATAIJ; 498 PetscBool flg; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 503 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 504 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 505 ierr = PetscOptionsList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 506 if (flg) { 507 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 508 } 509 ierr = PetscOptionsList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 510 if (flg) { 511 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 512 } 513 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 514 if (dm->ops->setfromoptions) { 515 ierr = (*dm->ops->setfromoptions)(dm);CHKERRQ(ierr); 516 } 517 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 518 ierr = PetscObjectProcessOptionsHandlers((PetscObject) dm);CHKERRQ(ierr); 519 ierr = PetscOptionsEnd();CHKERRQ(ierr); 520 ierr = DMViewFromOptions(dm,"-dm_view");CHKERRQ(ierr); 521 PetscFunctionReturn(0); 522 } 523 524 #undef __FUNCT__ 525 #define __FUNCT__ "DMView" 526 /*@C 527 DMView - Views a vector packer or DMDA. 528 529 Collective on DM 530 531 Input Parameter: 532 + dm - the DM object to view 533 - v - the viewer 534 535 Level: developer 536 537 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 538 539 @*/ 540 PetscErrorCode DMView(DM dm,PetscViewer v) 541 { 542 PetscErrorCode ierr; 543 PetscBool isbinary; 544 545 PetscFunctionBegin; 546 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 547 if (!v) { 548 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 549 } 550 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 551 if (isbinary) { 552 PetscInt classid = DM_FILE_CLASSID; 553 char type[256]; 554 555 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 556 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 557 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 558 } 559 if (dm->ops->view) { 560 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 561 } 562 PetscFunctionReturn(0); 563 } 564 565 #undef __FUNCT__ 566 #define __FUNCT__ "DMCreateGlobalVector" 567 /*@ 568 DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object 569 570 Collective on DM 571 572 Input Parameter: 573 . dm - the DM object 574 575 Output Parameter: 576 . vec - the global vector 577 578 Level: beginner 579 580 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 581 582 @*/ 583 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 584 { 585 PetscErrorCode ierr; 586 587 PetscFunctionBegin; 588 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 589 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 590 PetscFunctionReturn(0); 591 } 592 593 #undef __FUNCT__ 594 #define __FUNCT__ "DMCreateLocalVector" 595 /*@ 596 DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object 597 598 Not Collective 599 600 Input Parameter: 601 . dm - the DM object 602 603 Output Parameter: 604 . vec - the local vector 605 606 Level: beginner 607 608 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 609 610 @*/ 611 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 612 { 613 PetscErrorCode ierr; 614 615 PetscFunctionBegin; 616 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 617 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 618 PetscFunctionReturn(0); 619 } 620 621 #undef __FUNCT__ 622 #define __FUNCT__ "DMGetLocalToGlobalMapping" 623 /*@ 624 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 625 626 Collective on DM 627 628 Input Parameter: 629 . dm - the DM that provides the mapping 630 631 Output Parameter: 632 . ltog - the mapping 633 634 Level: intermediate 635 636 Notes: 637 This mapping can then be used by VecSetLocalToGlobalMapping() or 638 MatSetLocalToGlobalMapping(). 639 640 .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMappingBlock() 641 @*/ 642 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 643 { 644 PetscErrorCode ierr; 645 646 PetscFunctionBegin; 647 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 648 PetscValidPointer(ltog,2); 649 if (!dm->ltogmap) { 650 PetscSection section, sectionGlobal; 651 652 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 653 if (section) { 654 PetscInt *ltog; 655 PetscInt pStart, pEnd, size, p, l; 656 657 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 658 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 659 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 660 ierr = PetscMalloc(size * sizeof(PetscInt), <og);CHKERRQ(ierr); /* We want the local+overlap size */ 661 for (p = pStart, l = 0; p < pEnd; ++p) { 662 PetscInt dof, off, c; 663 664 /* Should probably use constrained dofs */ 665 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 666 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 667 for (c = 0; c < dof; ++c, ++l) { 668 ltog[l] = off+c; 669 } 670 } 671 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 672 ierr = PetscLogObjectParent(dm, dm->ltogmap);CHKERRQ(ierr); 673 } else { 674 if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 675 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 676 } 677 } 678 *ltog = dm->ltogmap; 679 PetscFunctionReturn(0); 680 } 681 682 #undef __FUNCT__ 683 #define __FUNCT__ "DMGetLocalToGlobalMappingBlock" 684 /*@ 685 DMGetLocalToGlobalMappingBlock - Accesses the blocked local-to-global mapping in a DM. 686 687 Collective on DM 688 689 Input Parameter: 690 . da - the distributed array that provides the mapping 691 692 Output Parameter: 693 . ltog - the block mapping 694 695 Level: intermediate 696 697 Notes: 698 This mapping can then be used by VecSetLocalToGlobalMappingBlock() or 699 MatSetLocalToGlobalMappingBlock(). 700 701 .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMapping(), DMGetBlockSize(), VecSetBlockSize(), MatSetBlockSize() 702 @*/ 703 PetscErrorCode DMGetLocalToGlobalMappingBlock(DM dm,ISLocalToGlobalMapping *ltog) 704 { 705 PetscErrorCode ierr; 706 707 PetscFunctionBegin; 708 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 709 PetscValidPointer(ltog,2); 710 if (!dm->ltogmapb) { 711 PetscInt bs; 712 ierr = DMGetBlockSize(dm,&bs);CHKERRQ(ierr); 713 if (bs > 1) { 714 if (!dm->ops->getlocaltoglobalmappingblock) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMappingBlock"); 715 ierr = (*dm->ops->getlocaltoglobalmappingblock)(dm);CHKERRQ(ierr); 716 } else { 717 ierr = DMGetLocalToGlobalMapping(dm,&dm->ltogmapb);CHKERRQ(ierr); 718 ierr = PetscObjectReference((PetscObject)dm->ltogmapb);CHKERRQ(ierr); 719 } 720 } 721 *ltog = dm->ltogmapb; 722 PetscFunctionReturn(0); 723 } 724 725 #undef __FUNCT__ 726 #define __FUNCT__ "DMGetBlockSize" 727 /*@ 728 DMGetBlockSize - Gets the inherent block size associated with a DM 729 730 Not Collective 731 732 Input Parameter: 733 . dm - the DM with block structure 734 735 Output Parameter: 736 . bs - the block size, 1 implies no exploitable block structure 737 738 Level: intermediate 739 740 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMappingBlock() 741 @*/ 742 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 743 { 744 PetscFunctionBegin; 745 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 746 PetscValidPointer(bs,2); 747 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 748 *bs = dm->bs; 749 PetscFunctionReturn(0); 750 } 751 752 #undef __FUNCT__ 753 #define __FUNCT__ "DMCreateInterpolation" 754 /*@ 755 DMCreateInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects 756 757 Collective on DM 758 759 Input Parameter: 760 + dm1 - the DM object 761 - dm2 - the second, finer DM object 762 763 Output Parameter: 764 + mat - the interpolation 765 - vec - the scaling (optional) 766 767 Level: developer 768 769 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 770 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 771 772 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 773 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 774 775 776 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen() 777 778 @*/ 779 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 780 { 781 PetscErrorCode ierr; 782 783 PetscFunctionBegin; 784 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 785 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 786 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 787 PetscFunctionReturn(0); 788 } 789 790 #undef __FUNCT__ 791 #define __FUNCT__ "DMCreateInjection" 792 /*@ 793 DMCreateInjection - Gets injection matrix between two DMDA or DMComposite objects 794 795 Collective on DM 796 797 Input Parameter: 798 + dm1 - the DM object 799 - dm2 - the second, finer DM object 800 801 Output Parameter: 802 . ctx - the injection 803 804 Level: developer 805 806 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 807 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 808 809 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 810 811 @*/ 812 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,VecScatter *ctx) 813 { 814 PetscErrorCode ierr; 815 816 PetscFunctionBegin; 817 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 818 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 819 ierr = (*dm1->ops->getinjection)(dm1,dm2,ctx);CHKERRQ(ierr); 820 PetscFunctionReturn(0); 821 } 822 823 #undef __FUNCT__ 824 #define __FUNCT__ "DMCreateColoring" 825 /*@C 826 DMCreateColoring - Gets coloring for a DMDA or DMComposite 827 828 Collective on DM 829 830 Input Parameter: 831 + dm - the DM object 832 . ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL 833 - matype - either MATAIJ or MATBAIJ 834 835 Output Parameter: 836 . coloring - the coloring 837 838 Level: developer 839 840 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix() 841 842 @*/ 843 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,MatType mtype,ISColoring *coloring) 844 { 845 PetscErrorCode ierr; 846 847 PetscFunctionBegin; 848 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 849 if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet"); 850 ierr = (*dm->ops->getcoloring)(dm,ctype,mtype,coloring);CHKERRQ(ierr); 851 PetscFunctionReturn(0); 852 } 853 854 #undef __FUNCT__ 855 #define __FUNCT__ "DMCreateMatrix" 856 /*@C 857 DMCreateMatrix - Gets empty Jacobian for a DMDA or DMComposite 858 859 Collective on DM 860 861 Input Parameter: 862 + dm - the DM object 863 - mtype - Supported types are MATSEQAIJ, MATMPIAIJ, MATSEQBAIJ, MATMPIBAIJ, or 864 any type which inherits from one of these (such as MATAIJ) 865 866 Output Parameter: 867 . mat - the empty Jacobian 868 869 Level: beginner 870 871 Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 872 do not need to do it yourself. 873 874 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 875 the nonzero pattern call DMDASetMatPreallocateOnly() 876 877 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 878 internally by PETSc. 879 880 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 881 the indices for the global numbering for DMDAs which is complicated. 882 883 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 884 885 @*/ 886 PetscErrorCode DMCreateMatrix(DM dm,MatType mtype,Mat *mat) 887 { 888 PetscErrorCode ierr; 889 890 PetscFunctionBegin; 891 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 892 #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 893 ierr = MatInitializePackage();CHKERRQ(ierr); 894 #endif 895 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 896 PetscValidPointer(mat,3); 897 if (dm->mattype) { 898 ierr = (*dm->ops->creatematrix)(dm,dm->mattype,mat);CHKERRQ(ierr); 899 } else { 900 ierr = (*dm->ops->creatematrix)(dm,mtype,mat);CHKERRQ(ierr); 901 } 902 PetscFunctionReturn(0); 903 } 904 905 #undef __FUNCT__ 906 #define __FUNCT__ "DMSetMatrixPreallocateOnly" 907 /*@ 908 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 909 preallocated but the nonzero structure and zero values will not be set. 910 911 Logically Collective on DMDA 912 913 Input Parameter: 914 + dm - the DM 915 - only - PETSC_TRUE if only want preallocation 916 917 Level: developer 918 .seealso DMCreateMatrix() 919 @*/ 920 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 921 { 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 924 dm->prealloc_only = only; 925 PetscFunctionReturn(0); 926 } 927 928 #undef __FUNCT__ 929 #define __FUNCT__ "DMGetWorkArray" 930 /*@C 931 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 932 933 Not Collective 934 935 Input Parameters: 936 + dm - the DM object 937 . count - The minium size 938 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 939 940 Output Parameter: 941 . array - the work array 942 943 Level: developer 944 945 .seealso DMDestroy(), DMCreate() 946 @*/ 947 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 948 { 949 PetscErrorCode ierr; 950 DMWorkLink link; 951 size_t size; 952 953 PetscFunctionBegin; 954 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 955 PetscValidPointer(mem,4); 956 if (dm->workin) { 957 link = dm->workin; 958 dm->workin = dm->workin->next; 959 } else { 960 ierr = PetscNewLog(dm,struct _DMWorkLink,&link);CHKERRQ(ierr); 961 } 962 ierr = PetscDataTypeGetSize(dtype,&size);CHKERRQ(ierr); 963 if (size*count > link->bytes) { 964 ierr = PetscFree(link->mem);CHKERRQ(ierr); 965 ierr = PetscMalloc(size*count,&link->mem);CHKERRQ(ierr); 966 link->bytes = size*count; 967 } 968 link->next = dm->workout; 969 dm->workout = link; 970 *(void**)mem = link->mem; 971 PetscFunctionReturn(0); 972 } 973 974 #undef __FUNCT__ 975 #define __FUNCT__ "DMRestoreWorkArray" 976 /*@C 977 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 978 979 Not Collective 980 981 Input Parameters: 982 + dm - the DM object 983 . count - The minium size 984 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 985 986 Output Parameter: 987 . array - the work array 988 989 Level: developer 990 991 .seealso DMDestroy(), DMCreate() 992 @*/ 993 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 994 { 995 DMWorkLink *p,link; 996 997 PetscFunctionBegin; 998 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 999 PetscValidPointer(mem,4); 1000 for (p=&dm->workout; (link=*p); p=&link->next) { 1001 if (link->mem == *(void**)mem) { 1002 *p = link->next; 1003 link->next = dm->workin; 1004 dm->workin = link; 1005 *(void**)mem = NULL; 1006 PetscFunctionReturn(0); 1007 } 1008 } 1009 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1010 PetscFunctionReturn(0); 1011 } 1012 1013 #undef __FUNCT__ 1014 #define __FUNCT__ "DMSetNullSpaceConstructor" 1015 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1016 { 1017 PetscFunctionBegin; 1018 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1019 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1020 dm->nullspaceConstructors[field] = nullsp; 1021 PetscFunctionReturn(0); 1022 } 1023 1024 #undef __FUNCT__ 1025 #define __FUNCT__ "DMCreateFieldIS" 1026 /*@C 1027 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1028 1029 Not collective 1030 1031 Input Parameter: 1032 . dm - the DM object 1033 1034 Output Parameters: 1035 + numFields - The number of fields (or NULL if not requested) 1036 . fieldNames - The name for each field (or NULL if not requested) 1037 - fields - The global indices for each field (or NULL if not requested) 1038 1039 Level: intermediate 1040 1041 Notes: 1042 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1043 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1044 PetscFree(). 1045 1046 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1047 @*/ 1048 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1049 { 1050 PetscSection section, sectionGlobal; 1051 PetscErrorCode ierr; 1052 1053 PetscFunctionBegin; 1054 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1055 if (numFields) { 1056 PetscValidPointer(numFields,2); 1057 *numFields = 0; 1058 } 1059 if (fieldNames) { 1060 PetscValidPointer(fieldNames,3); 1061 *fieldNames = NULL; 1062 } 1063 if (fields) { 1064 PetscValidPointer(fields,4); 1065 *fields = NULL; 1066 } 1067 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1068 if (section) { 1069 PetscInt *fieldSizes, **fieldIndices; 1070 PetscInt nF, f, pStart, pEnd, p; 1071 1072 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1073 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1074 ierr = PetscMalloc2(nF,PetscInt,&fieldSizes,nF,PetscInt*,&fieldIndices);CHKERRQ(ierr); 1075 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1076 for (f = 0; f < nF; ++f) { 1077 fieldSizes[f] = 0; 1078 } 1079 for (p = pStart; p < pEnd; ++p) { 1080 PetscInt gdof; 1081 1082 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1083 if (gdof > 0) { 1084 for (f = 0; f < nF; ++f) { 1085 PetscInt fdof, fcdof; 1086 1087 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1088 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1089 fieldSizes[f] += fdof-fcdof; 1090 } 1091 } 1092 } 1093 for (f = 0; f < nF; ++f) { 1094 ierr = PetscMalloc(fieldSizes[f] * sizeof(PetscInt), &fieldIndices[f]);CHKERRQ(ierr); 1095 fieldSizes[f] = 0; 1096 } 1097 for (p = pStart; p < pEnd; ++p) { 1098 PetscInt gdof, goff; 1099 1100 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1101 if (gdof > 0) { 1102 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1103 for (f = 0; f < nF; ++f) { 1104 PetscInt fdof, fcdof, fc; 1105 1106 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1107 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1108 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1109 fieldIndices[f][fieldSizes[f]] = goff++; 1110 } 1111 } 1112 } 1113 } 1114 if (numFields) *numFields = nF; 1115 if (fieldNames) { 1116 ierr = PetscMalloc(nF * sizeof(char*), fieldNames);CHKERRQ(ierr); 1117 for (f = 0; f < nF; ++f) { 1118 const char *fieldName; 1119 1120 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1121 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1122 } 1123 } 1124 if (fields) { 1125 ierr = PetscMalloc(nF * sizeof(IS), fields);CHKERRQ(ierr); 1126 for (f = 0; f < nF; ++f) { 1127 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1128 } 1129 } 1130 ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr); 1131 } else if (dm->ops->createfieldis) { 1132 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1133 } 1134 PetscFunctionReturn(0); 1135 } 1136 1137 1138 #undef __FUNCT__ 1139 #define __FUNCT__ "DMCreateFieldDecomposition" 1140 /*@C 1141 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1142 corresponding to different fields: each IS contains the global indices of the dofs of the 1143 corresponding field. The optional list of DMs define the DM for each subproblem. 1144 Generalizes DMCreateFieldIS(). 1145 1146 Not collective 1147 1148 Input Parameter: 1149 . dm - the DM object 1150 1151 Output Parameters: 1152 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1153 . namelist - The name for each field (or NULL if not requested) 1154 . islist - The global indices for each field (or NULL if not requested) 1155 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1156 1157 Level: intermediate 1158 1159 Notes: 1160 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1161 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1162 and all of the arrays should be freed with PetscFree(). 1163 1164 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1165 @*/ 1166 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1167 { 1168 PetscErrorCode ierr; 1169 1170 PetscFunctionBegin; 1171 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1172 if (len) { 1173 PetscValidPointer(len,2); 1174 *len = 0; 1175 } 1176 if (namelist) { 1177 PetscValidPointer(namelist,3); 1178 *namelist = 0; 1179 } 1180 if (islist) { 1181 PetscValidPointer(islist,4); 1182 *islist = 0; 1183 } 1184 if (dmlist) { 1185 PetscValidPointer(dmlist,5); 1186 *dmlist = 0; 1187 } 1188 /* 1189 Is it a good idea to apply the following check across all impls? 1190 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1191 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1192 */ 1193 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1194 if (!dm->ops->createfielddecomposition) { 1195 PetscSection section; 1196 PetscInt numFields, f; 1197 1198 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1199 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1200 if (section && numFields && dm->ops->createsubdm) { 1201 *len = numFields; 1202 ierr = PetscMalloc3(numFields,char*,namelist,numFields,IS,islist,numFields,DM,dmlist);CHKERRQ(ierr); 1203 for (f = 0; f < numFields; ++f) { 1204 const char *fieldName; 1205 1206 ierr = DMCreateSubDM(dm, 1, &f, &(*islist)[f], &(*dmlist)[f]);CHKERRQ(ierr); 1207 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1208 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1209 } 1210 } else { 1211 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1212 /* By default there are no DMs associated with subproblems. */ 1213 if (dmlist) *dmlist = NULL; 1214 } 1215 } else { 1216 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1217 } 1218 PetscFunctionReturn(0); 1219 } 1220 1221 #undef __FUNCT__ 1222 #define __FUNCT__ "DMCreateSubDM" 1223 /*@C 1224 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1225 The fields are defined by DMCreateFieldIS(). 1226 1227 Not collective 1228 1229 Input Parameters: 1230 + dm - the DM object 1231 . numFields - number of fields in this subproblem 1232 - len - The number of subproblems in the decomposition (or NULL if not requested) 1233 1234 Output Parameters: 1235 . is - The global indices for the subproblem 1236 - dm - The DM for the subproblem 1237 1238 Level: intermediate 1239 1240 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1241 @*/ 1242 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1243 { 1244 PetscErrorCode ierr; 1245 1246 PetscFunctionBegin; 1247 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1248 PetscValidPointer(fields,3); 1249 if (is) PetscValidPointer(is,4); 1250 if (subdm) PetscValidPointer(subdm,5); 1251 if (dm->ops->createsubdm) { 1252 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1253 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1254 PetscFunctionReturn(0); 1255 } 1256 1257 1258 #undef __FUNCT__ 1259 #define __FUNCT__ "DMCreateDomainDecomposition" 1260 /*@C 1261 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1262 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1263 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1264 define a nonoverlapping covering, while outer subdomains can overlap. 1265 The optional list of DMs define the DM for each subproblem. 1266 1267 Not collective 1268 1269 Input Parameter: 1270 . dm - the DM object 1271 1272 Output Parameters: 1273 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1274 . namelist - The name for each subdomain (or NULL if not requested) 1275 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1276 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1277 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1278 1279 Level: intermediate 1280 1281 Notes: 1282 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1283 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1284 and all of the arrays should be freed with PetscFree(). 1285 1286 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1287 @*/ 1288 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1289 { 1290 PetscErrorCode ierr; 1291 DMSubDomainHookLink link; 1292 PetscInt i,l; 1293 1294 PetscFunctionBegin; 1295 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1296 if (len) {PetscValidPointer(len,2); *len = 0;} 1297 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1298 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1299 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1300 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1301 /* 1302 Is it a good idea to apply the following check across all impls? 1303 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1304 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1305 */ 1306 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1307 if (dm->ops->createdomaindecomposition) { 1308 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1309 /* copy subdomain hooks and context over to the subdomain DMs */ 1310 if (dmlist) { 1311 for (i = 0; i < l; i++) { 1312 for (link=dm->subdomainhook; link; link=link->next) { 1313 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1314 } 1315 (*dmlist)[i]->ctx = dm->ctx; 1316 } 1317 } 1318 if (len) *len = l; 1319 } 1320 PetscFunctionReturn(0); 1321 } 1322 1323 1324 #undef __FUNCT__ 1325 #define __FUNCT__ "DMCreateDomainDecompositionScatters" 1326 /*@C 1327 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1328 1329 Not collective 1330 1331 Input Parameters: 1332 + dm - the DM object 1333 . n - the number of subdomain scatters 1334 - subdms - the local subdomains 1335 1336 Output Parameters: 1337 + n - the number of scatters returned 1338 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1339 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1340 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1341 1342 Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1343 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1344 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1345 solution and residual data. 1346 1347 Level: developer 1348 1349 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1350 @*/ 1351 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1352 { 1353 PetscErrorCode ierr; 1354 1355 PetscFunctionBegin; 1356 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1357 PetscValidPointer(subdms,3); 1358 PetscValidPointer(iscat,4); 1359 PetscValidPointer(oscat,5); 1360 PetscValidPointer(gscat,6); 1361 if (dm->ops->createddscatters) { 1362 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1363 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined"); 1364 PetscFunctionReturn(0); 1365 } 1366 1367 #undef __FUNCT__ 1368 #define __FUNCT__ "DMRefine" 1369 /*@ 1370 DMRefine - Refines a DM object 1371 1372 Collective on DM 1373 1374 Input Parameter: 1375 + dm - the DM object 1376 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1377 1378 Output Parameter: 1379 . dmf - the refined DM, or NULL 1380 1381 Note: If no refinement was done, the return value is NULL 1382 1383 Level: developer 1384 1385 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1386 @*/ 1387 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1388 { 1389 PetscErrorCode ierr; 1390 DMRefineHookLink link; 1391 1392 PetscFunctionBegin; 1393 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1394 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1395 if (*dmf) { 1396 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1397 1398 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1399 1400 (*dmf)->ctx = dm->ctx; 1401 (*dmf)->leveldown = dm->leveldown; 1402 (*dmf)->levelup = dm->levelup + 1; 1403 1404 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1405 for (link=dm->refinehook; link; link=link->next) { 1406 if (link->refinehook) { 1407 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1408 } 1409 } 1410 } 1411 PetscFunctionReturn(0); 1412 } 1413 1414 #undef __FUNCT__ 1415 #define __FUNCT__ "DMRefineHookAdd" 1416 /*@C 1417 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1418 1419 Logically Collective 1420 1421 Input Arguments: 1422 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1423 . refinehook - function to run when setting up a coarser level 1424 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1425 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1426 1427 Calling sequence of refinehook: 1428 $ refinehook(DM coarse,DM fine,void *ctx); 1429 1430 + coarse - coarse level DM 1431 . fine - fine level DM to interpolate problem to 1432 - ctx - optional user-defined function context 1433 1434 Calling sequence for interphook: 1435 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1436 1437 + coarse - coarse level DM 1438 . interp - matrix interpolating a coarse-level solution to the finer grid 1439 . fine - fine level DM to update 1440 - ctx - optional user-defined function context 1441 1442 Level: advanced 1443 1444 Notes: 1445 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1446 1447 If this function is called multiple times, the hooks will be run in the order they are added. 1448 1449 This function is currently not available from Fortran. 1450 1451 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1452 @*/ 1453 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1454 { 1455 PetscErrorCode ierr; 1456 DMRefineHookLink link,*p; 1457 1458 PetscFunctionBegin; 1459 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1460 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1461 ierr = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr); 1462 link->refinehook = refinehook; 1463 link->interphook = interphook; 1464 link->ctx = ctx; 1465 link->next = NULL; 1466 *p = link; 1467 PetscFunctionReturn(0); 1468 } 1469 1470 #undef __FUNCT__ 1471 #define __FUNCT__ "DMInterpolate" 1472 /*@ 1473 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1474 1475 Collective if any hooks are 1476 1477 Input Arguments: 1478 + coarse - coarser DM to use as a base 1479 . restrct - interpolation matrix, apply using MatInterpolate() 1480 - fine - finer DM to update 1481 1482 Level: developer 1483 1484 .seealso: DMRefineHookAdd(), MatInterpolate() 1485 @*/ 1486 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1487 { 1488 PetscErrorCode ierr; 1489 DMRefineHookLink link; 1490 1491 PetscFunctionBegin; 1492 for (link=fine->refinehook; link; link=link->next) { 1493 if (link->interphook) { 1494 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1495 } 1496 } 1497 PetscFunctionReturn(0); 1498 } 1499 1500 #undef __FUNCT__ 1501 #define __FUNCT__ "DMGetRefineLevel" 1502 /*@ 1503 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1504 1505 Not Collective 1506 1507 Input Parameter: 1508 . dm - the DM object 1509 1510 Output Parameter: 1511 . level - number of refinements 1512 1513 Level: developer 1514 1515 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1516 1517 @*/ 1518 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1519 { 1520 PetscFunctionBegin; 1521 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1522 *level = dm->levelup; 1523 PetscFunctionReturn(0); 1524 } 1525 1526 #undef __FUNCT__ 1527 #define __FUNCT__ "DMGlobalToLocalHookAdd" 1528 /*@C 1529 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1530 1531 Logically Collective 1532 1533 Input Arguments: 1534 + dm - the DM 1535 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 1536 . endhook - function to run after DMGlobalToLocalEnd() has completed 1537 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1538 1539 Calling sequence for beginhook: 1540 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1541 1542 + dm - global DM 1543 . g - global vector 1544 . mode - mode 1545 . l - local vector 1546 - ctx - optional user-defined function context 1547 1548 1549 Calling sequence for endhook: 1550 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1551 1552 + global - global DM 1553 - ctx - optional user-defined function context 1554 1555 Level: advanced 1556 1557 Notes: 1558 This function is only needed if auxiliary data needs to be set up on coarse grids. 1559 1560 If this function is called multiple times, the hooks will be run in the order they are added. 1561 1562 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 1563 extract the finest level information from its context (instead of from the SNES). 1564 1565 This function is currently not available from Fortran. 1566 1567 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1568 @*/ 1569 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1570 { 1571 PetscErrorCode ierr; 1572 DMGlobalToLocalHookLink link,*p; 1573 1574 PetscFunctionBegin; 1575 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1576 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1577 ierr = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr); 1578 link->beginhook = beginhook; 1579 link->endhook = endhook; 1580 link->ctx = ctx; 1581 link->next = NULL; 1582 *p = link; 1583 PetscFunctionReturn(0); 1584 } 1585 1586 #undef __FUNCT__ 1587 #define __FUNCT__ "DMGlobalToLocalBegin" 1588 /*@ 1589 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1590 1591 Neighbor-wise Collective on DM 1592 1593 Input Parameters: 1594 + dm - the DM object 1595 . g - the global vector 1596 . mode - INSERT_VALUES or ADD_VALUES 1597 - l - the local vector 1598 1599 1600 Level: beginner 1601 1602 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1603 1604 @*/ 1605 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1606 { 1607 PetscSF sf; 1608 PetscErrorCode ierr; 1609 DMGlobalToLocalHookLink link; 1610 1611 PetscFunctionBegin; 1612 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1613 for (link=dm->gtolhook; link; link=link->next) { 1614 if (link->beginhook) { 1615 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 1616 } 1617 } 1618 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1619 if (sf) { 1620 PetscScalar *lArray, *gArray; 1621 1622 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1623 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1624 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1625 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1626 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1627 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1628 } else { 1629 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1630 } 1631 PetscFunctionReturn(0); 1632 } 1633 1634 #undef __FUNCT__ 1635 #define __FUNCT__ "DMGlobalToLocalEnd" 1636 /*@ 1637 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1638 1639 Neighbor-wise Collective on DM 1640 1641 Input Parameters: 1642 + dm - the DM object 1643 . g - the global vector 1644 . mode - INSERT_VALUES or ADD_VALUES 1645 - l - the local vector 1646 1647 1648 Level: beginner 1649 1650 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1651 1652 @*/ 1653 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 1654 { 1655 PetscSF sf; 1656 PetscErrorCode ierr; 1657 PetscScalar *lArray, *gArray; 1658 DMGlobalToLocalHookLink link; 1659 1660 PetscFunctionBegin; 1661 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1662 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1663 if (sf) { 1664 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1665 1666 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1667 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1668 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1669 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1670 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1671 } else { 1672 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1673 } 1674 for (link=dm->gtolhook; link; link=link->next) { 1675 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 1676 } 1677 PetscFunctionReturn(0); 1678 } 1679 1680 #undef __FUNCT__ 1681 #define __FUNCT__ "DMLocalToGlobalBegin" 1682 /*@ 1683 DMLocalToGlobalBegin - updates global vectors from local vectors 1684 1685 Neighbor-wise Collective on DM 1686 1687 Input Parameters: 1688 + dm - the DM object 1689 . l - the local vector 1690 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that 1691 base point. 1692 - - the global vector 1693 1694 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. If you would like to simply add the non-ghosted values in the local 1695 array into the global array you need to either (1) zero the ghosted locations and use ADD_VALUES or (2) use INSERT_VALUES into a work global array and then add the work 1696 global array to the final global array with VecAXPY(). 1697 1698 Level: beginner 1699 1700 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 1701 1702 @*/ 1703 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 1704 { 1705 PetscSF sf; 1706 PetscErrorCode ierr; 1707 1708 PetscFunctionBegin; 1709 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1710 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1711 if (sf) { 1712 MPI_Op op; 1713 PetscScalar *lArray, *gArray; 1714 1715 switch (mode) { 1716 case INSERT_VALUES: 1717 case INSERT_ALL_VALUES: 1718 #if defined(PETSC_HAVE_MPI_REPLACE) 1719 op = MPI_REPLACE; break; 1720 #else 1721 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No support for INSERT_VALUES without an MPI-2 implementation"); 1722 #endif 1723 case ADD_VALUES: 1724 case ADD_ALL_VALUES: 1725 op = MPI_SUM; break; 1726 default: 1727 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1728 } 1729 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1730 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1731 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr); 1732 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1733 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1734 } else { 1735 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1736 } 1737 PetscFunctionReturn(0); 1738 } 1739 1740 #undef __FUNCT__ 1741 #define __FUNCT__ "DMLocalToGlobalEnd" 1742 /*@ 1743 DMLocalToGlobalEnd - updates global vectors from local vectors 1744 1745 Neighbor-wise Collective on DM 1746 1747 Input Parameters: 1748 + dm - the DM object 1749 . l - the local vector 1750 . mode - INSERT_VALUES or ADD_VALUES 1751 - g - the global vector 1752 1753 1754 Level: beginner 1755 1756 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 1757 1758 @*/ 1759 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 1760 { 1761 PetscSF sf; 1762 PetscErrorCode ierr; 1763 1764 PetscFunctionBegin; 1765 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1766 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1767 if (sf) { 1768 MPI_Op op; 1769 PetscScalar *lArray, *gArray; 1770 1771 switch (mode) { 1772 case INSERT_VALUES: 1773 case INSERT_ALL_VALUES: 1774 #if defined(PETSC_HAVE_MPI_REPLACE) 1775 op = MPI_REPLACE; break; 1776 #else 1777 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No support for INSERT_VALUES without an MPI-2 implementation"); 1778 #endif 1779 case ADD_VALUES: 1780 case ADD_ALL_VALUES: 1781 op = MPI_SUM; break; 1782 default: 1783 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1784 } 1785 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1786 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1787 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr); 1788 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1789 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1790 } else { 1791 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1792 } 1793 PetscFunctionReturn(0); 1794 } 1795 1796 #undef __FUNCT__ 1797 #define __FUNCT__ "DMCoarsen" 1798 /*@ 1799 DMCoarsen - Coarsens a DM object 1800 1801 Collective on DM 1802 1803 Input Parameter: 1804 + dm - the DM object 1805 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1806 1807 Output Parameter: 1808 . dmc - the coarsened DM 1809 1810 Level: developer 1811 1812 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1813 1814 @*/ 1815 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 1816 { 1817 PetscErrorCode ierr; 1818 DMCoarsenHookLink link; 1819 1820 PetscFunctionBegin; 1821 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1822 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 1823 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 1824 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 1825 (*dmc)->ctx = dm->ctx; 1826 (*dmc)->levelup = dm->levelup; 1827 (*dmc)->leveldown = dm->leveldown + 1; 1828 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 1829 for (link=dm->coarsenhook; link; link=link->next) { 1830 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 1831 } 1832 PetscFunctionReturn(0); 1833 } 1834 1835 #undef __FUNCT__ 1836 #define __FUNCT__ "DMCoarsenHookAdd" 1837 /*@C 1838 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 1839 1840 Logically Collective 1841 1842 Input Arguments: 1843 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 1844 . coarsenhook - function to run when setting up a coarser level 1845 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 1846 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1847 1848 Calling sequence of coarsenhook: 1849 $ coarsenhook(DM fine,DM coarse,void *ctx); 1850 1851 + fine - fine level DM 1852 . coarse - coarse level DM to restrict problem to 1853 - ctx - optional user-defined function context 1854 1855 Calling sequence for restricthook: 1856 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 1857 1858 + fine - fine level DM 1859 . mrestrict - matrix restricting a fine-level solution to the coarse grid 1860 . rscale - scaling vector for restriction 1861 . inject - matrix restricting by injection 1862 . coarse - coarse level DM to update 1863 - ctx - optional user-defined function context 1864 1865 Level: advanced 1866 1867 Notes: 1868 This function is only needed if auxiliary data needs to be set up on coarse grids. 1869 1870 If this function is called multiple times, the hooks will be run in the order they are added. 1871 1872 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 1873 extract the finest level information from its context (instead of from the SNES). 1874 1875 This function is currently not available from Fortran. 1876 1877 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1878 @*/ 1879 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 1880 { 1881 PetscErrorCode ierr; 1882 DMCoarsenHookLink link,*p; 1883 1884 PetscFunctionBegin; 1885 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 1886 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1887 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 1888 link->coarsenhook = coarsenhook; 1889 link->restricthook = restricthook; 1890 link->ctx = ctx; 1891 link->next = NULL; 1892 *p = link; 1893 PetscFunctionReturn(0); 1894 } 1895 1896 #undef __FUNCT__ 1897 #define __FUNCT__ "DMRestrict" 1898 /*@ 1899 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 1900 1901 Collective if any hooks are 1902 1903 Input Arguments: 1904 + fine - finer DM to use as a base 1905 . restrct - restriction matrix, apply using MatRestrict() 1906 . inject - injection matrix, also use MatRestrict() 1907 - coarse - coarer DM to update 1908 1909 Level: developer 1910 1911 .seealso: DMCoarsenHookAdd(), MatRestrict() 1912 @*/ 1913 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 1914 { 1915 PetscErrorCode ierr; 1916 DMCoarsenHookLink link; 1917 1918 PetscFunctionBegin; 1919 for (link=fine->coarsenhook; link; link=link->next) { 1920 if (link->restricthook) { 1921 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 1922 } 1923 } 1924 PetscFunctionReturn(0); 1925 } 1926 1927 #undef __FUNCT__ 1928 #define __FUNCT__ "DMSubDomainHookAdd" 1929 /*@C 1930 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 1931 1932 Logically Collective 1933 1934 Input Arguments: 1935 + global - global DM 1936 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 1937 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1938 1939 Calling sequence for restricthook: 1940 $ restricthook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1941 1942 + global - global DM 1943 . out - scatter to the outer (with ghost and overlap points) block vector 1944 . in - scatter to block vector values only owned locally 1945 . block - block DM (may just be a shell if the global DM is passed in correctly) 1946 - ctx - optional user-defined function context 1947 1948 Level: advanced 1949 1950 Notes: 1951 This function is only needed if auxiliary data needs to be set up on coarse grids. 1952 1953 If this function is called multiple times, the hooks will be run in the order they are added. 1954 1955 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 1956 extract the finest level information from its context (instead of from the SNES). 1957 1958 This function is currently not available from Fortran. 1959 1960 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1961 @*/ 1962 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 1963 { 1964 PetscErrorCode ierr; 1965 DMSubDomainHookLink link,*p; 1966 1967 PetscFunctionBegin; 1968 PetscValidHeaderSpecific(global,DM_CLASSID,1); 1969 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1970 ierr = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr); 1971 link->restricthook = restricthook; 1972 link->ddhook = ddhook; 1973 link->ctx = ctx; 1974 link->next = NULL; 1975 *p = link; 1976 PetscFunctionReturn(0); 1977 } 1978 1979 #undef __FUNCT__ 1980 #define __FUNCT__ "DMSubDomainRestrict" 1981 /*@ 1982 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 1983 1984 Collective if any hooks are 1985 1986 Input Arguments: 1987 + fine - finer DM to use as a base 1988 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 1989 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 1990 - coarse - coarer DM to update 1991 1992 Level: developer 1993 1994 .seealso: DMCoarsenHookAdd(), MatRestrict() 1995 @*/ 1996 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 1997 { 1998 PetscErrorCode ierr; 1999 DMSubDomainHookLink link; 2000 2001 PetscFunctionBegin; 2002 for (link=global->subdomainhook; link; link=link->next) { 2003 if (link->restricthook) { 2004 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2005 } 2006 } 2007 PetscFunctionReturn(0); 2008 } 2009 2010 #undef __FUNCT__ 2011 #define __FUNCT__ "DMGetCoarsenLevel" 2012 /*@ 2013 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2014 2015 Not Collective 2016 2017 Input Parameter: 2018 . dm - the DM object 2019 2020 Output Parameter: 2021 . level - number of coarsenings 2022 2023 Level: developer 2024 2025 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2026 2027 @*/ 2028 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2029 { 2030 PetscFunctionBegin; 2031 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2032 *level = dm->leveldown; 2033 PetscFunctionReturn(0); 2034 } 2035 2036 2037 2038 #undef __FUNCT__ 2039 #define __FUNCT__ "DMRefineHierarchy" 2040 /*@C 2041 DMRefineHierarchy - Refines a DM object, all levels at once 2042 2043 Collective on DM 2044 2045 Input Parameter: 2046 + dm - the DM object 2047 - nlevels - the number of levels of refinement 2048 2049 Output Parameter: 2050 . dmf - the refined DM hierarchy 2051 2052 Level: developer 2053 2054 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2055 2056 @*/ 2057 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2058 { 2059 PetscErrorCode ierr; 2060 2061 PetscFunctionBegin; 2062 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2063 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2064 if (nlevels == 0) PetscFunctionReturn(0); 2065 if (dm->ops->refinehierarchy) { 2066 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2067 } else if (dm->ops->refine) { 2068 PetscInt i; 2069 2070 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2071 for (i=1; i<nlevels; i++) { 2072 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2073 } 2074 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2075 PetscFunctionReturn(0); 2076 } 2077 2078 #undef __FUNCT__ 2079 #define __FUNCT__ "DMCoarsenHierarchy" 2080 /*@C 2081 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2082 2083 Collective on DM 2084 2085 Input Parameter: 2086 + dm - the DM object 2087 - nlevels - the number of levels of coarsening 2088 2089 Output Parameter: 2090 . dmc - the coarsened DM hierarchy 2091 2092 Level: developer 2093 2094 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2095 2096 @*/ 2097 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2098 { 2099 PetscErrorCode ierr; 2100 2101 PetscFunctionBegin; 2102 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2103 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2104 if (nlevels == 0) PetscFunctionReturn(0); 2105 PetscValidPointer(dmc,3); 2106 if (dm->ops->coarsenhierarchy) { 2107 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2108 } else if (dm->ops->coarsen) { 2109 PetscInt i; 2110 2111 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2112 for (i=1; i<nlevels; i++) { 2113 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2114 } 2115 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2116 PetscFunctionReturn(0); 2117 } 2118 2119 #undef __FUNCT__ 2120 #define __FUNCT__ "DMCreateAggregates" 2121 /*@ 2122 DMCreateAggregates - Gets the aggregates that map between 2123 grids associated with two DMs. 2124 2125 Collective on DM 2126 2127 Input Parameters: 2128 + dmc - the coarse grid DM 2129 - dmf - the fine grid DM 2130 2131 Output Parameters: 2132 . rest - the restriction matrix (transpose of the projection matrix) 2133 2134 Level: intermediate 2135 2136 .keywords: interpolation, restriction, multigrid 2137 2138 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2139 @*/ 2140 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2141 { 2142 PetscErrorCode ierr; 2143 2144 PetscFunctionBegin; 2145 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2146 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2147 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2148 PetscFunctionReturn(0); 2149 } 2150 2151 #undef __FUNCT__ 2152 #define __FUNCT__ "DMSetApplicationContextDestroy" 2153 /*@C 2154 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2155 2156 Not Collective 2157 2158 Input Parameters: 2159 + dm - the DM object 2160 - destroy - the destroy function 2161 2162 Level: intermediate 2163 2164 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2165 2166 @*/ 2167 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2168 { 2169 PetscFunctionBegin; 2170 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2171 dm->ctxdestroy = destroy; 2172 PetscFunctionReturn(0); 2173 } 2174 2175 #undef __FUNCT__ 2176 #define __FUNCT__ "DMSetApplicationContext" 2177 /*@ 2178 DMSetApplicationContext - Set a user context into a DM object 2179 2180 Not Collective 2181 2182 Input Parameters: 2183 + dm - the DM object 2184 - ctx - the user context 2185 2186 Level: intermediate 2187 2188 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2189 2190 @*/ 2191 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2192 { 2193 PetscFunctionBegin; 2194 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2195 dm->ctx = ctx; 2196 PetscFunctionReturn(0); 2197 } 2198 2199 #undef __FUNCT__ 2200 #define __FUNCT__ "DMGetApplicationContext" 2201 /*@ 2202 DMGetApplicationContext - Gets a user context from a DM object 2203 2204 Not Collective 2205 2206 Input Parameter: 2207 . dm - the DM object 2208 2209 Output Parameter: 2210 . ctx - the user context 2211 2212 Level: intermediate 2213 2214 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2215 2216 @*/ 2217 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2218 { 2219 PetscFunctionBegin; 2220 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2221 *(void**)ctx = dm->ctx; 2222 PetscFunctionReturn(0); 2223 } 2224 2225 #undef __FUNCT__ 2226 #define __FUNCT__ "DMSetVariableBounds" 2227 /*@C 2228 DMSetVariableBounds - sets a function to compute the the lower and upper bound vectors for SNESVI. 2229 2230 Logically Collective on DM 2231 2232 Input Parameter: 2233 + dm - the DM object 2234 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2235 2236 Level: intermediate 2237 2238 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2239 DMSetJacobian() 2240 2241 @*/ 2242 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2243 { 2244 PetscFunctionBegin; 2245 dm->ops->computevariablebounds = f; 2246 PetscFunctionReturn(0); 2247 } 2248 2249 #undef __FUNCT__ 2250 #define __FUNCT__ "DMHasVariableBounds" 2251 /*@ 2252 DMHasVariableBounds - does the DM object have a variable bounds function? 2253 2254 Not Collective 2255 2256 Input Parameter: 2257 . dm - the DM object to destroy 2258 2259 Output Parameter: 2260 . flg - PETSC_TRUE if the variable bounds function exists 2261 2262 Level: developer 2263 2264 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2265 2266 @*/ 2267 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2268 { 2269 PetscFunctionBegin; 2270 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2271 PetscFunctionReturn(0); 2272 } 2273 2274 #undef __FUNCT__ 2275 #define __FUNCT__ "DMComputeVariableBounds" 2276 /*@C 2277 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2278 2279 Logically Collective on DM 2280 2281 Input Parameters: 2282 + dm - the DM object to destroy 2283 - x - current solution at which the bounds are computed 2284 2285 Output parameters: 2286 + xl - lower bound 2287 - xu - upper bound 2288 2289 Level: intermediate 2290 2291 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2292 2293 @*/ 2294 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2295 { 2296 PetscErrorCode ierr; 2297 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2300 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2301 if (dm->ops->computevariablebounds) { 2302 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2303 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2304 PetscFunctionReturn(0); 2305 } 2306 2307 #undef __FUNCT__ 2308 #define __FUNCT__ "DMHasColoring" 2309 /*@ 2310 DMHasColoring - does the DM object have a method of providing a coloring? 2311 2312 Not Collective 2313 2314 Input Parameter: 2315 . dm - the DM object 2316 2317 Output Parameter: 2318 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2319 2320 Level: developer 2321 2322 .seealso DMHasFunction(), DMCreateColoring() 2323 2324 @*/ 2325 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2326 { 2327 PetscFunctionBegin; 2328 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2329 PetscFunctionReturn(0); 2330 } 2331 2332 #undef __FUNCT__ 2333 #define __FUNCT__ "DMSetVec" 2334 /*@C 2335 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2336 2337 Collective on DM 2338 2339 Input Parameter: 2340 + dm - the DM object 2341 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2342 2343 Level: developer 2344 2345 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2346 2347 @*/ 2348 PetscErrorCode DMSetVec(DM dm,Vec x) 2349 { 2350 PetscErrorCode ierr; 2351 2352 PetscFunctionBegin; 2353 if (x) { 2354 if (!dm->x) { 2355 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2356 } 2357 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2358 } else if (dm->x) { 2359 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2360 } 2361 PetscFunctionReturn(0); 2362 } 2363 2364 PetscFunctionList DMList = NULL; 2365 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2366 2367 #undef __FUNCT__ 2368 #define __FUNCT__ "DMSetType" 2369 /*@C 2370 DMSetType - Builds a DM, for a particular DM implementation. 2371 2372 Collective on DM 2373 2374 Input Parameters: 2375 + dm - The DM object 2376 - method - The name of the DM type 2377 2378 Options Database Key: 2379 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2380 2381 Notes: 2382 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2383 2384 Level: intermediate 2385 2386 .keywords: DM, set, type 2387 .seealso: DMGetType(), DMCreate() 2388 @*/ 2389 PetscErrorCode DMSetType(DM dm, DMType method) 2390 { 2391 PetscErrorCode (*r)(DM); 2392 PetscBool match; 2393 PetscErrorCode ierr; 2394 2395 PetscFunctionBegin; 2396 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2397 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2398 if (match) PetscFunctionReturn(0); 2399 2400 if (!DMRegisterAllCalled) {ierr = DMRegisterAll();CHKERRQ(ierr);} 2401 ierr = PetscFunctionListFind(DMList, method,(void (**)(void)) &r);CHKERRQ(ierr); 2402 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2403 2404 if (dm->ops->destroy) { 2405 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2406 dm->ops->destroy = NULL; 2407 } 2408 ierr = (*r)(dm);CHKERRQ(ierr); 2409 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2410 PetscFunctionReturn(0); 2411 } 2412 2413 #undef __FUNCT__ 2414 #define __FUNCT__ "DMGetType" 2415 /*@C 2416 DMGetType - Gets the DM type name (as a string) from the DM. 2417 2418 Not Collective 2419 2420 Input Parameter: 2421 . dm - The DM 2422 2423 Output Parameter: 2424 . type - The DM type name 2425 2426 Level: intermediate 2427 2428 .keywords: DM, get, type, name 2429 .seealso: DMSetType(), DMCreate() 2430 @*/ 2431 PetscErrorCode DMGetType(DM dm, DMType *type) 2432 { 2433 PetscErrorCode ierr; 2434 2435 PetscFunctionBegin; 2436 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2437 PetscValidCharPointer(type,2); 2438 if (!DMRegisterAllCalled) { 2439 ierr = DMRegisterAll();CHKERRQ(ierr); 2440 } 2441 *type = ((PetscObject)dm)->type_name; 2442 PetscFunctionReturn(0); 2443 } 2444 2445 #undef __FUNCT__ 2446 #define __FUNCT__ "DMConvert" 2447 /*@C 2448 DMConvert - Converts a DM to another DM, either of the same or different type. 2449 2450 Collective on DM 2451 2452 Input Parameters: 2453 + dm - the DM 2454 - newtype - new DM type (use "same" for the same type) 2455 2456 Output Parameter: 2457 . M - pointer to new DM 2458 2459 Notes: 2460 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 2461 the MPI communicator of the generated DM is always the same as the communicator 2462 of the input DM. 2463 2464 Level: intermediate 2465 2466 .seealso: DMCreate() 2467 @*/ 2468 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 2469 { 2470 DM B; 2471 char convname[256]; 2472 PetscBool sametype, issame; 2473 PetscErrorCode ierr; 2474 2475 PetscFunctionBegin; 2476 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2477 PetscValidType(dm,1); 2478 PetscValidPointer(M,3); 2479 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 2480 ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); 2481 { 2482 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 2483 2484 /* 2485 Order of precedence: 2486 1) See if a specialized converter is known to the current DM. 2487 2) See if a specialized converter is known to the desired DM class. 2488 3) See if a good general converter is registered for the desired class 2489 4) See if a good general converter is known for the current matrix. 2490 5) Use a really basic converter. 2491 */ 2492 2493 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2494 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2495 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2496 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2497 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2498 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2499 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,(void (**)(void))&conv);CHKERRQ(ierr); 2500 if (conv) goto foundconv; 2501 2502 /* 2) See if a specialized converter is known to the desired DM class. */ 2503 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 2504 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2505 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2506 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2507 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2508 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2509 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2510 ierr = PetscObjectQueryFunction((PetscObject)B,convname,(void (**)(void))&conv);CHKERRQ(ierr); 2511 if (conv) { 2512 ierr = DMDestroy(&B);CHKERRQ(ierr); 2513 goto foundconv; 2514 } 2515 2516 #if 0 2517 /* 3) See if a good general converter is registered for the desired class */ 2518 conv = B->ops->convertfrom; 2519 ierr = DMDestroy(&B);CHKERRQ(ierr); 2520 if (conv) goto foundconv; 2521 2522 /* 4) See if a good general converter is known for the current matrix */ 2523 if (dm->ops->convert) { 2524 conv = dm->ops->convert; 2525 } 2526 if (conv) goto foundconv; 2527 #endif 2528 2529 /* 5) Use a really basic converter. */ 2530 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 2531 2532 foundconv: 2533 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2534 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 2535 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2536 } 2537 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 2538 PetscFunctionReturn(0); 2539 } 2540 2541 /*--------------------------------------------------------------------------------------------------------------------*/ 2542 2543 #undef __FUNCT__ 2544 #define __FUNCT__ "DMRegister" 2545 /*@C 2546 DMRegister - Adds a new DM component implementation 2547 2548 Not Collective 2549 2550 Input Parameters: 2551 + name - The name of a new user-defined creation routine 2552 - create_func - The creation routine itself 2553 2554 Notes: 2555 DMRegister() may be called multiple times to add several user-defined DMs 2556 2557 2558 Sample usage: 2559 .vb 2560 DMRegister("my_da", MyDMCreate); 2561 .ve 2562 2563 Then, your DM type can be chosen with the procedural interface via 2564 .vb 2565 DMCreate(MPI_Comm, DM *); 2566 DMSetType(DM,"my_da"); 2567 .ve 2568 or at runtime via the option 2569 .vb 2570 -da_type my_da 2571 .ve 2572 2573 Level: advanced 2574 2575 .keywords: DM, register 2576 .seealso: DMRegisterAll(), DMRegisterDestroy() 2577 2578 @*/ 2579 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 2580 { 2581 PetscErrorCode ierr; 2582 2583 PetscFunctionBegin; 2584 ierr = PetscFunctionListAdd(&DMList, sname, (void (*)(void))function);CHKERRQ(ierr); 2585 PetscFunctionReturn(0); 2586 } 2587 2588 2589 /*--------------------------------------------------------------------------------------------------------------------*/ 2590 #undef __FUNCT__ 2591 #define __FUNCT__ "DMRegisterDestroy" 2592 /*@C 2593 DMRegisterDestroy - Frees the list of DM methods that were registered by DMRegister(). 2594 2595 Not Collective 2596 2597 Level: advanced 2598 2599 .keywords: DM, register, destroy 2600 .seealso: DMRegister(), DMRegisterAll() 2601 @*/ 2602 PetscErrorCode DMRegisterDestroy(void) 2603 { 2604 PetscErrorCode ierr; 2605 2606 PetscFunctionBegin; 2607 ierr = PetscFunctionListDestroy(&DMList);CHKERRQ(ierr); 2608 DMRegisterAllCalled = PETSC_FALSE; 2609 PetscFunctionReturn(0); 2610 } 2611 2612 #undef __FUNCT__ 2613 #define __FUNCT__ "DMLoad" 2614 /*@C 2615 DMLoad - Loads a DM that has been stored in binary with DMView(). 2616 2617 Collective on PetscViewer 2618 2619 Input Parameters: 2620 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 2621 some related function before a call to DMLoad(). 2622 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 2623 HDF5 file viewer, obtained from PetscViewerHDF5Open() 2624 2625 Level: intermediate 2626 2627 Notes: 2628 The type is determined by the data in the file, any type set into the DM before this call is ignored. 2629 2630 Notes for advanced users: 2631 Most users should not need to know the details of the binary storage 2632 format, since DMLoad() and DMView() completely hide these details. 2633 But for anyone who's interested, the standard binary matrix storage 2634 format is 2635 .vb 2636 has not yet been determined 2637 .ve 2638 2639 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 2640 @*/ 2641 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 2642 { 2643 PetscErrorCode ierr; 2644 PetscBool isbinary; 2645 PetscInt classid; 2646 char type[256]; 2647 2648 PetscFunctionBegin; 2649 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 2650 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2651 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 2652 if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 2653 2654 ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr); 2655 if (classid != DM_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file"); 2656 ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr); 2657 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 2658 if (newdm->ops->load) { 2659 ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr); 2660 } 2661 PetscFunctionReturn(0); 2662 } 2663 2664 /******************************** FEM Support **********************************/ 2665 2666 #undef __FUNCT__ 2667 #define __FUNCT__ "DMPrintCellVector" 2668 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 2669 { 2670 PetscInt f; 2671 PetscErrorCode ierr; 2672 2673 PetscFunctionBegin; 2674 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2675 for (f = 0; f < len; ++f) { 2676 ierr = PetscPrintf(PETSC_COMM_SELF, " | %G |\n", PetscRealPart(x[f]));CHKERRQ(ierr); 2677 } 2678 PetscFunctionReturn(0); 2679 } 2680 2681 #undef __FUNCT__ 2682 #define __FUNCT__ "DMPrintCellMatrix" 2683 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 2684 { 2685 PetscInt f, g; 2686 PetscErrorCode ierr; 2687 2688 PetscFunctionBegin; 2689 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2690 for (f = 0; f < rows; ++f) { 2691 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 2692 for (g = 0; g < cols; ++g) { 2693 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5G", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 2694 } 2695 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 2696 } 2697 PetscFunctionReturn(0); 2698 } 2699 2700 #undef __FUNCT__ 2701 #define __FUNCT__ "DMGetDefaultSection" 2702 /*@ 2703 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 2704 2705 Input Parameter: 2706 . dm - The DM 2707 2708 Output Parameter: 2709 . section - The PetscSection 2710 2711 Level: intermediate 2712 2713 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 2714 2715 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 2716 @*/ 2717 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 2718 { 2719 PetscFunctionBegin; 2720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2721 PetscValidPointer(section, 2); 2722 *section = dm->defaultSection; 2723 PetscFunctionReturn(0); 2724 } 2725 2726 #undef __FUNCT__ 2727 #define __FUNCT__ "DMSetDefaultSection" 2728 /*@ 2729 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 2730 2731 Input Parameters: 2732 + dm - The DM 2733 - section - The PetscSection 2734 2735 Level: intermediate 2736 2737 Note: Any existing Section will be destroyed 2738 2739 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 2740 @*/ 2741 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 2742 { 2743 PetscInt numFields; 2744 PetscInt f; 2745 PetscErrorCode ierr; 2746 2747 PetscFunctionBegin; 2748 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2749 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 2750 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 2751 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 2752 dm->defaultSection = section; 2753 ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr); 2754 if (numFields) { 2755 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 2756 for (f = 0; f < numFields; ++f) { 2757 const char *name; 2758 2759 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 2760 ierr = PetscObjectSetName(dm->fields[f], name);CHKERRQ(ierr); 2761 } 2762 } 2763 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 2764 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 2765 PetscFunctionReturn(0); 2766 } 2767 2768 #undef __FUNCT__ 2769 #define __FUNCT__ "DMGetDefaultGlobalSection" 2770 /*@ 2771 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 2772 2773 Collective on DM 2774 2775 Input Parameter: 2776 . dm - The DM 2777 2778 Output Parameter: 2779 . section - The PetscSection 2780 2781 Level: intermediate 2782 2783 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 2784 2785 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 2786 @*/ 2787 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 2788 { 2789 PetscErrorCode ierr; 2790 2791 PetscFunctionBegin; 2792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2793 PetscValidPointer(section, 2); 2794 if (!dm->defaultGlobalSection) { 2795 if (!dm->defaultSection || !dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection and PetscSF in order to create a global PetscSection"); 2796 ierr = PetscSectionCreateGlobalSection(dm->defaultSection, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 2797 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm),dm->defaultGlobalSection,&dm->map);CHKERRQ(ierr); 2798 } 2799 *section = dm->defaultGlobalSection; 2800 PetscFunctionReturn(0); 2801 } 2802 2803 #undef __FUNCT__ 2804 #define __FUNCT__ "DMSetDefaultGlobalSection" 2805 /*@ 2806 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 2807 2808 Input Parameters: 2809 + dm - The DM 2810 - section - The PetscSection, or NULL 2811 2812 Level: intermediate 2813 2814 Note: Any existing Section will be destroyed 2815 2816 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 2817 @*/ 2818 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 2819 { 2820 PetscErrorCode ierr; 2821 2822 PetscFunctionBegin; 2823 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2824 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 2825 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 2826 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 2827 dm->defaultGlobalSection = section; 2828 PetscFunctionReturn(0); 2829 } 2830 2831 #undef __FUNCT__ 2832 #define __FUNCT__ "DMGetDefaultSF" 2833 /*@ 2834 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 2835 it is created from the default PetscSection layouts in the DM. 2836 2837 Input Parameter: 2838 . dm - The DM 2839 2840 Output Parameter: 2841 . sf - The PetscSF 2842 2843 Level: intermediate 2844 2845 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 2846 2847 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 2848 @*/ 2849 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 2850 { 2851 PetscInt nroots; 2852 PetscErrorCode ierr; 2853 2854 PetscFunctionBegin; 2855 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2856 PetscValidPointer(sf, 2); 2857 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 2858 if (nroots < 0) { 2859 PetscSection section, gSection; 2860 2861 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 2862 if (section) { 2863 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 2864 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 2865 } else { 2866 *sf = NULL; 2867 PetscFunctionReturn(0); 2868 } 2869 } 2870 *sf = dm->defaultSF; 2871 PetscFunctionReturn(0); 2872 } 2873 2874 #undef __FUNCT__ 2875 #define __FUNCT__ "DMSetDefaultSF" 2876 /*@ 2877 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 2878 2879 Input Parameters: 2880 + dm - The DM 2881 - sf - The PetscSF 2882 2883 Level: intermediate 2884 2885 Note: Any previous SF is destroyed 2886 2887 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 2888 @*/ 2889 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 2890 { 2891 PetscErrorCode ierr; 2892 2893 PetscFunctionBegin; 2894 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2895 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 2896 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 2897 dm->defaultSF = sf; 2898 PetscFunctionReturn(0); 2899 } 2900 2901 #undef __FUNCT__ 2902 #define __FUNCT__ "DMCreateDefaultSF" 2903 /*@C 2904 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 2905 describing the data layout. 2906 2907 Input Parameters: 2908 + dm - The DM 2909 . localSection - PetscSection describing the local data layout 2910 - globalSection - PetscSection describing the global data layout 2911 2912 Level: intermediate 2913 2914 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 2915 @*/ 2916 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 2917 { 2918 MPI_Comm comm; 2919 PetscLayout layout; 2920 const PetscInt *ranges; 2921 PetscInt *local; 2922 PetscSFNode *remote; 2923 PetscInt pStart, pEnd, p, nroots, nleaves, l; 2924 PetscMPIInt size, rank; 2925 PetscErrorCode ierr; 2926 2927 PetscFunctionBegin; 2928 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2929 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2930 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2931 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2932 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 2933 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 2934 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 2935 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 2936 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 2937 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 2938 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 2939 for (p = pStart, nleaves = 0; p < pEnd; ++p) { 2940 PetscInt gdof, gcdof; 2941 2942 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 2943 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 2944 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 2945 } 2946 ierr = PetscMalloc(nleaves * sizeof(PetscInt), &local);CHKERRQ(ierr); 2947 ierr = PetscMalloc(nleaves * sizeof(PetscSFNode), &remote);CHKERRQ(ierr); 2948 for (p = pStart, l = 0; p < pEnd; ++p) { 2949 const PetscInt *cind; 2950 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 2951 2952 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 2953 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 2954 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 2955 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 2956 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 2957 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 2958 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 2959 if (!gdof) continue; /* Censored point */ 2960 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 2961 if (gsize != dof-cdof) { 2962 if (gsize != dof) SETERRQ4(comm, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is neither the constrained size %d, nor the unconstrained %d", gsize, p, dof-cdof, dof); 2963 cdof = 0; /* Ignore constraints */ 2964 } 2965 for (d = 0, c = 0; d < dof; ++d) { 2966 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 2967 local[l+d-c] = off+d; 2968 } 2969 if (gdof < 0) { 2970 for (d = 0; d < gsize; ++d, ++l) { 2971 PetscInt offset = -(goff+1) + d, r; 2972 2973 ierr = PetscFindInt(offset,size,ranges,&r);CHKERRQ(ierr); 2974 if (r < 0) r = -(r+2); 2975 remote[l].rank = r; 2976 remote[l].index = offset - ranges[r]; 2977 } 2978 } else { 2979 for (d = 0; d < gsize; ++d, ++l) { 2980 remote[l].rank = rank; 2981 remote[l].index = goff+d - ranges[rank]; 2982 } 2983 } 2984 } 2985 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 2986 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 2987 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 2988 PetscFunctionReturn(0); 2989 } 2990 2991 #undef __FUNCT__ 2992 #define __FUNCT__ "DMGetPointSF" 2993 /*@ 2994 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 2995 2996 Input Parameter: 2997 . dm - The DM 2998 2999 Output Parameter: 3000 . sf - The PetscSF 3001 3002 Level: intermediate 3003 3004 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3005 3006 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3007 @*/ 3008 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3009 { 3010 PetscFunctionBegin; 3011 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3012 PetscValidPointer(sf, 2); 3013 *sf = dm->sf; 3014 PetscFunctionReturn(0); 3015 } 3016 3017 #undef __FUNCT__ 3018 #define __FUNCT__ "DMSetPointSF" 3019 /*@ 3020 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3021 3022 Input Parameters: 3023 + dm - The DM 3024 - sf - The PetscSF 3025 3026 Level: intermediate 3027 3028 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3029 @*/ 3030 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3031 { 3032 PetscErrorCode ierr; 3033 3034 PetscFunctionBegin; 3035 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3036 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3037 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3038 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3039 dm->sf = sf; 3040 PetscFunctionReturn(0); 3041 } 3042 3043 #undef __FUNCT__ 3044 #define __FUNCT__ "DMGetNumFields" 3045 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3046 { 3047 PetscFunctionBegin; 3048 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3049 PetscValidPointer(numFields, 2); 3050 *numFields = dm->numFields; 3051 PetscFunctionReturn(0); 3052 } 3053 3054 #undef __FUNCT__ 3055 #define __FUNCT__ "DMSetNumFields" 3056 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3057 { 3058 PetscInt f; 3059 PetscErrorCode ierr; 3060 3061 PetscFunctionBegin; 3062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3063 for (f = 0; f < dm->numFields; ++f) { 3064 ierr = PetscObjectDestroy(&dm->fields[f]);CHKERRQ(ierr); 3065 } 3066 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 3067 dm->numFields = numFields; 3068 ierr = PetscMalloc(dm->numFields * sizeof(PetscObject), &dm->fields);CHKERRQ(ierr); 3069 for (f = 0; f < dm->numFields; ++f) { 3070 ierr = PetscContainerCreate(PetscObjectComm((PetscObject)dm), (PetscContainer*) &dm->fields[f]);CHKERRQ(ierr); 3071 } 3072 PetscFunctionReturn(0); 3073 } 3074 3075 #undef __FUNCT__ 3076 #define __FUNCT__ "DMGetField" 3077 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3078 { 3079 PetscFunctionBegin; 3080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3081 PetscValidPointer(field, 2); 3082 if (!dm->fields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Fields have not been setup in this DM. Call DMSetNumFields()"); 3083 if ((f < 0) || (f >= dm->numFields)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Field %d should be in [%d,%d)", f, 0, dm->numFields); 3084 *field = dm->fields[f]; 3085 PetscFunctionReturn(0); 3086 } 3087 3088 #undef __FUNCT__ 3089 #define __FUNCT__ "DMSetCoordinates" 3090 /*@ 3091 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3092 3093 Collective on DM 3094 3095 Input Parameters: 3096 + dm - the DM 3097 - c - coordinate vector 3098 3099 Note: 3100 The coordinates do include those for ghost points, which are in the local vector 3101 3102 Level: intermediate 3103 3104 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3105 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3106 @*/ 3107 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3108 { 3109 PetscErrorCode ierr; 3110 3111 PetscFunctionBegin; 3112 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3113 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3114 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3115 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3116 dm->coordinates = c; 3117 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3118 PetscFunctionReturn(0); 3119 } 3120 3121 #undef __FUNCT__ 3122 #define __FUNCT__ "DMSetCoordinatesLocal" 3123 /*@ 3124 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3125 3126 Collective on DM 3127 3128 Input Parameters: 3129 + dm - the DM 3130 - c - coordinate vector 3131 3132 Note: 3133 The coordinates of ghost points can be set using DMSetCoordinates() 3134 followed by DMGetCoordinatesLocal(). This is intended to enable the 3135 setting of ghost coordinates outside of the domain. 3136 3137 Level: intermediate 3138 3139 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3140 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3141 @*/ 3142 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3143 { 3144 PetscErrorCode ierr; 3145 3146 PetscFunctionBegin; 3147 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3148 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3149 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3150 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3151 3152 dm->coordinatesLocal = c; 3153 3154 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3155 PetscFunctionReturn(0); 3156 } 3157 3158 #undef __FUNCT__ 3159 #define __FUNCT__ "DMGetCoordinates" 3160 /*@ 3161 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3162 3163 Not Collective 3164 3165 Input Parameter: 3166 . dm - the DM 3167 3168 Output Parameter: 3169 . c - global coordinate vector 3170 3171 Note: 3172 This is a borrowed reference, so the user should NOT destroy this vector 3173 3174 Each process has only the local coordinates (does NOT have the ghost coordinates). 3175 3176 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3177 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3178 3179 Level: intermediate 3180 3181 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3182 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3183 @*/ 3184 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 3185 { 3186 PetscErrorCode ierr; 3187 3188 PetscFunctionBegin; 3189 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3190 PetscValidPointer(c,2); 3191 if (!dm->coordinates && dm->coordinatesLocal) { 3192 DM cdm = NULL; 3193 3194 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3195 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 3196 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 3197 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3198 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3199 } 3200 *c = dm->coordinates; 3201 PetscFunctionReturn(0); 3202 } 3203 3204 #undef __FUNCT__ 3205 #define __FUNCT__ "DMGetCoordinatesLocal" 3206 /*@ 3207 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 3208 3209 Collective on DM 3210 3211 Input Parameter: 3212 . dm - the DM 3213 3214 Output Parameter: 3215 . c - coordinate vector 3216 3217 Note: 3218 This is a borrowed reference, so the user should NOT destroy this vector 3219 3220 Each process has the local and ghost coordinates 3221 3222 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3223 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3224 3225 Level: intermediate 3226 3227 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3228 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 3229 @*/ 3230 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 3231 { 3232 PetscErrorCode ierr; 3233 3234 PetscFunctionBegin; 3235 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3236 PetscValidPointer(c,2); 3237 if (!dm->coordinatesLocal && dm->coordinates) { 3238 DM cdm = NULL; 3239 3240 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3241 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 3242 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 3243 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3244 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3245 } 3246 *c = dm->coordinatesLocal; 3247 PetscFunctionReturn(0); 3248 } 3249 3250 #undef __FUNCT__ 3251 #define __FUNCT__ "DMGetCoordinateDM" 3252 /*@ 3253 DMGetCoordinateDM - Gets the DM that scatters between global and local coordinates 3254 3255 Collective on DM 3256 3257 Input Parameter: 3258 . dm - the DM 3259 3260 Output Parameter: 3261 . cdm - coordinate DM 3262 3263 Level: intermediate 3264 3265 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3266 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3267 @*/ 3268 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 3269 { 3270 PetscErrorCode ierr; 3271 3272 PetscFunctionBegin; 3273 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3274 PetscValidPointer(cdm,2); 3275 if (!dm->coordinateDM) { 3276 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 3277 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 3278 } 3279 *cdm = dm->coordinateDM; 3280 PetscFunctionReturn(0); 3281 } 3282 3283 #undef __FUNCT__ 3284 #define __FUNCT__ "DMLocatePoints" 3285 /*@ 3286 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 3287 3288 Not collective 3289 3290 Input Parameters: 3291 + dm - The DM 3292 - v - The Vec of points 3293 3294 Output Parameter: 3295 . cells - The local cell numbers for cells which contain the points 3296 3297 Level: developer 3298 3299 .keywords: point location, mesh 3300 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3301 @*/ 3302 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 3303 { 3304 PetscErrorCode ierr; 3305 3306 PetscFunctionBegin; 3307 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3308 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 3309 PetscValidPointer(cells,3); 3310 if (dm->ops->locatepoints) { 3311 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 3312 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 3313 PetscFunctionReturn(0); 3314 } 3315