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