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