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