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