1 #include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/ 2 #include <petscsf.h> 3 #include <petscds.h> 4 5 PetscClassId DM_CLASSID; 6 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal; 7 8 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0}; 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "DMCreate" 12 /*@ 13 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 14 15 If you never call DMSetType() it will generate an 16 error when you try to use the vector. 17 18 Collective on MPI_Comm 19 20 Input Parameter: 21 . comm - The communicator for the DM object 22 23 Output Parameter: 24 . dm - The DM object 25 26 Level: beginner 27 28 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE 29 @*/ 30 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 31 { 32 DM v; 33 PetscErrorCode ierr; 34 35 PetscFunctionBegin; 36 PetscValidPointer(dm,2); 37 *dm = NULL; 38 ierr = PetscSysInitializePackage();CHKERRQ(ierr); 39 ierr = VecInitializePackage();CHKERRQ(ierr); 40 ierr = MatInitializePackage();CHKERRQ(ierr); 41 ierr = DMInitializePackage();CHKERRQ(ierr); 42 43 ierr = PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 44 ierr = PetscMemzero(v->ops, sizeof(struct _DMOps));CHKERRQ(ierr); 45 46 47 v->ltogmap = NULL; 48 v->bs = 1; 49 v->coloringtype = IS_COLORING_GLOBAL; 50 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 51 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 52 v->defaultSection = NULL; 53 v->defaultGlobalSection = NULL; 54 v->defaultConstraintSection = NULL; 55 v->defaultConstraintMat = NULL; 56 v->L = NULL; 57 v->maxCell = NULL; 58 v->bdtype = NULL; 59 v->dimEmbed = PETSC_DEFAULT; 60 { 61 PetscInt i; 62 for (i = 0; i < 10; ++i) { 63 v->nullspaceConstructors[i] = NULL; 64 } 65 } 66 ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr); 67 v->dmBC = NULL; 68 v->outputSequenceNum = -1; 69 v->outputSequenceVal = 0.0; 70 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 71 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 72 *dm = v; 73 PetscFunctionReturn(0); 74 } 75 76 #undef __FUNCT__ 77 #define __FUNCT__ "DMClone" 78 /*@ 79 DMClone - Creates a DM object with the same topology as the original. 80 81 Collective on MPI_Comm 82 83 Input Parameter: 84 . dm - The original DM object 85 86 Output Parameter: 87 . newdm - The new DM object 88 89 Level: beginner 90 91 .keywords: DM, topology, create 92 @*/ 93 PetscErrorCode DMClone(DM dm, DM *newdm) 94 { 95 PetscSF sf; 96 Vec coords; 97 void *ctx; 98 PetscInt dim; 99 PetscErrorCode ierr; 100 101 PetscFunctionBegin; 102 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103 PetscValidPointer(newdm,2); 104 ierr = DMCreate(PetscObjectComm((PetscObject)dm), newdm);CHKERRQ(ierr); 105 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 106 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr); 107 if (dm->ops->clone) { 108 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 109 } 110 (*newdm)->setupcalled = PETSC_TRUE; 111 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 112 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 113 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 114 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 115 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 116 if (coords) { 117 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 118 } else { 119 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 120 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 121 } 122 if (dm->maxCell) { 123 const PetscReal *maxCell, *L; 124 const DMBoundaryType *bd; 125 ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr); 126 ierr = DMSetPeriodicity(*newdm, maxCell, L, bd);CHKERRQ(ierr); 127 } 128 PetscFunctionReturn(0); 129 } 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "DMSetVecType" 133 /*@C 134 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 135 136 Logically Collective on DMDA 137 138 Input Parameter: 139 + da - initial distributed array 140 . ctype - the vector type, currently either VECSTANDARD or VECCUSP 141 142 Options Database: 143 . -dm_vec_type ctype 144 145 Level: intermediate 146 147 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType, DMGetVecType() 148 @*/ 149 PetscErrorCode DMSetVecType(DM da,VecType ctype) 150 { 151 PetscErrorCode ierr; 152 153 PetscFunctionBegin; 154 PetscValidHeaderSpecific(da,DM_CLASSID,1); 155 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 156 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 157 PetscFunctionReturn(0); 158 } 159 160 #undef __FUNCT__ 161 #define __FUNCT__ "DMGetVecType" 162 /*@C 163 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 164 165 Logically Collective on DMDA 166 167 Input Parameter: 168 . da - initial distributed array 169 170 Output Parameter: 171 . ctype - the vector type 172 173 Level: intermediate 174 175 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType 176 @*/ 177 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 178 { 179 PetscFunctionBegin; 180 PetscValidHeaderSpecific(da,DM_CLASSID,1); 181 *ctype = da->vectype; 182 PetscFunctionReturn(0); 183 } 184 185 #undef __FUNCT__ 186 #define __FUNCT__ "VecGetDM" 187 /*@ 188 VecGetDM - Gets the DM defining the data layout of the vector 189 190 Not collective 191 192 Input Parameter: 193 . v - The Vec 194 195 Output Parameter: 196 . dm - The DM 197 198 Level: intermediate 199 200 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 201 @*/ 202 PetscErrorCode VecGetDM(Vec v, DM *dm) 203 { 204 PetscErrorCode ierr; 205 206 PetscFunctionBegin; 207 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 208 PetscValidPointer(dm,2); 209 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 210 PetscFunctionReturn(0); 211 } 212 213 #undef __FUNCT__ 214 #define __FUNCT__ "VecSetDM" 215 /*@ 216 VecSetDM - Sets the DM defining the data layout of the vector 217 218 Not collective 219 220 Input Parameters: 221 + v - The Vec 222 - dm - The DM 223 224 Level: intermediate 225 226 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 227 @*/ 228 PetscErrorCode VecSetDM(Vec v, DM dm) 229 { 230 PetscErrorCode ierr; 231 232 PetscFunctionBegin; 233 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 234 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 235 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 236 PetscFunctionReturn(0); 237 } 238 239 #undef __FUNCT__ 240 #define __FUNCT__ "DMSetMatType" 241 /*@C 242 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 243 244 Logically Collective on DM 245 246 Input Parameter: 247 + dm - the DM context 248 . ctype - the matrix type 249 250 Options Database: 251 . -dm_mat_type ctype 252 253 Level: intermediate 254 255 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType() 256 @*/ 257 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 258 { 259 PetscErrorCode ierr; 260 261 PetscFunctionBegin; 262 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 263 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 264 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 265 PetscFunctionReturn(0); 266 } 267 268 #undef __FUNCT__ 269 #define __FUNCT__ "DMGetMatType" 270 /*@C 271 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 272 273 Logically Collective on DM 274 275 Input Parameter: 276 . dm - the DM context 277 278 Output Parameter: 279 . ctype - the matrix type 280 281 Options Database: 282 . -dm_mat_type ctype 283 284 Level: intermediate 285 286 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType() 287 @*/ 288 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 289 { 290 PetscFunctionBegin; 291 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 292 *ctype = dm->mattype; 293 PetscFunctionReturn(0); 294 } 295 296 #undef __FUNCT__ 297 #define __FUNCT__ "MatGetDM" 298 /*@ 299 MatGetDM - Gets the DM defining the data layout of the matrix 300 301 Not collective 302 303 Input Parameter: 304 . A - The Mat 305 306 Output Parameter: 307 . dm - The DM 308 309 Level: intermediate 310 311 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 312 @*/ 313 PetscErrorCode MatGetDM(Mat A, DM *dm) 314 { 315 PetscErrorCode ierr; 316 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 319 PetscValidPointer(dm,2); 320 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 321 PetscFunctionReturn(0); 322 } 323 324 #undef __FUNCT__ 325 #define __FUNCT__ "MatSetDM" 326 /*@ 327 MatSetDM - Sets the DM defining the data layout of the matrix 328 329 Not collective 330 331 Input Parameters: 332 + A - The Mat 333 - dm - The DM 334 335 Level: intermediate 336 337 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 338 @*/ 339 PetscErrorCode MatSetDM(Mat A, DM dm) 340 { 341 PetscErrorCode ierr; 342 343 PetscFunctionBegin; 344 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 345 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 346 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 347 PetscFunctionReturn(0); 348 } 349 350 #undef __FUNCT__ 351 #define __FUNCT__ "DMSetOptionsPrefix" 352 /*@C 353 DMSetOptionsPrefix - Sets the prefix used for searching for all 354 DMDA options in the database. 355 356 Logically Collective on DMDA 357 358 Input Parameter: 359 + da - the DMDA context 360 - prefix - the prefix to prepend to all option names 361 362 Notes: 363 A hyphen (-) must NOT be given at the beginning of the prefix name. 364 The first character of all runtime options is AUTOMATICALLY the hyphen. 365 366 Level: advanced 367 368 .keywords: DMDA, set, options, prefix, database 369 370 .seealso: DMSetFromOptions() 371 @*/ 372 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 373 { 374 PetscErrorCode ierr; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 378 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 379 PetscFunctionReturn(0); 380 } 381 382 #undef __FUNCT__ 383 #define __FUNCT__ "DMDestroy" 384 /*@ 385 DMDestroy - Destroys a vector packer or DMDA. 386 387 Collective on DM 388 389 Input Parameter: 390 . dm - the DM object to destroy 391 392 Level: developer 393 394 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 395 396 @*/ 397 PetscErrorCode DMDestroy(DM *dm) 398 { 399 PetscInt i, cnt = 0; 400 DMNamedVecLink nlink,nnext; 401 PetscErrorCode ierr; 402 403 PetscFunctionBegin; 404 if (!*dm) PetscFunctionReturn(0); 405 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 406 407 /* count all the circular references of DM and its contained Vecs */ 408 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 409 if ((*dm)->localin[i]) cnt++; 410 if ((*dm)->globalin[i]) cnt++; 411 } 412 for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++; 413 for (nlink=(*dm)->namedlocal; nlink; nlink=nlink->next) cnt++; 414 if ((*dm)->x) { 415 DM obj; 416 ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr); 417 if (obj == *dm) cnt++; 418 } 419 420 if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 421 /* 422 Need this test because the dm references the vectors that 423 reference the dm, so destroying the dm calls destroy on the 424 vectors that cause another destroy on the dm 425 */ 426 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 427 ((PetscObject) (*dm))->refct = 0; 428 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 429 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 430 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 431 } 432 nnext=(*dm)->namedglobal; 433 (*dm)->namedglobal = NULL; 434 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 435 nnext = nlink->next; 436 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 437 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 438 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 439 ierr = PetscFree(nlink);CHKERRQ(ierr); 440 } 441 nnext=(*dm)->namedlocal; 442 (*dm)->namedlocal = NULL; 443 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 444 nnext = nlink->next; 445 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 446 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 447 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 448 ierr = PetscFree(nlink);CHKERRQ(ierr); 449 } 450 451 /* Destroy the list of hooks */ 452 { 453 DMCoarsenHookLink link,next; 454 for (link=(*dm)->coarsenhook; link; link=next) { 455 next = link->next; 456 ierr = PetscFree(link);CHKERRQ(ierr); 457 } 458 (*dm)->coarsenhook = NULL; 459 } 460 { 461 DMRefineHookLink link,next; 462 for (link=(*dm)->refinehook; link; link=next) { 463 next = link->next; 464 ierr = PetscFree(link);CHKERRQ(ierr); 465 } 466 (*dm)->refinehook = NULL; 467 } 468 { 469 DMSubDomainHookLink link,next; 470 for (link=(*dm)->subdomainhook; link; link=next) { 471 next = link->next; 472 ierr = PetscFree(link);CHKERRQ(ierr); 473 } 474 (*dm)->subdomainhook = NULL; 475 } 476 { 477 DMGlobalToLocalHookLink link,next; 478 for (link=(*dm)->gtolhook; link; link=next) { 479 next = link->next; 480 ierr = PetscFree(link);CHKERRQ(ierr); 481 } 482 (*dm)->gtolhook = NULL; 483 } 484 { 485 DMLocalToGlobalHookLink link,next; 486 for (link=(*dm)->ltoghook; link; link=next) { 487 next = link->next; 488 ierr = PetscFree(link);CHKERRQ(ierr); 489 } 490 (*dm)->ltoghook = NULL; 491 } 492 /* Destroy the work arrays */ 493 { 494 DMWorkLink link,next; 495 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 496 for (link=(*dm)->workin; link; link=next) { 497 next = link->next; 498 ierr = PetscFree(link->mem);CHKERRQ(ierr); 499 ierr = PetscFree(link);CHKERRQ(ierr); 500 } 501 (*dm)->workin = NULL; 502 } 503 504 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 505 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 506 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 507 508 if ((*dm)->ctx && (*dm)->ctxdestroy) { 509 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 510 } 511 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 512 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 513 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 514 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 515 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 516 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 517 518 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 519 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 520 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 521 ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr); 522 ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr); 523 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 524 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 525 526 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 527 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 528 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 529 ierr = PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);CHKERRQ(ierr); 530 531 ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr); 532 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 533 /* if memory was published with SAWs then destroy it */ 534 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 535 536 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 537 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 538 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 539 PetscFunctionReturn(0); 540 } 541 542 #undef __FUNCT__ 543 #define __FUNCT__ "DMSetUp" 544 /*@ 545 DMSetUp - sets up the data structures inside a DM object 546 547 Collective on DM 548 549 Input Parameter: 550 . dm - the DM object to setup 551 552 Level: developer 553 554 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 555 556 @*/ 557 PetscErrorCode DMSetUp(DM dm) 558 { 559 PetscErrorCode ierr; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 563 if (dm->setupcalled) PetscFunctionReturn(0); 564 if (dm->ops->setup) { 565 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 566 } 567 dm->setupcalled = PETSC_TRUE; 568 PetscFunctionReturn(0); 569 } 570 571 #undef __FUNCT__ 572 #define __FUNCT__ "DMSetFromOptions" 573 /*@ 574 DMSetFromOptions - sets parameters in a DM from the options database 575 576 Collective on DM 577 578 Input Parameter: 579 . dm - the DM object to set options for 580 581 Options Database: 582 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 583 . -dm_vec_type <type> - type of vector to create inside DM 584 . -dm_mat_type <type> - type of matrix to create inside DM 585 - -dm_coloring_type - <global or ghosted> 586 587 Level: developer 588 589 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 590 591 @*/ 592 PetscErrorCode DMSetFromOptions(DM dm) 593 { 594 char typeName[256]; 595 PetscBool flg; 596 PetscErrorCode ierr; 597 598 PetscFunctionBegin; 599 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 600 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 601 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 602 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 603 if (flg) { 604 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 605 } 606 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 607 if (flg) { 608 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 609 } 610 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 611 if (dm->ops->setfromoptions) { 612 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr); 613 } 614 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 615 ierr = PetscObjectProcessOptionsHandlers((PetscObject) dm);CHKERRQ(ierr); 616 ierr = PetscOptionsEnd();CHKERRQ(ierr); 617 PetscFunctionReturn(0); 618 } 619 620 #undef __FUNCT__ 621 #define __FUNCT__ "DMView" 622 /*@C 623 DMView - Views a vector packer or DMDA. 624 625 Collective on DM 626 627 Input Parameter: 628 + dm - the DM object to view 629 - v - the viewer 630 631 Level: developer 632 633 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 634 635 @*/ 636 PetscErrorCode DMView(DM dm,PetscViewer v) 637 { 638 PetscErrorCode ierr; 639 PetscBool isbinary; 640 641 PetscFunctionBegin; 642 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 643 if (!v) { 644 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 645 } 646 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 647 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 648 if (isbinary) { 649 PetscInt classid = DM_FILE_CLASSID; 650 char type[256]; 651 652 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 653 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 654 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 655 } 656 if (dm->ops->view) { 657 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 658 } 659 PetscFunctionReturn(0); 660 } 661 662 #undef __FUNCT__ 663 #define __FUNCT__ "DMCreateGlobalVector" 664 /*@ 665 DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object 666 667 Collective on DM 668 669 Input Parameter: 670 . dm - the DM object 671 672 Output Parameter: 673 . vec - the global vector 674 675 Level: beginner 676 677 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 678 679 @*/ 680 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 681 { 682 PetscErrorCode ierr; 683 684 PetscFunctionBegin; 685 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 686 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 687 PetscFunctionReturn(0); 688 } 689 690 #undef __FUNCT__ 691 #define __FUNCT__ "DMCreateLocalVector" 692 /*@ 693 DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object 694 695 Not Collective 696 697 Input Parameter: 698 . dm - the DM object 699 700 Output Parameter: 701 . vec - the local vector 702 703 Level: beginner 704 705 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 706 707 @*/ 708 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 709 { 710 PetscErrorCode ierr; 711 712 PetscFunctionBegin; 713 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 714 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 715 PetscFunctionReturn(0); 716 } 717 718 #undef __FUNCT__ 719 #define __FUNCT__ "DMGetLocalToGlobalMapping" 720 /*@ 721 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 722 723 Collective on DM 724 725 Input Parameter: 726 . dm - the DM that provides the mapping 727 728 Output Parameter: 729 . ltog - the mapping 730 731 Level: intermediate 732 733 Notes: 734 This mapping can then be used by VecSetLocalToGlobalMapping() or 735 MatSetLocalToGlobalMapping(). 736 737 .seealso: DMCreateLocalVector() 738 @*/ 739 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 740 { 741 PetscErrorCode ierr; 742 743 PetscFunctionBegin; 744 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 745 PetscValidPointer(ltog,2); 746 if (!dm->ltogmap) { 747 PetscSection section, sectionGlobal; 748 749 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 750 if (section) { 751 PetscInt *ltog; 752 PetscInt pStart, pEnd, size, p, l; 753 754 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 755 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 756 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 757 ierr = PetscMalloc1(size, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 758 for (p = pStart, l = 0; p < pEnd; ++p) { 759 PetscInt dof, off, c; 760 761 /* Should probably use constrained dofs */ 762 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 763 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 764 for (c = 0; c < dof; ++c, ++l) { 765 ltog[l] = off+c; 766 } 767 } 768 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 769 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 770 } else { 771 if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 772 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 773 } 774 } 775 *ltog = dm->ltogmap; 776 PetscFunctionReturn(0); 777 } 778 779 #undef __FUNCT__ 780 #define __FUNCT__ "DMGetBlockSize" 781 /*@ 782 DMGetBlockSize - Gets the inherent block size associated with a DM 783 784 Not Collective 785 786 Input Parameter: 787 . dm - the DM with block structure 788 789 Output Parameter: 790 . bs - the block size, 1 implies no exploitable block structure 791 792 Level: intermediate 793 794 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 795 @*/ 796 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 797 { 798 PetscFunctionBegin; 799 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 800 PetscValidPointer(bs,2); 801 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 802 *bs = dm->bs; 803 PetscFunctionReturn(0); 804 } 805 806 #undef __FUNCT__ 807 #define __FUNCT__ "DMCreateInterpolation" 808 /*@ 809 DMCreateInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects 810 811 Collective on DM 812 813 Input Parameter: 814 + dm1 - the DM object 815 - dm2 - the second, finer DM object 816 817 Output Parameter: 818 + mat - the interpolation 819 - vec - the scaling (optional) 820 821 Level: developer 822 823 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 824 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 825 826 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 827 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 828 829 830 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen() 831 832 @*/ 833 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 834 { 835 PetscErrorCode ierr; 836 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 839 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 840 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 841 PetscFunctionReturn(0); 842 } 843 844 #undef __FUNCT__ 845 #define __FUNCT__ "DMCreateInjection" 846 /*@ 847 DMCreateInjection - Gets injection matrix between two DMDA or DMComposite objects 848 849 Collective on DM 850 851 Input Parameter: 852 + dm1 - the DM object 853 - dm2 - the second, finer DM object 854 855 Output Parameter: 856 . mat - the injection 857 858 Level: developer 859 860 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 861 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 862 863 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 864 865 @*/ 866 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat) 867 { 868 PetscErrorCode ierr; 869 870 PetscFunctionBegin; 871 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 872 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 873 ierr = (*dm1->ops->getinjection)(dm1,dm2,mat);CHKERRQ(ierr); 874 PetscFunctionReturn(0); 875 } 876 877 #undef __FUNCT__ 878 #define __FUNCT__ "DMCreateColoring" 879 /*@ 880 DMCreateColoring - Gets coloring for a DM 881 882 Collective on DM 883 884 Input Parameter: 885 + dm - the DM object 886 - ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL 887 888 Output Parameter: 889 . coloring - the coloring 890 891 Level: developer 892 893 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType() 894 895 @*/ 896 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 897 { 898 PetscErrorCode ierr; 899 900 PetscFunctionBegin; 901 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 902 if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet"); 903 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 904 PetscFunctionReturn(0); 905 } 906 907 #undef __FUNCT__ 908 #define __FUNCT__ "DMCreateMatrix" 909 /*@ 910 DMCreateMatrix - Gets empty Jacobian for a DMDA or DMComposite 911 912 Collective on DM 913 914 Input Parameter: 915 . dm - the DM object 916 917 Output Parameter: 918 . mat - the empty Jacobian 919 920 Level: beginner 921 922 Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 923 do not need to do it yourself. 924 925 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 926 the nonzero pattern call DMDASetMatPreallocateOnly() 927 928 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 929 internally by PETSc. 930 931 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 932 the indices for the global numbering for DMDAs which is complicated. 933 934 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 935 936 @*/ 937 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 938 { 939 PetscErrorCode ierr; 940 941 PetscFunctionBegin; 942 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 943 ierr = MatInitializePackage();CHKERRQ(ierr); 944 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 945 PetscValidPointer(mat,3); 946 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 947 PetscFunctionReturn(0); 948 } 949 950 #undef __FUNCT__ 951 #define __FUNCT__ "DMSetMatrixPreallocateOnly" 952 /*@ 953 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 954 preallocated but the nonzero structure and zero values will not be set. 955 956 Logically Collective on DMDA 957 958 Input Parameter: 959 + dm - the DM 960 - only - PETSC_TRUE if only want preallocation 961 962 Level: developer 963 .seealso DMCreateMatrix() 964 @*/ 965 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 966 { 967 PetscFunctionBegin; 968 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 969 dm->prealloc_only = only; 970 PetscFunctionReturn(0); 971 } 972 973 #undef __FUNCT__ 974 #define __FUNCT__ "DMGetWorkArray" 975 /*@C 976 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 977 978 Not Collective 979 980 Input Parameters: 981 + dm - the DM object 982 . count - The minium size 983 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 984 985 Output Parameter: 986 . array - the work array 987 988 Level: developer 989 990 .seealso DMDestroy(), DMCreate() 991 @*/ 992 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 993 { 994 PetscErrorCode ierr; 995 DMWorkLink link; 996 size_t dsize; 997 998 PetscFunctionBegin; 999 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1000 PetscValidPointer(mem,4); 1001 if (dm->workin) { 1002 link = dm->workin; 1003 dm->workin = dm->workin->next; 1004 } else { 1005 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1006 } 1007 ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr); 1008 if (dsize*count > link->bytes) { 1009 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1010 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr); 1011 link->bytes = dsize*count; 1012 } 1013 link->next = dm->workout; 1014 dm->workout = link; 1015 *(void**)mem = link->mem; 1016 PetscFunctionReturn(0); 1017 } 1018 1019 #undef __FUNCT__ 1020 #define __FUNCT__ "DMRestoreWorkArray" 1021 /*@C 1022 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1023 1024 Not Collective 1025 1026 Input Parameters: 1027 + dm - the DM object 1028 . count - The minium size 1029 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1030 1031 Output Parameter: 1032 . array - the work array 1033 1034 Level: developer 1035 1036 .seealso DMDestroy(), DMCreate() 1037 @*/ 1038 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1039 { 1040 DMWorkLink *p,link; 1041 1042 PetscFunctionBegin; 1043 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1044 PetscValidPointer(mem,4); 1045 for (p=&dm->workout; (link=*p); p=&link->next) { 1046 if (link->mem == *(void**)mem) { 1047 *p = link->next; 1048 link->next = dm->workin; 1049 dm->workin = link; 1050 *(void**)mem = NULL; 1051 PetscFunctionReturn(0); 1052 } 1053 } 1054 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1055 PetscFunctionReturn(0); 1056 } 1057 1058 #undef __FUNCT__ 1059 #define __FUNCT__ "DMSetNullSpaceConstructor" 1060 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1061 { 1062 PetscFunctionBegin; 1063 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1064 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1065 dm->nullspaceConstructors[field] = nullsp; 1066 PetscFunctionReturn(0); 1067 } 1068 1069 #undef __FUNCT__ 1070 #define __FUNCT__ "DMCreateFieldIS" 1071 /*@C 1072 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1073 1074 Not collective 1075 1076 Input Parameter: 1077 . dm - the DM object 1078 1079 Output Parameters: 1080 + numFields - The number of fields (or NULL if not requested) 1081 . fieldNames - The name for each field (or NULL if not requested) 1082 - fields - The global indices for each field (or NULL if not requested) 1083 1084 Level: intermediate 1085 1086 Notes: 1087 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1088 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1089 PetscFree(). 1090 1091 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1092 @*/ 1093 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1094 { 1095 PetscSection section, sectionGlobal; 1096 PetscErrorCode ierr; 1097 1098 PetscFunctionBegin; 1099 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1100 if (numFields) { 1101 PetscValidPointer(numFields,2); 1102 *numFields = 0; 1103 } 1104 if (fieldNames) { 1105 PetscValidPointer(fieldNames,3); 1106 *fieldNames = NULL; 1107 } 1108 if (fields) { 1109 PetscValidPointer(fields,4); 1110 *fields = NULL; 1111 } 1112 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1113 if (section) { 1114 PetscInt *fieldSizes, **fieldIndices; 1115 PetscInt nF, f, pStart, pEnd, p; 1116 1117 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1118 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1119 ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr); 1120 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1121 for (f = 0; f < nF; ++f) { 1122 fieldSizes[f] = 0; 1123 } 1124 for (p = pStart; p < pEnd; ++p) { 1125 PetscInt gdof; 1126 1127 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1128 if (gdof > 0) { 1129 for (f = 0; f < nF; ++f) { 1130 PetscInt fdof, fcdof; 1131 1132 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1133 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1134 fieldSizes[f] += fdof-fcdof; 1135 } 1136 } 1137 } 1138 for (f = 0; f < nF; ++f) { 1139 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1140 fieldSizes[f] = 0; 1141 } 1142 for (p = pStart; p < pEnd; ++p) { 1143 PetscInt gdof, goff; 1144 1145 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1146 if (gdof > 0) { 1147 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1148 for (f = 0; f < nF; ++f) { 1149 PetscInt fdof, fcdof, fc; 1150 1151 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1152 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1153 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1154 fieldIndices[f][fieldSizes[f]] = goff++; 1155 } 1156 } 1157 } 1158 } 1159 if (numFields) *numFields = nF; 1160 if (fieldNames) { 1161 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1162 for (f = 0; f < nF; ++f) { 1163 const char *fieldName; 1164 1165 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1166 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1167 } 1168 } 1169 if (fields) { 1170 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1171 for (f = 0; f < nF; ++f) { 1172 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1173 } 1174 } 1175 ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr); 1176 } else if (dm->ops->createfieldis) { 1177 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1178 } 1179 PetscFunctionReturn(0); 1180 } 1181 1182 1183 #undef __FUNCT__ 1184 #define __FUNCT__ "DMCreateFieldDecomposition" 1185 /*@C 1186 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1187 corresponding to different fields: each IS contains the global indices of the dofs of the 1188 corresponding field. The optional list of DMs define the DM for each subproblem. 1189 Generalizes DMCreateFieldIS(). 1190 1191 Not collective 1192 1193 Input Parameter: 1194 . dm - the DM object 1195 1196 Output Parameters: 1197 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1198 . namelist - The name for each field (or NULL if not requested) 1199 . islist - The global indices for each field (or NULL if not requested) 1200 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1201 1202 Level: intermediate 1203 1204 Notes: 1205 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1206 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1207 and all of the arrays should be freed with PetscFree(). 1208 1209 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1210 @*/ 1211 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1212 { 1213 PetscErrorCode ierr; 1214 1215 PetscFunctionBegin; 1216 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1217 if (len) { 1218 PetscValidPointer(len,2); 1219 *len = 0; 1220 } 1221 if (namelist) { 1222 PetscValidPointer(namelist,3); 1223 *namelist = 0; 1224 } 1225 if (islist) { 1226 PetscValidPointer(islist,4); 1227 *islist = 0; 1228 } 1229 if (dmlist) { 1230 PetscValidPointer(dmlist,5); 1231 *dmlist = 0; 1232 } 1233 /* 1234 Is it a good idea to apply the following check across all impls? 1235 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1236 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1237 */ 1238 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1239 if (!dm->ops->createfielddecomposition) { 1240 PetscSection section; 1241 PetscInt numFields, f; 1242 1243 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1244 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1245 if (section && numFields && dm->ops->createsubdm) { 1246 *len = numFields; 1247 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1248 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1249 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1250 for (f = 0; f < numFields; ++f) { 1251 const char *fieldName; 1252 1253 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1254 if (namelist) { 1255 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1256 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1257 } 1258 } 1259 } else { 1260 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1261 /* By default there are no DMs associated with subproblems. */ 1262 if (dmlist) *dmlist = NULL; 1263 } 1264 } else { 1265 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1266 } 1267 PetscFunctionReturn(0); 1268 } 1269 1270 #undef __FUNCT__ 1271 #define __FUNCT__ "DMCreateSubDM" 1272 /*@C 1273 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1274 The fields are defined by DMCreateFieldIS(). 1275 1276 Not collective 1277 1278 Input Parameters: 1279 + dm - the DM object 1280 . numFields - number of fields in this subproblem 1281 - len - The number of subproblems in the decomposition (or NULL if not requested) 1282 1283 Output Parameters: 1284 . is - The global indices for the subproblem 1285 - dm - The DM for the subproblem 1286 1287 Level: intermediate 1288 1289 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1290 @*/ 1291 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1292 { 1293 PetscErrorCode ierr; 1294 1295 PetscFunctionBegin; 1296 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1297 PetscValidPointer(fields,3); 1298 if (is) PetscValidPointer(is,4); 1299 if (subdm) PetscValidPointer(subdm,5); 1300 if (dm->ops->createsubdm) { 1301 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1302 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1303 PetscFunctionReturn(0); 1304 } 1305 1306 1307 #undef __FUNCT__ 1308 #define __FUNCT__ "DMCreateDomainDecomposition" 1309 /*@C 1310 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1311 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1312 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1313 define a nonoverlapping covering, while outer subdomains can overlap. 1314 The optional list of DMs define the DM for each subproblem. 1315 1316 Not collective 1317 1318 Input Parameter: 1319 . dm - the DM object 1320 1321 Output Parameters: 1322 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1323 . namelist - The name for each subdomain (or NULL if not requested) 1324 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1325 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1326 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1327 1328 Level: intermediate 1329 1330 Notes: 1331 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1332 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1333 and all of the arrays should be freed with PetscFree(). 1334 1335 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1336 @*/ 1337 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1338 { 1339 PetscErrorCode ierr; 1340 DMSubDomainHookLink link; 1341 PetscInt i,l; 1342 1343 PetscFunctionBegin; 1344 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1345 if (len) {PetscValidPointer(len,2); *len = 0;} 1346 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1347 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1348 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1349 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1350 /* 1351 Is it a good idea to apply the following check across all impls? 1352 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1353 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1354 */ 1355 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1356 if (dm->ops->createdomaindecomposition) { 1357 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1358 /* copy subdomain hooks and context over to the subdomain DMs */ 1359 if (dmlist) { 1360 for (i = 0; i < l; i++) { 1361 for (link=dm->subdomainhook; link; link=link->next) { 1362 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1363 } 1364 (*dmlist)[i]->ctx = dm->ctx; 1365 } 1366 } 1367 if (len) *len = l; 1368 } 1369 PetscFunctionReturn(0); 1370 } 1371 1372 1373 #undef __FUNCT__ 1374 #define __FUNCT__ "DMCreateDomainDecompositionScatters" 1375 /*@C 1376 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1377 1378 Not collective 1379 1380 Input Parameters: 1381 + dm - the DM object 1382 . n - the number of subdomain scatters 1383 - subdms - the local subdomains 1384 1385 Output Parameters: 1386 + n - the number of scatters returned 1387 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1388 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1389 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1390 1391 Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1392 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1393 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1394 solution and residual data. 1395 1396 Level: developer 1397 1398 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1399 @*/ 1400 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1401 { 1402 PetscErrorCode ierr; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1406 PetscValidPointer(subdms,3); 1407 if (dm->ops->createddscatters) { 1408 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1409 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined"); 1410 PetscFunctionReturn(0); 1411 } 1412 1413 #undef __FUNCT__ 1414 #define __FUNCT__ "DMRefine" 1415 /*@ 1416 DMRefine - Refines a DM object 1417 1418 Collective on DM 1419 1420 Input Parameter: 1421 + dm - the DM object 1422 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1423 1424 Output Parameter: 1425 . dmf - the refined DM, or NULL 1426 1427 Note: If no refinement was done, the return value is NULL 1428 1429 Level: developer 1430 1431 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1432 @*/ 1433 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1434 { 1435 PetscErrorCode ierr; 1436 DMRefineHookLink link; 1437 1438 PetscFunctionBegin; 1439 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1440 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1441 if (*dmf) { 1442 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1443 1444 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1445 1446 (*dmf)->ctx = dm->ctx; 1447 (*dmf)->leveldown = dm->leveldown; 1448 (*dmf)->levelup = dm->levelup + 1; 1449 1450 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1451 for (link=dm->refinehook; link; link=link->next) { 1452 if (link->refinehook) { 1453 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1454 } 1455 } 1456 } 1457 PetscFunctionReturn(0); 1458 } 1459 1460 #undef __FUNCT__ 1461 #define __FUNCT__ "DMRefineHookAdd" 1462 /*@C 1463 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1464 1465 Logically Collective 1466 1467 Input Arguments: 1468 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1469 . refinehook - function to run when setting up a coarser level 1470 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1471 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1472 1473 Calling sequence of refinehook: 1474 $ refinehook(DM coarse,DM fine,void *ctx); 1475 1476 + coarse - coarse level DM 1477 . fine - fine level DM to interpolate problem to 1478 - ctx - optional user-defined function context 1479 1480 Calling sequence for interphook: 1481 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1482 1483 + coarse - coarse level DM 1484 . interp - matrix interpolating a coarse-level solution to the finer grid 1485 . fine - fine level DM to update 1486 - ctx - optional user-defined function context 1487 1488 Level: advanced 1489 1490 Notes: 1491 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1492 1493 If this function is called multiple times, the hooks will be run in the order they are added. 1494 1495 This function is currently not available from Fortran. 1496 1497 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1498 @*/ 1499 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1500 { 1501 PetscErrorCode ierr; 1502 DMRefineHookLink link,*p; 1503 1504 PetscFunctionBegin; 1505 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1506 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1507 ierr = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr); 1508 link->refinehook = refinehook; 1509 link->interphook = interphook; 1510 link->ctx = ctx; 1511 link->next = NULL; 1512 *p = link; 1513 PetscFunctionReturn(0); 1514 } 1515 1516 #undef __FUNCT__ 1517 #define __FUNCT__ "DMInterpolate" 1518 /*@ 1519 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1520 1521 Collective if any hooks are 1522 1523 Input Arguments: 1524 + coarse - coarser DM to use as a base 1525 . restrct - interpolation matrix, apply using MatInterpolate() 1526 - fine - finer DM to update 1527 1528 Level: developer 1529 1530 .seealso: DMRefineHookAdd(), MatInterpolate() 1531 @*/ 1532 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1533 { 1534 PetscErrorCode ierr; 1535 DMRefineHookLink link; 1536 1537 PetscFunctionBegin; 1538 for (link=fine->refinehook; link; link=link->next) { 1539 if (link->interphook) { 1540 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1541 } 1542 } 1543 PetscFunctionReturn(0); 1544 } 1545 1546 #undef __FUNCT__ 1547 #define __FUNCT__ "DMGetRefineLevel" 1548 /*@ 1549 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1550 1551 Not Collective 1552 1553 Input Parameter: 1554 . dm - the DM object 1555 1556 Output Parameter: 1557 . level - number of refinements 1558 1559 Level: developer 1560 1561 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1562 1563 @*/ 1564 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1565 { 1566 PetscFunctionBegin; 1567 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1568 *level = dm->levelup; 1569 PetscFunctionReturn(0); 1570 } 1571 1572 #undef __FUNCT__ 1573 #define __FUNCT__ "DMGlobalToLocalHookAdd" 1574 /*@C 1575 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1576 1577 Logically Collective 1578 1579 Input Arguments: 1580 + dm - the DM 1581 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 1582 . endhook - function to run after DMGlobalToLocalEnd() has completed 1583 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1584 1585 Calling sequence for beginhook: 1586 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1587 1588 + dm - global DM 1589 . g - global vector 1590 . mode - mode 1591 . l - local vector 1592 - ctx - optional user-defined function context 1593 1594 1595 Calling sequence for endhook: 1596 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1597 1598 + global - global DM 1599 - ctx - optional user-defined function context 1600 1601 Level: advanced 1602 1603 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1604 @*/ 1605 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1606 { 1607 PetscErrorCode ierr; 1608 DMGlobalToLocalHookLink link,*p; 1609 1610 PetscFunctionBegin; 1611 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1612 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1613 ierr = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr); 1614 link->beginhook = beginhook; 1615 link->endhook = endhook; 1616 link->ctx = ctx; 1617 link->next = NULL; 1618 *p = link; 1619 PetscFunctionReturn(0); 1620 } 1621 1622 #undef __FUNCT__ 1623 #define __FUNCT__ "DMGlobalToLocalHook_Constraints" 1624 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 1625 { 1626 Mat cMat; 1627 Vec cVec; 1628 PetscSection section, cSec; 1629 PetscInt pStart, pEnd, p, dof; 1630 PetscErrorCode ierr; 1631 1632 PetscFunctionBegin; 1633 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1634 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1635 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 1636 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1637 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1638 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 1639 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1640 for (p = pStart; p < pEnd; p++) { 1641 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1642 if (dof) { 1643 PetscScalar *vals; 1644 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 1645 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 1646 } 1647 } 1648 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1649 } 1650 PetscFunctionReturn(0); 1651 } 1652 1653 #undef __FUNCT__ 1654 #define __FUNCT__ "DMGlobalToLocalBegin" 1655 /*@ 1656 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1657 1658 Neighbor-wise Collective on DM 1659 1660 Input Parameters: 1661 + dm - the DM object 1662 . g - the global vector 1663 . mode - INSERT_VALUES or ADD_VALUES 1664 - l - the local vector 1665 1666 1667 Level: beginner 1668 1669 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1670 1671 @*/ 1672 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1673 { 1674 PetscSF sf; 1675 PetscErrorCode ierr; 1676 DMGlobalToLocalHookLink link; 1677 1678 PetscFunctionBegin; 1679 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1680 for (link=dm->gtolhook; link; link=link->next) { 1681 if (link->beginhook) { 1682 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 1683 } 1684 } 1685 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1686 if (sf) { 1687 const PetscScalar *gArray; 1688 PetscScalar *lArray; 1689 1690 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1691 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1692 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1693 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1694 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1695 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1696 } else { 1697 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1698 } 1699 PetscFunctionReturn(0); 1700 } 1701 1702 #undef __FUNCT__ 1703 #define __FUNCT__ "DMGlobalToLocalEnd" 1704 /*@ 1705 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1706 1707 Neighbor-wise Collective on DM 1708 1709 Input Parameters: 1710 + dm - the DM object 1711 . g - the global vector 1712 . mode - INSERT_VALUES or ADD_VALUES 1713 - l - the local vector 1714 1715 1716 Level: beginner 1717 1718 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1719 1720 @*/ 1721 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 1722 { 1723 PetscSF sf; 1724 PetscErrorCode ierr; 1725 const PetscScalar *gArray; 1726 PetscScalar *lArray; 1727 DMGlobalToLocalHookLink link; 1728 1729 PetscFunctionBegin; 1730 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1731 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1732 if (sf) { 1733 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1734 1735 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1736 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1737 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1738 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1739 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1740 } else { 1741 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1742 } 1743 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 1744 for (link=dm->gtolhook; link; link=link->next) { 1745 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 1746 } 1747 PetscFunctionReturn(0); 1748 } 1749 1750 #undef __FUNCT__ 1751 #define __FUNCT__ "DMLocalToGlobalHookAdd" 1752 /*@C 1753 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 1754 1755 Logically Collective 1756 1757 Input Arguments: 1758 + dm - the DM 1759 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 1760 . endhook - function to run after DMLocalToGlobalEnd() has completed 1761 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1762 1763 Calling sequence for beginhook: 1764 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 1765 1766 + dm - global DM 1767 . l - local vector 1768 . mode - mode 1769 . g - global vector 1770 - ctx - optional user-defined function context 1771 1772 1773 Calling sequence for endhook: 1774 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 1775 1776 + global - global DM 1777 . l - local vector 1778 . mode - mode 1779 . g - global vector 1780 - ctx - optional user-defined function context 1781 1782 Level: advanced 1783 1784 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1785 @*/ 1786 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1787 { 1788 PetscErrorCode ierr; 1789 DMLocalToGlobalHookLink link,*p; 1790 1791 PetscFunctionBegin; 1792 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1793 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1794 ierr = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&link);CHKERRQ(ierr); 1795 link->beginhook = beginhook; 1796 link->endhook = endhook; 1797 link->ctx = ctx; 1798 link->next = NULL; 1799 *p = link; 1800 PetscFunctionReturn(0); 1801 } 1802 1803 #undef __FUNCT__ 1804 #define __FUNCT__ "DMLocalToGlobalHook_Constraints" 1805 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 1806 { 1807 Mat cMat; 1808 Vec cVec; 1809 PetscSection section, cSec; 1810 PetscInt pStart, pEnd, p, dof; 1811 PetscErrorCode ierr; 1812 1813 PetscFunctionBegin; 1814 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1815 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1816 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 1817 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1818 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1819 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1820 for (p = pStart; p < pEnd; p++) { 1821 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1822 if (dof) { 1823 PetscInt d; 1824 PetscScalar *vals; 1825 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 1826 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 1827 /* for this to be the true transpose, we have to zero the values that 1828 * we just extracted */ 1829 for (d = 0; d < dof; d++) { 1830 vals[d] = 0.; 1831 } 1832 } 1833 } 1834 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 1835 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1836 } 1837 PetscFunctionReturn(0); 1838 } 1839 1840 #undef __FUNCT__ 1841 #define __FUNCT__ "DMLocalToGlobalBegin" 1842 /*@ 1843 DMLocalToGlobalBegin - updates global vectors from local vectors 1844 1845 Neighbor-wise Collective on DM 1846 1847 Input Parameters: 1848 + dm - the DM object 1849 . l - the local vector 1850 . 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 base point. 1851 - g - the global vector 1852 1853 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 1854 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 1855 1856 Level: beginner 1857 1858 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 1859 1860 @*/ 1861 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 1862 { 1863 PetscSF sf; 1864 PetscSection s, gs; 1865 DMLocalToGlobalHookLink link; 1866 const PetscScalar *lArray; 1867 PetscScalar *gArray; 1868 PetscBool isInsert; 1869 PetscErrorCode ierr; 1870 1871 PetscFunctionBegin; 1872 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1873 for (link=dm->ltoghook; link; link=link->next) { 1874 if (link->beginhook) { 1875 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 1876 } 1877 } 1878 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 1879 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1880 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 1881 switch (mode) { 1882 case INSERT_VALUES: 1883 case INSERT_ALL_VALUES: 1884 isInsert = PETSC_TRUE; break; 1885 case ADD_VALUES: 1886 case ADD_ALL_VALUES: 1887 isInsert = PETSC_FALSE; break; 1888 default: 1889 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1890 } 1891 if (sf && !isInsert) { 1892 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 1893 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1894 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr); 1895 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 1896 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1897 } else if (s && isInsert) { 1898 PetscInt gStart, pStart, pEnd, p; 1899 1900 ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); 1901 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1902 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 1903 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 1904 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1905 for (p = pStart; p < pEnd; ++p) { 1906 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 1907 1908 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 1909 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 1910 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 1911 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 1912 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 1913 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 1914 /* Ignore off-process data and points with no global data */ 1915 if (!gdof || goff < 0) continue; 1916 if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 1917 /* If no constraints are enforced in the global vector */ 1918 if (!gcdof) { 1919 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 1920 /* If constraints are enforced in the global vector */ 1921 } else if (cdof == gcdof) { 1922 const PetscInt *cdofs; 1923 PetscInt cind = 0; 1924 1925 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 1926 for (d = 0, e = 0; d < dof; ++d) { 1927 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 1928 gArray[goff-gStart+e++] = lArray[off+d]; 1929 } 1930 } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 1931 } 1932 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 1933 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1934 } else { 1935 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1936 } 1937 PetscFunctionReturn(0); 1938 } 1939 1940 #undef __FUNCT__ 1941 #define __FUNCT__ "DMLocalToGlobalEnd" 1942 /*@ 1943 DMLocalToGlobalEnd - updates global vectors from local vectors 1944 1945 Neighbor-wise Collective on DM 1946 1947 Input Parameters: 1948 + dm - the DM object 1949 . l - the local vector 1950 . mode - INSERT_VALUES or ADD_VALUES 1951 - g - the global vector 1952 1953 1954 Level: beginner 1955 1956 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 1957 1958 @*/ 1959 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 1960 { 1961 PetscSF sf; 1962 PetscSection s; 1963 DMLocalToGlobalHookLink link; 1964 PetscBool isInsert; 1965 PetscErrorCode ierr; 1966 1967 PetscFunctionBegin; 1968 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1969 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1970 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 1971 switch (mode) { 1972 case INSERT_VALUES: 1973 case INSERT_ALL_VALUES: 1974 isInsert = PETSC_TRUE; break; 1975 case ADD_VALUES: 1976 case ADD_ALL_VALUES: 1977 isInsert = PETSC_FALSE; break; 1978 default: 1979 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1980 } 1981 if (sf && !isInsert) { 1982 const PetscScalar *lArray; 1983 PetscScalar *gArray; 1984 1985 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 1986 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1987 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr); 1988 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 1989 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1990 } else if (s && isInsert) { 1991 } else { 1992 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1993 } 1994 for (link=dm->ltoghook; link; link=link->next) { 1995 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 1996 } 1997 PetscFunctionReturn(0); 1998 } 1999 2000 #undef __FUNCT__ 2001 #define __FUNCT__ "DMLocalToLocalBegin" 2002 /*@ 2003 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2004 that contain irrelevant values) to another local vector where the ghost 2005 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2006 2007 Neighbor-wise Collective on DM and Vec 2008 2009 Input Parameters: 2010 + dm - the DM object 2011 . g - the original local vector 2012 - mode - one of INSERT_VALUES or ADD_VALUES 2013 2014 Output Parameter: 2015 . l - the local vector with correct ghost values 2016 2017 Level: intermediate 2018 2019 Notes: 2020 The local vectors used here need not be the same as those 2021 obtained from DMCreateLocalVector(), BUT they 2022 must have the same parallel data layout; they could, for example, be 2023 obtained with VecDuplicate() from the DM originating vectors. 2024 2025 .keywords: DM, local-to-local, begin 2026 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2027 2028 @*/ 2029 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2030 { 2031 PetscErrorCode ierr; 2032 2033 PetscFunctionBegin; 2034 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2035 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2036 PetscFunctionReturn(0); 2037 } 2038 2039 #undef __FUNCT__ 2040 #define __FUNCT__ "DMLocalToLocalEnd" 2041 /*@ 2042 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2043 that contain irrelevant values) to another local vector where the ghost 2044 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2045 2046 Neighbor-wise Collective on DM and Vec 2047 2048 Input Parameters: 2049 + da - the DM object 2050 . g - the original local vector 2051 - mode - one of INSERT_VALUES or ADD_VALUES 2052 2053 Output Parameter: 2054 . l - the local vector with correct ghost values 2055 2056 Level: intermediate 2057 2058 Notes: 2059 The local vectors used here need not be the same as those 2060 obtained from DMCreateLocalVector(), BUT they 2061 must have the same parallel data layout; they could, for example, be 2062 obtained with VecDuplicate() from the DM originating vectors. 2063 2064 .keywords: DM, local-to-local, end 2065 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2066 2067 @*/ 2068 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2069 { 2070 PetscErrorCode ierr; 2071 2072 PetscFunctionBegin; 2073 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2074 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2075 PetscFunctionReturn(0); 2076 } 2077 2078 2079 #undef __FUNCT__ 2080 #define __FUNCT__ "DMCoarsen" 2081 /*@ 2082 DMCoarsen - Coarsens a DM object 2083 2084 Collective on DM 2085 2086 Input Parameter: 2087 + dm - the DM object 2088 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2089 2090 Output Parameter: 2091 . dmc - the coarsened DM 2092 2093 Level: developer 2094 2095 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2096 2097 @*/ 2098 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2099 { 2100 PetscErrorCode ierr; 2101 DMCoarsenHookLink link; 2102 2103 PetscFunctionBegin; 2104 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2105 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2106 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2107 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2108 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2109 (*dmc)->ctx = dm->ctx; 2110 (*dmc)->levelup = dm->levelup; 2111 (*dmc)->leveldown = dm->leveldown + 1; 2112 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2113 for (link=dm->coarsenhook; link; link=link->next) { 2114 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2115 } 2116 PetscFunctionReturn(0); 2117 } 2118 2119 #undef __FUNCT__ 2120 #define __FUNCT__ "DMCoarsenHookAdd" 2121 /*@C 2122 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2123 2124 Logically Collective 2125 2126 Input Arguments: 2127 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2128 . coarsenhook - function to run when setting up a coarser level 2129 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2130 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2131 2132 Calling sequence of coarsenhook: 2133 $ coarsenhook(DM fine,DM coarse,void *ctx); 2134 2135 + fine - fine level DM 2136 . coarse - coarse level DM to restrict problem to 2137 - ctx - optional user-defined function context 2138 2139 Calling sequence for restricthook: 2140 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2141 2142 + fine - fine level DM 2143 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2144 . rscale - scaling vector for restriction 2145 . inject - matrix restricting by injection 2146 . coarse - coarse level DM to update 2147 - ctx - optional user-defined function context 2148 2149 Level: advanced 2150 2151 Notes: 2152 This function is only needed if auxiliary data needs to be set up on coarse grids. 2153 2154 If this function is called multiple times, the hooks will be run in the order they are added. 2155 2156 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2157 extract the finest level information from its context (instead of from the SNES). 2158 2159 This function is currently not available from Fortran. 2160 2161 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2162 @*/ 2163 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2164 { 2165 PetscErrorCode ierr; 2166 DMCoarsenHookLink link,*p; 2167 2168 PetscFunctionBegin; 2169 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2170 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2171 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 2172 link->coarsenhook = coarsenhook; 2173 link->restricthook = restricthook; 2174 link->ctx = ctx; 2175 link->next = NULL; 2176 *p = link; 2177 PetscFunctionReturn(0); 2178 } 2179 2180 #undef __FUNCT__ 2181 #define __FUNCT__ "DMRestrict" 2182 /*@ 2183 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2184 2185 Collective if any hooks are 2186 2187 Input Arguments: 2188 + fine - finer DM to use as a base 2189 . restrct - restriction matrix, apply using MatRestrict() 2190 . inject - injection matrix, also use MatRestrict() 2191 - coarse - coarer DM to update 2192 2193 Level: developer 2194 2195 .seealso: DMCoarsenHookAdd(), MatRestrict() 2196 @*/ 2197 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2198 { 2199 PetscErrorCode ierr; 2200 DMCoarsenHookLink link; 2201 2202 PetscFunctionBegin; 2203 for (link=fine->coarsenhook; link; link=link->next) { 2204 if (link->restricthook) { 2205 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2206 } 2207 } 2208 PetscFunctionReturn(0); 2209 } 2210 2211 #undef __FUNCT__ 2212 #define __FUNCT__ "DMSubDomainHookAdd" 2213 /*@C 2214 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2215 2216 Logically Collective 2217 2218 Input Arguments: 2219 + global - global DM 2220 . ddhook - function to run to pass data to the decomposition DM upon its creation 2221 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2222 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2223 2224 2225 Calling sequence for ddhook: 2226 $ ddhook(DM global,DM block,void *ctx) 2227 2228 + global - global DM 2229 . block - block DM 2230 - ctx - optional user-defined function context 2231 2232 Calling sequence for restricthook: 2233 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2234 2235 + global - global DM 2236 . out - scatter to the outer (with ghost and overlap points) block vector 2237 . in - scatter to block vector values only owned locally 2238 . block - block DM 2239 - ctx - optional user-defined function context 2240 2241 Level: advanced 2242 2243 Notes: 2244 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2245 2246 If this function is called multiple times, the hooks will be run in the order they are added. 2247 2248 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2249 extract the global information from its context (instead of from the SNES). 2250 2251 This function is currently not available from Fortran. 2252 2253 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2254 @*/ 2255 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2256 { 2257 PetscErrorCode ierr; 2258 DMSubDomainHookLink link,*p; 2259 2260 PetscFunctionBegin; 2261 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2262 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2263 ierr = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr); 2264 link->restricthook = restricthook; 2265 link->ddhook = ddhook; 2266 link->ctx = ctx; 2267 link->next = NULL; 2268 *p = link; 2269 PetscFunctionReturn(0); 2270 } 2271 2272 #undef __FUNCT__ 2273 #define __FUNCT__ "DMSubDomainRestrict" 2274 /*@ 2275 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2276 2277 Collective if any hooks are 2278 2279 Input Arguments: 2280 + fine - finer DM to use as a base 2281 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2282 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2283 - coarse - coarer DM to update 2284 2285 Level: developer 2286 2287 .seealso: DMCoarsenHookAdd(), MatRestrict() 2288 @*/ 2289 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2290 { 2291 PetscErrorCode ierr; 2292 DMSubDomainHookLink link; 2293 2294 PetscFunctionBegin; 2295 for (link=global->subdomainhook; link; link=link->next) { 2296 if (link->restricthook) { 2297 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2298 } 2299 } 2300 PetscFunctionReturn(0); 2301 } 2302 2303 #undef __FUNCT__ 2304 #define __FUNCT__ "DMGetCoarsenLevel" 2305 /*@ 2306 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2307 2308 Not Collective 2309 2310 Input Parameter: 2311 . dm - the DM object 2312 2313 Output Parameter: 2314 . level - number of coarsenings 2315 2316 Level: developer 2317 2318 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2319 2320 @*/ 2321 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2322 { 2323 PetscFunctionBegin; 2324 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2325 *level = dm->leveldown; 2326 PetscFunctionReturn(0); 2327 } 2328 2329 2330 2331 #undef __FUNCT__ 2332 #define __FUNCT__ "DMRefineHierarchy" 2333 /*@C 2334 DMRefineHierarchy - Refines a DM object, all levels at once 2335 2336 Collective on DM 2337 2338 Input Parameter: 2339 + dm - the DM object 2340 - nlevels - the number of levels of refinement 2341 2342 Output Parameter: 2343 . dmf - the refined DM hierarchy 2344 2345 Level: developer 2346 2347 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2348 2349 @*/ 2350 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2351 { 2352 PetscErrorCode ierr; 2353 2354 PetscFunctionBegin; 2355 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2356 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2357 if (nlevels == 0) PetscFunctionReturn(0); 2358 if (dm->ops->refinehierarchy) { 2359 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2360 } else if (dm->ops->refine) { 2361 PetscInt i; 2362 2363 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2364 for (i=1; i<nlevels; i++) { 2365 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2366 } 2367 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2368 PetscFunctionReturn(0); 2369 } 2370 2371 #undef __FUNCT__ 2372 #define __FUNCT__ "DMCoarsenHierarchy" 2373 /*@C 2374 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2375 2376 Collective on DM 2377 2378 Input Parameter: 2379 + dm - the DM object 2380 - nlevels - the number of levels of coarsening 2381 2382 Output Parameter: 2383 . dmc - the coarsened DM hierarchy 2384 2385 Level: developer 2386 2387 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2388 2389 @*/ 2390 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2391 { 2392 PetscErrorCode ierr; 2393 2394 PetscFunctionBegin; 2395 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2396 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2397 if (nlevels == 0) PetscFunctionReturn(0); 2398 PetscValidPointer(dmc,3); 2399 if (dm->ops->coarsenhierarchy) { 2400 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2401 } else if (dm->ops->coarsen) { 2402 PetscInt i; 2403 2404 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2405 for (i=1; i<nlevels; i++) { 2406 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2407 } 2408 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2409 PetscFunctionReturn(0); 2410 } 2411 2412 #undef __FUNCT__ 2413 #define __FUNCT__ "DMCreateAggregates" 2414 /*@ 2415 DMCreateAggregates - Gets the aggregates that map between 2416 grids associated with two DMs. 2417 2418 Collective on DM 2419 2420 Input Parameters: 2421 + dmc - the coarse grid DM 2422 - dmf - the fine grid DM 2423 2424 Output Parameters: 2425 . rest - the restriction matrix (transpose of the projection matrix) 2426 2427 Level: intermediate 2428 2429 .keywords: interpolation, restriction, multigrid 2430 2431 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2432 @*/ 2433 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2434 { 2435 PetscErrorCode ierr; 2436 2437 PetscFunctionBegin; 2438 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2439 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2440 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2441 PetscFunctionReturn(0); 2442 } 2443 2444 #undef __FUNCT__ 2445 #define __FUNCT__ "DMSetApplicationContextDestroy" 2446 /*@C 2447 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2448 2449 Not Collective 2450 2451 Input Parameters: 2452 + dm - the DM object 2453 - destroy - the destroy function 2454 2455 Level: intermediate 2456 2457 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2458 2459 @*/ 2460 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2461 { 2462 PetscFunctionBegin; 2463 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2464 dm->ctxdestroy = destroy; 2465 PetscFunctionReturn(0); 2466 } 2467 2468 #undef __FUNCT__ 2469 #define __FUNCT__ "DMSetApplicationContext" 2470 /*@ 2471 DMSetApplicationContext - Set a user context into a DM object 2472 2473 Not Collective 2474 2475 Input Parameters: 2476 + dm - the DM object 2477 - ctx - the user context 2478 2479 Level: intermediate 2480 2481 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2482 2483 @*/ 2484 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2485 { 2486 PetscFunctionBegin; 2487 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2488 dm->ctx = ctx; 2489 PetscFunctionReturn(0); 2490 } 2491 2492 #undef __FUNCT__ 2493 #define __FUNCT__ "DMGetApplicationContext" 2494 /*@ 2495 DMGetApplicationContext - Gets a user context from a DM object 2496 2497 Not Collective 2498 2499 Input Parameter: 2500 . dm - the DM object 2501 2502 Output Parameter: 2503 . ctx - the user context 2504 2505 Level: intermediate 2506 2507 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2508 2509 @*/ 2510 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2511 { 2512 PetscFunctionBegin; 2513 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2514 *(void**)ctx = dm->ctx; 2515 PetscFunctionReturn(0); 2516 } 2517 2518 #undef __FUNCT__ 2519 #define __FUNCT__ "DMSetVariableBounds" 2520 /*@C 2521 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2522 2523 Logically Collective on DM 2524 2525 Input Parameter: 2526 + dm - the DM object 2527 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2528 2529 Level: intermediate 2530 2531 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2532 DMSetJacobian() 2533 2534 @*/ 2535 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2536 { 2537 PetscFunctionBegin; 2538 dm->ops->computevariablebounds = f; 2539 PetscFunctionReturn(0); 2540 } 2541 2542 #undef __FUNCT__ 2543 #define __FUNCT__ "DMHasVariableBounds" 2544 /*@ 2545 DMHasVariableBounds - does the DM object have a variable bounds function? 2546 2547 Not Collective 2548 2549 Input Parameter: 2550 . dm - the DM object to destroy 2551 2552 Output Parameter: 2553 . flg - PETSC_TRUE if the variable bounds function exists 2554 2555 Level: developer 2556 2557 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2558 2559 @*/ 2560 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2561 { 2562 PetscFunctionBegin; 2563 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2564 PetscFunctionReturn(0); 2565 } 2566 2567 #undef __FUNCT__ 2568 #define __FUNCT__ "DMComputeVariableBounds" 2569 /*@C 2570 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2571 2572 Logically Collective on DM 2573 2574 Input Parameters: 2575 . dm - the DM object 2576 2577 Output parameters: 2578 + xl - lower bound 2579 - xu - upper bound 2580 2581 Level: advanced 2582 2583 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2584 2585 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2586 2587 @*/ 2588 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2589 { 2590 PetscErrorCode ierr; 2591 2592 PetscFunctionBegin; 2593 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2594 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2595 if (dm->ops->computevariablebounds) { 2596 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2597 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2598 PetscFunctionReturn(0); 2599 } 2600 2601 #undef __FUNCT__ 2602 #define __FUNCT__ "DMHasColoring" 2603 /*@ 2604 DMHasColoring - does the DM object have a method of providing a coloring? 2605 2606 Not Collective 2607 2608 Input Parameter: 2609 . dm - the DM object 2610 2611 Output Parameter: 2612 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2613 2614 Level: developer 2615 2616 .seealso DMHasFunction(), DMCreateColoring() 2617 2618 @*/ 2619 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2620 { 2621 PetscFunctionBegin; 2622 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2623 PetscFunctionReturn(0); 2624 } 2625 2626 #undef __FUNCT__ 2627 #define __FUNCT__ "DMSetVec" 2628 /*@C 2629 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2630 2631 Collective on DM 2632 2633 Input Parameter: 2634 + dm - the DM object 2635 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2636 2637 Level: developer 2638 2639 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2640 2641 @*/ 2642 PetscErrorCode DMSetVec(DM dm,Vec x) 2643 { 2644 PetscErrorCode ierr; 2645 2646 PetscFunctionBegin; 2647 if (x) { 2648 if (!dm->x) { 2649 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2650 } 2651 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2652 } else if (dm->x) { 2653 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2654 } 2655 PetscFunctionReturn(0); 2656 } 2657 2658 PetscFunctionList DMList = NULL; 2659 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2660 2661 #undef __FUNCT__ 2662 #define __FUNCT__ "DMSetType" 2663 /*@C 2664 DMSetType - Builds a DM, for a particular DM implementation. 2665 2666 Collective on DM 2667 2668 Input Parameters: 2669 + dm - The DM object 2670 - method - The name of the DM type 2671 2672 Options Database Key: 2673 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2674 2675 Notes: 2676 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2677 2678 Level: intermediate 2679 2680 .keywords: DM, set, type 2681 .seealso: DMGetType(), DMCreate() 2682 @*/ 2683 PetscErrorCode DMSetType(DM dm, DMType method) 2684 { 2685 PetscErrorCode (*r)(DM); 2686 PetscBool match; 2687 PetscErrorCode ierr; 2688 2689 PetscFunctionBegin; 2690 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2691 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2692 if (match) PetscFunctionReturn(0); 2693 2694 ierr = DMRegisterAll();CHKERRQ(ierr); 2695 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 2696 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2697 2698 if (dm->ops->destroy) { 2699 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2700 dm->ops->destroy = NULL; 2701 } 2702 ierr = (*r)(dm);CHKERRQ(ierr); 2703 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2704 PetscFunctionReturn(0); 2705 } 2706 2707 #undef __FUNCT__ 2708 #define __FUNCT__ "DMGetType" 2709 /*@C 2710 DMGetType - Gets the DM type name (as a string) from the DM. 2711 2712 Not Collective 2713 2714 Input Parameter: 2715 . dm - The DM 2716 2717 Output Parameter: 2718 . type - The DM type name 2719 2720 Level: intermediate 2721 2722 .keywords: DM, get, type, name 2723 .seealso: DMSetType(), DMCreate() 2724 @*/ 2725 PetscErrorCode DMGetType(DM dm, DMType *type) 2726 { 2727 PetscErrorCode ierr; 2728 2729 PetscFunctionBegin; 2730 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2731 PetscValidPointer(type,2); 2732 ierr = DMRegisterAll();CHKERRQ(ierr); 2733 *type = ((PetscObject)dm)->type_name; 2734 PetscFunctionReturn(0); 2735 } 2736 2737 #undef __FUNCT__ 2738 #define __FUNCT__ "DMConvert" 2739 /*@C 2740 DMConvert - Converts a DM to another DM, either of the same or different type. 2741 2742 Collective on DM 2743 2744 Input Parameters: 2745 + dm - the DM 2746 - newtype - new DM type (use "same" for the same type) 2747 2748 Output Parameter: 2749 . M - pointer to new DM 2750 2751 Notes: 2752 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 2753 the MPI communicator of the generated DM is always the same as the communicator 2754 of the input DM. 2755 2756 Level: intermediate 2757 2758 .seealso: DMCreate() 2759 @*/ 2760 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 2761 { 2762 DM B; 2763 char convname[256]; 2764 PetscBool sametype, issame; 2765 PetscErrorCode ierr; 2766 2767 PetscFunctionBegin; 2768 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2769 PetscValidType(dm,1); 2770 PetscValidPointer(M,3); 2771 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 2772 ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); 2773 { 2774 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 2775 2776 /* 2777 Order of precedence: 2778 1) See if a specialized converter is known to the current DM. 2779 2) See if a specialized converter is known to the desired DM class. 2780 3) See if a good general converter is registered for the desired class 2781 4) See if a good general converter is known for the current matrix. 2782 5) Use a really basic converter. 2783 */ 2784 2785 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2786 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2787 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2788 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2789 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2790 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2791 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 2792 if (conv) goto foundconv; 2793 2794 /* 2) See if a specialized converter is known to the desired DM class. */ 2795 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 2796 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2797 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2798 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2799 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2800 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2801 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2802 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 2803 if (conv) { 2804 ierr = DMDestroy(&B);CHKERRQ(ierr); 2805 goto foundconv; 2806 } 2807 2808 #if 0 2809 /* 3) See if a good general converter is registered for the desired class */ 2810 conv = B->ops->convertfrom; 2811 ierr = DMDestroy(&B);CHKERRQ(ierr); 2812 if (conv) goto foundconv; 2813 2814 /* 4) See if a good general converter is known for the current matrix */ 2815 if (dm->ops->convert) { 2816 conv = dm->ops->convert; 2817 } 2818 if (conv) goto foundconv; 2819 #endif 2820 2821 /* 5) Use a really basic converter. */ 2822 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 2823 2824 foundconv: 2825 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2826 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 2827 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2828 } 2829 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 2830 PetscFunctionReturn(0); 2831 } 2832 2833 /*--------------------------------------------------------------------------------------------------------------------*/ 2834 2835 #undef __FUNCT__ 2836 #define __FUNCT__ "DMRegister" 2837 /*@C 2838 DMRegister - Adds a new DM component implementation 2839 2840 Not Collective 2841 2842 Input Parameters: 2843 + name - The name of a new user-defined creation routine 2844 - create_func - The creation routine itself 2845 2846 Notes: 2847 DMRegister() may be called multiple times to add several user-defined DMs 2848 2849 2850 Sample usage: 2851 .vb 2852 DMRegister("my_da", MyDMCreate); 2853 .ve 2854 2855 Then, your DM type can be chosen with the procedural interface via 2856 .vb 2857 DMCreate(MPI_Comm, DM *); 2858 DMSetType(DM,"my_da"); 2859 .ve 2860 or at runtime via the option 2861 .vb 2862 -da_type my_da 2863 .ve 2864 2865 Level: advanced 2866 2867 .keywords: DM, register 2868 .seealso: DMRegisterAll(), DMRegisterDestroy() 2869 2870 @*/ 2871 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 2872 { 2873 PetscErrorCode ierr; 2874 2875 PetscFunctionBegin; 2876 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 2877 PetscFunctionReturn(0); 2878 } 2879 2880 #undef __FUNCT__ 2881 #define __FUNCT__ "DMLoad" 2882 /*@C 2883 DMLoad - Loads a DM that has been stored in binary with DMView(). 2884 2885 Collective on PetscViewer 2886 2887 Input Parameters: 2888 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 2889 some related function before a call to DMLoad(). 2890 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 2891 HDF5 file viewer, obtained from PetscViewerHDF5Open() 2892 2893 Level: intermediate 2894 2895 Notes: 2896 The type is determined by the data in the file, any type set into the DM before this call is ignored. 2897 2898 Notes for advanced users: 2899 Most users should not need to know the details of the binary storage 2900 format, since DMLoad() and DMView() completely hide these details. 2901 But for anyone who's interested, the standard binary matrix storage 2902 format is 2903 .vb 2904 has not yet been determined 2905 .ve 2906 2907 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 2908 @*/ 2909 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 2910 { 2911 PetscBool isbinary, ishdf5; 2912 PetscErrorCode ierr; 2913 2914 PetscFunctionBegin; 2915 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 2916 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2917 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 2918 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2919 if (isbinary) { 2920 PetscInt classid; 2921 char type[256]; 2922 2923 ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr); 2924 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 2925 ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr); 2926 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 2927 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 2928 } else if (ishdf5) { 2929 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 2930 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 2931 PetscFunctionReturn(0); 2932 } 2933 2934 /******************************** FEM Support **********************************/ 2935 2936 #undef __FUNCT__ 2937 #define __FUNCT__ "DMPrintCellVector" 2938 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 2939 { 2940 PetscInt f; 2941 PetscErrorCode ierr; 2942 2943 PetscFunctionBegin; 2944 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2945 for (f = 0; f < len; ++f) { 2946 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 2947 } 2948 PetscFunctionReturn(0); 2949 } 2950 2951 #undef __FUNCT__ 2952 #define __FUNCT__ "DMPrintCellMatrix" 2953 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 2954 { 2955 PetscInt f, g; 2956 PetscErrorCode ierr; 2957 2958 PetscFunctionBegin; 2959 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2960 for (f = 0; f < rows; ++f) { 2961 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 2962 for (g = 0; g < cols; ++g) { 2963 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 2964 } 2965 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 2966 } 2967 PetscFunctionReturn(0); 2968 } 2969 2970 #undef __FUNCT__ 2971 #define __FUNCT__ "DMPrintLocalVec" 2972 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 2973 { 2974 PetscMPIInt rank, numProcs; 2975 PetscInt p; 2976 PetscErrorCode ierr; 2977 2978 PetscFunctionBegin; 2979 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 2980 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 2981 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 2982 for (p = 0; p < numProcs; ++p) { 2983 if (p == rank) { 2984 Vec x; 2985 2986 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 2987 ierr = VecCopy(X, x);CHKERRQ(ierr); 2988 ierr = VecChop(x, tol);CHKERRQ(ierr); 2989 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 2990 ierr = VecDestroy(&x);CHKERRQ(ierr); 2991 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 2992 } 2993 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 2994 } 2995 PetscFunctionReturn(0); 2996 } 2997 2998 #undef __FUNCT__ 2999 #define __FUNCT__ "DMGetDefaultSection" 3000 /*@ 3001 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3002 3003 Input Parameter: 3004 . dm - The DM 3005 3006 Output Parameter: 3007 . section - The PetscSection 3008 3009 Level: intermediate 3010 3011 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3012 3013 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3014 @*/ 3015 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3016 { 3017 PetscErrorCode ierr; 3018 3019 PetscFunctionBegin; 3020 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3021 PetscValidPointer(section, 2); 3022 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3023 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3024 ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, "dm_", "-petscsection_view");CHKERRQ(ierr); 3025 } 3026 *section = dm->defaultSection; 3027 PetscFunctionReturn(0); 3028 } 3029 3030 #undef __FUNCT__ 3031 #define __FUNCT__ "DMSetDefaultSection" 3032 /*@ 3033 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3034 3035 Input Parameters: 3036 + dm - The DM 3037 - section - The PetscSection 3038 3039 Level: intermediate 3040 3041 Note: Any existing Section will be destroyed 3042 3043 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3044 @*/ 3045 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3046 { 3047 PetscInt numFields; 3048 PetscInt f; 3049 PetscErrorCode ierr; 3050 3051 PetscFunctionBegin; 3052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3053 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3054 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3055 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3056 dm->defaultSection = section; 3057 ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr); 3058 if (numFields) { 3059 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3060 for (f = 0; f < numFields; ++f) { 3061 PetscObject disc; 3062 const char *name; 3063 3064 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3065 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3066 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3067 } 3068 } 3069 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3070 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3071 PetscFunctionReturn(0); 3072 } 3073 3074 #undef __FUNCT__ 3075 #define __FUNCT__ "DMGetDefaultConstraints" 3076 /*@ 3077 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3078 3079 not collective 3080 3081 Input Parameter: 3082 . dm - The DM 3083 3084 Output Parameter: 3085 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Returns NULL if there are no local constraints. 3086 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section. Returns NULL if there are no local constraints. 3087 3088 Level: advanced 3089 3090 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3091 3092 .seealso: DMSetDefaultConstraints() 3093 @*/ 3094 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3095 { 3096 PetscErrorCode ierr; 3097 3098 PetscFunctionBegin; 3099 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3100 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3101 if (section) {*section = dm->defaultConstraintSection;} 3102 if (mat) {*mat = dm->defaultConstraintMat;} 3103 PetscFunctionReturn(0); 3104 } 3105 3106 #undef __FUNCT__ 3107 #define __FUNCT__ "DMSetDefaultConstraints" 3108 /*@ 3109 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3110 3111 If a constraint matrix is specified, then it is applied during DMGlobalToLocalEnd() when mode is INSERT_VALUES, INSERT_BC_VALUES, or INSERT_ALL_VALUES. Without a constraint matrix, the local vector l returned by DMGlobalToLocalEnd() contains values that have been scattered from a global vector without modification; with a constraint matrix A, l is modified by computing c = A * l, l[s[i]] = c[i], where the scatter s is defined by the PetscSection returned by DMGetDefaultConstraintMatrix(). 3112 3113 If a constraint matrix is specified, then its adjoint is applied during DMLocalToGlobalBegin() when mode is ADD_VALUES, ADD_BC_VALUES, or ADD_ALL_VALUES. Without a constraint matrix, the local vector l is accumulated into a global vector without modification; with a constraint matrix A, l is first modified by computing c[i] = l[s[i]], l[s[i]] = 0, l = l + A'*c, which is the adjoint of the operation described above. 3114 3115 collective on dm 3116 3117 Input Parameters: 3118 + dm - The DM 3119 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Must have a local communicator (PETSC_COMM_SELF or derivative). 3120 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section: NULL indicates no constraints. Must have a local communicator (PETSC_COMM_SELF or derivative). 3121 3122 Level: advanced 3123 3124 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3125 3126 .seealso: DMGetDefaultConstraints() 3127 @*/ 3128 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3129 { 3130 PetscMPIInt result; 3131 PetscErrorCode ierr; 3132 3133 PetscFunctionBegin; 3134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3135 if (section) { 3136 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3137 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3138 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3139 } 3140 if (mat) { 3141 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3142 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3143 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3144 } 3145 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3146 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3147 dm->defaultConstraintSection = section; 3148 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3149 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3150 dm->defaultConstraintMat = mat; 3151 PetscFunctionReturn(0); 3152 } 3153 3154 #undef __FUNCT__ 3155 #define __FUNCT__ "DMGetDefaultGlobalSection" 3156 /*@ 3157 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3158 3159 Collective on DM 3160 3161 Input Parameter: 3162 . dm - The DM 3163 3164 Output Parameter: 3165 . section - The PetscSection 3166 3167 Level: intermediate 3168 3169 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3170 3171 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3172 @*/ 3173 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3174 { 3175 PetscErrorCode ierr; 3176 3177 PetscFunctionBegin; 3178 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3179 PetscValidPointer(section, 2); 3180 if (!dm->defaultGlobalSection) { 3181 PetscSection s; 3182 3183 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3184 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3185 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3186 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3187 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3188 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3189 } 3190 *section = dm->defaultGlobalSection; 3191 PetscFunctionReturn(0); 3192 } 3193 3194 #undef __FUNCT__ 3195 #define __FUNCT__ "DMSetDefaultGlobalSection" 3196 /*@ 3197 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3198 3199 Input Parameters: 3200 + dm - The DM 3201 - section - The PetscSection, or NULL 3202 3203 Level: intermediate 3204 3205 Note: Any existing Section will be destroyed 3206 3207 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3208 @*/ 3209 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3210 { 3211 PetscErrorCode ierr; 3212 3213 PetscFunctionBegin; 3214 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3215 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3216 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3217 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3218 dm->defaultGlobalSection = section; 3219 PetscFunctionReturn(0); 3220 } 3221 3222 #undef __FUNCT__ 3223 #define __FUNCT__ "DMGetDefaultSF" 3224 /*@ 3225 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3226 it is created from the default PetscSection layouts in the DM. 3227 3228 Input Parameter: 3229 . dm - The DM 3230 3231 Output Parameter: 3232 . sf - The PetscSF 3233 3234 Level: intermediate 3235 3236 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3237 3238 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3239 @*/ 3240 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3241 { 3242 PetscInt nroots; 3243 PetscErrorCode ierr; 3244 3245 PetscFunctionBegin; 3246 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3247 PetscValidPointer(sf, 2); 3248 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3249 if (nroots < 0) { 3250 PetscSection section, gSection; 3251 3252 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3253 if (section) { 3254 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3255 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3256 } else { 3257 *sf = NULL; 3258 PetscFunctionReturn(0); 3259 } 3260 } 3261 *sf = dm->defaultSF; 3262 PetscFunctionReturn(0); 3263 } 3264 3265 #undef __FUNCT__ 3266 #define __FUNCT__ "DMSetDefaultSF" 3267 /*@ 3268 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3269 3270 Input Parameters: 3271 + dm - The DM 3272 - sf - The PetscSF 3273 3274 Level: intermediate 3275 3276 Note: Any previous SF is destroyed 3277 3278 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3279 @*/ 3280 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3281 { 3282 PetscErrorCode ierr; 3283 3284 PetscFunctionBegin; 3285 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3286 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3287 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3288 dm->defaultSF = sf; 3289 PetscFunctionReturn(0); 3290 } 3291 3292 #undef __FUNCT__ 3293 #define __FUNCT__ "DMCreateDefaultSF" 3294 /*@C 3295 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3296 describing the data layout. 3297 3298 Input Parameters: 3299 + dm - The DM 3300 . localSection - PetscSection describing the local data layout 3301 - globalSection - PetscSection describing the global data layout 3302 3303 Level: intermediate 3304 3305 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3306 @*/ 3307 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3308 { 3309 MPI_Comm comm; 3310 PetscLayout layout; 3311 const PetscInt *ranges; 3312 PetscInt *local; 3313 PetscSFNode *remote; 3314 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3315 PetscMPIInt size, rank; 3316 PetscErrorCode ierr; 3317 3318 PetscFunctionBegin; 3319 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3320 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3321 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3322 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3323 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3324 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3325 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3326 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3327 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3328 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3329 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3330 for (p = pStart; p < pEnd; ++p) { 3331 PetscInt gdof, gcdof; 3332 3333 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3334 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3335 if (gcdof > (gdof < 0 ? -(gdof+1) : gdof)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d has %d constraints > %d dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof)); 3336 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3337 } 3338 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3339 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3340 for (p = pStart, l = 0; p < pEnd; ++p) { 3341 const PetscInt *cind; 3342 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3343 3344 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3345 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3346 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3347 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3348 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3349 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3350 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3351 if (!gdof) continue; /* Censored point */ 3352 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3353 if (gsize != dof-cdof) { 3354 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); 3355 cdof = 0; /* Ignore constraints */ 3356 } 3357 for (d = 0, c = 0; d < dof; ++d) { 3358 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3359 local[l+d-c] = off+d; 3360 } 3361 if (gdof < 0) { 3362 for (d = 0; d < gsize; ++d, ++l) { 3363 PetscInt offset = -(goff+1) + d, r; 3364 3365 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3366 if (r < 0) r = -(r+2); 3367 if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff); 3368 remote[l].rank = r; 3369 remote[l].index = offset - ranges[r]; 3370 } 3371 } else { 3372 for (d = 0; d < gsize; ++d, ++l) { 3373 remote[l].rank = rank; 3374 remote[l].index = goff+d - ranges[rank]; 3375 } 3376 } 3377 } 3378 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3379 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3380 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3381 PetscFunctionReturn(0); 3382 } 3383 3384 #undef __FUNCT__ 3385 #define __FUNCT__ "DMGetPointSF" 3386 /*@ 3387 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3388 3389 Input Parameter: 3390 . dm - The DM 3391 3392 Output Parameter: 3393 . sf - The PetscSF 3394 3395 Level: intermediate 3396 3397 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3398 3399 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3400 @*/ 3401 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3402 { 3403 PetscFunctionBegin; 3404 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3405 PetscValidPointer(sf, 2); 3406 *sf = dm->sf; 3407 PetscFunctionReturn(0); 3408 } 3409 3410 #undef __FUNCT__ 3411 #define __FUNCT__ "DMSetPointSF" 3412 /*@ 3413 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3414 3415 Input Parameters: 3416 + dm - The DM 3417 - sf - The PetscSF 3418 3419 Level: intermediate 3420 3421 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3422 @*/ 3423 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3424 { 3425 PetscErrorCode ierr; 3426 3427 PetscFunctionBegin; 3428 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3429 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3430 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3431 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3432 dm->sf = sf; 3433 PetscFunctionReturn(0); 3434 } 3435 3436 #undef __FUNCT__ 3437 #define __FUNCT__ "DMGetDS" 3438 /*@ 3439 DMGetDS - Get the PetscDS 3440 3441 Input Parameter: 3442 . dm - The DM 3443 3444 Output Parameter: 3445 . prob - The PetscDS 3446 3447 Level: developer 3448 3449 .seealso: DMSetDS() 3450 @*/ 3451 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3452 { 3453 PetscFunctionBegin; 3454 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3455 PetscValidPointer(prob, 2); 3456 *prob = dm->prob; 3457 PetscFunctionReturn(0); 3458 } 3459 3460 #undef __FUNCT__ 3461 #define __FUNCT__ "DMSetDS" 3462 /*@ 3463 DMSetDS - Set the PetscDS 3464 3465 Input Parameters: 3466 + dm - The DM 3467 - prob - The PetscDS 3468 3469 Level: developer 3470 3471 .seealso: DMGetDS() 3472 @*/ 3473 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3474 { 3475 PetscErrorCode ierr; 3476 3477 PetscFunctionBegin; 3478 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3479 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3480 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3481 dm->prob = prob; 3482 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3483 PetscFunctionReturn(0); 3484 } 3485 3486 #undef __FUNCT__ 3487 #define __FUNCT__ "DMGetNumFields" 3488 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3489 { 3490 PetscErrorCode ierr; 3491 3492 PetscFunctionBegin; 3493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3494 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3495 PetscFunctionReturn(0); 3496 } 3497 3498 #undef __FUNCT__ 3499 #define __FUNCT__ "DMSetNumFields" 3500 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3501 { 3502 PetscInt Nf, f; 3503 PetscErrorCode ierr; 3504 3505 PetscFunctionBegin; 3506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3507 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3508 for (f = Nf; f < numFields; ++f) { 3509 PetscContainer obj; 3510 3511 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3512 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3513 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3514 } 3515 PetscFunctionReturn(0); 3516 } 3517 3518 #undef __FUNCT__ 3519 #define __FUNCT__ "DMGetField" 3520 /*@ 3521 DMGetField - Return the discretization object for a given DM field 3522 3523 Not collective 3524 3525 Input Parameters: 3526 + dm - The DM 3527 - f - The field number 3528 3529 Output Parameter: 3530 . field - The discretization object 3531 3532 Level: developer 3533 3534 .seealso: DMSetField() 3535 @*/ 3536 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3537 { 3538 PetscErrorCode ierr; 3539 3540 PetscFunctionBegin; 3541 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3542 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3543 PetscFunctionReturn(0); 3544 } 3545 3546 #undef __FUNCT__ 3547 #define __FUNCT__ "DMSetField" 3548 /*@ 3549 DMSetField - Set the discretization object for a given DM field 3550 3551 Logically collective on DM 3552 3553 Input Parameters: 3554 + dm - The DM 3555 . f - The field number 3556 - field - The discretization object 3557 3558 Level: developer 3559 3560 .seealso: DMGetField() 3561 @*/ 3562 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3563 { 3564 PetscErrorCode ierr; 3565 3566 PetscFunctionBegin; 3567 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3568 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3569 PetscFunctionReturn(0); 3570 } 3571 3572 #undef __FUNCT__ 3573 #define __FUNCT__ "DMRestrictHook_Coordinates" 3574 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3575 { 3576 DM dm_coord,dmc_coord; 3577 PetscErrorCode ierr; 3578 Vec coords,ccoords; 3579 Mat inject; 3580 PetscFunctionBegin; 3581 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3582 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3583 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3584 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3585 if (coords && !ccoords) { 3586 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3587 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3588 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3589 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3590 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3591 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3592 } 3593 PetscFunctionReturn(0); 3594 } 3595 3596 #undef __FUNCT__ 3597 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3598 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3599 { 3600 DM dm_coord,subdm_coord; 3601 PetscErrorCode ierr; 3602 Vec coords,ccoords,clcoords; 3603 VecScatter *scat_i,*scat_g; 3604 PetscFunctionBegin; 3605 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3606 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3607 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3608 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3609 if (coords && !ccoords) { 3610 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3611 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3612 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3613 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3614 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3615 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3616 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3617 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3618 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3619 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3620 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3621 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3622 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3623 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3624 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3625 } 3626 PetscFunctionReturn(0); 3627 } 3628 3629 #undef __FUNCT__ 3630 #define __FUNCT__ "DMGetDimension" 3631 /*@ 3632 DMGetDimension - Return the topological dimension of the DM 3633 3634 Not collective 3635 3636 Input Parameter: 3637 . dm - The DM 3638 3639 Output Parameter: 3640 . dim - The topological dimension 3641 3642 Level: beginner 3643 3644 .seealso: DMSetDimension(), DMCreate() 3645 @*/ 3646 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3647 { 3648 PetscFunctionBegin; 3649 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3650 PetscValidPointer(dim, 2); 3651 *dim = dm->dim; 3652 PetscFunctionReturn(0); 3653 } 3654 3655 #undef __FUNCT__ 3656 #define __FUNCT__ "DMSetDimension" 3657 /*@ 3658 DMSetDimension - Set the topological dimension of the DM 3659 3660 Collective on dm 3661 3662 Input Parameters: 3663 + dm - The DM 3664 - dim - The topological dimension 3665 3666 Level: beginner 3667 3668 .seealso: DMGetDimension(), DMCreate() 3669 @*/ 3670 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3671 { 3672 PetscFunctionBegin; 3673 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3674 PetscValidLogicalCollectiveInt(dm, dim, 2); 3675 dm->dim = dim; 3676 PetscFunctionReturn(0); 3677 } 3678 3679 #undef __FUNCT__ 3680 #define __FUNCT__ "DMGetDimPoints" 3681 /*@ 3682 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3683 3684 Collective on DM 3685 3686 Input Parameters: 3687 + dm - the DM 3688 - dim - the dimension 3689 3690 Output Parameters: 3691 + pStart - The first point of the given dimension 3692 . pEnd - The first point following points of the given dimension 3693 3694 Note: 3695 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3696 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3697 then the interval is empty. 3698 3699 Level: intermediate 3700 3701 .keywords: point, Hasse Diagram, dimension 3702 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3703 @*/ 3704 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3705 { 3706 PetscInt d; 3707 PetscErrorCode ierr; 3708 3709 PetscFunctionBegin; 3710 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3711 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3712 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3713 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3714 PetscFunctionReturn(0); 3715 } 3716 3717 #undef __FUNCT__ 3718 #define __FUNCT__ "DMSetCoordinates" 3719 /*@ 3720 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3721 3722 Collective on DM 3723 3724 Input Parameters: 3725 + dm - the DM 3726 - c - coordinate vector 3727 3728 Note: 3729 The coordinates do include those for ghost points, which are in the local vector 3730 3731 Level: intermediate 3732 3733 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3734 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3735 @*/ 3736 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3737 { 3738 PetscErrorCode ierr; 3739 3740 PetscFunctionBegin; 3741 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3742 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3743 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3744 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3745 dm->coordinates = c; 3746 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3747 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3748 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3749 PetscFunctionReturn(0); 3750 } 3751 3752 #undef __FUNCT__ 3753 #define __FUNCT__ "DMSetCoordinatesLocal" 3754 /*@ 3755 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3756 3757 Collective on DM 3758 3759 Input Parameters: 3760 + dm - the DM 3761 - c - coordinate vector 3762 3763 Note: 3764 The coordinates of ghost points can be set using DMSetCoordinates() 3765 followed by DMGetCoordinatesLocal(). This is intended to enable the 3766 setting of ghost coordinates outside of the domain. 3767 3768 Level: intermediate 3769 3770 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3771 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3772 @*/ 3773 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3774 { 3775 PetscErrorCode ierr; 3776 3777 PetscFunctionBegin; 3778 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3779 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3780 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3781 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3782 3783 dm->coordinatesLocal = c; 3784 3785 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3786 PetscFunctionReturn(0); 3787 } 3788 3789 #undef __FUNCT__ 3790 #define __FUNCT__ "DMGetCoordinates" 3791 /*@ 3792 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3793 3794 Not Collective 3795 3796 Input Parameter: 3797 . dm - the DM 3798 3799 Output Parameter: 3800 . c - global coordinate vector 3801 3802 Note: 3803 This is a borrowed reference, so the user should NOT destroy this vector 3804 3805 Each process has only the local coordinates (does NOT have the ghost coordinates). 3806 3807 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3808 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3809 3810 Level: intermediate 3811 3812 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3813 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3814 @*/ 3815 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 3816 { 3817 PetscErrorCode ierr; 3818 3819 PetscFunctionBegin; 3820 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3821 PetscValidPointer(c,2); 3822 if (!dm->coordinates && dm->coordinatesLocal) { 3823 DM cdm = NULL; 3824 3825 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3826 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 3827 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 3828 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3829 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3830 } 3831 *c = dm->coordinates; 3832 PetscFunctionReturn(0); 3833 } 3834 3835 #undef __FUNCT__ 3836 #define __FUNCT__ "DMGetCoordinatesLocal" 3837 /*@ 3838 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 3839 3840 Collective on DM 3841 3842 Input Parameter: 3843 . dm - the DM 3844 3845 Output Parameter: 3846 . c - coordinate vector 3847 3848 Note: 3849 This is a borrowed reference, so the user should NOT destroy this vector 3850 3851 Each process has the local and ghost coordinates 3852 3853 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3854 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3855 3856 Level: intermediate 3857 3858 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3859 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 3860 @*/ 3861 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 3862 { 3863 PetscErrorCode ierr; 3864 3865 PetscFunctionBegin; 3866 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3867 PetscValidPointer(c,2); 3868 if (!dm->coordinatesLocal && dm->coordinates) { 3869 DM cdm = NULL; 3870 3871 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3872 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 3873 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 3874 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3875 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3876 } 3877 *c = dm->coordinatesLocal; 3878 PetscFunctionReturn(0); 3879 } 3880 3881 #undef __FUNCT__ 3882 #define __FUNCT__ "DMGetCoordinateDM" 3883 /*@ 3884 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 3885 3886 Collective on DM 3887 3888 Input Parameter: 3889 . dm - the DM 3890 3891 Output Parameter: 3892 . cdm - coordinate DM 3893 3894 Level: intermediate 3895 3896 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3897 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3898 @*/ 3899 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 3900 { 3901 PetscErrorCode ierr; 3902 3903 PetscFunctionBegin; 3904 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3905 PetscValidPointer(cdm,2); 3906 if (!dm->coordinateDM) { 3907 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 3908 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 3909 } 3910 *cdm = dm->coordinateDM; 3911 PetscFunctionReturn(0); 3912 } 3913 3914 #undef __FUNCT__ 3915 #define __FUNCT__ "DMSetCoordinateDM" 3916 /*@ 3917 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 3918 3919 Logically Collective on DM 3920 3921 Input Parameters: 3922 + dm - the DM 3923 - cdm - coordinate DM 3924 3925 Level: intermediate 3926 3927 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3928 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3929 @*/ 3930 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 3931 { 3932 PetscErrorCode ierr; 3933 3934 PetscFunctionBegin; 3935 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3936 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 3937 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 3938 dm->coordinateDM = cdm; 3939 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 3940 PetscFunctionReturn(0); 3941 } 3942 3943 #undef __FUNCT__ 3944 #define __FUNCT__ "DMGetCoordinateDim" 3945 /*@ 3946 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 3947 3948 Not Collective 3949 3950 Input Parameter: 3951 . dm - The DM object 3952 3953 Output Parameter: 3954 . dim - The embedding dimension 3955 3956 Level: intermediate 3957 3958 .keywords: mesh, coordinates 3959 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 3960 @*/ 3961 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 3962 { 3963 PetscFunctionBegin; 3964 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3965 PetscValidPointer(dim, 2); 3966 if (dm->dimEmbed == PETSC_DEFAULT) { 3967 dm->dimEmbed = dm->dim; 3968 } 3969 *dim = dm->dimEmbed; 3970 PetscFunctionReturn(0); 3971 } 3972 3973 #undef __FUNCT__ 3974 #define __FUNCT__ "DMSetCoordinateDim" 3975 /*@ 3976 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 3977 3978 Not Collective 3979 3980 Input Parameters: 3981 + dm - The DM object 3982 - dim - The embedding dimension 3983 3984 Level: intermediate 3985 3986 .keywords: mesh, coordinates 3987 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 3988 @*/ 3989 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 3990 { 3991 PetscFunctionBegin; 3992 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3993 dm->dimEmbed = dim; 3994 PetscFunctionReturn(0); 3995 } 3996 3997 #undef __FUNCT__ 3998 #define __FUNCT__ "DMGetCoordinateSection" 3999 /*@ 4000 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4001 4002 Not Collective 4003 4004 Input Parameter: 4005 . dm - The DM object 4006 4007 Output Parameter: 4008 . section - The PetscSection object 4009 4010 Level: intermediate 4011 4012 .keywords: mesh, coordinates 4013 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4014 @*/ 4015 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4016 { 4017 DM cdm; 4018 PetscErrorCode ierr; 4019 4020 PetscFunctionBegin; 4021 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4022 PetscValidPointer(section, 2); 4023 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4024 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4025 PetscFunctionReturn(0); 4026 } 4027 4028 #undef __FUNCT__ 4029 #define __FUNCT__ "DMSetCoordinateSection" 4030 /*@ 4031 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4032 4033 Not Collective 4034 4035 Input Parameters: 4036 + dm - The DM object 4037 . dim - The embedding dimension, or PETSC_DETERMINE 4038 - section - The PetscSection object 4039 4040 Level: intermediate 4041 4042 .keywords: mesh, coordinates 4043 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4044 @*/ 4045 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4046 { 4047 DM cdm; 4048 PetscErrorCode ierr; 4049 4050 PetscFunctionBegin; 4051 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4052 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4053 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4054 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4055 if (dim == PETSC_DETERMINE) { 4056 PetscInt d = dim; 4057 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4058 4059 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4060 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4061 pStart = PetscMax(vStart, pStart); 4062 pEnd = PetscMin(vEnd, pEnd); 4063 for (v = pStart; v < pEnd; ++v) { 4064 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4065 if (dd) {d = dd; break;} 4066 } 4067 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4068 } 4069 PetscFunctionReturn(0); 4070 } 4071 4072 #undef __FUNCT__ 4073 #define __FUNCT__ "DMGetPeriodicity" 4074 /*@C 4075 DMSetPeriodicity - Set the description of mesh periodicity 4076 4077 Input Parameters: 4078 + dm - The DM object 4079 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4080 . L - If we assume the mesh is a torus, this is the length of each coordinate 4081 - bd - This describes the type of periodicity in each topological dimension 4082 4083 Level: developer 4084 4085 .seealso: DMGetPeriodicity() 4086 @*/ 4087 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4088 { 4089 PetscFunctionBegin; 4090 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4091 if (L) *L = dm->L; 4092 if (maxCell) *maxCell = dm->maxCell; 4093 if (bd) *bd = dm->bdtype; 4094 PetscFunctionReturn(0); 4095 } 4096 4097 #undef __FUNCT__ 4098 #define __FUNCT__ "DMSetPeriodicity" 4099 /*@C 4100 DMSetPeriodicity - Set the description of mesh periodicity 4101 4102 Input Parameters: 4103 + dm - The DM object 4104 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4105 . L - If we assume the mesh is a torus, this is the length of each coordinate 4106 - bd - This describes the type of periodicity in each topological dimension 4107 4108 Level: developer 4109 4110 .seealso: DMGetPeriodicity() 4111 @*/ 4112 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4113 { 4114 PetscInt dim, d; 4115 PetscErrorCode ierr; 4116 4117 PetscFunctionBegin; 4118 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4119 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4120 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4121 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4122 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4123 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4124 PetscFunctionReturn(0); 4125 } 4126 4127 #undef __FUNCT__ 4128 #define __FUNCT__ "DMLocatePoints" 4129 /*@ 4130 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4131 4132 Not collective 4133 4134 Input Parameters: 4135 + dm - The DM 4136 - v - The Vec of points 4137 4138 Output Parameter: 4139 . cells - The local cell numbers for cells which contain the points 4140 4141 Level: developer 4142 4143 .keywords: point location, mesh 4144 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4145 @*/ 4146 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4147 { 4148 PetscErrorCode ierr; 4149 4150 PetscFunctionBegin; 4151 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4152 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4153 PetscValidPointer(cells,3); 4154 if (dm->ops->locatepoints) { 4155 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4156 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4157 PetscFunctionReturn(0); 4158 } 4159 4160 #undef __FUNCT__ 4161 #define __FUNCT__ "DMGetOutputDM" 4162 /*@ 4163 DMGetOutputDM - Retrieve the DM associated with the layout for output 4164 4165 Input Parameter: 4166 . dm - The original DM 4167 4168 Output Parameter: 4169 . odm - The DM which provides the layout for output 4170 4171 Level: intermediate 4172 4173 .seealso: VecView(), DMGetDefaultGlobalSection() 4174 @*/ 4175 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4176 { 4177 PetscSection section; 4178 PetscBool hasConstraints; 4179 PetscErrorCode ierr; 4180 4181 PetscFunctionBegin; 4182 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4183 PetscValidPointer(odm,2); 4184 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4185 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4186 if (!hasConstraints) { 4187 *odm = dm; 4188 PetscFunctionReturn(0); 4189 } 4190 if (!dm->dmBC) { 4191 PetscSection newSection, gsection; 4192 PetscSF sf; 4193 4194 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4195 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4196 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4197 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4198 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4199 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr); 4200 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4201 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4202 } 4203 *odm = dm->dmBC; 4204 PetscFunctionReturn(0); 4205 } 4206 4207 #undef __FUNCT__ 4208 #define __FUNCT__ "DMGetOutputSequenceNumber" 4209 /*@ 4210 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4211 4212 Input Parameter: 4213 . dm - The original DM 4214 4215 Output Parameters: 4216 + num - The output sequence number 4217 - val - The output sequence value 4218 4219 Level: intermediate 4220 4221 Note: This is intended for output that should appear in sequence, for instance 4222 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4223 4224 .seealso: VecView() 4225 @*/ 4226 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4227 { 4228 PetscFunctionBegin; 4229 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4230 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4231 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4232 PetscFunctionReturn(0); 4233 } 4234 4235 #undef __FUNCT__ 4236 #define __FUNCT__ "DMSetOutputSequenceNumber" 4237 /*@ 4238 DMSetOutputSequenceNumber - Set the sequence number/value for output 4239 4240 Input Parameters: 4241 + dm - The original DM 4242 . num - The output sequence number 4243 - val - The output sequence value 4244 4245 Level: intermediate 4246 4247 Note: This is intended for output that should appear in sequence, for instance 4248 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4249 4250 .seealso: VecView() 4251 @*/ 4252 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4253 { 4254 PetscFunctionBegin; 4255 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4256 dm->outputSequenceNum = num; 4257 dm->outputSequenceVal = val; 4258 PetscFunctionReturn(0); 4259 } 4260 4261 #undef __FUNCT__ 4262 #define __FUNCT__ "DMOutputSequenceLoad" 4263 /*@C 4264 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4265 4266 Input Parameters: 4267 + dm - The original DM 4268 . name - The sequence name 4269 - num - The output sequence number 4270 4271 Output Parameter: 4272 . val - The output sequence value 4273 4274 Level: intermediate 4275 4276 Note: This is intended for output that should appear in sequence, for instance 4277 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4278 4279 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4280 @*/ 4281 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4282 { 4283 PetscBool ishdf5; 4284 PetscErrorCode ierr; 4285 4286 PetscFunctionBegin; 4287 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4288 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4289 PetscValidPointer(val,4); 4290 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4291 if (ishdf5) { 4292 #if defined(PETSC_HAVE_HDF5) 4293 PetscScalar value; 4294 4295 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4296 *val = PetscRealPart(value); 4297 #endif 4298 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4299 PetscFunctionReturn(0); 4300 } 4301