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