1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 2 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 3 #include <petsc/private/petscdsimpl.h> /*I "petscds.h" I*/ 4 #include <petscdmplex.h> 5 #include <petscdmfield.h> 6 #include <petscsf.h> 7 #include <petscds.h> 8 9 PetscClassId DM_CLASSID; 10 PetscClassId DMLABEL_CLASSID; 11 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction; 12 13 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DMBoundaryType","DM_BOUNDARY_",0}; 14 15 static PetscErrorCode DMHasCreateInjection_Default(DM dm, PetscBool *flg) 16 { 17 PetscFunctionBegin; 18 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 19 PetscValidPointer(flg,2); 20 *flg = PETSC_FALSE; 21 PetscFunctionReturn(0); 22 } 23 24 /*@ 25 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 26 27 If you never call DMSetType() it will generate an 28 error when you try to use the vector. 29 30 Collective on MPI_Comm 31 32 Input Parameter: 33 . comm - The communicator for the DM object 34 35 Output Parameter: 36 . dm - The DM object 37 38 Level: beginner 39 40 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK 41 @*/ 42 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 43 { 44 DM v; 45 PetscErrorCode ierr; 46 47 PetscFunctionBegin; 48 PetscValidPointer(dm,2); 49 *dm = NULL; 50 ierr = DMInitializePackage();CHKERRQ(ierr); 51 52 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 53 54 v->ltogmap = NULL; 55 v->bs = 1; 56 v->coloringtype = IS_COLORING_GLOBAL; 57 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 58 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 59 v->labels = NULL; 60 v->depthLabel = NULL; 61 v->defaultSection = NULL; 62 v->defaultGlobalSection = NULL; 63 v->defaultConstraintSection = NULL; 64 v->defaultConstraintMat = NULL; 65 v->L = NULL; 66 v->maxCell = NULL; 67 v->bdtype = NULL; 68 v->dimEmbed = PETSC_DEFAULT; 69 v->dim = PETSC_DETERMINE; 70 { 71 PetscInt i; 72 for (i = 0; i < 10; ++i) { 73 v->nullspaceConstructors[i] = NULL; 74 v->nearnullspaceConstructors[i] = NULL; 75 } 76 } 77 ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr); 78 v->dmBC = NULL; 79 v->coarseMesh = NULL; 80 v->outputSequenceNum = -1; 81 v->outputSequenceVal = 0.0; 82 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 83 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 84 ierr = PetscNew(&(v->labels));CHKERRQ(ierr); 85 v->labels->refct = 1; 86 87 v->ops->hascreateinjection = DMHasCreateInjection_Default; 88 89 *dm = v; 90 PetscFunctionReturn(0); 91 } 92 93 /*@ 94 DMClone - Creates a DM object with the same topology as the original. 95 96 Collective on MPI_Comm 97 98 Input Parameter: 99 . dm - The original DM object 100 101 Output Parameter: 102 . newdm - The new DM object 103 104 Level: beginner 105 106 .keywords: DM, topology, create 107 @*/ 108 PetscErrorCode DMClone(DM dm, DM *newdm) 109 { 110 PetscSF sf; 111 Vec coords; 112 void *ctx; 113 PetscInt dim, cdim; 114 PetscErrorCode ierr; 115 116 PetscFunctionBegin; 117 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 118 PetscValidPointer(newdm,2); 119 ierr = DMCreate(PetscObjectComm((PetscObject) dm), newdm);CHKERRQ(ierr); 120 ierr = PetscFree((*newdm)->labels);CHKERRQ(ierr); 121 dm->labels->refct++; 122 (*newdm)->labels = dm->labels; 123 (*newdm)->depthLabel = dm->depthLabel; 124 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 125 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr); 126 if (dm->ops->clone) { 127 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 128 } 129 (*newdm)->setupcalled = dm->setupcalled; 130 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 131 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 132 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 133 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 134 if (dm->coordinateDM) { 135 DM ncdm; 136 PetscSection cs; 137 PetscInt pEnd = -1, pEndMax = -1; 138 139 ierr = DMGetSection(dm->coordinateDM, &cs);CHKERRQ(ierr); 140 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);} 141 ierr = MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 142 if (pEndMax >= 0) { 143 ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr); 144 ierr = DMSetSection(ncdm, cs);CHKERRQ(ierr); 145 ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr); 146 ierr = DMDestroy(&ncdm);CHKERRQ(ierr); 147 } 148 } 149 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 150 ierr = DMSetCoordinateDim(*newdm, cdim);CHKERRQ(ierr); 151 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 152 if (coords) { 153 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 154 } else { 155 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 156 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 157 } 158 { 159 PetscBool isper; 160 const PetscReal *maxCell, *L; 161 const DMBoundaryType *bd; 162 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 163 ierr = DMSetPeriodicity(*newdm, isper, maxCell, L, bd);CHKERRQ(ierr); 164 } 165 PetscFunctionReturn(0); 166 } 167 168 /*@C 169 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 170 171 Logically Collective on DM 172 173 Input Parameter: 174 + da - initial distributed array 175 . ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL 176 177 Options Database: 178 . -dm_vec_type ctype 179 180 Level: intermediate 181 182 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType(), DMSetMatType(), DMGetMatType() 183 @*/ 184 PetscErrorCode DMSetVecType(DM da,VecType ctype) 185 { 186 PetscErrorCode ierr; 187 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(da,DM_CLASSID,1); 190 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 191 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 192 PetscFunctionReturn(0); 193 } 194 195 /*@C 196 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 197 198 Logically Collective on DM 199 200 Input Parameter: 201 . da - initial distributed array 202 203 Output Parameter: 204 . ctype - the vector type 205 206 Level: intermediate 207 208 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMSetMatType(), DMGetMatType(), DMSetVecType() 209 @*/ 210 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 211 { 212 PetscFunctionBegin; 213 PetscValidHeaderSpecific(da,DM_CLASSID,1); 214 *ctype = da->vectype; 215 PetscFunctionReturn(0); 216 } 217 218 /*@ 219 VecGetDM - Gets the DM defining the data layout of the vector 220 221 Not collective 222 223 Input Parameter: 224 . v - The Vec 225 226 Output Parameter: 227 . dm - The DM 228 229 Level: intermediate 230 231 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 232 @*/ 233 PetscErrorCode VecGetDM(Vec v, DM *dm) 234 { 235 PetscErrorCode ierr; 236 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 239 PetscValidPointer(dm,2); 240 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 241 PetscFunctionReturn(0); 242 } 243 244 /*@ 245 VecSetDM - Sets the DM defining the data layout of the vector. 246 247 Not collective 248 249 Input Parameters: 250 + v - The Vec 251 - dm - The DM 252 253 Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member. 254 255 Level: intermediate 256 257 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 258 @*/ 259 PetscErrorCode VecSetDM(Vec v, DM dm) 260 { 261 PetscErrorCode ierr; 262 263 PetscFunctionBegin; 264 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 265 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 266 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 267 PetscFunctionReturn(0); 268 } 269 270 /*@C 271 DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM 272 273 Logically Collective on DM 274 275 Input Parameters: 276 + dm - the DM context 277 - ctype - the matrix type 278 279 Options Database: 280 . -dm_is_coloring_type - global or local 281 282 Level: intermediate 283 284 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), 285 DMGetISColoringType() 286 @*/ 287 PetscErrorCode DMSetISColoringType(DM dm,ISColoringType ctype) 288 { 289 PetscFunctionBegin; 290 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 291 dm->coloringtype = ctype; 292 PetscFunctionReturn(0); 293 } 294 295 /*@C 296 DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM 297 298 Logically Collective on DM 299 300 Input Parameter: 301 . dm - the DM context 302 303 Output Parameter: 304 . ctype - the matrix type 305 306 Options Database: 307 . -dm_is_coloring_type - global or local 308 309 Level: intermediate 310 311 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), 312 DMGetISColoringType() 313 @*/ 314 PetscErrorCode DMGetISColoringType(DM dm,ISColoringType *ctype) 315 { 316 PetscFunctionBegin; 317 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 318 *ctype = dm->coloringtype; 319 PetscFunctionReturn(0); 320 } 321 322 /*@C 323 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 324 325 Logically Collective on DM 326 327 Input Parameters: 328 + dm - the DM context 329 - ctype - the matrix type 330 331 Options Database: 332 . -dm_mat_type ctype 333 334 Level: intermediate 335 336 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), DMSetMatType(), DMGetMatType() 337 @*/ 338 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 339 { 340 PetscErrorCode ierr; 341 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 344 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 345 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 346 PetscFunctionReturn(0); 347 } 348 349 /*@C 350 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 351 352 Logically Collective on DM 353 354 Input Parameter: 355 . dm - the DM context 356 357 Output Parameter: 358 . ctype - the matrix type 359 360 Options Database: 361 . -dm_mat_type ctype 362 363 Level: intermediate 364 365 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType(), DMSetMatType(), DMGetMatType() 366 @*/ 367 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 368 { 369 PetscFunctionBegin; 370 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 371 *ctype = dm->mattype; 372 PetscFunctionReturn(0); 373 } 374 375 /*@ 376 MatGetDM - Gets the DM defining the data layout of the matrix 377 378 Not collective 379 380 Input Parameter: 381 . A - The Mat 382 383 Output Parameter: 384 . dm - The DM 385 386 Level: intermediate 387 388 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 389 the Mat through a PetscObjectCompose() operation 390 391 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 392 @*/ 393 PetscErrorCode MatGetDM(Mat A, DM *dm) 394 { 395 PetscErrorCode ierr; 396 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 399 PetscValidPointer(dm,2); 400 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 401 PetscFunctionReturn(0); 402 } 403 404 /*@ 405 MatSetDM - Sets the DM defining the data layout of the matrix 406 407 Not collective 408 409 Input Parameters: 410 + A - The Mat 411 - dm - The DM 412 413 Level: intermediate 414 415 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 416 the Mat through a PetscObjectCompose() operation 417 418 419 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 420 @*/ 421 PetscErrorCode MatSetDM(Mat A, DM dm) 422 { 423 PetscErrorCode ierr; 424 425 PetscFunctionBegin; 426 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 427 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 428 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 429 PetscFunctionReturn(0); 430 } 431 432 /*@C 433 DMSetOptionsPrefix - Sets the prefix used for searching for all 434 DM options in the database. 435 436 Logically Collective on DM 437 438 Input Parameter: 439 + da - the DM context 440 - prefix - the prefix to prepend to all option names 441 442 Notes: 443 A hyphen (-) must NOT be given at the beginning of the prefix name. 444 The first character of all runtime options is AUTOMATICALLY the hyphen. 445 446 Level: advanced 447 448 .keywords: DM, set, options, prefix, database 449 450 .seealso: DMSetFromOptions() 451 @*/ 452 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 453 { 454 PetscErrorCode ierr; 455 456 PetscFunctionBegin; 457 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 458 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 459 if (dm->sf) { 460 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr); 461 } 462 if (dm->defaultSF) { 463 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);CHKERRQ(ierr); 464 } 465 PetscFunctionReturn(0); 466 } 467 468 /*@C 469 DMAppendOptionsPrefix - Appends to the prefix used for searching for all 470 DM options in the database. 471 472 Logically Collective on DM 473 474 Input Parameters: 475 + dm - the DM context 476 - prefix - the prefix string to prepend to all DM option requests 477 478 Notes: 479 A hyphen (-) must NOT be given at the beginning of the prefix name. 480 The first character of all runtime options is AUTOMATICALLY the hyphen. 481 482 Level: advanced 483 484 .keywords: DM, append, options, prefix, database 485 486 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix() 487 @*/ 488 PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[]) 489 { 490 PetscErrorCode ierr; 491 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 494 ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 495 PetscFunctionReturn(0); 496 } 497 498 /*@C 499 DMGetOptionsPrefix - Gets the prefix used for searching for all 500 DM options in the database. 501 502 Not Collective 503 504 Input Parameters: 505 . dm - the DM context 506 507 Output Parameters: 508 . prefix - pointer to the prefix string used is returned 509 510 Notes: 511 On the fortran side, the user should pass in a string 'prefix' of 512 sufficient length to hold the prefix. 513 514 Level: advanced 515 516 .keywords: DM, set, options, prefix, database 517 518 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix() 519 @*/ 520 PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[]) 521 { 522 PetscErrorCode ierr; 523 524 PetscFunctionBegin; 525 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 526 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 527 PetscFunctionReturn(0); 528 } 529 530 static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct) 531 { 532 PetscInt i, refct = ((PetscObject) dm)->refct; 533 DMNamedVecLink nlink; 534 PetscErrorCode ierr; 535 536 PetscFunctionBegin; 537 *ncrefct = 0; 538 /* count all the circular references of DM and its contained Vecs */ 539 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 540 if (dm->localin[i]) refct--; 541 if (dm->globalin[i]) refct--; 542 } 543 for (nlink=dm->namedglobal; nlink; nlink=nlink->next) refct--; 544 for (nlink=dm->namedlocal; nlink; nlink=nlink->next) refct--; 545 if (dm->x) { 546 DM obj; 547 ierr = VecGetDM(dm->x, &obj);CHKERRQ(ierr); 548 if (obj == dm) refct--; 549 } 550 if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) { 551 refct--; 552 if (recurseCoarse) { 553 PetscInt coarseCount; 554 555 ierr = DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);CHKERRQ(ierr); 556 refct += coarseCount; 557 } 558 } 559 if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) { 560 refct--; 561 if (recurseFine) { 562 PetscInt fineCount; 563 564 ierr = DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);CHKERRQ(ierr); 565 refct += fineCount; 566 } 567 } 568 *ncrefct = refct; 569 PetscFunctionReturn(0); 570 } 571 572 PetscErrorCode DMDestroyLabelLinkList(DM dm) 573 { 574 PetscErrorCode ierr; 575 576 PetscFunctionBegin; 577 if (!--(dm->labels->refct)) { 578 DMLabelLink next = dm->labels->next; 579 580 /* destroy the labels */ 581 while (next) { 582 DMLabelLink tmp = next->next; 583 584 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 585 ierr = PetscFree(next);CHKERRQ(ierr); 586 next = tmp; 587 } 588 ierr = PetscFree(dm->labels);CHKERRQ(ierr); 589 } 590 PetscFunctionReturn(0); 591 } 592 593 /*@ 594 DMDestroy - Destroys a vector packer or DM. 595 596 Collective on DM 597 598 Input Parameter: 599 . dm - the DM object to destroy 600 601 Level: developer 602 603 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 604 605 @*/ 606 PetscErrorCode DMDestroy(DM *dm) 607 { 608 PetscInt i, cnt; 609 DMNamedVecLink nlink,nnext; 610 PetscErrorCode ierr; 611 612 PetscFunctionBegin; 613 if (!*dm) PetscFunctionReturn(0); 614 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 615 616 /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */ 617 ierr = DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);CHKERRQ(ierr); 618 --((PetscObject)(*dm))->refct; 619 if (--cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 620 /* 621 Need this test because the dm references the vectors that 622 reference the dm, so destroying the dm calls destroy on the 623 vectors that cause another destroy on the dm 624 */ 625 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 626 ((PetscObject) (*dm))->refct = 0; 627 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 628 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 629 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 630 } 631 nnext=(*dm)->namedglobal; 632 (*dm)->namedglobal = NULL; 633 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 634 nnext = nlink->next; 635 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 636 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 637 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 638 ierr = PetscFree(nlink);CHKERRQ(ierr); 639 } 640 nnext=(*dm)->namedlocal; 641 (*dm)->namedlocal = NULL; 642 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 643 nnext = nlink->next; 644 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 645 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 646 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 647 ierr = PetscFree(nlink);CHKERRQ(ierr); 648 } 649 650 /* Destroy the list of hooks */ 651 { 652 DMCoarsenHookLink link,next; 653 for (link=(*dm)->coarsenhook; link; link=next) { 654 next = link->next; 655 ierr = PetscFree(link);CHKERRQ(ierr); 656 } 657 (*dm)->coarsenhook = NULL; 658 } 659 { 660 DMRefineHookLink link,next; 661 for (link=(*dm)->refinehook; link; link=next) { 662 next = link->next; 663 ierr = PetscFree(link);CHKERRQ(ierr); 664 } 665 (*dm)->refinehook = NULL; 666 } 667 { 668 DMSubDomainHookLink link,next; 669 for (link=(*dm)->subdomainhook; link; link=next) { 670 next = link->next; 671 ierr = PetscFree(link);CHKERRQ(ierr); 672 } 673 (*dm)->subdomainhook = NULL; 674 } 675 { 676 DMGlobalToLocalHookLink link,next; 677 for (link=(*dm)->gtolhook; link; link=next) { 678 next = link->next; 679 ierr = PetscFree(link);CHKERRQ(ierr); 680 } 681 (*dm)->gtolhook = NULL; 682 } 683 { 684 DMLocalToGlobalHookLink link,next; 685 for (link=(*dm)->ltoghook; link; link=next) { 686 next = link->next; 687 ierr = PetscFree(link);CHKERRQ(ierr); 688 } 689 (*dm)->ltoghook = NULL; 690 } 691 /* Destroy the work arrays */ 692 { 693 DMWorkLink link,next; 694 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 695 for (link=(*dm)->workin; link; link=next) { 696 next = link->next; 697 ierr = PetscFree(link->mem);CHKERRQ(ierr); 698 ierr = PetscFree(link);CHKERRQ(ierr); 699 } 700 (*dm)->workin = NULL; 701 } 702 if (!--((*dm)->labels->refct)) { 703 DMLabelLink next = (*dm)->labels->next; 704 705 /* destroy the labels */ 706 while (next) { 707 DMLabelLink tmp = next->next; 708 709 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 710 ierr = PetscFree(next);CHKERRQ(ierr); 711 next = tmp; 712 } 713 ierr = PetscFree((*dm)->labels);CHKERRQ(ierr); 714 } 715 { 716 DMBoundary next = (*dm)->boundary; 717 while (next) { 718 DMBoundary b = next; 719 720 next = b->next; 721 ierr = PetscFree(b);CHKERRQ(ierr); 722 } 723 } 724 725 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 726 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 727 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 728 729 if ((*dm)->ctx && (*dm)->ctxdestroy) { 730 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 731 } 732 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 733 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 734 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 735 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 736 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 737 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 738 739 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 740 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 741 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 742 ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr); 743 ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr); 744 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 745 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 746 if ((*dm)->useNatural) { 747 if ((*dm)->sfNatural) { 748 ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr); 749 } 750 ierr = PetscObjectDereference((PetscObject) (*dm)->sfMigration);CHKERRQ(ierr); 751 } 752 if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) { 753 ierr = DMSetFineDM((*dm)->coarseMesh,NULL);CHKERRQ(ierr); 754 } 755 ierr = DMDestroy(&(*dm)->coarseMesh);CHKERRQ(ierr); 756 if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) { 757 ierr = DMSetCoarseDM((*dm)->fineMesh,NULL);CHKERRQ(ierr); 758 } 759 ierr = DMDestroy(&(*dm)->fineMesh);CHKERRQ(ierr); 760 ierr = DMFieldDestroy(&(*dm)->coordinateField);CHKERRQ(ierr); 761 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 762 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 763 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 764 ierr = PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);CHKERRQ(ierr); 765 766 ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr); 767 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 768 /* if memory was published with SAWs then destroy it */ 769 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 770 771 if ((*dm)->ops->destroy) { 772 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 773 } 774 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 775 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 776 PetscFunctionReturn(0); 777 } 778 779 /*@ 780 DMSetUp - sets up the data structures inside a DM object 781 782 Collective on DM 783 784 Input Parameter: 785 . dm - the DM object to setup 786 787 Level: developer 788 789 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 790 791 @*/ 792 PetscErrorCode DMSetUp(DM dm) 793 { 794 PetscErrorCode ierr; 795 796 PetscFunctionBegin; 797 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 798 if (dm->setupcalled) PetscFunctionReturn(0); 799 if (dm->ops->setup) { 800 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 801 } 802 dm->setupcalled = PETSC_TRUE; 803 PetscFunctionReturn(0); 804 } 805 806 /*@ 807 DMSetFromOptions - sets parameters in a DM from the options database 808 809 Collective on DM 810 811 Input Parameter: 812 . dm - the DM object to set options for 813 814 Options Database: 815 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 816 . -dm_vec_type <type> - type of vector to create inside DM 817 . -dm_mat_type <type> - type of matrix to create inside DM 818 - -dm_is_coloring_type - <global or local> 819 820 Level: developer 821 822 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 823 824 @*/ 825 PetscErrorCode DMSetFromOptions(DM dm) 826 { 827 char typeName[256]; 828 PetscBool flg; 829 PetscErrorCode ierr; 830 831 PetscFunctionBegin; 832 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 833 if (dm->prob) { 834 ierr = PetscDSSetFromOptions(dm->prob);CHKERRQ(ierr); 835 } 836 if (dm->sf) { 837 ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr); 838 } 839 if (dm->defaultSF) { 840 ierr = PetscSFSetFromOptions(dm->defaultSF);CHKERRQ(ierr); 841 } 842 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 843 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 844 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 845 if (flg) { 846 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 847 } 848 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 849 if (flg) { 850 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 851 } 852 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 853 if (dm->ops->setfromoptions) { 854 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr); 855 } 856 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 857 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr); 858 ierr = PetscOptionsEnd();CHKERRQ(ierr); 859 PetscFunctionReturn(0); 860 } 861 862 /*@C 863 DMView - Views a DM 864 865 Collective on DM 866 867 Input Parameter: 868 + dm - the DM object to view 869 - v - the viewer 870 871 Level: beginner 872 873 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 874 875 @*/ 876 PetscErrorCode DMView(DM dm,PetscViewer v) 877 { 878 PetscErrorCode ierr; 879 PetscBool isbinary; 880 PetscMPIInt size; 881 PetscViewerFormat format; 882 883 PetscFunctionBegin; 884 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 885 if (!v) { 886 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 887 } 888 ierr = PetscViewerGetFormat(v,&format);CHKERRQ(ierr); 889 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRQ(ierr); 890 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 891 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 892 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 893 if (isbinary) { 894 PetscInt classid = DM_FILE_CLASSID; 895 char type[256]; 896 897 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 898 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 899 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 900 } 901 if (dm->ops->view) { 902 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 903 } 904 PetscFunctionReturn(0); 905 } 906 907 /*@ 908 DMCreateGlobalVector - Creates a global vector from a DM object 909 910 Collective on DM 911 912 Input Parameter: 913 . dm - the DM object 914 915 Output Parameter: 916 . vec - the global vector 917 918 Level: beginner 919 920 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 921 922 @*/ 923 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 924 { 925 PetscErrorCode ierr; 926 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 929 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 930 PetscFunctionReturn(0); 931 } 932 933 /*@ 934 DMCreateLocalVector - Creates a local vector from a DM object 935 936 Not Collective 937 938 Input Parameter: 939 . dm - the DM object 940 941 Output Parameter: 942 . vec - the local vector 943 944 Level: beginner 945 946 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 947 948 @*/ 949 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 950 { 951 PetscErrorCode ierr; 952 953 PetscFunctionBegin; 954 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 955 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 956 PetscFunctionReturn(0); 957 } 958 959 /*@ 960 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 961 962 Collective on DM 963 964 Input Parameter: 965 . dm - the DM that provides the mapping 966 967 Output Parameter: 968 . ltog - the mapping 969 970 Level: intermediate 971 972 Notes: 973 This mapping can then be used by VecSetLocalToGlobalMapping() or 974 MatSetLocalToGlobalMapping(). 975 976 .seealso: DMCreateLocalVector() 977 @*/ 978 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 979 { 980 PetscInt bs = -1, bsLocal[2], bsMinMax[2]; 981 PetscErrorCode ierr; 982 983 PetscFunctionBegin; 984 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 985 PetscValidPointer(ltog,2); 986 if (!dm->ltogmap) { 987 PetscSection section, sectionGlobal; 988 989 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 990 if (section) { 991 const PetscInt *cdofs; 992 PetscInt *ltog; 993 PetscInt pStart, pEnd, n, p, k, l; 994 995 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 996 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 997 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 998 ierr = PetscMalloc1(n, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 999 for (p = pStart, l = 0; p < pEnd; ++p) { 1000 PetscInt bdof, cdof, dof, off, c, cind = 0; 1001 1002 /* Should probably use constrained dofs */ 1003 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 1004 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 1005 ierr = PetscSectionGetConstraintIndices(section, p, &cdofs);CHKERRQ(ierr); 1006 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 1007 /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */ 1008 bdof = cdof && (dof-cdof) ? 1 : dof; 1009 if (dof) { 1010 if (bs < 0) {bs = bdof;} 1011 else if (bs != bdof) {bs = 1;} 1012 } 1013 for (c = 0; c < dof; ++c, ++l) { 1014 if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c; 1015 else ltog[l] = (off < 0 ? -(off+1) : off) + c; 1016 } 1017 } 1018 /* Must have same blocksize on all procs (some might have no points) */ 1019 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 1020 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 1021 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 1022 else {bs = bsMinMax[0];} 1023 bs = bs < 0 ? 1 : bs; 1024 /* Must reduce indices by blocksize */ 1025 if (bs > 1) { 1026 for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs; 1027 n /= bs; 1028 } 1029 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 1030 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 1031 } else { 1032 if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 1033 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 1034 } 1035 } 1036 *ltog = dm->ltogmap; 1037 PetscFunctionReturn(0); 1038 } 1039 1040 /*@ 1041 DMGetBlockSize - Gets the inherent block size associated with a DM 1042 1043 Not Collective 1044 1045 Input Parameter: 1046 . dm - the DM with block structure 1047 1048 Output Parameter: 1049 . bs - the block size, 1 implies no exploitable block structure 1050 1051 Level: intermediate 1052 1053 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 1054 @*/ 1055 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 1056 { 1057 PetscFunctionBegin; 1058 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1059 PetscValidPointer(bs,2); 1060 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 1061 *bs = dm->bs; 1062 PetscFunctionReturn(0); 1063 } 1064 1065 /*@ 1066 DMCreateInterpolation - Gets interpolation matrix between two DM objects 1067 1068 Collective on DM 1069 1070 Input Parameter: 1071 + dm1 - the DM object 1072 - dm2 - the second, finer DM object 1073 1074 Output Parameter: 1075 + mat - the interpolation 1076 - vec - the scaling (optional) 1077 1078 Level: developer 1079 1080 Notes: 1081 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1082 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1083 1084 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 1085 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 1086 1087 1088 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction() 1089 1090 @*/ 1091 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 1092 { 1093 PetscErrorCode ierr; 1094 1095 PetscFunctionBegin; 1096 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 1097 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 1098 PetscValidPointer(mat,3); 1099 if (!dm1->ops->createinterpolation) SETERRQ1(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateInterpolation not implemented for type %s",((PetscObject)dm1)->type_name); 1100 ierr = PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr); 1101 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 1102 ierr = PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr); 1103 PetscFunctionReturn(0); 1104 } 1105 1106 /*@ 1107 DMCreateRestriction - Gets restriction matrix between two DM objects 1108 1109 Collective on DM 1110 1111 Input Parameter: 1112 + dm1 - the DM object 1113 - dm2 - the second, finer DM object 1114 1115 Output Parameter: 1116 . mat - the restriction 1117 1118 1119 Level: developer 1120 1121 Notes: 1122 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1123 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1124 1125 1126 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation() 1127 1128 @*/ 1129 PetscErrorCode DMCreateRestriction(DM dm1,DM dm2,Mat *mat) 1130 { 1131 PetscErrorCode ierr; 1132 1133 PetscFunctionBegin; 1134 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 1135 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 1136 ierr = PetscLogEventBegin(DM_CreateRestriction,dm1,dm2,0,0);CHKERRQ(ierr); 1137 if (!dm1->ops->createrestriction) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateRestriction not implemented for this type"); 1138 ierr = (*dm1->ops->createrestriction)(dm1,dm2,mat);CHKERRQ(ierr); 1139 ierr = PetscLogEventEnd(DM_CreateRestriction,dm1,dm2,0,0);CHKERRQ(ierr); 1140 PetscFunctionReturn(0); 1141 } 1142 1143 /*@ 1144 DMCreateInjection - Gets injection matrix between two DM objects 1145 1146 Collective on DM 1147 1148 Input Parameter: 1149 + dm1 - the DM object 1150 - dm2 - the second, finer DM object 1151 1152 Output Parameter: 1153 . mat - the injection 1154 1155 Level: developer 1156 1157 Notes: 1158 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1159 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 1160 1161 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 1162 1163 @*/ 1164 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat) 1165 { 1166 PetscErrorCode ierr; 1167 1168 PetscFunctionBegin; 1169 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 1170 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 1171 if (!dm1->ops->getinjection) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateInjection not implemented for this type"); 1172 ierr = (*dm1->ops->getinjection)(dm1,dm2,mat);CHKERRQ(ierr); 1173 PetscFunctionReturn(0); 1174 } 1175 1176 /*@ 1177 DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j 1178 1179 Collective on DM 1180 1181 Input Parameter: 1182 + dm1 - the DM object 1183 - dm2 - the second, finer DM object 1184 1185 Output Parameter: 1186 . mat - the interpolation 1187 1188 Level: developer 1189 1190 .seealso DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection() 1191 @*/ 1192 PetscErrorCode DMCreateMassMatrix(DM dm1, DM dm2, Mat *mat) 1193 { 1194 PetscErrorCode ierr; 1195 1196 PetscFunctionBegin; 1197 PetscValidHeaderSpecific(dm1, DM_CLASSID, 1); 1198 PetscValidHeaderSpecific(dm2, DM_CLASSID, 2); 1199 ierr = (*dm1->ops->createmassmatrix)(dm1, dm2, mat);CHKERRQ(ierr); 1200 PetscFunctionReturn(0); 1201 } 1202 1203 /*@ 1204 DMCreateColoring - Gets coloring for a DM 1205 1206 Collective on DM 1207 1208 Input Parameter: 1209 + dm - the DM object 1210 - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL 1211 1212 Output Parameter: 1213 . coloring - the coloring 1214 1215 Level: developer 1216 1217 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType() 1218 1219 @*/ 1220 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 1221 { 1222 PetscErrorCode ierr; 1223 1224 PetscFunctionBegin; 1225 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1226 if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet"); 1227 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 1228 PetscFunctionReturn(0); 1229 } 1230 1231 /*@ 1232 DMCreateMatrix - Gets empty Jacobian for a DM 1233 1234 Collective on DM 1235 1236 Input Parameter: 1237 . dm - the DM object 1238 1239 Output Parameter: 1240 . mat - the empty Jacobian 1241 1242 Level: beginner 1243 1244 Notes: 1245 This properly preallocates the number of nonzeros in the sparse matrix so you 1246 do not need to do it yourself. 1247 1248 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 1249 the nonzero pattern call DMSetMatrixPreallocateOnly() 1250 1251 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 1252 internally by PETSc. 1253 1254 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 1255 the indices for the global numbering for DMDAs which is complicated. 1256 1257 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 1258 1259 @*/ 1260 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 1261 { 1262 PetscErrorCode ierr; 1263 1264 PetscFunctionBegin; 1265 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1266 ierr = MatInitializePackage();CHKERRQ(ierr); 1267 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1268 PetscValidPointer(mat,3); 1269 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 1270 /* Handle nullspace and near nullspace */ 1271 if (dm->prob) { 1272 MatNullSpace nullSpace; 1273 PetscInt Nf; 1274 1275 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 1276 if (Nf == 1) { 1277 if (dm->nullspaceConstructors[0]) { 1278 ierr = (*dm->nullspaceConstructors[0])(dm, 0, &nullSpace);CHKERRQ(ierr); 1279 ierr = MatSetNullSpace(*mat, nullSpace);CHKERRQ(ierr); 1280 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1281 } 1282 if (dm->nearnullspaceConstructors[0]) { 1283 ierr = (*dm->nearnullspaceConstructors[0])(dm, 0, &nullSpace);CHKERRQ(ierr); 1284 ierr = MatSetNearNullSpace(*mat, nullSpace);CHKERRQ(ierr); 1285 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1286 } 1287 } 1288 } 1289 PetscFunctionReturn(0); 1290 } 1291 1292 /*@ 1293 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 1294 preallocated but the nonzero structure and zero values will not be set. 1295 1296 Logically Collective on DM 1297 1298 Input Parameter: 1299 + dm - the DM 1300 - only - PETSC_TRUE if only want preallocation 1301 1302 Level: developer 1303 .seealso DMCreateMatrix(), DMSetMatrixStructureOnly() 1304 @*/ 1305 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 1306 { 1307 PetscFunctionBegin; 1308 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1309 dm->prealloc_only = only; 1310 PetscFunctionReturn(0); 1311 } 1312 1313 /*@ 1314 DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created 1315 but the array for values will not be allocated. 1316 1317 Logically Collective on DM 1318 1319 Input Parameter: 1320 + dm - the DM 1321 - only - PETSC_TRUE if only want matrix stucture 1322 1323 Level: developer 1324 .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly() 1325 @*/ 1326 PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only) 1327 { 1328 PetscFunctionBegin; 1329 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1330 dm->structure_only = only; 1331 PetscFunctionReturn(0); 1332 } 1333 1334 /*@C 1335 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1336 1337 Not Collective 1338 1339 Input Parameters: 1340 + dm - the DM object 1341 . count - The minium size 1342 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT) 1343 1344 Output Parameter: 1345 . array - the work array 1346 1347 Level: developer 1348 1349 .seealso DMDestroy(), DMCreate() 1350 @*/ 1351 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem) 1352 { 1353 PetscErrorCode ierr; 1354 DMWorkLink link; 1355 PetscMPIInt dsize; 1356 1357 PetscFunctionBegin; 1358 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1359 PetscValidPointer(mem,4); 1360 if (dm->workin) { 1361 link = dm->workin; 1362 dm->workin = dm->workin->next; 1363 } else { 1364 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1365 } 1366 ierr = MPI_Type_size(dtype,&dsize);CHKERRQ(ierr); 1367 if (((size_t)dsize*count) > link->bytes) { 1368 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1369 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr); 1370 link->bytes = dsize*count; 1371 } 1372 link->next = dm->workout; 1373 dm->workout = link; 1374 *(void**)mem = link->mem; 1375 PetscFunctionReturn(0); 1376 } 1377 1378 /*@C 1379 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1380 1381 Not Collective 1382 1383 Input Parameters: 1384 + dm - the DM object 1385 . count - The minium size 1386 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT 1387 1388 Output Parameter: 1389 . array - the work array 1390 1391 Level: developer 1392 1393 Developer Notes: 1394 count and dtype are ignored, they are only needed for DMGetWorkArray() 1395 .seealso DMDestroy(), DMCreate() 1396 @*/ 1397 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem) 1398 { 1399 DMWorkLink *p,link; 1400 1401 PetscFunctionBegin; 1402 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1403 PetscValidPointer(mem,4); 1404 for (p=&dm->workout; (link=*p); p=&link->next) { 1405 if (link->mem == *(void**)mem) { 1406 *p = link->next; 1407 link->next = dm->workin; 1408 dm->workin = link; 1409 *(void**)mem = NULL; 1410 PetscFunctionReturn(0); 1411 } 1412 } 1413 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1414 } 1415 1416 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1417 { 1418 PetscFunctionBegin; 1419 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1420 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1421 dm->nullspaceConstructors[field] = nullsp; 1422 PetscFunctionReturn(0); 1423 } 1424 1425 PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1426 { 1427 PetscFunctionBegin; 1428 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1429 PetscValidPointer(nullsp, 3); 1430 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1431 *nullsp = dm->nullspaceConstructors[field]; 1432 PetscFunctionReturn(0); 1433 } 1434 1435 PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1436 { 1437 PetscFunctionBegin; 1438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1439 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1440 dm->nearnullspaceConstructors[field] = nullsp; 1441 PetscFunctionReturn(0); 1442 } 1443 1444 PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1445 { 1446 PetscFunctionBegin; 1447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1448 PetscValidPointer(nullsp, 3); 1449 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1450 *nullsp = dm->nearnullspaceConstructors[field]; 1451 PetscFunctionReturn(0); 1452 } 1453 1454 /*@C 1455 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1456 1457 Not collective 1458 1459 Input Parameter: 1460 . dm - the DM object 1461 1462 Output Parameters: 1463 + numFields - The number of fields (or NULL if not requested) 1464 . fieldNames - The name for each field (or NULL if not requested) 1465 - fields - The global indices for each field (or NULL if not requested) 1466 1467 Level: intermediate 1468 1469 Notes: 1470 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1471 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1472 PetscFree(). 1473 1474 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1475 @*/ 1476 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1477 { 1478 PetscSection section, sectionGlobal; 1479 PetscErrorCode ierr; 1480 1481 PetscFunctionBegin; 1482 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1483 if (numFields) { 1484 PetscValidPointer(numFields,2); 1485 *numFields = 0; 1486 } 1487 if (fieldNames) { 1488 PetscValidPointer(fieldNames,3); 1489 *fieldNames = NULL; 1490 } 1491 if (fields) { 1492 PetscValidPointer(fields,4); 1493 *fields = NULL; 1494 } 1495 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 1496 if (section) { 1497 PetscInt *fieldSizes, *fieldNc, **fieldIndices; 1498 PetscInt nF, f, pStart, pEnd, p; 1499 1500 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1501 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1502 ierr = PetscMalloc3(nF,&fieldSizes,nF,&fieldNc,nF,&fieldIndices);CHKERRQ(ierr); 1503 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1504 for (f = 0; f < nF; ++f) { 1505 fieldSizes[f] = 0; 1506 ierr = PetscSectionGetFieldComponents(section, f, &fieldNc[f]);CHKERRQ(ierr); 1507 } 1508 for (p = pStart; p < pEnd; ++p) { 1509 PetscInt gdof; 1510 1511 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1512 if (gdof > 0) { 1513 for (f = 0; f < nF; ++f) { 1514 PetscInt fdof, fcdof, fpdof; 1515 1516 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1517 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1518 fpdof = fdof-fcdof; 1519 if (fpdof && fpdof != fieldNc[f]) { 1520 /* Layout does not admit a pointwise block size */ 1521 fieldNc[f] = 1; 1522 } 1523 fieldSizes[f] += fpdof; 1524 } 1525 } 1526 } 1527 for (f = 0; f < nF; ++f) { 1528 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1529 fieldSizes[f] = 0; 1530 } 1531 for (p = pStart; p < pEnd; ++p) { 1532 PetscInt gdof, goff; 1533 1534 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1535 if (gdof > 0) { 1536 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1537 for (f = 0; f < nF; ++f) { 1538 PetscInt fdof, fcdof, fc; 1539 1540 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1541 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1542 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1543 fieldIndices[f][fieldSizes[f]] = goff++; 1544 } 1545 } 1546 } 1547 } 1548 if (numFields) *numFields = nF; 1549 if (fieldNames) { 1550 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1551 for (f = 0; f < nF; ++f) { 1552 const char *fieldName; 1553 1554 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1555 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1556 } 1557 } 1558 if (fields) { 1559 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1560 for (f = 0; f < nF; ++f) { 1561 PetscInt bs, in[2], out[2]; 1562 1563 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1564 in[0] = -fieldNc[f]; 1565 in[1] = fieldNc[f]; 1566 ierr = MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1567 bs = (-out[0] == out[1]) ? out[1] : 1; 1568 ierr = ISSetBlockSize((*fields)[f], bs);CHKERRQ(ierr); 1569 } 1570 } 1571 ierr = PetscFree3(fieldSizes,fieldNc,fieldIndices);CHKERRQ(ierr); 1572 } else if (dm->ops->createfieldis) { 1573 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1574 } 1575 PetscFunctionReturn(0); 1576 } 1577 1578 1579 /*@C 1580 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1581 corresponding to different fields: each IS contains the global indices of the dofs of the 1582 corresponding field. The optional list of DMs define the DM for each subproblem. 1583 Generalizes DMCreateFieldIS(). 1584 1585 Not collective 1586 1587 Input Parameter: 1588 . dm - the DM object 1589 1590 Output Parameters: 1591 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1592 . namelist - The name for each field (or NULL if not requested) 1593 . islist - The global indices for each field (or NULL if not requested) 1594 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1595 1596 Level: intermediate 1597 1598 Notes: 1599 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1600 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1601 and all of the arrays should be freed with PetscFree(). 1602 1603 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1604 @*/ 1605 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1606 { 1607 PetscErrorCode ierr; 1608 1609 PetscFunctionBegin; 1610 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1611 if (len) { 1612 PetscValidPointer(len,2); 1613 *len = 0; 1614 } 1615 if (namelist) { 1616 PetscValidPointer(namelist,3); 1617 *namelist = 0; 1618 } 1619 if (islist) { 1620 PetscValidPointer(islist,4); 1621 *islist = 0; 1622 } 1623 if (dmlist) { 1624 PetscValidPointer(dmlist,5); 1625 *dmlist = 0; 1626 } 1627 /* 1628 Is it a good idea to apply the following check across all impls? 1629 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1630 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1631 */ 1632 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1633 if (!dm->ops->createfielddecomposition) { 1634 PetscSection section; 1635 PetscInt numFields, f; 1636 1637 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 1638 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1639 if (section && numFields && dm->ops->createsubdm) { 1640 if (len) *len = numFields; 1641 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1642 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1643 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1644 for (f = 0; f < numFields; ++f) { 1645 const char *fieldName; 1646 1647 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1648 if (namelist) { 1649 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1650 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1651 } 1652 } 1653 } else { 1654 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1655 /* By default there are no DMs associated with subproblems. */ 1656 if (dmlist) *dmlist = NULL; 1657 } 1658 } else { 1659 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1660 } 1661 PetscFunctionReturn(0); 1662 } 1663 1664 /*@ 1665 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1666 The fields are defined by DMCreateFieldIS(). 1667 1668 Not collective 1669 1670 Input Parameters: 1671 + dm - The DM object 1672 . numFields - The number of fields in this subproblem 1673 - fields - The field numbers of the selected fields 1674 1675 Output Parameters: 1676 + is - The global indices for the subproblem 1677 - subdm - The DM for the subproblem 1678 1679 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed 1680 1681 Level: intermediate 1682 1683 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1684 @*/ 1685 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 1686 { 1687 PetscErrorCode ierr; 1688 1689 PetscFunctionBegin; 1690 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1691 PetscValidPointer(fields,3); 1692 if (is) PetscValidPointer(is,4); 1693 if (subdm) PetscValidPointer(subdm,5); 1694 if (dm->ops->createsubdm) { 1695 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1696 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1697 PetscFunctionReturn(0); 1698 } 1699 1700 /*@C 1701 DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in. 1702 1703 Not collective 1704 1705 Input Parameter: 1706 + dms - The DM objects 1707 - len - The number of DMs 1708 1709 Output Parameters: 1710 + is - The global indices for the subproblem, or NULL 1711 - superdm - The DM for the superproblem 1712 1713 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed 1714 1715 Level: intermediate 1716 1717 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1718 @*/ 1719 PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm) 1720 { 1721 PetscInt i; 1722 PetscErrorCode ierr; 1723 1724 PetscFunctionBegin; 1725 PetscValidPointer(dms,1); 1726 for (i = 0; i < len; ++i) {PetscValidHeaderSpecific(dms[i],DM_CLASSID,1);} 1727 if (is) PetscValidPointer(is,3); 1728 PetscValidPointer(superdm,4); 1729 if (len < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len); 1730 if (len) { 1731 if (dms[0]->ops->createsuperdm) {ierr = (*dms[0]->ops->createsuperdm)(dms, len, is, superdm);CHKERRQ(ierr);} 1732 else SETERRQ(PetscObjectComm((PetscObject) dms[0]), PETSC_ERR_SUP, "This type has no DMCreateSuperDM implementation defined"); 1733 } 1734 PetscFunctionReturn(0); 1735 } 1736 1737 1738 /*@C 1739 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1740 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1741 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1742 define a nonoverlapping covering, while outer subdomains can overlap. 1743 The optional list of DMs define the DM for each subproblem. 1744 1745 Not collective 1746 1747 Input Parameter: 1748 . dm - the DM object 1749 1750 Output Parameters: 1751 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1752 . namelist - The name for each subdomain (or NULL if not requested) 1753 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1754 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1755 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1756 1757 Level: intermediate 1758 1759 Notes: 1760 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1761 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1762 and all of the arrays should be freed with PetscFree(). 1763 1764 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1765 @*/ 1766 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1767 { 1768 PetscErrorCode ierr; 1769 DMSubDomainHookLink link; 1770 PetscInt i,l; 1771 1772 PetscFunctionBegin; 1773 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1774 if (len) {PetscValidPointer(len,2); *len = 0;} 1775 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1776 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1777 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1778 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1779 /* 1780 Is it a good idea to apply the following check across all impls? 1781 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1782 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1783 */ 1784 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1785 if (dm->ops->createdomaindecomposition) { 1786 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1787 /* copy subdomain hooks and context over to the subdomain DMs */ 1788 if (dmlist && *dmlist) { 1789 for (i = 0; i < l; i++) { 1790 for (link=dm->subdomainhook; link; link=link->next) { 1791 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1792 } 1793 if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx; 1794 } 1795 } 1796 if (len) *len = l; 1797 } 1798 PetscFunctionReturn(0); 1799 } 1800 1801 1802 /*@C 1803 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1804 1805 Not collective 1806 1807 Input Parameters: 1808 + dm - the DM object 1809 . n - the number of subdomain scatters 1810 - subdms - the local subdomains 1811 1812 Output Parameters: 1813 + n - the number of scatters returned 1814 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1815 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1816 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1817 1818 Notes: 1819 This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1820 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1821 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1822 solution and residual data. 1823 1824 Level: developer 1825 1826 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1827 @*/ 1828 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1829 { 1830 PetscErrorCode ierr; 1831 1832 PetscFunctionBegin; 1833 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1834 PetscValidPointer(subdms,3); 1835 if (dm->ops->createddscatters) { 1836 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1837 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionScatter implementation defined"); 1838 PetscFunctionReturn(0); 1839 } 1840 1841 /*@ 1842 DMRefine - Refines a DM object 1843 1844 Collective on DM 1845 1846 Input Parameter: 1847 + dm - the DM object 1848 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1849 1850 Output Parameter: 1851 . dmf - the refined DM, or NULL 1852 1853 Note: If no refinement was done, the return value is NULL 1854 1855 Level: developer 1856 1857 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1858 @*/ 1859 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1860 { 1861 PetscErrorCode ierr; 1862 DMRefineHookLink link; 1863 1864 PetscFunctionBegin; 1865 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1866 ierr = PetscLogEventBegin(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 1867 if (!dm->ops->refine) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot refine"); 1868 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1869 if (*dmf) { 1870 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1871 1872 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1873 1874 (*dmf)->ctx = dm->ctx; 1875 (*dmf)->leveldown = dm->leveldown; 1876 (*dmf)->levelup = dm->levelup + 1; 1877 1878 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1879 for (link=dm->refinehook; link; link=link->next) { 1880 if (link->refinehook) { 1881 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1882 } 1883 } 1884 } 1885 ierr = PetscLogEventEnd(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 1886 PetscFunctionReturn(0); 1887 } 1888 1889 /*@C 1890 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1891 1892 Logically Collective 1893 1894 Input Arguments: 1895 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1896 . refinehook - function to run when setting up a coarser level 1897 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1898 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1899 1900 Calling sequence of refinehook: 1901 $ refinehook(DM coarse,DM fine,void *ctx); 1902 1903 + coarse - coarse level DM 1904 . fine - fine level DM to interpolate problem to 1905 - ctx - optional user-defined function context 1906 1907 Calling sequence for interphook: 1908 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1909 1910 + coarse - coarse level DM 1911 . interp - matrix interpolating a coarse-level solution to the finer grid 1912 . fine - fine level DM to update 1913 - ctx - optional user-defined function context 1914 1915 Level: advanced 1916 1917 Notes: 1918 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1919 1920 If this function is called multiple times, the hooks will be run in the order they are added. 1921 1922 This function is currently not available from Fortran. 1923 1924 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1925 @*/ 1926 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1927 { 1928 PetscErrorCode ierr; 1929 DMRefineHookLink link,*p; 1930 1931 PetscFunctionBegin; 1932 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1933 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 1934 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(0); 1935 } 1936 ierr = PetscNew(&link);CHKERRQ(ierr); 1937 link->refinehook = refinehook; 1938 link->interphook = interphook; 1939 link->ctx = ctx; 1940 link->next = NULL; 1941 *p = link; 1942 PetscFunctionReturn(0); 1943 } 1944 1945 /*@C 1946 DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid 1947 1948 Logically Collective 1949 1950 Input Arguments: 1951 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1952 . refinehook - function to run when setting up a coarser level 1953 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1954 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1955 1956 Level: advanced 1957 1958 Notes: 1959 This function does nothing if the hook is not in the list. 1960 1961 This function is currently not available from Fortran. 1962 1963 .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1964 @*/ 1965 PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1966 { 1967 PetscErrorCode ierr; 1968 DMRefineHookLink link,*p; 1969 1970 PetscFunctionBegin; 1971 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1972 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 1973 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) { 1974 link = *p; 1975 *p = link->next; 1976 ierr = PetscFree(link);CHKERRQ(ierr); 1977 break; 1978 } 1979 } 1980 PetscFunctionReturn(0); 1981 } 1982 1983 /*@ 1984 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1985 1986 Collective if any hooks are 1987 1988 Input Arguments: 1989 + coarse - coarser DM to use as a base 1990 . interp - interpolation matrix, apply using MatInterpolate() 1991 - fine - finer DM to update 1992 1993 Level: developer 1994 1995 .seealso: DMRefineHookAdd(), MatInterpolate() 1996 @*/ 1997 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1998 { 1999 PetscErrorCode ierr; 2000 DMRefineHookLink link; 2001 2002 PetscFunctionBegin; 2003 for (link=fine->refinehook; link; link=link->next) { 2004 if (link->interphook) { 2005 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 2006 } 2007 } 2008 PetscFunctionReturn(0); 2009 } 2010 2011 /*@ 2012 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 2013 2014 Not Collective 2015 2016 Input Parameter: 2017 . dm - the DM object 2018 2019 Output Parameter: 2020 . level - number of refinements 2021 2022 Level: developer 2023 2024 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2025 2026 @*/ 2027 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 2028 { 2029 PetscFunctionBegin; 2030 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2031 *level = dm->levelup; 2032 PetscFunctionReturn(0); 2033 } 2034 2035 /*@ 2036 DMSetRefineLevel - Set's the number of refinements that have generated this DM. 2037 2038 Not Collective 2039 2040 Input Parameter: 2041 + dm - the DM object 2042 - level - number of refinements 2043 2044 Level: advanced 2045 2046 Notes: 2047 This value is used by PCMG to determine how many multigrid levels to use 2048 2049 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2050 2051 @*/ 2052 PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level) 2053 { 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2056 dm->levelup = level; 2057 PetscFunctionReturn(0); 2058 } 2059 2060 /*@C 2061 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 2062 2063 Logically Collective 2064 2065 Input Arguments: 2066 + dm - the DM 2067 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 2068 . endhook - function to run after DMGlobalToLocalEnd() has completed 2069 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2070 2071 Calling sequence for beginhook: 2072 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2073 2074 + dm - global DM 2075 . g - global vector 2076 . mode - mode 2077 . l - local vector 2078 - ctx - optional user-defined function context 2079 2080 2081 Calling sequence for endhook: 2082 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2083 2084 + global - global DM 2085 - ctx - optional user-defined function context 2086 2087 Level: advanced 2088 2089 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2090 @*/ 2091 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2092 { 2093 PetscErrorCode ierr; 2094 DMGlobalToLocalHookLink link,*p; 2095 2096 PetscFunctionBegin; 2097 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2098 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2099 ierr = PetscNew(&link);CHKERRQ(ierr); 2100 link->beginhook = beginhook; 2101 link->endhook = endhook; 2102 link->ctx = ctx; 2103 link->next = NULL; 2104 *p = link; 2105 PetscFunctionReturn(0); 2106 } 2107 2108 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 2109 { 2110 Mat cMat; 2111 Vec cVec; 2112 PetscSection section, cSec; 2113 PetscInt pStart, pEnd, p, dof; 2114 PetscErrorCode ierr; 2115 2116 PetscFunctionBegin; 2117 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2118 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2119 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 2120 PetscInt nRows; 2121 2122 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2123 if (nRows <= 0) PetscFunctionReturn(0); 2124 ierr = DMGetSection(dm,§ion);CHKERRQ(ierr); 2125 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2126 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 2127 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2128 for (p = pStart; p < pEnd; p++) { 2129 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2130 if (dof) { 2131 PetscScalar *vals; 2132 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 2133 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 2134 } 2135 } 2136 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2137 } 2138 PetscFunctionReturn(0); 2139 } 2140 2141 /*@ 2142 DMGlobalToLocal - update local vectors from global vector 2143 2144 Neighbor-wise Collective on DM 2145 2146 Input Parameters: 2147 + dm - the DM object 2148 . g - the global vector 2149 . mode - INSERT_VALUES or ADD_VALUES 2150 - l - the local vector 2151 2152 Notes: 2153 The communication involved in this update can be overlapped with computation by using 2154 DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). 2155 2156 Level: beginner 2157 2158 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2159 2160 @*/ 2161 PetscErrorCode DMGlobalToLocal(DM dm,Vec g,InsertMode mode,Vec l) 2162 { 2163 PetscErrorCode ierr; 2164 2165 PetscFunctionBegin; 2166 ierr = DMGlobalToLocalBegin(dm,g,mode,l);CHKERRQ(ierr); 2167 ierr = DMGlobalToLocalEnd(dm,g,mode,l);CHKERRQ(ierr); 2168 PetscFunctionReturn(0); 2169 } 2170 2171 /*@ 2172 DMGlobalToLocalBegin - Begins updating local vectors from global vector 2173 2174 Neighbor-wise Collective on DM 2175 2176 Input Parameters: 2177 + dm - the DM object 2178 . g - the global vector 2179 . mode - INSERT_VALUES or ADD_VALUES 2180 - l - the local vector 2181 2182 Level: intermediate 2183 2184 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2185 2186 @*/ 2187 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2188 { 2189 PetscSF sf; 2190 PetscErrorCode ierr; 2191 DMGlobalToLocalHookLink link; 2192 2193 PetscFunctionBegin; 2194 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2195 for (link=dm->gtolhook; link; link=link->next) { 2196 if (link->beginhook) { 2197 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 2198 } 2199 } 2200 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2201 if (sf) { 2202 const PetscScalar *gArray; 2203 PetscScalar *lArray; 2204 2205 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2206 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 2207 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 2208 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2209 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 2210 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 2211 } else { 2212 if (!dm->ops->globaltolocalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalBegin() for type %s",((PetscObject)dm)->type_name); 2213 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2214 } 2215 PetscFunctionReturn(0); 2216 } 2217 2218 /*@ 2219 DMGlobalToLocalEnd - Ends updating local vectors from global vector 2220 2221 Neighbor-wise Collective on DM 2222 2223 Input Parameters: 2224 + dm - the DM object 2225 . g - the global vector 2226 . mode - INSERT_VALUES or ADD_VALUES 2227 - l - the local vector 2228 2229 Level: intermediate 2230 2231 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2232 2233 @*/ 2234 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2235 { 2236 PetscSF sf; 2237 PetscErrorCode ierr; 2238 const PetscScalar *gArray; 2239 PetscScalar *lArray; 2240 DMGlobalToLocalHookLink link; 2241 2242 PetscFunctionBegin; 2243 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2244 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2245 if (sf) { 2246 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2247 2248 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 2249 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 2250 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2251 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 2252 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 2253 } else { 2254 if (!dm->ops->globaltolocalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalEnd() for type %s",((PetscObject)dm)->type_name); 2255 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2256 } 2257 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 2258 for (link=dm->gtolhook; link; link=link->next) { 2259 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2260 } 2261 PetscFunctionReturn(0); 2262 } 2263 2264 /*@C 2265 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 2266 2267 Logically Collective 2268 2269 Input Arguments: 2270 + dm - the DM 2271 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 2272 . endhook - function to run after DMLocalToGlobalEnd() has completed 2273 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2274 2275 Calling sequence for beginhook: 2276 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2277 2278 + dm - global DM 2279 . l - local vector 2280 . mode - mode 2281 . g - global vector 2282 - ctx - optional user-defined function context 2283 2284 2285 Calling sequence for endhook: 2286 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2287 2288 + global - global DM 2289 . l - local vector 2290 . mode - mode 2291 . g - global vector 2292 - ctx - optional user-defined function context 2293 2294 Level: advanced 2295 2296 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2297 @*/ 2298 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2299 { 2300 PetscErrorCode ierr; 2301 DMLocalToGlobalHookLink link,*p; 2302 2303 PetscFunctionBegin; 2304 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2305 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2306 ierr = PetscNew(&link);CHKERRQ(ierr); 2307 link->beginhook = beginhook; 2308 link->endhook = endhook; 2309 link->ctx = ctx; 2310 link->next = NULL; 2311 *p = link; 2312 PetscFunctionReturn(0); 2313 } 2314 2315 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 2316 { 2317 Mat cMat; 2318 Vec cVec; 2319 PetscSection section, cSec; 2320 PetscInt pStart, pEnd, p, dof; 2321 PetscErrorCode ierr; 2322 2323 PetscFunctionBegin; 2324 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2325 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2326 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 2327 PetscInt nRows; 2328 2329 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2330 if (nRows <= 0) PetscFunctionReturn(0); 2331 ierr = DMGetSection(dm,§ion);CHKERRQ(ierr); 2332 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2333 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2334 for (p = pStart; p < pEnd; p++) { 2335 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2336 if (dof) { 2337 PetscInt d; 2338 PetscScalar *vals; 2339 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 2340 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 2341 /* for this to be the true transpose, we have to zero the values that 2342 * we just extracted */ 2343 for (d = 0; d < dof; d++) { 2344 vals[d] = 0.; 2345 } 2346 } 2347 } 2348 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 2349 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2350 } 2351 PetscFunctionReturn(0); 2352 } 2353 /*@ 2354 DMLocalToGlobal - updates global vectors from local vectors 2355 2356 Neighbor-wise Collective on DM 2357 2358 Input Parameters: 2359 + dm - the DM object 2360 . l - the local vector 2361 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point. 2362 - g - the global vector 2363 2364 Notes: 2365 The communication involved in this update can be overlapped with computation by using 2366 DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). 2367 2368 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2369 INSERT_VALUES is not supported for DMDA; in that case simply compute the values directly into a global vector instead of a local one. 2370 2371 Level: beginner 2372 2373 .seealso DMLocalToGlobalBegin(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2374 2375 @*/ 2376 PetscErrorCode DMLocalToGlobal(DM dm,Vec l,InsertMode mode,Vec g) 2377 { 2378 PetscErrorCode ierr; 2379 2380 PetscFunctionBegin; 2381 ierr = DMLocalToGlobalBegin(dm,l,mode,g);CHKERRQ(ierr); 2382 ierr = DMLocalToGlobalEnd(dm,l,mode,g);CHKERRQ(ierr); 2383 PetscFunctionReturn(0); 2384 } 2385 2386 /*@ 2387 DMLocalToGlobalBegin - begins updating global vectors from local vectors 2388 2389 Neighbor-wise Collective on DM 2390 2391 Input Parameters: 2392 + dm - the DM object 2393 . l - the local vector 2394 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point. 2395 - g - the global vector 2396 2397 Notes: 2398 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2399 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 2400 2401 Level: intermediate 2402 2403 .seealso DMLocalToGlobal(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2404 2405 @*/ 2406 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 2407 { 2408 PetscSF sf; 2409 PetscSection s, gs; 2410 DMLocalToGlobalHookLink link; 2411 const PetscScalar *lArray; 2412 PetscScalar *gArray; 2413 PetscBool isInsert; 2414 PetscErrorCode ierr; 2415 2416 PetscFunctionBegin; 2417 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2418 for (link=dm->ltoghook; link; link=link->next) { 2419 if (link->beginhook) { 2420 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 2421 } 2422 } 2423 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 2424 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2425 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 2426 switch (mode) { 2427 case INSERT_VALUES: 2428 case INSERT_ALL_VALUES: 2429 case INSERT_BC_VALUES: 2430 isInsert = PETSC_TRUE; break; 2431 case ADD_VALUES: 2432 case ADD_ALL_VALUES: 2433 case ADD_BC_VALUES: 2434 isInsert = PETSC_FALSE; break; 2435 default: 2436 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2437 } 2438 if (sf && !isInsert) { 2439 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2440 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2441 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2442 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2443 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2444 } else if (s && isInsert) { 2445 PetscInt gStart, pStart, pEnd, p; 2446 2447 ierr = DMGetGlobalSection(dm, &gs);CHKERRQ(ierr); 2448 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2449 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2450 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2451 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2452 for (p = pStart; p < pEnd; ++p) { 2453 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2454 2455 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2456 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2457 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2458 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2459 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2460 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2461 /* Ignore off-process data and points with no global data */ 2462 if (!gdof || goff < 0) continue; 2463 if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 2464 /* If no constraints are enforced in the global vector */ 2465 if (!gcdof) { 2466 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2467 /* If constraints are enforced in the global vector */ 2468 } else if (cdof == gcdof) { 2469 const PetscInt *cdofs; 2470 PetscInt cind = 0; 2471 2472 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2473 for (d = 0, e = 0; d < dof; ++d) { 2474 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2475 gArray[goff-gStart+e++] = lArray[off+d]; 2476 } 2477 } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 2478 } 2479 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2480 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2481 } else { 2482 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2483 } 2484 PetscFunctionReturn(0); 2485 } 2486 2487 /*@ 2488 DMLocalToGlobalEnd - updates global vectors from local vectors 2489 2490 Neighbor-wise Collective on DM 2491 2492 Input Parameters: 2493 + dm - the DM object 2494 . l - the local vector 2495 . mode - INSERT_VALUES or ADD_VALUES 2496 - g - the global vector 2497 2498 Level: intermediate 2499 2500 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2501 2502 @*/ 2503 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2504 { 2505 PetscSF sf; 2506 PetscSection s; 2507 DMLocalToGlobalHookLink link; 2508 PetscBool isInsert; 2509 PetscErrorCode ierr; 2510 2511 PetscFunctionBegin; 2512 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2513 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2514 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 2515 switch (mode) { 2516 case INSERT_VALUES: 2517 case INSERT_ALL_VALUES: 2518 isInsert = PETSC_TRUE; break; 2519 case ADD_VALUES: 2520 case ADD_ALL_VALUES: 2521 isInsert = PETSC_FALSE; break; 2522 default: 2523 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2524 } 2525 if (sf && !isInsert) { 2526 const PetscScalar *lArray; 2527 PetscScalar *gArray; 2528 2529 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2530 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2531 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2532 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2533 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2534 } else if (s && isInsert) { 2535 } else { 2536 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2537 } 2538 for (link=dm->ltoghook; link; link=link->next) { 2539 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2540 } 2541 PetscFunctionReturn(0); 2542 } 2543 2544 /*@ 2545 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2546 that contain irrelevant values) to another local vector where the ghost 2547 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2548 2549 Neighbor-wise Collective on DM and Vec 2550 2551 Input Parameters: 2552 + dm - the DM object 2553 . g - the original local vector 2554 - mode - one of INSERT_VALUES or ADD_VALUES 2555 2556 Output Parameter: 2557 . l - the local vector with correct ghost values 2558 2559 Level: intermediate 2560 2561 Notes: 2562 The local vectors used here need not be the same as those 2563 obtained from DMCreateLocalVector(), BUT they 2564 must have the same parallel data layout; they could, for example, be 2565 obtained with VecDuplicate() from the DM originating vectors. 2566 2567 .keywords: DM, local-to-local, begin 2568 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2569 2570 @*/ 2571 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2572 { 2573 PetscErrorCode ierr; 2574 2575 PetscFunctionBegin; 2576 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2577 if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2578 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2579 PetscFunctionReturn(0); 2580 } 2581 2582 /*@ 2583 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2584 that contain irrelevant values) to another local vector where the ghost 2585 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2586 2587 Neighbor-wise Collective on DM and Vec 2588 2589 Input Parameters: 2590 + da - the DM object 2591 . g - the original local vector 2592 - mode - one of INSERT_VALUES or ADD_VALUES 2593 2594 Output Parameter: 2595 . l - the local vector with correct ghost values 2596 2597 Level: intermediate 2598 2599 Notes: 2600 The local vectors used here need not be the same as those 2601 obtained from DMCreateLocalVector(), BUT they 2602 must have the same parallel data layout; they could, for example, be 2603 obtained with VecDuplicate() from the DM originating vectors. 2604 2605 .keywords: DM, local-to-local, end 2606 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2607 2608 @*/ 2609 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2610 { 2611 PetscErrorCode ierr; 2612 2613 PetscFunctionBegin; 2614 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2615 if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2616 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2617 PetscFunctionReturn(0); 2618 } 2619 2620 2621 /*@ 2622 DMCoarsen - Coarsens a DM object 2623 2624 Collective on DM 2625 2626 Input Parameter: 2627 + dm - the DM object 2628 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2629 2630 Output Parameter: 2631 . dmc - the coarsened DM 2632 2633 Level: developer 2634 2635 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2636 2637 @*/ 2638 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2639 { 2640 PetscErrorCode ierr; 2641 DMCoarsenHookLink link; 2642 2643 PetscFunctionBegin; 2644 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2645 if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen"); 2646 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2647 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2648 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2649 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 2650 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2651 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2652 (*dmc)->ctx = dm->ctx; 2653 (*dmc)->levelup = dm->levelup; 2654 (*dmc)->leveldown = dm->leveldown + 1; 2655 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2656 for (link=dm->coarsenhook; link; link=link->next) { 2657 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2658 } 2659 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2660 PetscFunctionReturn(0); 2661 } 2662 2663 /*@C 2664 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2665 2666 Logically Collective 2667 2668 Input Arguments: 2669 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2670 . coarsenhook - function to run when setting up a coarser level 2671 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2672 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2673 2674 Calling sequence of coarsenhook: 2675 $ coarsenhook(DM fine,DM coarse,void *ctx); 2676 2677 + fine - fine level DM 2678 . coarse - coarse level DM to restrict problem to 2679 - ctx - optional user-defined function context 2680 2681 Calling sequence for restricthook: 2682 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2683 2684 + fine - fine level DM 2685 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2686 . rscale - scaling vector for restriction 2687 . inject - matrix restricting by injection 2688 . coarse - coarse level DM to update 2689 - ctx - optional user-defined function context 2690 2691 Level: advanced 2692 2693 Notes: 2694 This function is only needed if auxiliary data needs to be set up on coarse grids. 2695 2696 If this function is called multiple times, the hooks will be run in the order they are added. 2697 2698 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2699 extract the finest level information from its context (instead of from the SNES). 2700 2701 This function is currently not available from Fortran. 2702 2703 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2704 @*/ 2705 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2706 { 2707 PetscErrorCode ierr; 2708 DMCoarsenHookLink link,*p; 2709 2710 PetscFunctionBegin; 2711 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2712 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2713 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2714 } 2715 ierr = PetscNew(&link);CHKERRQ(ierr); 2716 link->coarsenhook = coarsenhook; 2717 link->restricthook = restricthook; 2718 link->ctx = ctx; 2719 link->next = NULL; 2720 *p = link; 2721 PetscFunctionReturn(0); 2722 } 2723 2724 /*@C 2725 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid 2726 2727 Logically Collective 2728 2729 Input Arguments: 2730 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2731 . coarsenhook - function to run when setting up a coarser level 2732 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2733 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2734 2735 Level: advanced 2736 2737 Notes: 2738 This function does nothing if the hook is not in the list. 2739 2740 This function is currently not available from Fortran. 2741 2742 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2743 @*/ 2744 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2745 { 2746 PetscErrorCode ierr; 2747 DMCoarsenHookLink link,*p; 2748 2749 PetscFunctionBegin; 2750 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2751 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2752 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2753 link = *p; 2754 *p = link->next; 2755 ierr = PetscFree(link);CHKERRQ(ierr); 2756 break; 2757 } 2758 } 2759 PetscFunctionReturn(0); 2760 } 2761 2762 2763 /*@ 2764 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2765 2766 Collective if any hooks are 2767 2768 Input Arguments: 2769 + fine - finer DM to use as a base 2770 . restrct - restriction matrix, apply using MatRestrict() 2771 . rscale - scaling vector for restriction 2772 . inject - injection matrix, also use MatRestrict() 2773 - coarse - coarser DM to update 2774 2775 Level: developer 2776 2777 .seealso: DMCoarsenHookAdd(), MatRestrict() 2778 @*/ 2779 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2780 { 2781 PetscErrorCode ierr; 2782 DMCoarsenHookLink link; 2783 2784 PetscFunctionBegin; 2785 for (link=fine->coarsenhook; link; link=link->next) { 2786 if (link->restricthook) { 2787 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2788 } 2789 } 2790 PetscFunctionReturn(0); 2791 } 2792 2793 /*@C 2794 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2795 2796 Logically Collective 2797 2798 Input Arguments: 2799 + global - global DM 2800 . ddhook - function to run to pass data to the decomposition DM upon its creation 2801 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2802 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2803 2804 2805 Calling sequence for ddhook: 2806 $ ddhook(DM global,DM block,void *ctx) 2807 2808 + global - global DM 2809 . block - block DM 2810 - ctx - optional user-defined function context 2811 2812 Calling sequence for restricthook: 2813 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2814 2815 + global - global DM 2816 . out - scatter to the outer (with ghost and overlap points) block vector 2817 . in - scatter to block vector values only owned locally 2818 . block - block DM 2819 - ctx - optional user-defined function context 2820 2821 Level: advanced 2822 2823 Notes: 2824 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2825 2826 If this function is called multiple times, the hooks will be run in the order they are added. 2827 2828 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2829 extract the global information from its context (instead of from the SNES). 2830 2831 This function is currently not available from Fortran. 2832 2833 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2834 @*/ 2835 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2836 { 2837 PetscErrorCode ierr; 2838 DMSubDomainHookLink link,*p; 2839 2840 PetscFunctionBegin; 2841 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2842 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2843 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2844 } 2845 ierr = PetscNew(&link);CHKERRQ(ierr); 2846 link->restricthook = restricthook; 2847 link->ddhook = ddhook; 2848 link->ctx = ctx; 2849 link->next = NULL; 2850 *p = link; 2851 PetscFunctionReturn(0); 2852 } 2853 2854 /*@C 2855 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid 2856 2857 Logically Collective 2858 2859 Input Arguments: 2860 + global - global DM 2861 . ddhook - function to run to pass data to the decomposition DM upon its creation 2862 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2863 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2864 2865 Level: advanced 2866 2867 Notes: 2868 2869 This function is currently not available from Fortran. 2870 2871 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2872 @*/ 2873 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2874 { 2875 PetscErrorCode ierr; 2876 DMSubDomainHookLink link,*p; 2877 2878 PetscFunctionBegin; 2879 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2880 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2881 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2882 link = *p; 2883 *p = link->next; 2884 ierr = PetscFree(link);CHKERRQ(ierr); 2885 break; 2886 } 2887 } 2888 PetscFunctionReturn(0); 2889 } 2890 2891 /*@ 2892 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2893 2894 Collective if any hooks are 2895 2896 Input Arguments: 2897 + fine - finer DM to use as a base 2898 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2899 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2900 - coarse - coarer DM to update 2901 2902 Level: developer 2903 2904 .seealso: DMCoarsenHookAdd(), MatRestrict() 2905 @*/ 2906 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2907 { 2908 PetscErrorCode ierr; 2909 DMSubDomainHookLink link; 2910 2911 PetscFunctionBegin; 2912 for (link=global->subdomainhook; link; link=link->next) { 2913 if (link->restricthook) { 2914 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2915 } 2916 } 2917 PetscFunctionReturn(0); 2918 } 2919 2920 /*@ 2921 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2922 2923 Not Collective 2924 2925 Input Parameter: 2926 . dm - the DM object 2927 2928 Output Parameter: 2929 . level - number of coarsenings 2930 2931 Level: developer 2932 2933 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2934 2935 @*/ 2936 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2937 { 2938 PetscFunctionBegin; 2939 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2940 *level = dm->leveldown; 2941 PetscFunctionReturn(0); 2942 } 2943 2944 2945 2946 /*@C 2947 DMRefineHierarchy - Refines a DM object, all levels at once 2948 2949 Collective on DM 2950 2951 Input Parameter: 2952 + dm - the DM object 2953 - nlevels - the number of levels of refinement 2954 2955 Output Parameter: 2956 . dmf - the refined DM hierarchy 2957 2958 Level: developer 2959 2960 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2961 2962 @*/ 2963 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2964 { 2965 PetscErrorCode ierr; 2966 2967 PetscFunctionBegin; 2968 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2969 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2970 if (nlevels == 0) PetscFunctionReturn(0); 2971 if (dm->ops->refinehierarchy) { 2972 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2973 } else if (dm->ops->refine) { 2974 PetscInt i; 2975 2976 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2977 for (i=1; i<nlevels; i++) { 2978 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2979 } 2980 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2981 PetscFunctionReturn(0); 2982 } 2983 2984 /*@C 2985 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2986 2987 Collective on DM 2988 2989 Input Parameter: 2990 + dm - the DM object 2991 - nlevels - the number of levels of coarsening 2992 2993 Output Parameter: 2994 . dmc - the coarsened DM hierarchy 2995 2996 Level: developer 2997 2998 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2999 3000 @*/ 3001 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 3002 { 3003 PetscErrorCode ierr; 3004 3005 PetscFunctionBegin; 3006 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3007 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 3008 if (nlevels == 0) PetscFunctionReturn(0); 3009 PetscValidPointer(dmc,3); 3010 if (dm->ops->coarsenhierarchy) { 3011 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 3012 } else if (dm->ops->coarsen) { 3013 PetscInt i; 3014 3015 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 3016 for (i=1; i<nlevels; i++) { 3017 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 3018 } 3019 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 3020 PetscFunctionReturn(0); 3021 } 3022 3023 /*@ 3024 DMCreateAggregates - Gets the aggregates that map between 3025 grids associated with two DMs. 3026 3027 Collective on DM 3028 3029 Input Parameters: 3030 + dmc - the coarse grid DM 3031 - dmf - the fine grid DM 3032 3033 Output Parameters: 3034 . rest - the restriction matrix (transpose of the projection matrix) 3035 3036 Level: intermediate 3037 3038 .keywords: interpolation, restriction, multigrid 3039 3040 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 3041 @*/ 3042 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 3043 { 3044 PetscErrorCode ierr; 3045 3046 PetscFunctionBegin; 3047 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 3048 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 3049 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 3050 PetscFunctionReturn(0); 3051 } 3052 3053 /*@C 3054 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 3055 3056 Not Collective 3057 3058 Input Parameters: 3059 + dm - the DM object 3060 - destroy - the destroy function 3061 3062 Level: intermediate 3063 3064 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3065 3066 @*/ 3067 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 3068 { 3069 PetscFunctionBegin; 3070 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3071 dm->ctxdestroy = destroy; 3072 PetscFunctionReturn(0); 3073 } 3074 3075 /*@ 3076 DMSetApplicationContext - Set a user context into a DM object 3077 3078 Not Collective 3079 3080 Input Parameters: 3081 + dm - the DM object 3082 - ctx - the user context 3083 3084 Level: intermediate 3085 3086 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3087 3088 @*/ 3089 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 3090 { 3091 PetscFunctionBegin; 3092 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3093 dm->ctx = ctx; 3094 PetscFunctionReturn(0); 3095 } 3096 3097 /*@ 3098 DMGetApplicationContext - Gets a user context from a DM object 3099 3100 Not Collective 3101 3102 Input Parameter: 3103 . dm - the DM object 3104 3105 Output Parameter: 3106 . ctx - the user context 3107 3108 Level: intermediate 3109 3110 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3111 3112 @*/ 3113 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 3114 { 3115 PetscFunctionBegin; 3116 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3117 *(void**)ctx = dm->ctx; 3118 PetscFunctionReturn(0); 3119 } 3120 3121 /*@C 3122 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 3123 3124 Logically Collective on DM 3125 3126 Input Parameter: 3127 + dm - the DM object 3128 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 3129 3130 Level: intermediate 3131 3132 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 3133 DMSetJacobian() 3134 3135 @*/ 3136 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 3137 { 3138 PetscFunctionBegin; 3139 dm->ops->computevariablebounds = f; 3140 PetscFunctionReturn(0); 3141 } 3142 3143 /*@ 3144 DMHasVariableBounds - does the DM object have a variable bounds function? 3145 3146 Not Collective 3147 3148 Input Parameter: 3149 . dm - the DM object to destroy 3150 3151 Output Parameter: 3152 . flg - PETSC_TRUE if the variable bounds function exists 3153 3154 Level: developer 3155 3156 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3157 3158 @*/ 3159 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 3160 { 3161 PetscFunctionBegin; 3162 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 3163 PetscFunctionReturn(0); 3164 } 3165 3166 /*@C 3167 DMComputeVariableBounds - compute variable bounds used by SNESVI. 3168 3169 Logically Collective on DM 3170 3171 Input Parameters: 3172 . dm - the DM object 3173 3174 Output parameters: 3175 + xl - lower bound 3176 - xu - upper bound 3177 3178 Level: advanced 3179 3180 Notes: 3181 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 3182 3183 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3184 3185 @*/ 3186 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 3187 { 3188 PetscErrorCode ierr; 3189 3190 PetscFunctionBegin; 3191 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 3192 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 3193 if (dm->ops->computevariablebounds) { 3194 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 3195 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 3196 PetscFunctionReturn(0); 3197 } 3198 3199 /*@ 3200 DMHasColoring - does the DM object have a method of providing a coloring? 3201 3202 Not Collective 3203 3204 Input Parameter: 3205 . dm - the DM object 3206 3207 Output Parameter: 3208 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 3209 3210 Level: developer 3211 3212 .seealso DMHasFunction(), DMCreateColoring() 3213 3214 @*/ 3215 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 3216 { 3217 PetscFunctionBegin; 3218 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 3219 PetscFunctionReturn(0); 3220 } 3221 3222 /*@ 3223 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 3224 3225 Not Collective 3226 3227 Input Parameter: 3228 . dm - the DM object 3229 3230 Output Parameter: 3231 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 3232 3233 Level: developer 3234 3235 .seealso DMHasFunction(), DMCreateRestriction() 3236 3237 @*/ 3238 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 3239 { 3240 PetscFunctionBegin; 3241 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 3242 PetscFunctionReturn(0); 3243 } 3244 3245 3246 /*@ 3247 DMHasCreateInjection - does the DM object have a method of providing an injection? 3248 3249 Not Collective 3250 3251 Input Parameter: 3252 . dm - the DM object 3253 3254 Output Parameter: 3255 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection(). 3256 3257 Level: developer 3258 3259 .seealso DMHasFunction(), DMCreateInjection() 3260 3261 @*/ 3262 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg) 3263 { 3264 PetscErrorCode ierr; 3265 PetscFunctionBegin; 3266 if (!dm->ops->hascreateinjection) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMHasCreateInjection not implemented for this type"); 3267 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr); 3268 PetscFunctionReturn(0); 3269 } 3270 3271 /*@C 3272 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 3273 3274 Collective on DM 3275 3276 Input Parameter: 3277 + dm - the DM object 3278 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 3279 3280 Level: developer 3281 3282 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3283 3284 @*/ 3285 PetscErrorCode DMSetVec(DM dm,Vec x) 3286 { 3287 PetscErrorCode ierr; 3288 3289 PetscFunctionBegin; 3290 if (x) { 3291 if (!dm->x) { 3292 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 3293 } 3294 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 3295 } else if (dm->x) { 3296 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 3297 } 3298 PetscFunctionReturn(0); 3299 } 3300 3301 PetscFunctionList DMList = NULL; 3302 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3303 3304 /*@C 3305 DMSetType - Builds a DM, for a particular DM implementation. 3306 3307 Collective on DM 3308 3309 Input Parameters: 3310 + dm - The DM object 3311 - method - The name of the DM type 3312 3313 Options Database Key: 3314 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3315 3316 Notes: 3317 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3318 3319 Level: intermediate 3320 3321 .keywords: DM, set, type 3322 .seealso: DMGetType(), DMCreate() 3323 @*/ 3324 PetscErrorCode DMSetType(DM dm, DMType method) 3325 { 3326 PetscErrorCode (*r)(DM); 3327 PetscBool match; 3328 PetscErrorCode ierr; 3329 3330 PetscFunctionBegin; 3331 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3332 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3333 if (match) PetscFunctionReturn(0); 3334 3335 ierr = DMRegisterAll();CHKERRQ(ierr); 3336 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3337 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3338 3339 if (dm->ops->destroy) { 3340 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3341 dm->ops->destroy = NULL; 3342 } 3343 ierr = (*r)(dm);CHKERRQ(ierr); 3344 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3345 PetscFunctionReturn(0); 3346 } 3347 3348 /*@C 3349 DMGetType - Gets the DM type name (as a string) from the DM. 3350 3351 Not Collective 3352 3353 Input Parameter: 3354 . dm - The DM 3355 3356 Output Parameter: 3357 . type - The DM type name 3358 3359 Level: intermediate 3360 3361 .keywords: DM, get, type, name 3362 .seealso: DMSetType(), DMCreate() 3363 @*/ 3364 PetscErrorCode DMGetType(DM dm, DMType *type) 3365 { 3366 PetscErrorCode ierr; 3367 3368 PetscFunctionBegin; 3369 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3370 PetscValidPointer(type,2); 3371 ierr = DMRegisterAll();CHKERRQ(ierr); 3372 *type = ((PetscObject)dm)->type_name; 3373 PetscFunctionReturn(0); 3374 } 3375 3376 /*@C 3377 DMConvert - Converts a DM to another DM, either of the same or different type. 3378 3379 Collective on DM 3380 3381 Input Parameters: 3382 + dm - the DM 3383 - newtype - new DM type (use "same" for the same type) 3384 3385 Output Parameter: 3386 . M - pointer to new DM 3387 3388 Notes: 3389 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3390 the MPI communicator of the generated DM is always the same as the communicator 3391 of the input DM. 3392 3393 Level: intermediate 3394 3395 .seealso: DMCreate() 3396 @*/ 3397 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3398 { 3399 DM B; 3400 char convname[256]; 3401 PetscBool sametype/*, issame */; 3402 PetscErrorCode ierr; 3403 3404 PetscFunctionBegin; 3405 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3406 PetscValidType(dm,1); 3407 PetscValidPointer(M,3); 3408 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3409 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3410 if (sametype) { 3411 *M = dm; 3412 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3413 PetscFunctionReturn(0); 3414 } else { 3415 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3416 3417 /* 3418 Order of precedence: 3419 1) See if a specialized converter is known to the current DM. 3420 2) See if a specialized converter is known to the desired DM class. 3421 3) See if a good general converter is registered for the desired class 3422 4) See if a good general converter is known for the current matrix. 3423 5) Use a really basic converter. 3424 */ 3425 3426 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3427 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3428 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3429 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3430 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3431 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3432 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3433 if (conv) goto foundconv; 3434 3435 /* 2) See if a specialized converter is known to the desired DM class. */ 3436 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3437 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3438 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3439 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3440 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3441 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3442 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3443 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3444 if (conv) { 3445 ierr = DMDestroy(&B);CHKERRQ(ierr); 3446 goto foundconv; 3447 } 3448 3449 #if 0 3450 /* 3) See if a good general converter is registered for the desired class */ 3451 conv = B->ops->convertfrom; 3452 ierr = DMDestroy(&B);CHKERRQ(ierr); 3453 if (conv) goto foundconv; 3454 3455 /* 4) See if a good general converter is known for the current matrix */ 3456 if (dm->ops->convert) { 3457 conv = dm->ops->convert; 3458 } 3459 if (conv) goto foundconv; 3460 #endif 3461 3462 /* 5) Use a really basic converter. */ 3463 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3464 3465 foundconv: 3466 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3467 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3468 /* Things that are independent of DM type: We should consult DMClone() here */ 3469 { 3470 PetscBool isper; 3471 const PetscReal *maxCell, *L; 3472 const DMBoundaryType *bd; 3473 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3474 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3475 } 3476 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3477 } 3478 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3479 PetscFunctionReturn(0); 3480 } 3481 3482 /*--------------------------------------------------------------------------------------------------------------------*/ 3483 3484 /*@C 3485 DMRegister - Adds a new DM component implementation 3486 3487 Not Collective 3488 3489 Input Parameters: 3490 + name - The name of a new user-defined creation routine 3491 - create_func - The creation routine itself 3492 3493 Notes: 3494 DMRegister() may be called multiple times to add several user-defined DMs 3495 3496 3497 Sample usage: 3498 .vb 3499 DMRegister("my_da", MyDMCreate); 3500 .ve 3501 3502 Then, your DM type can be chosen with the procedural interface via 3503 .vb 3504 DMCreate(MPI_Comm, DM *); 3505 DMSetType(DM,"my_da"); 3506 .ve 3507 or at runtime via the option 3508 .vb 3509 -da_type my_da 3510 .ve 3511 3512 Level: advanced 3513 3514 .keywords: DM, register 3515 .seealso: DMRegisterAll(), DMRegisterDestroy() 3516 3517 @*/ 3518 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3519 { 3520 PetscErrorCode ierr; 3521 3522 PetscFunctionBegin; 3523 ierr = DMInitializePackage();CHKERRQ(ierr); 3524 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3525 PetscFunctionReturn(0); 3526 } 3527 3528 /*@C 3529 DMLoad - Loads a DM that has been stored in binary with DMView(). 3530 3531 Collective on PetscViewer 3532 3533 Input Parameters: 3534 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3535 some related function before a call to DMLoad(). 3536 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3537 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3538 3539 Level: intermediate 3540 3541 Notes: 3542 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3543 3544 Notes for advanced users: 3545 Most users should not need to know the details of the binary storage 3546 format, since DMLoad() and DMView() completely hide these details. 3547 But for anyone who's interested, the standard binary matrix storage 3548 format is 3549 .vb 3550 has not yet been determined 3551 .ve 3552 3553 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3554 @*/ 3555 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3556 { 3557 PetscBool isbinary, ishdf5; 3558 PetscErrorCode ierr; 3559 3560 PetscFunctionBegin; 3561 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3562 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3563 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3564 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3565 if (isbinary) { 3566 PetscInt classid; 3567 char type[256]; 3568 3569 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3570 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3571 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3572 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3573 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3574 } else if (ishdf5) { 3575 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3576 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3577 PetscFunctionReturn(0); 3578 } 3579 3580 /******************************** FEM Support **********************************/ 3581 3582 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3583 { 3584 PetscInt f; 3585 PetscErrorCode ierr; 3586 3587 PetscFunctionBegin; 3588 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3589 for (f = 0; f < len; ++f) { 3590 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3591 } 3592 PetscFunctionReturn(0); 3593 } 3594 3595 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3596 { 3597 PetscInt f, g; 3598 PetscErrorCode ierr; 3599 3600 PetscFunctionBegin; 3601 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3602 for (f = 0; f < rows; ++f) { 3603 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3604 for (g = 0; g < cols; ++g) { 3605 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3606 } 3607 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3608 } 3609 PetscFunctionReturn(0); 3610 } 3611 3612 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3613 { 3614 PetscInt localSize, bs; 3615 PetscMPIInt size; 3616 Vec x, xglob; 3617 const PetscScalar *xarray; 3618 PetscErrorCode ierr; 3619 3620 PetscFunctionBegin; 3621 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr); 3622 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3623 ierr = VecCopy(X, x);CHKERRQ(ierr); 3624 ierr = VecChop(x, tol);CHKERRQ(ierr); 3625 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 3626 if (size > 1) { 3627 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 3628 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 3629 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 3630 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 3631 } else { 3632 xglob = x; 3633 } 3634 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 3635 if (size > 1) { 3636 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 3637 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 3638 } 3639 ierr = VecDestroy(&x);CHKERRQ(ierr); 3640 PetscFunctionReturn(0); 3641 } 3642 3643 /*@ 3644 DMGetSection - Get the PetscSection encoding the local data layout for the DM. 3645 3646 Input Parameter: 3647 . dm - The DM 3648 3649 Output Parameter: 3650 . section - The PetscSection 3651 3652 Options Database Keys: 3653 . -dm_petscsection_view - View the Section created by the DM 3654 3655 Level: intermediate 3656 3657 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3658 3659 .seealso: DMSetSection(), DMGetGlobalSection() 3660 @*/ 3661 PetscErrorCode DMGetSection(DM dm, PetscSection *section) 3662 { 3663 PetscErrorCode ierr; 3664 3665 PetscFunctionBegin; 3666 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3667 PetscValidPointer(section, 2); 3668 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3669 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3670 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3671 } 3672 *section = dm->defaultSection; 3673 PetscFunctionReturn(0); 3674 } 3675 3676 /*@ 3677 DMSetSection - Set the PetscSection encoding the local data layout for the DM. 3678 3679 Input Parameters: 3680 + dm - The DM 3681 - section - The PetscSection 3682 3683 Level: intermediate 3684 3685 Note: Any existing Section will be destroyed 3686 3687 .seealso: DMSetSection(), DMGetGlobalSection() 3688 @*/ 3689 PetscErrorCode DMSetSection(DM dm, PetscSection section) 3690 { 3691 PetscInt numFields = 0; 3692 PetscInt f; 3693 PetscErrorCode ierr; 3694 3695 PetscFunctionBegin; 3696 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3697 if (section) { 3698 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3699 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3700 } 3701 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3702 dm->defaultSection = section; 3703 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3704 if (numFields) { 3705 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3706 for (f = 0; f < numFields; ++f) { 3707 PetscObject disc; 3708 const char *name; 3709 3710 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3711 ierr = DMGetField(dm, f, NULL, &disc);CHKERRQ(ierr); 3712 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3713 } 3714 } 3715 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */ 3716 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3717 PetscFunctionReturn(0); 3718 } 3719 3720 /*@ 3721 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3722 3723 not collective 3724 3725 Input Parameter: 3726 . dm - The DM 3727 3728 Output Parameter: 3729 + 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. 3730 - 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. 3731 3732 Level: advanced 3733 3734 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3735 3736 .seealso: DMSetDefaultConstraints() 3737 @*/ 3738 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3739 { 3740 PetscErrorCode ierr; 3741 3742 PetscFunctionBegin; 3743 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3744 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3745 if (section) {*section = dm->defaultConstraintSection;} 3746 if (mat) {*mat = dm->defaultConstraintMat;} 3747 PetscFunctionReturn(0); 3748 } 3749 3750 /*@ 3751 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3752 3753 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(). 3754 3755 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. 3756 3757 collective on dm 3758 3759 Input Parameters: 3760 + dm - The DM 3761 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Must have a local communicator (PETSC_COMM_SELF or derivative). 3762 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section: NULL indicates no constraints. Must have a local communicator (PETSC_COMM_SELF or derivative). 3763 3764 Level: advanced 3765 3766 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3767 3768 .seealso: DMGetDefaultConstraints() 3769 @*/ 3770 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3771 { 3772 PetscMPIInt result; 3773 PetscErrorCode ierr; 3774 3775 PetscFunctionBegin; 3776 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3777 if (section) { 3778 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3779 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3780 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3781 } 3782 if (mat) { 3783 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3784 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3785 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3786 } 3787 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3788 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3789 dm->defaultConstraintSection = section; 3790 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3791 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3792 dm->defaultConstraintMat = mat; 3793 PetscFunctionReturn(0); 3794 } 3795 3796 #if defined(PETSC_USE_DEBUG) 3797 /* 3798 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3799 3800 Input Parameters: 3801 + dm - The DM 3802 . localSection - PetscSection describing the local data layout 3803 - globalSection - PetscSection describing the global data layout 3804 3805 Level: intermediate 3806 3807 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3808 */ 3809 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3810 { 3811 MPI_Comm comm; 3812 PetscLayout layout; 3813 const PetscInt *ranges; 3814 PetscInt pStart, pEnd, p, nroots; 3815 PetscMPIInt size, rank; 3816 PetscBool valid = PETSC_TRUE, gvalid; 3817 PetscErrorCode ierr; 3818 3819 PetscFunctionBegin; 3820 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3822 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3823 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3824 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3825 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3826 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3827 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3828 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3829 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3830 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3831 for (p = pStart; p < pEnd; ++p) { 3832 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3833 3834 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3835 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3836 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3837 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3838 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3839 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3840 if (!gdof) continue; /* Censored point */ 3841 if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof);CHKERRQ(ierr); valid = PETSC_FALSE;} 3842 if (gcdof && (gcdof != cdof)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof);CHKERRQ(ierr); valid = PETSC_FALSE;} 3843 if (gdof < 0) { 3844 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3845 for (d = 0; d < gsize; ++d) { 3846 PetscInt offset = -(goff+1) + d, r; 3847 3848 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3849 if (r < 0) r = -(r+2); 3850 if ((r < 0) || (r >= size)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff);CHKERRQ(ierr); valid = PETSC_FALSE;break;} 3851 } 3852 } 3853 } 3854 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3855 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3856 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3857 if (!gvalid) { 3858 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3859 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3860 } 3861 PetscFunctionReturn(0); 3862 } 3863 #endif 3864 3865 /*@ 3866 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3867 3868 Collective on DM 3869 3870 Input Parameter: 3871 . dm - The DM 3872 3873 Output Parameter: 3874 . section - The PetscSection 3875 3876 Level: intermediate 3877 3878 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3879 3880 .seealso: DMSetSection(), DMGetSection() 3881 @*/ 3882 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section) 3883 { 3884 PetscErrorCode ierr; 3885 3886 PetscFunctionBegin; 3887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3888 PetscValidPointer(section, 2); 3889 if (!dm->defaultGlobalSection) { 3890 PetscSection s; 3891 3892 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 3893 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3894 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection"); 3895 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3896 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3897 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3898 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3899 } 3900 *section = dm->defaultGlobalSection; 3901 PetscFunctionReturn(0); 3902 } 3903 3904 /*@ 3905 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3906 3907 Input Parameters: 3908 + dm - The DM 3909 - section - The PetscSection, or NULL 3910 3911 Level: intermediate 3912 3913 Note: Any existing Section will be destroyed 3914 3915 .seealso: DMGetGlobalSection(), DMSetSection() 3916 @*/ 3917 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section) 3918 { 3919 PetscErrorCode ierr; 3920 3921 PetscFunctionBegin; 3922 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3923 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3924 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3925 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3926 dm->defaultGlobalSection = section; 3927 #if defined(PETSC_USE_DEBUG) 3928 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3929 #endif 3930 PetscFunctionReturn(0); 3931 } 3932 3933 /*@ 3934 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3935 it is created from the default PetscSection layouts in the DM. 3936 3937 Input Parameter: 3938 . dm - The DM 3939 3940 Output Parameter: 3941 . sf - The PetscSF 3942 3943 Level: intermediate 3944 3945 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3946 3947 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3948 @*/ 3949 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3950 { 3951 PetscInt nroots; 3952 PetscErrorCode ierr; 3953 3954 PetscFunctionBegin; 3955 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3956 PetscValidPointer(sf, 2); 3957 if (!dm->defaultSF) { 3958 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->defaultSF);CHKERRQ(ierr); 3959 } 3960 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3961 if (nroots < 0) { 3962 PetscSection section, gSection; 3963 3964 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 3965 if (section) { 3966 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr); 3967 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3968 } else { 3969 *sf = NULL; 3970 PetscFunctionReturn(0); 3971 } 3972 } 3973 *sf = dm->defaultSF; 3974 PetscFunctionReturn(0); 3975 } 3976 3977 /*@ 3978 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3979 3980 Input Parameters: 3981 + dm - The DM 3982 - sf - The PetscSF 3983 3984 Level: intermediate 3985 3986 Note: Any previous SF is destroyed 3987 3988 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3989 @*/ 3990 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3991 { 3992 PetscErrorCode ierr; 3993 3994 PetscFunctionBegin; 3995 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3996 if (sf) { 3997 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3998 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3999 } 4000 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 4001 dm->defaultSF = sf; 4002 PetscFunctionReturn(0); 4003 } 4004 4005 /*@C 4006 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 4007 describing the data layout. 4008 4009 Input Parameters: 4010 + dm - The DM 4011 . localSection - PetscSection describing the local data layout 4012 - globalSection - PetscSection describing the global data layout 4013 4014 Level: intermediate 4015 4016 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 4017 @*/ 4018 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 4019 { 4020 MPI_Comm comm; 4021 PetscLayout layout; 4022 const PetscInt *ranges; 4023 PetscInt *local; 4024 PetscSFNode *remote; 4025 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 4026 PetscMPIInt size, rank; 4027 PetscErrorCode ierr; 4028 4029 PetscFunctionBegin; 4030 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4031 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4032 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 4033 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4034 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4035 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4036 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4037 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4038 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4039 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4040 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4041 for (p = pStart; p < pEnd; ++p) { 4042 PetscInt gdof, gcdof; 4043 4044 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4045 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4046 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)); 4047 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4048 } 4049 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 4050 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 4051 for (p = pStart, l = 0; p < pEnd; ++p) { 4052 const PetscInt *cind; 4053 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 4054 4055 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4056 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4057 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4058 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 4059 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4060 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4061 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4062 if (!gdof) continue; /* Censored point */ 4063 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4064 if (gsize != dof-cdof) { 4065 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); 4066 cdof = 0; /* Ignore constraints */ 4067 } 4068 for (d = 0, c = 0; d < dof; ++d) { 4069 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 4070 local[l+d-c] = off+d; 4071 } 4072 if (gdof < 0) { 4073 for (d = 0; d < gsize; ++d, ++l) { 4074 PetscInt offset = -(goff+1) + d, r; 4075 4076 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4077 if (r < 0) r = -(r+2); 4078 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); 4079 remote[l].rank = r; 4080 remote[l].index = offset - ranges[r]; 4081 } 4082 } else { 4083 for (d = 0; d < gsize; ++d, ++l) { 4084 remote[l].rank = rank; 4085 remote[l].index = goff+d - ranges[rank]; 4086 } 4087 } 4088 } 4089 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 4090 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4091 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 4092 PetscFunctionReturn(0); 4093 } 4094 4095 /*@ 4096 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 4097 4098 Input Parameter: 4099 . dm - The DM 4100 4101 Output Parameter: 4102 . sf - The PetscSF 4103 4104 Level: intermediate 4105 4106 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4107 4108 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 4109 @*/ 4110 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 4111 { 4112 PetscFunctionBegin; 4113 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4114 PetscValidPointer(sf, 2); 4115 *sf = dm->sf; 4116 PetscFunctionReturn(0); 4117 } 4118 4119 /*@ 4120 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 4121 4122 Input Parameters: 4123 + dm - The DM 4124 - sf - The PetscSF 4125 4126 Level: intermediate 4127 4128 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 4129 @*/ 4130 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 4131 { 4132 PetscErrorCode ierr; 4133 4134 PetscFunctionBegin; 4135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4136 if (sf) { 4137 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4138 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4139 } 4140 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4141 dm->sf = sf; 4142 PetscFunctionReturn(0); 4143 } 4144 4145 /*@ 4146 DMGetDS - Get the PetscDS 4147 4148 Input Parameter: 4149 . dm - The DM 4150 4151 Output Parameter: 4152 . prob - The PetscDS 4153 4154 Level: developer 4155 4156 .seealso: DMSetDS() 4157 @*/ 4158 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 4159 { 4160 PetscFunctionBegin; 4161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4162 PetscValidPointer(prob, 2); 4163 *prob = dm->prob; 4164 PetscFunctionReturn(0); 4165 } 4166 4167 /*@ 4168 DMSetDS - Set the PetscDS 4169 4170 Input Parameters: 4171 + dm - The DM 4172 - prob - The PetscDS 4173 4174 Level: developer 4175 4176 .seealso: DMGetDS() 4177 @*/ 4178 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 4179 { 4180 PetscInt dimEmbed; 4181 PetscErrorCode ierr; 4182 4183 PetscFunctionBegin; 4184 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4185 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 4186 ierr = PetscObjectReference((PetscObject) prob);CHKERRQ(ierr); 4187 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 4188 dm->prob = prob; 4189 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 4190 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 4191 PetscFunctionReturn(0); 4192 } 4193 4194 static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew) 4195 { 4196 RegionField *tmpr; 4197 PetscInt Nf = dm->Nf, f; 4198 PetscErrorCode ierr; 4199 4200 PetscFunctionBegin; 4201 if (Nf >= NfNew) PetscFunctionReturn(0); 4202 ierr = PetscMalloc1(NfNew, &tmpr);CHKERRQ(ierr); 4203 for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f]; 4204 for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL;} 4205 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4206 dm->Nf = NfNew; 4207 dm->fields = tmpr; 4208 PetscFunctionReturn(0); 4209 } 4210 4211 /*@ 4212 DMClearFields - Remove all fields from the DM 4213 4214 Logically collective on DM 4215 4216 Input Parameter: 4217 . dm - The DM 4218 4219 Level: intermediate 4220 4221 .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField() 4222 @*/ 4223 PetscErrorCode DMClearFields(DM dm) 4224 { 4225 PetscInt f; 4226 PetscErrorCode ierr; 4227 4228 PetscFunctionBegin; 4229 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4230 for (f = 0; f < dm->Nf; ++f) { 4231 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4232 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4233 } 4234 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4235 dm->fields = NULL; 4236 dm->Nf = 0; 4237 PetscFunctionReturn(0); 4238 } 4239 4240 /*@ 4241 DMGetNumFields - Get the number of fields in the DM 4242 4243 Not collective 4244 4245 Input Parameter: 4246 . dm - The DM 4247 4248 Output Parameter: 4249 . Nf - The number of fields 4250 4251 Level: intermediate 4252 4253 .seealso: DMSetNumFields(), DMSetField() 4254 @*/ 4255 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4256 { 4257 PetscFunctionBegin; 4258 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4259 PetscValidPointer(numFields, 2); 4260 *numFields = dm->Nf; 4261 PetscFunctionReturn(0); 4262 } 4263 4264 /*@ 4265 DMSetNumFields - Set the number of fields in the DM 4266 4267 Logically collective on DM 4268 4269 Input Parameters: 4270 + dm - The DM 4271 - Nf - The number of fields 4272 4273 Level: intermediate 4274 4275 .seealso: DMGetNumFields(), DMSetField() 4276 @*/ 4277 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4278 { 4279 PetscInt Nf, f; 4280 PetscErrorCode ierr; 4281 4282 PetscFunctionBegin; 4283 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4284 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4285 for (f = Nf; f < numFields; ++f) { 4286 PetscContainer obj; 4287 4288 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4289 ierr = DMAddField(dm, NULL, (PetscObject) obj);CHKERRQ(ierr); 4290 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4291 } 4292 PetscFunctionReturn(0); 4293 } 4294 4295 /*@ 4296 DMGetField - Return the discretization object for a given DM field 4297 4298 Not collective 4299 4300 Input Parameters: 4301 + dm - The DM 4302 - f - The field number 4303 4304 Output Parameters: 4305 + label - The label indicating the support of the field, or NULL for the entire mesh 4306 - field - The discretization object 4307 4308 Level: intermediate 4309 4310 .seealso: DMAddField(), DMSetField() 4311 @*/ 4312 PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field) 4313 { 4314 PetscFunctionBegin; 4315 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4316 PetscValidPointer(field, 3); 4317 if ((f < 0) || (f >= dm->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, dm->Nf); 4318 if (label) *label = dm->fields[f].label; 4319 if (field) *field = dm->fields[f].disc; 4320 PetscFunctionReturn(0); 4321 } 4322 4323 /*@ 4324 DMSetField - Set the discretization object for a given DM field 4325 4326 Logically collective on DM 4327 4328 Input Parameters: 4329 + dm - The DM 4330 . f - The field number 4331 . label - The label indicating the support of the field, or NULL for the entire mesh 4332 - field - The discretization object 4333 4334 Level: intermediate 4335 4336 .seealso: DMAddField(), DMGetField() 4337 @*/ 4338 PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field) 4339 { 4340 PetscErrorCode ierr; 4341 4342 PetscFunctionBegin; 4343 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4344 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4345 PetscValidHeader(field, 4); 4346 if ((f < 0) || (f >= dm->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, dm->Nf); 4347 ierr = DMFieldEnlarge_Static(dm, f+1);CHKERRQ(ierr); 4348 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4349 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4350 dm->fields[f].label = label; 4351 dm->fields[f].disc = field; 4352 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4353 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4354 PetscFunctionReturn(0); 4355 } 4356 4357 /*@ 4358 DMAddField - Add the discretization object for the given DM field 4359 4360 Logically collective on DM 4361 4362 Input Parameters: 4363 + dm - The DM 4364 . label - The label indicating the support of the field, or NULL for the entire mesh 4365 - field - The discretization object 4366 4367 Level: intermediate 4368 4369 .seealso: DMSetField(), DMGetField() 4370 @*/ 4371 PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field) 4372 { 4373 PetscInt Nf = dm->Nf; 4374 PetscErrorCode ierr; 4375 4376 PetscFunctionBegin; 4377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4378 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4379 PetscValidHeader(field, 3); 4380 ierr = DMFieldEnlarge_Static(dm, Nf+1);CHKERRQ(ierr); 4381 dm->fields[Nf].label = label; 4382 dm->fields[Nf].disc = field; 4383 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4384 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4385 PetscFunctionReturn(0); 4386 } 4387 4388 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 4389 { 4390 DM dm_coord,dmc_coord; 4391 PetscErrorCode ierr; 4392 Vec coords,ccoords; 4393 Mat inject; 4394 PetscFunctionBegin; 4395 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4396 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 4397 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4398 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 4399 if (coords && !ccoords) { 4400 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 4401 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4402 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 4403 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 4404 ierr = MatDestroy(&inject);CHKERRQ(ierr); 4405 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 4406 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4407 } 4408 PetscFunctionReturn(0); 4409 } 4410 4411 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 4412 { 4413 DM dm_coord,subdm_coord; 4414 PetscErrorCode ierr; 4415 Vec coords,ccoords,clcoords; 4416 VecScatter *scat_i,*scat_g; 4417 PetscFunctionBegin; 4418 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4419 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 4420 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4421 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 4422 if (coords && !ccoords) { 4423 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 4424 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4425 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 4426 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 4427 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 4428 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4429 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4430 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4431 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4432 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4433 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4434 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4435 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4436 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4437 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4438 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4439 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4440 } 4441 PetscFunctionReturn(0); 4442 } 4443 4444 /*@ 4445 DMGetDimension - Return the topological dimension of the DM 4446 4447 Not collective 4448 4449 Input Parameter: 4450 . dm - The DM 4451 4452 Output Parameter: 4453 . dim - The topological dimension 4454 4455 Level: beginner 4456 4457 .seealso: DMSetDimension(), DMCreate() 4458 @*/ 4459 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4460 { 4461 PetscFunctionBegin; 4462 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4463 PetscValidPointer(dim, 2); 4464 *dim = dm->dim; 4465 PetscFunctionReturn(0); 4466 } 4467 4468 /*@ 4469 DMSetDimension - Set the topological dimension of the DM 4470 4471 Collective on dm 4472 4473 Input Parameters: 4474 + dm - The DM 4475 - dim - The topological dimension 4476 4477 Level: beginner 4478 4479 .seealso: DMGetDimension(), DMCreate() 4480 @*/ 4481 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4482 { 4483 PetscErrorCode ierr; 4484 4485 PetscFunctionBegin; 4486 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4487 PetscValidLogicalCollectiveInt(dm, dim, 2); 4488 dm->dim = dim; 4489 if (dm->prob->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dim);CHKERRQ(ierr);} 4490 PetscFunctionReturn(0); 4491 } 4492 4493 /*@ 4494 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4495 4496 Collective on DM 4497 4498 Input Parameters: 4499 + dm - the DM 4500 - dim - the dimension 4501 4502 Output Parameters: 4503 + pStart - The first point of the given dimension 4504 . pEnd - The first point following points of the given dimension 4505 4506 Note: 4507 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4508 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4509 then the interval is empty. 4510 4511 Level: intermediate 4512 4513 .keywords: point, Hasse Diagram, dimension 4514 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4515 @*/ 4516 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4517 { 4518 PetscInt d; 4519 PetscErrorCode ierr; 4520 4521 PetscFunctionBegin; 4522 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4523 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4524 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4525 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4526 PetscFunctionReturn(0); 4527 } 4528 4529 /*@ 4530 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4531 4532 Collective on DM 4533 4534 Input Parameters: 4535 + dm - the DM 4536 - c - coordinate vector 4537 4538 Notes: 4539 The coordinates do include those for ghost points, which are in the local vector. 4540 4541 The vector c should be destroyed by the caller. 4542 4543 Level: intermediate 4544 4545 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4546 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4547 @*/ 4548 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4549 { 4550 PetscErrorCode ierr; 4551 4552 PetscFunctionBegin; 4553 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4554 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4555 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4556 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4557 dm->coordinates = c; 4558 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4559 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4560 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4561 PetscFunctionReturn(0); 4562 } 4563 4564 /*@ 4565 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4566 4567 Not collective 4568 4569 Input Parameters: 4570 + dm - the DM 4571 - c - coordinate vector 4572 4573 Notes: 4574 The coordinates of ghost points can be set using DMSetCoordinates() 4575 followed by DMGetCoordinatesLocal(). This is intended to enable the 4576 setting of ghost coordinates outside of the domain. 4577 4578 The vector c should be destroyed by the caller. 4579 4580 Level: intermediate 4581 4582 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4583 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4584 @*/ 4585 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4586 { 4587 PetscErrorCode ierr; 4588 4589 PetscFunctionBegin; 4590 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4591 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4592 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4593 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4594 4595 dm->coordinatesLocal = c; 4596 4597 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4598 PetscFunctionReturn(0); 4599 } 4600 4601 /*@ 4602 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4603 4604 Collective on DM 4605 4606 Input Parameter: 4607 . dm - the DM 4608 4609 Output Parameter: 4610 . c - global coordinate vector 4611 4612 Note: 4613 This is a borrowed reference, so the user should NOT destroy this vector 4614 4615 Each process has only the local coordinates (does NOT have the ghost coordinates). 4616 4617 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4618 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4619 4620 Level: intermediate 4621 4622 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4623 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4624 @*/ 4625 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4626 { 4627 PetscErrorCode ierr; 4628 4629 PetscFunctionBegin; 4630 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4631 PetscValidPointer(c,2); 4632 if (!dm->coordinates && dm->coordinatesLocal) { 4633 DM cdm = NULL; 4634 4635 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4636 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4637 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4638 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4639 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4640 } 4641 *c = dm->coordinates; 4642 PetscFunctionReturn(0); 4643 } 4644 4645 /*@ 4646 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 4647 4648 Collective on DM 4649 4650 Input Parameter: 4651 . dm - the DM 4652 4653 Level: advanced 4654 4655 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4656 .seealso: DMGetCoordinatesLocalNoncollective() 4657 @*/ 4658 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 4659 { 4660 DM cdm = NULL; 4661 PetscErrorCode ierr; 4662 4663 PetscFunctionBegin; 4664 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4665 if (!dm->coordinatesLocal && dm->coordinates) { 4666 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4667 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4668 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4669 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4670 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4671 } 4672 PetscFunctionReturn(0); 4673 } 4674 4675 /*@ 4676 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4677 4678 Collective on DM 4679 4680 Input Parameter: 4681 . dm - the DM 4682 4683 Output Parameter: 4684 . c - coordinate vector 4685 4686 Note: 4687 This is a borrowed reference, so the user should NOT destroy this vector 4688 4689 Each process has the local and ghost coordinates 4690 4691 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4692 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4693 4694 Level: intermediate 4695 4696 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4697 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 4698 @*/ 4699 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4700 { 4701 PetscErrorCode ierr; 4702 4703 PetscFunctionBegin; 4704 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4705 PetscValidPointer(c,2); 4706 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 4707 *c = dm->coordinatesLocal; 4708 PetscFunctionReturn(0); 4709 } 4710 4711 /*@ 4712 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 4713 4714 Not collective 4715 4716 Input Parameter: 4717 . dm - the DM 4718 4719 Output Parameter: 4720 . c - coordinate vector 4721 4722 Level: advanced 4723 4724 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4725 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4726 @*/ 4727 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 4728 { 4729 PetscFunctionBegin; 4730 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4731 PetscValidPointer(c,2); 4732 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 4733 *c = dm->coordinatesLocal; 4734 PetscFunctionReturn(0); 4735 } 4736 4737 /*@ 4738 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 4739 4740 Not collective 4741 4742 Input Parameter: 4743 + dm - the DM 4744 - p - the IS of points whose coordinates will be returned 4745 4746 Output Parameter: 4747 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 4748 - pCoord - the Vec with coordinates of points in p 4749 4750 Note: 4751 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 4752 4753 This creates a new vector, so the user SHOULD destroy this vector 4754 4755 Each process has the local and ghost coordinates 4756 4757 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4758 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4759 4760 Level: advanced 4761 4762 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4763 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4764 @*/ 4765 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 4766 { 4767 PetscSection cs, newcs; 4768 Vec coords; 4769 const PetscScalar *arr; 4770 PetscScalar *newarr=NULL; 4771 PetscInt n; 4772 PetscErrorCode ierr; 4773 4774 PetscFunctionBegin; 4775 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4776 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 4777 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 4778 if (pCoord) PetscValidPointer(pCoord, 4); 4779 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 4780 if (!dm->coordinateDM || !dm->coordinateDM->defaultSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 4781 cs = dm->coordinateDM->defaultSection; 4782 coords = dm->coordinatesLocal; 4783 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 4784 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 4785 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 4786 if (pCoord) { 4787 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 4788 /* set array in two steps to mimic PETSC_OWN_POINTER */ 4789 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 4790 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 4791 } else { 4792 ierr = PetscFree(newarr);CHKERRQ(ierr); 4793 } 4794 if (pCoordSection) {*pCoordSection = newcs;} 4795 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 4796 PetscFunctionReturn(0); 4797 } 4798 4799 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 4800 { 4801 PetscErrorCode ierr; 4802 4803 PetscFunctionBegin; 4804 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4805 PetscValidPointer(field,2); 4806 if (!dm->coordinateField) { 4807 if (dm->ops->createcoordinatefield) { 4808 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 4809 } 4810 } 4811 *field = dm->coordinateField; 4812 PetscFunctionReturn(0); 4813 } 4814 4815 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 4816 { 4817 PetscErrorCode ierr; 4818 4819 PetscFunctionBegin; 4820 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4821 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 4822 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 4823 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 4824 dm->coordinateField = field; 4825 PetscFunctionReturn(0); 4826 } 4827 4828 /*@ 4829 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4830 4831 Collective on DM 4832 4833 Input Parameter: 4834 . dm - the DM 4835 4836 Output Parameter: 4837 . cdm - coordinate DM 4838 4839 Level: intermediate 4840 4841 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4842 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4843 @*/ 4844 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4845 { 4846 PetscErrorCode ierr; 4847 4848 PetscFunctionBegin; 4849 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4850 PetscValidPointer(cdm,2); 4851 if (!dm->coordinateDM) { 4852 DM cdm; 4853 4854 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4855 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 4856 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 4857 * until the call to CreateCoordinateDM) */ 4858 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4859 dm->coordinateDM = cdm; 4860 } 4861 *cdm = dm->coordinateDM; 4862 PetscFunctionReturn(0); 4863 } 4864 4865 /*@ 4866 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4867 4868 Logically Collective on DM 4869 4870 Input Parameters: 4871 + dm - the DM 4872 - cdm - coordinate DM 4873 4874 Level: intermediate 4875 4876 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4877 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4878 @*/ 4879 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4880 { 4881 PetscErrorCode ierr; 4882 4883 PetscFunctionBegin; 4884 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4885 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4886 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 4887 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4888 dm->coordinateDM = cdm; 4889 PetscFunctionReturn(0); 4890 } 4891 4892 /*@ 4893 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4894 4895 Not Collective 4896 4897 Input Parameter: 4898 . dm - The DM object 4899 4900 Output Parameter: 4901 . dim - The embedding dimension 4902 4903 Level: intermediate 4904 4905 .keywords: mesh, coordinates 4906 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetSection(), DMSetSection() 4907 @*/ 4908 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4909 { 4910 PetscFunctionBegin; 4911 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4912 PetscValidPointer(dim, 2); 4913 if (dm->dimEmbed == PETSC_DEFAULT) { 4914 dm->dimEmbed = dm->dim; 4915 } 4916 *dim = dm->dimEmbed; 4917 PetscFunctionReturn(0); 4918 } 4919 4920 /*@ 4921 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4922 4923 Not Collective 4924 4925 Input Parameters: 4926 + dm - The DM object 4927 - dim - The embedding dimension 4928 4929 Level: intermediate 4930 4931 .keywords: mesh, coordinates 4932 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetSection(), DMSetSection() 4933 @*/ 4934 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4935 { 4936 PetscErrorCode ierr; 4937 4938 PetscFunctionBegin; 4939 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4940 dm->dimEmbed = dim; 4941 ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);CHKERRQ(ierr); 4942 PetscFunctionReturn(0); 4943 } 4944 4945 /*@ 4946 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4947 4948 Collective on DM 4949 4950 Input Parameter: 4951 . dm - The DM object 4952 4953 Output Parameter: 4954 . section - The PetscSection object 4955 4956 Level: intermediate 4957 4958 .keywords: mesh, coordinates 4959 .seealso: DMGetCoordinateDM(), DMGetSection(), DMSetSection() 4960 @*/ 4961 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4962 { 4963 DM cdm; 4964 PetscErrorCode ierr; 4965 4966 PetscFunctionBegin; 4967 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4968 PetscValidPointer(section, 2); 4969 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4970 ierr = DMGetSection(cdm, section);CHKERRQ(ierr); 4971 PetscFunctionReturn(0); 4972 } 4973 4974 /*@ 4975 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4976 4977 Not Collective 4978 4979 Input Parameters: 4980 + dm - The DM object 4981 . dim - The embedding dimension, or PETSC_DETERMINE 4982 - section - The PetscSection object 4983 4984 Level: intermediate 4985 4986 .keywords: mesh, coordinates 4987 .seealso: DMGetCoordinateSection(), DMGetSection(), DMSetSection() 4988 @*/ 4989 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4990 { 4991 DM cdm; 4992 PetscErrorCode ierr; 4993 4994 PetscFunctionBegin; 4995 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4996 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4997 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4998 ierr = DMSetSection(cdm, section);CHKERRQ(ierr); 4999 if (dim == PETSC_DETERMINE) { 5000 PetscInt d = PETSC_DEFAULT; 5001 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 5002 5003 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5004 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5005 pStart = PetscMax(vStart, pStart); 5006 pEnd = PetscMin(vEnd, pEnd); 5007 for (v = pStart; v < pEnd; ++v) { 5008 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 5009 if (dd) {d = dd; break;} 5010 } 5011 if (d < 0) d = PETSC_DEFAULT; 5012 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 5013 } 5014 PetscFunctionReturn(0); 5015 } 5016 5017 /*@C 5018 DMGetPeriodicity - Get the description of mesh periodicity 5019 5020 Input Parameters: 5021 . dm - The DM object 5022 5023 Output Parameters: 5024 + per - Whether the DM is periodic or not 5025 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5026 . L - If we assume the mesh is a torus, this is the length of each coordinate 5027 - bd - This describes the type of periodicity in each topological dimension 5028 5029 Level: developer 5030 5031 .seealso: DMGetPeriodicity() 5032 @*/ 5033 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 5034 { 5035 PetscFunctionBegin; 5036 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5037 if (per) *per = dm->periodic; 5038 if (L) *L = dm->L; 5039 if (maxCell) *maxCell = dm->maxCell; 5040 if (bd) *bd = dm->bdtype; 5041 PetscFunctionReturn(0); 5042 } 5043 5044 /*@C 5045 DMSetPeriodicity - Set the description of mesh periodicity 5046 5047 Input Parameters: 5048 + dm - The DM object 5049 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 5050 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5051 . L - If we assume the mesh is a torus, this is the length of each coordinate 5052 - bd - This describes the type of periodicity in each topological dimension 5053 5054 Level: developer 5055 5056 .seealso: DMGetPeriodicity() 5057 @*/ 5058 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 5059 { 5060 PetscInt dim, d; 5061 PetscErrorCode ierr; 5062 5063 PetscFunctionBegin; 5064 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5065 PetscValidLogicalCollectiveBool(dm,per,2); 5066 if (maxCell) { 5067 PetscValidPointer(maxCell,3); 5068 PetscValidPointer(L,4); 5069 PetscValidPointer(bd,5); 5070 } 5071 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 5072 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5073 if (maxCell) { 5074 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 5075 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 5076 } 5077 dm->periodic = per; 5078 PetscFunctionReturn(0); 5079 } 5080 5081 /*@ 5082 DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension. 5083 5084 Input Parameters: 5085 + dm - The DM 5086 . in - The input coordinate point (dim numbers) 5087 - endpoint - Include the endpoint L_i 5088 5089 Output Parameter: 5090 . out - The localized coordinate point 5091 5092 Level: developer 5093 5094 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5095 @*/ 5096 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 5097 { 5098 PetscInt dim, d; 5099 PetscErrorCode ierr; 5100 5101 PetscFunctionBegin; 5102 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 5103 if (!dm->maxCell) { 5104 for (d = 0; d < dim; ++d) out[d] = in[d]; 5105 } else { 5106 if (endpoint) { 5107 for (d = 0; d < dim; ++d) { 5108 if ((PetscAbsReal(PetscRealPart(in[d])/dm->L[d] - PetscFloorReal(PetscRealPart(in[d])/dm->L[d])) < PETSC_SMALL) && (PetscRealPart(in[d])/dm->L[d] > PETSC_SMALL)) { 5109 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 5110 } else { 5111 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5112 } 5113 } 5114 } else { 5115 for (d = 0; d < dim; ++d) { 5116 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5117 } 5118 } 5119 } 5120 PetscFunctionReturn(0); 5121 } 5122 5123 /* 5124 DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 5125 5126 Input Parameters: 5127 + dm - The DM 5128 . dim - The spatial dimension 5129 . anchor - The anchor point, the input point can be no more than maxCell away from it 5130 - in - The input coordinate point (dim numbers) 5131 5132 Output Parameter: 5133 . out - The localized coordinate point 5134 5135 Level: developer 5136 5137 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 5138 5139 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5140 */ 5141 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5142 { 5143 PetscInt d; 5144 5145 PetscFunctionBegin; 5146 if (!dm->maxCell) { 5147 for (d = 0; d < dim; ++d) out[d] = in[d]; 5148 } else { 5149 for (d = 0; d < dim; ++d) { 5150 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5151 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5152 } else { 5153 out[d] = in[d]; 5154 } 5155 } 5156 } 5157 PetscFunctionReturn(0); 5158 } 5159 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 5160 { 5161 PetscInt d; 5162 5163 PetscFunctionBegin; 5164 if (!dm->maxCell) { 5165 for (d = 0; d < dim; ++d) out[d] = in[d]; 5166 } else { 5167 for (d = 0; d < dim; ++d) { 5168 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 5169 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5170 } else { 5171 out[d] = in[d]; 5172 } 5173 } 5174 } 5175 PetscFunctionReturn(0); 5176 } 5177 5178 /* 5179 DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 5180 5181 Input Parameters: 5182 + dm - The DM 5183 . dim - The spatial dimension 5184 . anchor - The anchor point, the input point can be no more than maxCell away from it 5185 . in - The input coordinate delta (dim numbers) 5186 - out - The input coordinate point (dim numbers) 5187 5188 Output Parameter: 5189 . out - The localized coordinate in + out 5190 5191 Level: developer 5192 5193 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 5194 5195 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 5196 */ 5197 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5198 { 5199 PetscInt d; 5200 5201 PetscFunctionBegin; 5202 if (!dm->maxCell) { 5203 for (d = 0; d < dim; ++d) out[d] += in[d]; 5204 } else { 5205 for (d = 0; d < dim; ++d) { 5206 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5207 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5208 } else { 5209 out[d] += in[d]; 5210 } 5211 } 5212 } 5213 PetscFunctionReturn(0); 5214 } 5215 5216 /*@ 5217 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 5218 5219 Not collective 5220 5221 Input Parameter: 5222 . dm - The DM 5223 5224 Output Parameter: 5225 areLocalized - True if localized 5226 5227 Level: developer 5228 5229 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 5230 @*/ 5231 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 5232 { 5233 DM cdm; 5234 PetscSection coordSection; 5235 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 5236 PetscBool isPlex, alreadyLocalized; 5237 PetscErrorCode ierr; 5238 5239 PetscFunctionBegin; 5240 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5241 PetscValidPointer(areLocalized, 2); 5242 *areLocalized = PETSC_FALSE; 5243 5244 /* We need some generic way of refering to cells/vertices */ 5245 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5246 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5247 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 5248 if (!isPlex) SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 5249 5250 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5251 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 5252 alreadyLocalized = PETSC_FALSE; 5253 for (c = cStart; c < cEnd; ++c) { 5254 if (c < sStart || c >= sEnd) continue; 5255 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 5256 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 5257 } 5258 *areLocalized = alreadyLocalized; 5259 PetscFunctionReturn(0); 5260 } 5261 5262 /*@ 5263 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 5264 5265 Collective on dm 5266 5267 Input Parameter: 5268 . dm - The DM 5269 5270 Output Parameter: 5271 areLocalized - True if localized 5272 5273 Level: developer 5274 5275 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 5276 @*/ 5277 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 5278 { 5279 PetscBool localized; 5280 PetscErrorCode ierr; 5281 5282 PetscFunctionBegin; 5283 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5284 PetscValidPointer(areLocalized, 2); 5285 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 5286 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 5287 PetscFunctionReturn(0); 5288 } 5289 5290 /*@ 5291 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 5292 5293 Collective on dm 5294 5295 Input Parameter: 5296 . dm - The DM 5297 5298 Level: developer 5299 5300 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 5301 @*/ 5302 PetscErrorCode DMLocalizeCoordinates(DM dm) 5303 { 5304 DM cdm; 5305 PetscSection coordSection, cSection; 5306 Vec coordinates, cVec; 5307 PetscScalar *coords, *coords2, *anchor, *localized; 5308 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 5309 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 5310 PetscInt maxHeight = 0, h; 5311 PetscInt *pStart = NULL, *pEnd = NULL; 5312 PetscErrorCode ierr; 5313 5314 PetscFunctionBegin; 5315 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5316 if (!dm->periodic) PetscFunctionReturn(0); 5317 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 5318 if (alreadyLocalized) PetscFunctionReturn(0); 5319 5320 /* We need some generic way of refering to cells/vertices */ 5321 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5322 { 5323 PetscBool isplex; 5324 5325 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 5326 if (isplex) { 5327 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5328 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 5329 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5330 pEnd = &pStart[maxHeight + 1]; 5331 newStart = vStart; 5332 newEnd = vEnd; 5333 for (h = 0; h <= maxHeight; h++) { 5334 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 5335 newStart = PetscMin(newStart,pStart[h]); 5336 newEnd = PetscMax(newEnd,pEnd[h]); 5337 } 5338 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 5339 } 5340 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5341 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 5342 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5343 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 5344 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 5345 5346 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 5347 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 5348 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 5349 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 5350 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 5351 5352 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5353 localized = &anchor[bs]; 5354 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 5355 for (h = 0; h <= maxHeight; h++) { 5356 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 5357 5358 for (c = cStart; c < cEnd; ++c) { 5359 PetscScalar *cellCoords = NULL; 5360 PetscInt b; 5361 5362 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 5363 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5364 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 5365 for (d = 0; d < dof/bs; ++d) { 5366 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 5367 for (b = 0; b < bs; b++) { 5368 if (cellCoords[d*bs + b] != localized[b]) break; 5369 } 5370 if (b < bs) break; 5371 } 5372 if (d < dof/bs) { 5373 if (c >= sStart && c < sEnd) { 5374 PetscInt cdof; 5375 5376 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 5377 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 5378 } 5379 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 5380 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 5381 } 5382 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5383 } 5384 } 5385 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 5386 if (alreadyLocalizedGlobal) { 5387 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5388 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 5389 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5390 PetscFunctionReturn(0); 5391 } 5392 for (v = vStart; v < vEnd; ++v) { 5393 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 5394 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 5395 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 5396 } 5397 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 5398 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 5399 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 5400 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 5401 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 5402 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 5403 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 5404 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5405 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 5406 for (v = vStart; v < vEnd; ++v) { 5407 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 5408 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5409 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 5410 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 5411 } 5412 for (h = 0; h <= maxHeight; h++) { 5413 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 5414 5415 for (c = cStart; c < cEnd; ++c) { 5416 PetscScalar *cellCoords = NULL; 5417 PetscInt b, cdof; 5418 5419 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 5420 if (!cdof) continue; 5421 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5422 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 5423 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 5424 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 5425 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5426 } 5427 } 5428 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5429 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5430 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5431 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 5432 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 5433 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 5434 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 5435 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 5436 PetscFunctionReturn(0); 5437 } 5438 5439 /*@ 5440 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 5441 5442 Collective on Vec v (see explanation below) 5443 5444 Input Parameters: 5445 + dm - The DM 5446 . v - The Vec of points 5447 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 5448 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 5449 5450 Output Parameter: 5451 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 5452 - cells - The PetscSF containing the ranks and local indices of the containing points. 5453 5454 5455 Level: developer 5456 5457 Notes: 5458 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 5459 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 5460 5461 If *cellSF is NULL on input, a PetscSF will be created. 5462 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 5463 5464 An array that maps each point to its containing cell can be obtained with 5465 5466 $ const PetscSFNode *cells; 5467 $ PetscInt nFound; 5468 $ const PetscInt *found; 5469 $ 5470 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 5471 5472 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 5473 the index of the cell in its rank's local numbering. 5474 5475 .keywords: point location, mesh 5476 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 5477 @*/ 5478 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 5479 { 5480 PetscErrorCode ierr; 5481 5482 PetscFunctionBegin; 5483 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5484 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 5485 PetscValidPointer(cellSF,4); 5486 if (*cellSF) { 5487 PetscMPIInt result; 5488 5489 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 5490 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 5491 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 5492 } else { 5493 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 5494 } 5495 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5496 if (dm->ops->locatepoints) { 5497 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 5498 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 5499 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5500 PetscFunctionReturn(0); 5501 } 5502 5503 /*@ 5504 DMGetOutputDM - Retrieve the DM associated with the layout for output 5505 5506 Collective on dm 5507 5508 Input Parameter: 5509 . dm - The original DM 5510 5511 Output Parameter: 5512 . odm - The DM which provides the layout for output 5513 5514 Level: intermediate 5515 5516 .seealso: VecView(), DMGetGlobalSection() 5517 @*/ 5518 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 5519 { 5520 PetscSection section; 5521 PetscBool hasConstraints, ghasConstraints; 5522 PetscErrorCode ierr; 5523 5524 PetscFunctionBegin; 5525 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5526 PetscValidPointer(odm,2); 5527 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 5528 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 5529 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 5530 if (!ghasConstraints) { 5531 *odm = dm; 5532 PetscFunctionReturn(0); 5533 } 5534 if (!dm->dmBC) { 5535 PetscDS ds; 5536 PetscSection newSection, gsection; 5537 PetscSF sf; 5538 5539 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 5540 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5541 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 5542 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 5543 ierr = DMSetSection(dm->dmBC, newSection);CHKERRQ(ierr); 5544 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 5545 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 5546 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 5547 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 5548 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 5549 } 5550 *odm = dm->dmBC; 5551 PetscFunctionReturn(0); 5552 } 5553 5554 /*@ 5555 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 5556 5557 Input Parameter: 5558 . dm - The original DM 5559 5560 Output Parameters: 5561 + num - The output sequence number 5562 - val - The output sequence value 5563 5564 Level: intermediate 5565 5566 Note: This is intended for output that should appear in sequence, for instance 5567 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5568 5569 .seealso: VecView() 5570 @*/ 5571 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5572 { 5573 PetscFunctionBegin; 5574 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5575 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5576 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5577 PetscFunctionReturn(0); 5578 } 5579 5580 /*@ 5581 DMSetOutputSequenceNumber - Set the sequence number/value for output 5582 5583 Input Parameters: 5584 + dm - The original DM 5585 . num - The output sequence number 5586 - val - The output sequence value 5587 5588 Level: intermediate 5589 5590 Note: This is intended for output that should appear in sequence, for instance 5591 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5592 5593 .seealso: VecView() 5594 @*/ 5595 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5596 { 5597 PetscFunctionBegin; 5598 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5599 dm->outputSequenceNum = num; 5600 dm->outputSequenceVal = val; 5601 PetscFunctionReturn(0); 5602 } 5603 5604 /*@C 5605 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5606 5607 Input Parameters: 5608 + dm - The original DM 5609 . name - The sequence name 5610 - num - The output sequence number 5611 5612 Output Parameter: 5613 . val - The output sequence value 5614 5615 Level: intermediate 5616 5617 Note: This is intended for output that should appear in sequence, for instance 5618 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5619 5620 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5621 @*/ 5622 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5623 { 5624 PetscBool ishdf5; 5625 PetscErrorCode ierr; 5626 5627 PetscFunctionBegin; 5628 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5629 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5630 PetscValidPointer(val,4); 5631 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5632 if (ishdf5) { 5633 #if defined(PETSC_HAVE_HDF5) 5634 PetscScalar value; 5635 5636 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 5637 *val = PetscRealPart(value); 5638 #endif 5639 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5640 PetscFunctionReturn(0); 5641 } 5642 5643 /*@ 5644 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5645 5646 Not collective 5647 5648 Input Parameter: 5649 . dm - The DM 5650 5651 Output Parameter: 5652 . useNatural - The flag to build the mapping to a natural order during distribution 5653 5654 Level: beginner 5655 5656 .seealso: DMSetUseNatural(), DMCreate() 5657 @*/ 5658 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5659 { 5660 PetscFunctionBegin; 5661 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5662 PetscValidPointer(useNatural, 2); 5663 *useNatural = dm->useNatural; 5664 PetscFunctionReturn(0); 5665 } 5666 5667 /*@ 5668 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 5669 5670 Collective on dm 5671 5672 Input Parameters: 5673 + dm - The DM 5674 - useNatural - The flag to build the mapping to a natural order during distribution 5675 5676 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 5677 5678 Level: beginner 5679 5680 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 5681 @*/ 5682 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5683 { 5684 PetscFunctionBegin; 5685 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5686 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 5687 dm->useNatural = useNatural; 5688 PetscFunctionReturn(0); 5689 } 5690 5691 5692 /*@C 5693 DMCreateLabel - Create a label of the given name if it does not already exist 5694 5695 Not Collective 5696 5697 Input Parameters: 5698 + dm - The DM object 5699 - name - The label name 5700 5701 Level: intermediate 5702 5703 .keywords: mesh 5704 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5705 @*/ 5706 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5707 { 5708 DMLabelLink next = dm->labels->next; 5709 PetscBool flg = PETSC_FALSE; 5710 const char *lname; 5711 PetscErrorCode ierr; 5712 5713 PetscFunctionBegin; 5714 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5715 PetscValidCharPointer(name, 2); 5716 while (next) { 5717 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 5718 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 5719 if (flg) break; 5720 next = next->next; 5721 } 5722 if (!flg) { 5723 DMLabelLink tmpLabel; 5724 5725 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5726 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &tmpLabel->label);CHKERRQ(ierr); 5727 tmpLabel->output = PETSC_TRUE; 5728 tmpLabel->next = dm->labels->next; 5729 dm->labels->next = tmpLabel; 5730 } 5731 PetscFunctionReturn(0); 5732 } 5733 5734 /*@C 5735 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5736 5737 Not Collective 5738 5739 Input Parameters: 5740 + dm - The DM object 5741 . name - The label name 5742 - point - The mesh point 5743 5744 Output Parameter: 5745 . value - The label value for this point, or -1 if the point is not in the label 5746 5747 Level: beginner 5748 5749 .keywords: mesh 5750 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5751 @*/ 5752 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5753 { 5754 DMLabel label; 5755 PetscErrorCode ierr; 5756 5757 PetscFunctionBegin; 5758 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5759 PetscValidCharPointer(name, 2); 5760 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5761 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 5762 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5763 PetscFunctionReturn(0); 5764 } 5765 5766 /*@C 5767 DMSetLabelValue - Add a point to a Sieve Label with given value 5768 5769 Not Collective 5770 5771 Input Parameters: 5772 + dm - The DM object 5773 . name - The label name 5774 . point - The mesh point 5775 - value - The label value for this point 5776 5777 Output Parameter: 5778 5779 Level: beginner 5780 5781 .keywords: mesh 5782 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5783 @*/ 5784 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5785 { 5786 DMLabel label; 5787 PetscErrorCode ierr; 5788 5789 PetscFunctionBegin; 5790 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5791 PetscValidCharPointer(name, 2); 5792 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5793 if (!label) { 5794 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5795 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5796 } 5797 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5798 PetscFunctionReturn(0); 5799 } 5800 5801 /*@C 5802 DMClearLabelValue - Remove a point from a Sieve Label with given value 5803 5804 Not Collective 5805 5806 Input Parameters: 5807 + dm - The DM object 5808 . name - The label name 5809 . point - The mesh point 5810 - value - The label value for this point 5811 5812 Output Parameter: 5813 5814 Level: beginner 5815 5816 .keywords: mesh 5817 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5818 @*/ 5819 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5820 { 5821 DMLabel label; 5822 PetscErrorCode ierr; 5823 5824 PetscFunctionBegin; 5825 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5826 PetscValidCharPointer(name, 2); 5827 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5828 if (!label) PetscFunctionReturn(0); 5829 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5830 PetscFunctionReturn(0); 5831 } 5832 5833 /*@C 5834 DMGetLabelSize - Get the number of different integer ids in a Label 5835 5836 Not Collective 5837 5838 Input Parameters: 5839 + dm - The DM object 5840 - name - The label name 5841 5842 Output Parameter: 5843 . size - The number of different integer ids, or 0 if the label does not exist 5844 5845 Level: beginner 5846 5847 .keywords: mesh 5848 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 5849 @*/ 5850 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5851 { 5852 DMLabel label; 5853 PetscErrorCode ierr; 5854 5855 PetscFunctionBegin; 5856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5857 PetscValidCharPointer(name, 2); 5858 PetscValidPointer(size, 3); 5859 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5860 *size = 0; 5861 if (!label) PetscFunctionReturn(0); 5862 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5863 PetscFunctionReturn(0); 5864 } 5865 5866 /*@C 5867 DMGetLabelIdIS - Get the integer ids in a label 5868 5869 Not Collective 5870 5871 Input Parameters: 5872 + mesh - The DM object 5873 - name - The label name 5874 5875 Output Parameter: 5876 . ids - The integer ids, or NULL if the label does not exist 5877 5878 Level: beginner 5879 5880 .keywords: mesh 5881 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5882 @*/ 5883 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5884 { 5885 DMLabel label; 5886 PetscErrorCode ierr; 5887 5888 PetscFunctionBegin; 5889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5890 PetscValidCharPointer(name, 2); 5891 PetscValidPointer(ids, 3); 5892 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5893 *ids = NULL; 5894 if (label) { 5895 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5896 } else { 5897 /* returning an empty IS */ 5898 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 5899 } 5900 PetscFunctionReturn(0); 5901 } 5902 5903 /*@C 5904 DMGetStratumSize - Get the number of points in a label stratum 5905 5906 Not Collective 5907 5908 Input Parameters: 5909 + dm - The DM object 5910 . name - The label name 5911 - value - The stratum value 5912 5913 Output Parameter: 5914 . size - The stratum size 5915 5916 Level: beginner 5917 5918 .keywords: mesh 5919 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5920 @*/ 5921 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5922 { 5923 DMLabel label; 5924 PetscErrorCode ierr; 5925 5926 PetscFunctionBegin; 5927 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5928 PetscValidCharPointer(name, 2); 5929 PetscValidPointer(size, 4); 5930 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5931 *size = 0; 5932 if (!label) PetscFunctionReturn(0); 5933 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5934 PetscFunctionReturn(0); 5935 } 5936 5937 /*@C 5938 DMGetStratumIS - Get the points in a label stratum 5939 5940 Not Collective 5941 5942 Input Parameters: 5943 + dm - The DM object 5944 . name - The label name 5945 - value - The stratum value 5946 5947 Output Parameter: 5948 . points - The stratum points, or NULL if the label does not exist or does not have that value 5949 5950 Level: beginner 5951 5952 .keywords: mesh 5953 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5954 @*/ 5955 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5956 { 5957 DMLabel label; 5958 PetscErrorCode ierr; 5959 5960 PetscFunctionBegin; 5961 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5962 PetscValidCharPointer(name, 2); 5963 PetscValidPointer(points, 4); 5964 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5965 *points = NULL; 5966 if (!label) PetscFunctionReturn(0); 5967 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5968 PetscFunctionReturn(0); 5969 } 5970 5971 /*@C 5972 DMSetStratumIS - Set the points in a label stratum 5973 5974 Not Collective 5975 5976 Input Parameters: 5977 + dm - The DM object 5978 . name - The label name 5979 . value - The stratum value 5980 - points - The stratum points 5981 5982 Level: beginner 5983 5984 .keywords: mesh 5985 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5986 @*/ 5987 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5988 { 5989 DMLabel label; 5990 PetscErrorCode ierr; 5991 5992 PetscFunctionBegin; 5993 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5994 PetscValidCharPointer(name, 2); 5995 PetscValidPointer(points, 4); 5996 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5997 if (!label) PetscFunctionReturn(0); 5998 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5999 PetscFunctionReturn(0); 6000 } 6001 6002 /*@C 6003 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 6004 6005 Not Collective 6006 6007 Input Parameters: 6008 + dm - The DM object 6009 . name - The label name 6010 - value - The label value for this point 6011 6012 Output Parameter: 6013 6014 Level: beginner 6015 6016 .keywords: mesh 6017 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 6018 @*/ 6019 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 6020 { 6021 DMLabel label; 6022 PetscErrorCode ierr; 6023 6024 PetscFunctionBegin; 6025 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6026 PetscValidCharPointer(name, 2); 6027 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6028 if (!label) PetscFunctionReturn(0); 6029 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 6030 PetscFunctionReturn(0); 6031 } 6032 6033 /*@ 6034 DMGetNumLabels - Return the number of labels defined by the mesh 6035 6036 Not Collective 6037 6038 Input Parameter: 6039 . dm - The DM object 6040 6041 Output Parameter: 6042 . numLabels - the number of Labels 6043 6044 Level: intermediate 6045 6046 .keywords: mesh 6047 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6048 @*/ 6049 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 6050 { 6051 DMLabelLink next = dm->labels->next; 6052 PetscInt n = 0; 6053 6054 PetscFunctionBegin; 6055 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6056 PetscValidPointer(numLabels, 2); 6057 while (next) {++n; next = next->next;} 6058 *numLabels = n; 6059 PetscFunctionReturn(0); 6060 } 6061 6062 /*@C 6063 DMGetLabelName - Return the name of nth label 6064 6065 Not Collective 6066 6067 Input Parameters: 6068 + dm - The DM object 6069 - n - the label number 6070 6071 Output Parameter: 6072 . name - the label name 6073 6074 Level: intermediate 6075 6076 .keywords: mesh 6077 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6078 @*/ 6079 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 6080 { 6081 DMLabelLink next = dm->labels->next; 6082 PetscInt l = 0; 6083 PetscErrorCode ierr; 6084 6085 PetscFunctionBegin; 6086 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6087 PetscValidPointer(name, 3); 6088 while (next) { 6089 if (l == n) { 6090 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 6091 PetscFunctionReturn(0); 6092 } 6093 ++l; 6094 next = next->next; 6095 } 6096 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6097 } 6098 6099 /*@C 6100 DMHasLabel - Determine whether the mesh has a label of a given name 6101 6102 Not Collective 6103 6104 Input Parameters: 6105 + dm - The DM object 6106 - name - The label name 6107 6108 Output Parameter: 6109 . hasLabel - PETSC_TRUE if the label is present 6110 6111 Level: intermediate 6112 6113 .keywords: mesh 6114 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6115 @*/ 6116 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 6117 { 6118 DMLabelLink next = dm->labels->next; 6119 const char *lname; 6120 PetscErrorCode ierr; 6121 6122 PetscFunctionBegin; 6123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6124 PetscValidCharPointer(name, 2); 6125 PetscValidPointer(hasLabel, 3); 6126 *hasLabel = PETSC_FALSE; 6127 while (next) { 6128 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6129 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 6130 if (*hasLabel) break; 6131 next = next->next; 6132 } 6133 PetscFunctionReturn(0); 6134 } 6135 6136 /*@C 6137 DMGetLabel - Return the label of a given name, or NULL 6138 6139 Not Collective 6140 6141 Input Parameters: 6142 + dm - The DM object 6143 - name - The label name 6144 6145 Output Parameter: 6146 . label - The DMLabel, or NULL if the label is absent 6147 6148 Level: intermediate 6149 6150 .keywords: mesh 6151 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6152 @*/ 6153 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 6154 { 6155 DMLabelLink next = dm->labels->next; 6156 PetscBool hasLabel; 6157 const char *lname; 6158 PetscErrorCode ierr; 6159 6160 PetscFunctionBegin; 6161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6162 PetscValidCharPointer(name, 2); 6163 PetscValidPointer(label, 3); 6164 *label = NULL; 6165 while (next) { 6166 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6167 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6168 if (hasLabel) { 6169 *label = next->label; 6170 break; 6171 } 6172 next = next->next; 6173 } 6174 PetscFunctionReturn(0); 6175 } 6176 6177 /*@C 6178 DMGetLabelByNum - Return the nth label 6179 6180 Not Collective 6181 6182 Input Parameters: 6183 + dm - The DM object 6184 - n - the label number 6185 6186 Output Parameter: 6187 . label - the label 6188 6189 Level: intermediate 6190 6191 .keywords: mesh 6192 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6193 @*/ 6194 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 6195 { 6196 DMLabelLink next = dm->labels->next; 6197 PetscInt l = 0; 6198 6199 PetscFunctionBegin; 6200 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6201 PetscValidPointer(label, 3); 6202 while (next) { 6203 if (l == n) { 6204 *label = next->label; 6205 PetscFunctionReturn(0); 6206 } 6207 ++l; 6208 next = next->next; 6209 } 6210 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6211 } 6212 6213 /*@C 6214 DMAddLabel - Add the label to this mesh 6215 6216 Not Collective 6217 6218 Input Parameters: 6219 + dm - The DM object 6220 - label - The DMLabel 6221 6222 Level: developer 6223 6224 .keywords: mesh 6225 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6226 @*/ 6227 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 6228 { 6229 DMLabelLink tmpLabel; 6230 PetscBool hasLabel; 6231 const char *lname; 6232 PetscErrorCode ierr; 6233 6234 PetscFunctionBegin; 6235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6236 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 6237 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 6238 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 6239 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6240 tmpLabel->label = label; 6241 tmpLabel->output = PETSC_TRUE; 6242 tmpLabel->next = dm->labels->next; 6243 dm->labels->next = tmpLabel; 6244 PetscFunctionReturn(0); 6245 } 6246 6247 /*@C 6248 DMRemoveLabel - Remove the label from this mesh 6249 6250 Not Collective 6251 6252 Input Parameters: 6253 + dm - The DM object 6254 - name - The label name 6255 6256 Output Parameter: 6257 . label - The DMLabel, or NULL if the label is absent 6258 6259 Level: developer 6260 6261 .keywords: mesh 6262 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6263 @*/ 6264 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 6265 { 6266 DMLabelLink next = dm->labels->next; 6267 DMLabelLink last = NULL; 6268 PetscBool hasLabel; 6269 const char *lname; 6270 PetscErrorCode ierr; 6271 6272 PetscFunctionBegin; 6273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6274 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 6275 *label = NULL; 6276 if (!hasLabel) PetscFunctionReturn(0); 6277 while (next) { 6278 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6279 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6280 if (hasLabel) { 6281 if (last) last->next = next->next; 6282 else dm->labels->next = next->next; 6283 next->next = NULL; 6284 *label = next->label; 6285 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 6286 if (hasLabel) { 6287 dm->depthLabel = NULL; 6288 } 6289 ierr = PetscFree(next);CHKERRQ(ierr); 6290 break; 6291 } 6292 last = next; 6293 next = next->next; 6294 } 6295 PetscFunctionReturn(0); 6296 } 6297 6298 /*@C 6299 DMGetLabelOutput - Get the output flag for a given label 6300 6301 Not Collective 6302 6303 Input Parameters: 6304 + dm - The DM object 6305 - name - The label name 6306 6307 Output Parameter: 6308 . output - The flag for output 6309 6310 Level: developer 6311 6312 .keywords: mesh 6313 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6314 @*/ 6315 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 6316 { 6317 DMLabelLink next = dm->labels->next; 6318 const char *lname; 6319 PetscErrorCode ierr; 6320 6321 PetscFunctionBegin; 6322 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6323 PetscValidPointer(name, 2); 6324 PetscValidPointer(output, 3); 6325 while (next) { 6326 PetscBool flg; 6327 6328 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6329 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6330 if (flg) {*output = next->output; PetscFunctionReturn(0);} 6331 next = next->next; 6332 } 6333 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 6334 } 6335 6336 /*@C 6337 DMSetLabelOutput - Set the output flag for a given label 6338 6339 Not Collective 6340 6341 Input Parameters: 6342 + dm - The DM object 6343 . name - The label name 6344 - output - The flag for output 6345 6346 Level: developer 6347 6348 .keywords: mesh 6349 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6350 @*/ 6351 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 6352 { 6353 DMLabelLink next = dm->labels->next; 6354 const char *lname; 6355 PetscErrorCode ierr; 6356 6357 PetscFunctionBegin; 6358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6359 PetscValidPointer(name, 2); 6360 while (next) { 6361 PetscBool flg; 6362 6363 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6364 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6365 if (flg) {next->output = output; PetscFunctionReturn(0);} 6366 next = next->next; 6367 } 6368 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 6369 } 6370 6371 6372 /*@ 6373 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 6374 6375 Collective on DM 6376 6377 Input Parameter: 6378 . dmA - The DM object with initial labels 6379 6380 Output Parameter: 6381 . dmB - The DM object with copied labels 6382 6383 Level: intermediate 6384 6385 Note: This is typically used when interpolating or otherwise adding to a mesh 6386 6387 .keywords: mesh 6388 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 6389 @*/ 6390 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 6391 { 6392 PetscInt numLabels, l; 6393 PetscErrorCode ierr; 6394 6395 PetscFunctionBegin; 6396 if (dmA == dmB) PetscFunctionReturn(0); 6397 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 6398 for (l = 0; l < numLabels; ++l) { 6399 DMLabel label, labelNew; 6400 const char *name; 6401 PetscBool flg; 6402 6403 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 6404 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 6405 if (flg) continue; 6406 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 6407 if (flg) continue; 6408 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 6409 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 6410 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 6411 } 6412 PetscFunctionReturn(0); 6413 } 6414 6415 /*@ 6416 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 6417 6418 Input Parameter: 6419 . dm - The DM object 6420 6421 Output Parameter: 6422 . cdm - The coarse DM 6423 6424 Level: intermediate 6425 6426 .seealso: DMSetCoarseDM() 6427 @*/ 6428 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 6429 { 6430 PetscFunctionBegin; 6431 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6432 PetscValidPointer(cdm, 2); 6433 *cdm = dm->coarseMesh; 6434 PetscFunctionReturn(0); 6435 } 6436 6437 /*@ 6438 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 6439 6440 Input Parameters: 6441 + dm - The DM object 6442 - cdm - The coarse DM 6443 6444 Level: intermediate 6445 6446 .seealso: DMGetCoarseDM() 6447 @*/ 6448 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 6449 { 6450 PetscErrorCode ierr; 6451 6452 PetscFunctionBegin; 6453 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6454 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 6455 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6456 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 6457 dm->coarseMesh = cdm; 6458 PetscFunctionReturn(0); 6459 } 6460 6461 /*@ 6462 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 6463 6464 Input Parameter: 6465 . dm - The DM object 6466 6467 Output Parameter: 6468 . fdm - The fine DM 6469 6470 Level: intermediate 6471 6472 .seealso: DMSetFineDM() 6473 @*/ 6474 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 6475 { 6476 PetscFunctionBegin; 6477 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6478 PetscValidPointer(fdm, 2); 6479 *fdm = dm->fineMesh; 6480 PetscFunctionReturn(0); 6481 } 6482 6483 /*@ 6484 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 6485 6486 Input Parameters: 6487 + dm - The DM object 6488 - fdm - The fine DM 6489 6490 Level: intermediate 6491 6492 .seealso: DMGetFineDM() 6493 @*/ 6494 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 6495 { 6496 PetscErrorCode ierr; 6497 6498 PetscFunctionBegin; 6499 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6500 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 6501 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 6502 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 6503 dm->fineMesh = fdm; 6504 PetscFunctionReturn(0); 6505 } 6506 6507 /*=== DMBoundary code ===*/ 6508 6509 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 6510 { 6511 PetscErrorCode ierr; 6512 6513 PetscFunctionBegin; 6514 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 6515 PetscFunctionReturn(0); 6516 } 6517 6518 /*@C 6519 DMAddBoundary - Add a boundary condition to the model 6520 6521 Input Parameters: 6522 + dm - The DM, with a PetscDS that matches the problem being constrained 6523 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6524 . name - The BC name 6525 . labelname - The label defining constrained points 6526 . field - The field to constrain 6527 . numcomps - The number of constrained field components (0 will constrain all fields) 6528 . comps - An array of constrained component numbers 6529 . bcFunc - A pointwise function giving boundary values 6530 . numids - The number of DMLabel ids for constrained points 6531 . ids - An array of ids for constrained points 6532 - ctx - An optional user context for bcFunc 6533 6534 Options Database Keys: 6535 + -bc_<boundary name> <num> - Overrides the boundary ids 6536 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6537 6538 Level: developer 6539 6540 .seealso: DMGetBoundary() 6541 @*/ 6542 PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), PetscInt numids, const PetscInt *ids, void *ctx) 6543 { 6544 PetscErrorCode ierr; 6545 6546 PetscFunctionBegin; 6547 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6548 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 6549 PetscFunctionReturn(0); 6550 } 6551 6552 /*@ 6553 DMGetNumBoundary - Get the number of registered BC 6554 6555 Input Parameters: 6556 . dm - The mesh object 6557 6558 Output Parameters: 6559 . numBd - The number of BC 6560 6561 Level: intermediate 6562 6563 .seealso: DMAddBoundary(), DMGetBoundary() 6564 @*/ 6565 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6566 { 6567 PetscErrorCode ierr; 6568 6569 PetscFunctionBegin; 6570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6571 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 6572 PetscFunctionReturn(0); 6573 } 6574 6575 /*@C 6576 DMGetBoundary - Get a model boundary condition 6577 6578 Input Parameters: 6579 + dm - The mesh object 6580 - bd - The BC number 6581 6582 Output Parameters: 6583 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6584 . name - The BC name 6585 . labelname - The label defining constrained points 6586 . field - The field to constrain 6587 . numcomps - The number of constrained field components 6588 . comps - An array of constrained component numbers 6589 . bcFunc - A pointwise function giving boundary values 6590 . numids - The number of DMLabel ids for constrained points 6591 . ids - An array of ids for constrained points 6592 - ctx - An optional user context for bcFunc 6593 6594 Options Database Keys: 6595 + -bc_<boundary name> <num> - Overrides the boundary ids 6596 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6597 6598 Level: developer 6599 6600 .seealso: DMAddBoundary() 6601 @*/ 6602 PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), PetscInt *numids, const PetscInt **ids, void **ctx) 6603 { 6604 PetscErrorCode ierr; 6605 6606 PetscFunctionBegin; 6607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6608 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6609 PetscFunctionReturn(0); 6610 } 6611 6612 static PetscErrorCode DMPopulateBoundary(DM dm) 6613 { 6614 DMBoundary *lastnext; 6615 DSBoundary dsbound; 6616 PetscErrorCode ierr; 6617 6618 PetscFunctionBegin; 6619 dsbound = dm->prob->boundary; 6620 if (dm->boundary) { 6621 DMBoundary next = dm->boundary; 6622 6623 /* quick check to see if the PetscDS has changed */ 6624 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6625 /* the PetscDS has changed: tear down and rebuild */ 6626 while (next) { 6627 DMBoundary b = next; 6628 6629 next = b->next; 6630 ierr = PetscFree(b);CHKERRQ(ierr); 6631 } 6632 dm->boundary = NULL; 6633 } 6634 6635 lastnext = &(dm->boundary); 6636 while (dsbound) { 6637 DMBoundary dmbound; 6638 6639 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6640 dmbound->dsboundary = dsbound; 6641 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6642 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 6643 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6644 *lastnext = dmbound; 6645 lastnext = &(dmbound->next); 6646 dsbound = dsbound->next; 6647 } 6648 PetscFunctionReturn(0); 6649 } 6650 6651 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6652 { 6653 DMBoundary b; 6654 PetscErrorCode ierr; 6655 6656 PetscFunctionBegin; 6657 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6658 PetscValidPointer(isBd, 3); 6659 *isBd = PETSC_FALSE; 6660 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6661 b = dm->boundary; 6662 while (b && !(*isBd)) { 6663 DMLabel label = b->label; 6664 DSBoundary dsb = b->dsboundary; 6665 6666 if (label) { 6667 PetscInt i; 6668 6669 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6670 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6671 } 6672 } 6673 b = b->next; 6674 } 6675 PetscFunctionReturn(0); 6676 } 6677 6678 /*@C 6679 DMProjectFunction - This projects the given function into the function space provided. 6680 6681 Input Parameters: 6682 + dm - The DM 6683 . time - The time 6684 . funcs - The coordinate functions to evaluate, one per field 6685 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6686 - mode - The insertion mode for values 6687 6688 Output Parameter: 6689 . X - vector 6690 6691 Calling sequence of func: 6692 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6693 6694 + dim - The spatial dimension 6695 . x - The coordinates 6696 . Nf - The number of fields 6697 . u - The output field values 6698 - ctx - optional user-defined function context 6699 6700 Level: developer 6701 6702 .seealso: DMComputeL2Diff() 6703 @*/ 6704 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6705 { 6706 Vec localX; 6707 PetscErrorCode ierr; 6708 6709 PetscFunctionBegin; 6710 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6711 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6712 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6713 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6714 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6715 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6716 PetscFunctionReturn(0); 6717 } 6718 6719 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6720 { 6721 PetscErrorCode ierr; 6722 6723 PetscFunctionBegin; 6724 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6725 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6726 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6727 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6728 PetscFunctionReturn(0); 6729 } 6730 6731 PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6732 { 6733 Vec localX; 6734 PetscErrorCode ierr; 6735 6736 PetscFunctionBegin; 6737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6738 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6739 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6740 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6741 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6742 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6743 PetscFunctionReturn(0); 6744 } 6745 6746 PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6747 { 6748 PetscErrorCode ierr; 6749 6750 PetscFunctionBegin; 6751 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6752 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6753 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6754 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6755 PetscFunctionReturn(0); 6756 } 6757 6758 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6759 void (**funcs)(PetscInt, PetscInt, PetscInt, 6760 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6761 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6762 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6763 InsertMode mode, Vec localX) 6764 { 6765 PetscErrorCode ierr; 6766 6767 PetscFunctionBegin; 6768 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6769 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6770 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6771 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6772 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6773 PetscFunctionReturn(0); 6774 } 6775 6776 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 6777 void (**funcs)(PetscInt, PetscInt, PetscInt, 6778 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6779 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6780 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6781 InsertMode mode, Vec localX) 6782 { 6783 PetscErrorCode ierr; 6784 6785 PetscFunctionBegin; 6786 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6787 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6788 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6789 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6790 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 6791 PetscFunctionReturn(0); 6792 } 6793 6794 /*@C 6795 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6796 6797 Input Parameters: 6798 + dm - The DM 6799 . time - The time 6800 . funcs - The functions to evaluate for each field component 6801 . ctxs - Optional array of contexts to pass to each function, or NULL. 6802 - X - The coefficient vector u_h, a global vector 6803 6804 Output Parameter: 6805 . diff - The diff ||u - u_h||_2 6806 6807 Level: developer 6808 6809 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6810 @*/ 6811 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6812 { 6813 PetscErrorCode ierr; 6814 6815 PetscFunctionBegin; 6816 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6817 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6818 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 6819 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6820 PetscFunctionReturn(0); 6821 } 6822 6823 /*@C 6824 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6825 6826 Input Parameters: 6827 + dm - The DM 6828 , time - The time 6829 . funcs - The gradient functions to evaluate for each field component 6830 . ctxs - Optional array of contexts to pass to each function, or NULL. 6831 . X - The coefficient vector u_h, a global vector 6832 - n - The vector to project along 6833 6834 Output Parameter: 6835 . diff - The diff ||(grad u - grad u_h) . n||_2 6836 6837 Level: developer 6838 6839 .seealso: DMProjectFunction(), DMComputeL2Diff() 6840 @*/ 6841 PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff) 6842 { 6843 PetscErrorCode ierr; 6844 6845 PetscFunctionBegin; 6846 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6847 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6848 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6849 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6850 PetscFunctionReturn(0); 6851 } 6852 6853 /*@C 6854 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6855 6856 Input Parameters: 6857 + dm - The DM 6858 . time - The time 6859 . funcs - The functions to evaluate for each field component 6860 . ctxs - Optional array of contexts to pass to each function, or NULL. 6861 - X - The coefficient vector u_h, a global vector 6862 6863 Output Parameter: 6864 . diff - The array of differences, ||u^f - u^f_h||_2 6865 6866 Level: developer 6867 6868 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6869 @*/ 6870 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6871 { 6872 PetscErrorCode ierr; 6873 6874 PetscFunctionBegin; 6875 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6876 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6877 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6878 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6879 PetscFunctionReturn(0); 6880 } 6881 6882 /*@C 6883 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6884 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6885 6886 Collective on dm 6887 6888 Input parameters: 6889 + dm - the pre-adaptation DM object 6890 - label - label with the flags 6891 6892 Output parameters: 6893 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 6894 6895 Level: intermediate 6896 6897 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 6898 @*/ 6899 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 6900 { 6901 PetscErrorCode ierr; 6902 6903 PetscFunctionBegin; 6904 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6905 PetscValidPointer(label,2); 6906 PetscValidPointer(dmAdapt,3); 6907 *dmAdapt = NULL; 6908 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 6909 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 6910 PetscFunctionReturn(0); 6911 } 6912 6913 /*@C 6914 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 6915 6916 Input Parameters: 6917 + dm - The DM object 6918 . metric - The metric to which the mesh is adapted, defined vertex-wise. 6919 - bdLabel - Label for boundary tags, which will be preserved in the output mesh. bdLabel should be NULL if there is no such label, and should be different from "_boundary_". 6920 6921 Output Parameter: 6922 . dmAdapt - Pointer to the DM object containing the adapted mesh 6923 6924 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 6925 6926 Level: advanced 6927 6928 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 6929 @*/ 6930 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 6931 { 6932 PetscErrorCode ierr; 6933 6934 PetscFunctionBegin; 6935 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6936 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 6937 if (bdLabel) PetscValidPointer(bdLabel, 3); 6938 PetscValidPointer(dmAdapt, 4); 6939 *dmAdapt = NULL; 6940 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 6941 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 6942 PetscFunctionReturn(0); 6943 } 6944 6945 /*@C 6946 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6947 6948 Not Collective 6949 6950 Input Parameter: 6951 . dm - The DM 6952 6953 Output Parameter: 6954 . nranks - the number of neighbours 6955 . ranks - the neighbors ranks 6956 6957 Notes: 6958 Do not free the array, it is freed when the DM is destroyed. 6959 6960 Level: beginner 6961 6962 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6963 @*/ 6964 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6965 { 6966 PetscErrorCode ierr; 6967 6968 PetscFunctionBegin; 6969 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6970 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 6971 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6972 PetscFunctionReturn(0); 6973 } 6974 6975 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6976 6977 /* 6978 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6979 This has be a different function because it requires DM which is not defined in the Mat library 6980 */ 6981 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6982 { 6983 PetscErrorCode ierr; 6984 6985 PetscFunctionBegin; 6986 if (coloring->ctype == IS_COLORING_LOCAL) { 6987 Vec x1local; 6988 DM dm; 6989 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6990 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6991 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6992 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6993 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6994 x1 = x1local; 6995 } 6996 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6997 if (coloring->ctype == IS_COLORING_LOCAL) { 6998 DM dm; 6999 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 7000 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 7001 } 7002 PetscFunctionReturn(0); 7003 } 7004 7005 /*@ 7006 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 7007 7008 Input Parameter: 7009 . coloring - the MatFDColoring object 7010 7011 Developer Notes: 7012 this routine exists because the PETSc Mat library does not know about the DM objects 7013 7014 Level: advanced 7015 7016 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 7017 @*/ 7018 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 7019 { 7020 PetscFunctionBegin; 7021 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 7022 PetscFunctionReturn(0); 7023 } 7024 7025 /*@ 7026 DMGetCompatibility - determine if two DMs are compatible 7027 7028 Collective 7029 7030 Input Parameters: 7031 + dm - the first DM 7032 - dm2 - the second DM 7033 7034 Output Parameters: 7035 + compatible - whether or not the two DMs are compatible 7036 - set - whether or not the compatible value was set 7037 7038 Notes: 7039 Two DMs are deemed compatible if they represent the same parallel decomposition 7040 of the same topology. This implies that the the section (field data) on one 7041 "makes sense" with respect to the topology and parallel decomposition of the other. 7042 Loosely speaking, compatibile DMs represent the same domain, with the same parallel 7043 decomposition, with different data. 7044 7045 Typically, one would confirm compatibility if intending to simultaneously iterate 7046 over a pair of vectors obtained from different DMs. 7047 7048 For example, two DMDA objects are compatible if they have the same local 7049 and global sizes and the same stencil width. They can have different numbers 7050 of degrees of freedom per node. Thus, one could use the node numbering from 7051 either DM in bounds for a loop over vectors derived from either DM. 7052 7053 Consider the operation of summing data living on a 2-dof DMDA to data living 7054 on a 1-dof DMDA, which should be compatible, as in the following snippet. 7055 .vb 7056 ... 7057 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 7058 if (set && compatible) { 7059 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7060 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7061 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n);CHKERRQ(ierr); 7062 for (j=y; j<y+n; ++j) { 7063 for (i=x; i<x+m, ++i) { 7064 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 7065 } 7066 } 7067 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7068 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7069 } else { 7070 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 7071 } 7072 ... 7073 .ve 7074 7075 Checking compatibility might be expensive for a given implementation of DM, 7076 or might be impossible to unambiguously confirm or deny. For this reason, 7077 this function may decline to determine compatibility, and hence users should 7078 always check the "set" output parameter. 7079 7080 A DM is always compatible with itself. 7081 7082 In the current implementation, DMs which live on "unequal" communicators 7083 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 7084 incompatible. 7085 7086 This function is labeled "Collective," as information about all subdomains 7087 is required on each rank. However, in DM implementations which store all this 7088 information locally, this function may be merely "Logically Collective". 7089 7090 Developer Notes: 7091 Compatibility is assumed to be a symmetric concept; if DM A is compatible with DM B, 7092 the DM B is compatible with DM A. Thus, this function checks the implementations 7093 of both dm and dm2 (if they are of different types), attempting to determine 7094 compatibility. It is left to DM implementers to ensure that symmetry is 7095 preserved. The simplest way to do this is, when implementing type-specific 7096 logic for this function, to check for existing logic in the implementation 7097 of other DM types and let *set = PETSC_FALSE if found; the logic of this 7098 function will then call that logic. 7099 7100 Level: advanced 7101 7102 .seealso: DM, DMDACreateCompatibleDMDA() 7103 @*/ 7104 7105 PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set) 7106 { 7107 PetscErrorCode ierr; 7108 PetscMPIInt compareResult; 7109 DMType type,type2; 7110 PetscBool sameType; 7111 7112 PetscFunctionBegin; 7113 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7114 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 7115 7116 /* Declare a DM compatible with itself */ 7117 if (dm == dm2) { 7118 *set = PETSC_TRUE; 7119 *compatible = PETSC_TRUE; 7120 PetscFunctionReturn(0); 7121 } 7122 7123 /* Declare a DM incompatible with a DM that lives on an "unequal" 7124 communicator. Note that this does not preclude compatibility with 7125 DMs living on "congruent" or "similar" communicators, but this must be 7126 determined by the implementation-specific logic */ 7127 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 7128 if (compareResult == MPI_UNEQUAL) { 7129 *set = PETSC_TRUE; 7130 *compatible = PETSC_FALSE; 7131 PetscFunctionReturn(0); 7132 } 7133 7134 /* Pass to the implementation-specific routine, if one exists. */ 7135 if (dm->ops->getcompatibility) { 7136 ierr = (*dm->ops->getcompatibility)(dm,dm2,compatible,set);CHKERRQ(ierr); 7137 if (*set) { 7138 PetscFunctionReturn(0); 7139 } 7140 } 7141 7142 /* If dm and dm2 are of different types, then attempt to check compatibility 7143 with an implementation of this function from dm2 */ 7144 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 7145 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 7146 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 7147 if (!sameType && dm2->ops->getcompatibility) { 7148 ierr = (*dm2->ops->getcompatibility)(dm2,dm,compatible,set);CHKERRQ(ierr); /* Note argument order */ 7149 } else { 7150 *set = PETSC_FALSE; 7151 } 7152 PetscFunctionReturn(0); 7153 } 7154