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