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