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