1 #include <petscvec.h> 2 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 3 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 4 #include <petsc/private/petscdsimpl.h> /*I "petscds.h" I*/ 5 #include <petscdmplex.h> 6 #include <petscdmfield.h> 7 #include <petscsf.h> 8 #include <petscds.h> 9 10 #ifdef PETSC_HAVE_LIBCEED 11 #include <petscfeceed.h> 12 #endif 13 14 #if defined(PETSC_HAVE_VALGRIND) 15 # include <valgrind/memcheck.h> 16 #endif 17 18 PetscClassId DM_CLASSID; 19 PetscClassId DMLABEL_CLASSID; 20 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction, DM_CreateInjection, DM_CreateMatrix, DM_Load, DM_AdaptInterpolator; 21 22 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DMBoundaryType","DM_BOUNDARY_", NULL}; 23 const char *const DMBoundaryConditionTypes[] = {"INVALID","ESSENTIAL","NATURAL","INVALID","INVALID","ESSENTIAL_FIELD","NATURAL_FIELD","INVALID","INVALID","ESSENTIAL_BD_FIELD","NATURAL_RIEMANN","DMBoundaryConditionType","DM_BC_", NULL}; 24 const char *const DMPolytopeTypes[] = {"vertex", "segment", "tensor_segment", "triangle", "quadrilateral", "tensor_quad", "tetrahedron", "hexahedron", "triangular_prism", "tensor_triangular_prism", "tensor_quadrilateral_prism", "pyramid", "FV_ghost_cell", "interior_ghost_cell", "unknown", "invalid", "DMPolytopeType", "DM_POLYTOPE_", NULL}; 25 const char *const DMCopyLabelsModes[] = {"replace","keep","fail","DMCopyLabelsMode","DM_COPY_LABELS_", NULL}; 26 27 /*@ 28 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 29 30 If you never call DMSetType() it will generate an 31 error when you try to use the vector. 32 33 Collective 34 35 Input Parameter: 36 . comm - The communicator for the DM object 37 38 Output Parameter: 39 . dm - The DM object 40 41 Level: beginner 42 43 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK 44 @*/ 45 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 46 { 47 DM v; 48 PetscDS ds; 49 PetscErrorCode ierr; 50 51 PetscFunctionBegin; 52 PetscValidPointer(dm,2); 53 *dm = NULL; 54 ierr = DMInitializePackage();CHKERRQ(ierr); 55 56 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 57 58 v->setupcalled = PETSC_FALSE; 59 v->setfromoptionscalled = PETSC_FALSE; 60 v->ltogmap = NULL; 61 v->bind_below = 0; 62 v->bs = 1; 63 v->coloringtype = IS_COLORING_GLOBAL; 64 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 65 ierr = PetscSFCreate(comm, &v->sectionSF);CHKERRQ(ierr); 66 v->labels = NULL; 67 v->adjacency[0] = PETSC_FALSE; 68 v->adjacency[1] = PETSC_TRUE; 69 v->depthLabel = NULL; 70 v->celltypeLabel = NULL; 71 v->localSection = NULL; 72 v->globalSection = NULL; 73 v->defaultConstraintSection = NULL; 74 v->defaultConstraintMat = NULL; 75 v->L = NULL; 76 v->maxCell = NULL; 77 v->bdtype = NULL; 78 v->dimEmbed = PETSC_DEFAULT; 79 v->dim = PETSC_DETERMINE; 80 { 81 PetscInt i; 82 for (i = 0; i < 10; ++i) { 83 v->nullspaceConstructors[i] = NULL; 84 v->nearnullspaceConstructors[i] = NULL; 85 } 86 } 87 ierr = PetscDSCreate(PETSC_COMM_SELF, &ds);CHKERRQ(ierr); 88 ierr = DMSetRegionDS(v, NULL, NULL, ds);CHKERRQ(ierr); 89 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 90 ierr = PetscHMapAuxCreate(&v->auxData);CHKERRQ(ierr); 91 v->dmBC = NULL; 92 v->coarseMesh = NULL; 93 v->outputSequenceNum = -1; 94 v->outputSequenceVal = 0.0; 95 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 96 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 97 98 *dm = v; 99 PetscFunctionReturn(0); 100 } 101 102 /*@ 103 DMClone - Creates a DM object with the same topology as the original. 104 105 Collective 106 107 Input Parameter: 108 . dm - The original DM object 109 110 Output Parameter: 111 . newdm - The new DM object 112 113 Level: beginner 114 115 Notes: 116 For some DM implementations this is a shallow clone, the result of which may share (referent counted) information with its parent. For example, 117 DMClone() applied to a DMPLEX object will result in a new DMPLEX that shares the topology with the original DMPLEX. It does not 118 share the PetscSection of the original DM. 119 120 The clone is considered set up iff the original is. 121 122 .seealso: DMDestroy(), DMCreate(), DMSetType(), DMSetLocalSection(), DMSetGlobalSection() 123 124 @*/ 125 PetscErrorCode DMClone(DM dm, DM *newdm) 126 { 127 PetscSF sf; 128 Vec coords; 129 void *ctx; 130 PetscInt dim, cdim; 131 PetscErrorCode ierr; 132 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 135 PetscValidPointer(newdm,2); 136 ierr = DMCreate(PetscObjectComm((PetscObject) dm), newdm);CHKERRQ(ierr); 137 ierr = DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE, DM_COPY_LABELS_FAIL);CHKERRQ(ierr); 138 (*newdm)->leveldown = dm->leveldown; 139 (*newdm)->levelup = dm->levelup; 140 (*newdm)->prealloc_only = dm->prealloc_only; 141 ierr = PetscFree((*newdm)->vectype);CHKERRQ(ierr); 142 ierr = PetscStrallocpy(dm->vectype,(char**)&(*newdm)->vectype);CHKERRQ(ierr); 143 ierr = PetscFree((*newdm)->mattype);CHKERRQ(ierr); 144 ierr = PetscStrallocpy(dm->mattype,(char**)&(*newdm)->mattype);CHKERRQ(ierr); 145 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 146 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr); 147 if (dm->ops->clone) { 148 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 149 } 150 (*newdm)->setupcalled = dm->setupcalled; 151 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 152 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 153 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 154 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 155 if (dm->coordinateDM) { 156 DM ncdm; 157 PetscSection cs; 158 PetscInt pEnd = -1, pEndMax = -1; 159 160 ierr = DMGetLocalSection(dm->coordinateDM, &cs);CHKERRQ(ierr); 161 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);} 162 ierr = MPI_Allreduce(&pEnd,&pEndMax,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 163 if (pEndMax >= 0) { 164 ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr); 165 ierr = DMCopyDisc(dm->coordinateDM, ncdm);CHKERRQ(ierr); 166 ierr = DMSetLocalSection(ncdm, cs);CHKERRQ(ierr); 167 ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr); 168 ierr = DMDestroy(&ncdm);CHKERRQ(ierr); 169 } 170 } 171 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 172 ierr = DMSetCoordinateDim(*newdm, cdim);CHKERRQ(ierr); 173 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 174 if (coords) { 175 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 176 } else { 177 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 178 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 179 } 180 { 181 PetscBool isper; 182 const PetscReal *maxCell, *L; 183 const DMBoundaryType *bd; 184 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 185 ierr = DMSetPeriodicity(*newdm, isper, maxCell, L, bd);CHKERRQ(ierr); 186 } 187 { 188 PetscBool useCone, useClosure; 189 190 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure);CHKERRQ(ierr); 191 ierr = DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 192 } 193 PetscFunctionReturn(0); 194 } 195 196 /*@C 197 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 198 199 Logically Collective on da 200 201 Input Parameter: 202 + da - initial distributed array 203 . ctype - the vector type, currently either VECSTANDARD, VECCUDA, or VECVIENNACL 204 205 Options Database: 206 . -dm_vec_type ctype 207 208 Level: intermediate 209 210 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType(), DMSetMatType(), DMGetMatType() 211 @*/ 212 PetscErrorCode DMSetVecType(DM da,VecType ctype) 213 { 214 PetscErrorCode ierr; 215 216 PetscFunctionBegin; 217 PetscValidHeaderSpecific(da,DM_CLASSID,1); 218 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 219 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 220 PetscFunctionReturn(0); 221 } 222 223 /*@C 224 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 225 226 Logically Collective on da 227 228 Input Parameter: 229 . da - initial distributed array 230 231 Output Parameter: 232 . ctype - the vector type 233 234 Level: intermediate 235 236 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMSetMatType(), DMGetMatType(), DMSetVecType() 237 @*/ 238 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 239 { 240 PetscFunctionBegin; 241 PetscValidHeaderSpecific(da,DM_CLASSID,1); 242 *ctype = da->vectype; 243 PetscFunctionReturn(0); 244 } 245 246 /*@ 247 VecGetDM - Gets the DM defining the data layout of the vector 248 249 Not collective 250 251 Input Parameter: 252 . v - The Vec 253 254 Output Parameter: 255 . dm - The DM 256 257 Level: intermediate 258 259 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 260 @*/ 261 PetscErrorCode VecGetDM(Vec v, DM *dm) 262 { 263 PetscErrorCode ierr; 264 265 PetscFunctionBegin; 266 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 267 PetscValidPointer(dm,2); 268 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 269 PetscFunctionReturn(0); 270 } 271 272 /*@ 273 VecSetDM - Sets the DM defining the data layout of the vector. 274 275 Not collective 276 277 Input Parameters: 278 + v - The Vec 279 - dm - The DM 280 281 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. 282 283 Level: intermediate 284 285 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 286 @*/ 287 PetscErrorCode VecSetDM(Vec v, DM dm) 288 { 289 PetscErrorCode ierr; 290 291 PetscFunctionBegin; 292 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 293 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 294 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 295 PetscFunctionReturn(0); 296 } 297 298 /*@C 299 DMSetISColoringType - Sets the type of coloring, global or local, that is created by the DM 300 301 Logically Collective on dm 302 303 Input Parameters: 304 + dm - the DM context 305 - ctype - the matrix type 306 307 Options Database: 308 . -dm_is_coloring_type - global or local 309 310 Level: intermediate 311 312 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), 313 DMGetISColoringType() 314 @*/ 315 PetscErrorCode DMSetISColoringType(DM dm,ISColoringType ctype) 316 { 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 319 dm->coloringtype = ctype; 320 PetscFunctionReturn(0); 321 } 322 323 /*@C 324 DMGetISColoringType - Gets the type of coloring, global or local, that is created by the DM 325 326 Logically Collective on dm 327 328 Input Parameter: 329 . dm - the DM context 330 331 Output Parameter: 332 . ctype - the matrix type 333 334 Options Database: 335 . -dm_is_coloring_type - global or local 336 337 Level: intermediate 338 339 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), 340 DMGetISColoringType() 341 @*/ 342 PetscErrorCode DMGetISColoringType(DM dm,ISColoringType *ctype) 343 { 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 346 *ctype = dm->coloringtype; 347 PetscFunctionReturn(0); 348 } 349 350 /*@C 351 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 352 353 Logically Collective on dm 354 355 Input Parameters: 356 + dm - the DM context 357 - ctype - the matrix type 358 359 Options Database: 360 . -dm_mat_type ctype 361 362 Level: intermediate 363 364 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType(), DMSetMatType(), DMGetMatType() 365 @*/ 366 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 367 { 368 PetscErrorCode ierr; 369 370 PetscFunctionBegin; 371 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 372 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 373 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 374 PetscFunctionReturn(0); 375 } 376 377 /*@C 378 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 379 380 Logically Collective on dm 381 382 Input Parameter: 383 . dm - the DM context 384 385 Output Parameter: 386 . ctype - the matrix type 387 388 Options Database: 389 . -dm_mat_type ctype 390 391 Level: intermediate 392 393 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType(), DMSetMatType(), DMGetMatType() 394 @*/ 395 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 396 { 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 399 *ctype = dm->mattype; 400 PetscFunctionReturn(0); 401 } 402 403 /*@ 404 MatGetDM - Gets the DM defining the data layout of the matrix 405 406 Not collective 407 408 Input Parameter: 409 . A - The Mat 410 411 Output Parameter: 412 . dm - The DM 413 414 Level: intermediate 415 416 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 417 the Mat through a PetscObjectCompose() operation 418 419 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 420 @*/ 421 PetscErrorCode MatGetDM(Mat A, DM *dm) 422 { 423 PetscErrorCode ierr; 424 425 PetscFunctionBegin; 426 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 427 PetscValidPointer(dm,2); 428 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 429 PetscFunctionReturn(0); 430 } 431 432 /*@ 433 MatSetDM - Sets the DM defining the data layout of the matrix 434 435 Not collective 436 437 Input Parameters: 438 + A - The Mat 439 - dm - The DM 440 441 Level: intermediate 442 443 Developer Note: Since the Mat class doesn't know about the DM class the DM object is associated with 444 the Mat through a PetscObjectCompose() operation 445 446 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 447 @*/ 448 PetscErrorCode MatSetDM(Mat A, DM dm) 449 { 450 PetscErrorCode ierr; 451 452 PetscFunctionBegin; 453 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 454 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 455 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 456 PetscFunctionReturn(0); 457 } 458 459 /*@C 460 DMSetOptionsPrefix - Sets the prefix used for searching for all 461 DM options in the database. 462 463 Logically Collective on dm 464 465 Input Parameters: 466 + da - the DM context 467 - prefix - the prefix to prepend to all option names 468 469 Notes: 470 A hyphen (-) must NOT be given at the beginning of the prefix name. 471 The first character of all runtime options is AUTOMATICALLY the hyphen. 472 473 Level: advanced 474 475 .seealso: DMSetFromOptions() 476 @*/ 477 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 478 { 479 PetscErrorCode ierr; 480 481 PetscFunctionBegin; 482 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 483 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 484 if (dm->sf) { 485 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr); 486 } 487 if (dm->sectionSF) { 488 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF,prefix);CHKERRQ(ierr); 489 } 490 PetscFunctionReturn(0); 491 } 492 493 /*@C 494 DMAppendOptionsPrefix - Appends to the prefix used for searching for all 495 DM options in the database. 496 497 Logically Collective on dm 498 499 Input Parameters: 500 + dm - the DM context 501 - prefix - the prefix string to prepend to all DM option requests 502 503 Notes: 504 A hyphen (-) must NOT be given at the beginning of the prefix name. 505 The first character of all runtime options is AUTOMATICALLY the hyphen. 506 507 Level: advanced 508 509 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix() 510 @*/ 511 PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[]) 512 { 513 PetscErrorCode ierr; 514 515 PetscFunctionBegin; 516 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 517 ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 518 PetscFunctionReturn(0); 519 } 520 521 /*@C 522 DMGetOptionsPrefix - Gets the prefix used for searching for all 523 DM options in the database. 524 525 Not Collective 526 527 Input Parameters: 528 . dm - the DM context 529 530 Output Parameters: 531 . prefix - pointer to the prefix string used is returned 532 533 Notes: 534 On the fortran side, the user should pass in a string 'prefix' of 535 sufficient length to hold the prefix. 536 537 Level: advanced 538 539 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix() 540 @*/ 541 PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[]) 542 { 543 PetscErrorCode ierr; 544 545 PetscFunctionBegin; 546 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 547 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 548 PetscFunctionReturn(0); 549 } 550 551 static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct) 552 { 553 PetscInt refct = ((PetscObject) dm)->refct; 554 PetscErrorCode ierr; 555 556 PetscFunctionBegin; 557 *ncrefct = 0; 558 if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) { 559 refct--; 560 if (recurseCoarse) { 561 PetscInt coarseCount; 562 563 ierr = DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);CHKERRQ(ierr); 564 refct += coarseCount; 565 } 566 } 567 if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) { 568 refct--; 569 if (recurseFine) { 570 PetscInt fineCount; 571 572 ierr = DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);CHKERRQ(ierr); 573 refct += fineCount; 574 } 575 } 576 *ncrefct = refct; 577 PetscFunctionReturn(0); 578 } 579 580 PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm) 581 { 582 DMLabelLink next = dm->labels; 583 PetscErrorCode ierr; 584 585 PetscFunctionBegin; 586 /* destroy the labels */ 587 while (next) { 588 DMLabelLink tmp = next->next; 589 590 if (next->label == dm->depthLabel) dm->depthLabel = NULL; 591 if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL; 592 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 593 ierr = PetscFree(next);CHKERRQ(ierr); 594 next = tmp; 595 } 596 dm->labels = NULL; 597 PetscFunctionReturn(0); 598 } 599 600 /*@C 601 DMDestroy - Destroys a vector packer or DM. 602 603 Collective on dm 604 605 Input Parameter: 606 . dm - the DM object to destroy 607 608 Level: developer 609 610 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 611 612 @*/ 613 PetscErrorCode DMDestroy(DM *dm) 614 { 615 PetscInt cnt; 616 DMNamedVecLink nlink,nnext; 617 PetscErrorCode ierr; 618 619 PetscFunctionBegin; 620 if (!*dm) PetscFunctionReturn(0); 621 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 622 623 /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */ 624 ierr = DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);CHKERRQ(ierr); 625 --((PetscObject)(*dm))->refct; 626 if (--cnt > 0) {*dm = NULL; PetscFunctionReturn(0);} 627 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 628 ((PetscObject)(*dm))->refct = 0; 629 630 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 631 ierr = DMClearLocalVectors(*dm);CHKERRQ(ierr); 632 633 nnext=(*dm)->namedglobal; 634 (*dm)->namedglobal = NULL; 635 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 636 nnext = nlink->next; 637 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 638 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 639 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 640 ierr = PetscFree(nlink);CHKERRQ(ierr); 641 } 642 nnext=(*dm)->namedlocal; 643 (*dm)->namedlocal = NULL; 644 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 645 nnext = nlink->next; 646 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 647 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 648 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 649 ierr = PetscFree(nlink);CHKERRQ(ierr); 650 } 651 652 /* Destroy the list of hooks */ 653 { 654 DMCoarsenHookLink link,next; 655 for (link=(*dm)->coarsenhook; link; link=next) { 656 next = link->next; 657 ierr = PetscFree(link);CHKERRQ(ierr); 658 } 659 (*dm)->coarsenhook = NULL; 660 } 661 { 662 DMRefineHookLink link,next; 663 for (link=(*dm)->refinehook; link; link=next) { 664 next = link->next; 665 ierr = PetscFree(link);CHKERRQ(ierr); 666 } 667 (*dm)->refinehook = NULL; 668 } 669 { 670 DMSubDomainHookLink link,next; 671 for (link=(*dm)->subdomainhook; link; link=next) { 672 next = link->next; 673 ierr = PetscFree(link);CHKERRQ(ierr); 674 } 675 (*dm)->subdomainhook = NULL; 676 } 677 { 678 DMGlobalToLocalHookLink link,next; 679 for (link=(*dm)->gtolhook; link; link=next) { 680 next = link->next; 681 ierr = PetscFree(link);CHKERRQ(ierr); 682 } 683 (*dm)->gtolhook = NULL; 684 } 685 { 686 DMLocalToGlobalHookLink link,next; 687 for (link=(*dm)->ltoghook; link; link=next) { 688 next = link->next; 689 ierr = PetscFree(link);CHKERRQ(ierr); 690 } 691 (*dm)->ltoghook = NULL; 692 } 693 /* Destroy the work arrays */ 694 { 695 DMWorkLink link,next; 696 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 697 for (link=(*dm)->workin; link; link=next) { 698 next = link->next; 699 ierr = PetscFree(link->mem);CHKERRQ(ierr); 700 ierr = PetscFree(link);CHKERRQ(ierr); 701 } 702 (*dm)->workin = NULL; 703 } 704 /* destroy the labels */ 705 ierr = DMDestroyLabelLinkList_Internal(*dm);CHKERRQ(ierr); 706 /* destroy the fields */ 707 ierr = DMClearFields(*dm);CHKERRQ(ierr); 708 /* destroy the boundaries */ 709 { 710 DMBoundary next = (*dm)->boundary; 711 while (next) { 712 DMBoundary b = next; 713 714 next = b->next; 715 ierr = PetscFree(b);CHKERRQ(ierr); 716 } 717 } 718 719 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 720 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 721 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 722 723 if ((*dm)->ctx && (*dm)->ctxdestroy) { 724 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 725 } 726 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 727 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 728 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 729 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 730 731 ierr = PetscSectionDestroy(&(*dm)->localSection);CHKERRQ(ierr); 732 ierr = PetscSectionDestroy(&(*dm)->globalSection);CHKERRQ(ierr); 733 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 734 ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr); 735 ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr); 736 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 737 ierr = PetscSFDestroy(&(*dm)->sectionSF);CHKERRQ(ierr); 738 if ((*dm)->useNatural) { 739 if ((*dm)->sfNatural) { 740 ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr); 741 } 742 ierr = PetscObjectDereference((PetscObject) (*dm)->sfMigration);CHKERRQ(ierr); 743 } 744 { 745 Vec *auxData; 746 PetscInt n, i, off = 0; 747 748 ierr = PetscHMapAuxGetSize((*dm)->auxData, &n);CHKERRQ(ierr); 749 ierr = PetscMalloc1(n, &auxData);CHKERRQ(ierr); 750 ierr = PetscHMapAuxGetVals((*dm)->auxData, &off, auxData);CHKERRQ(ierr); 751 for (i = 0; i < n; ++i) {ierr = VecDestroy(&auxData[i]);CHKERRQ(ierr);} 752 ierr = PetscFree(auxData);CHKERRQ(ierr); 753 ierr = PetscHMapAuxDestroy(&(*dm)->auxData);CHKERRQ(ierr); 754 } 755 if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) { 756 ierr = DMSetFineDM((*dm)->coarseMesh,NULL);CHKERRQ(ierr); 757 } 758 759 ierr = DMDestroy(&(*dm)->coarseMesh);CHKERRQ(ierr); 760 if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) { 761 ierr = DMSetCoarseDM((*dm)->fineMesh,NULL);CHKERRQ(ierr); 762 } 763 ierr = DMDestroy(&(*dm)->fineMesh);CHKERRQ(ierr); 764 ierr = DMFieldDestroy(&(*dm)->coordinateField);CHKERRQ(ierr); 765 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 766 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 767 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 768 ierr = PetscFree((*dm)->L);CHKERRQ(ierr); 769 ierr = PetscFree((*dm)->maxCell);CHKERRQ(ierr); 770 ierr = PetscFree((*dm)->bdtype);CHKERRQ(ierr); 771 if ((*dm)->transformDestroy) {ierr = (*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx);CHKERRQ(ierr);} 772 ierr = DMDestroy(&(*dm)->transformDM);CHKERRQ(ierr); 773 ierr = VecDestroy(&(*dm)->transform);CHKERRQ(ierr); 774 775 ierr = DMClearDS(*dm);CHKERRQ(ierr); 776 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 777 /* if memory was published with SAWs then destroy it */ 778 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 779 780 if ((*dm)->ops->destroy) { 781 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 782 } 783 ierr = DMMonitorCancel(*dm);CHKERRQ(ierr); 784 #ifdef PETSC_HAVE_LIBCEED 785 ierr = CeedElemRestrictionDestroy(&(*dm)->ceedERestrict);CHKERRQ(ierr); 786 ierr = CeedDestroy(&(*dm)->ceed);CHKERRQ(ierr); 787 #endif 788 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 789 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 790 PetscFunctionReturn(0); 791 } 792 793 /*@ 794 DMSetUp - sets up the data structures inside a DM object 795 796 Collective on dm 797 798 Input Parameter: 799 . dm - the DM object to setup 800 801 Level: developer 802 803 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 804 805 @*/ 806 PetscErrorCode DMSetUp(DM dm) 807 { 808 PetscErrorCode ierr; 809 810 PetscFunctionBegin; 811 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 812 if (dm->setupcalled) PetscFunctionReturn(0); 813 if (dm->ops->setup) { 814 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 815 } 816 dm->setupcalled = PETSC_TRUE; 817 PetscFunctionReturn(0); 818 } 819 820 /*@ 821 DMSetFromOptions - sets parameters in a DM from the options database 822 823 Collective on dm 824 825 Input Parameter: 826 . dm - the DM object to set options for 827 828 Options Database: 829 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 830 . -dm_vec_type <type> - type of vector to create inside DM 831 . -dm_mat_type <type> - type of matrix to create inside DM 832 . -dm_is_coloring_type - <global or local> 833 - -dm_bind_below <n> - bind (force execution on CPU) for Vec and Mat objects with local size (number of vector entries or matrix rows) below n; currently only supported for DMDA 834 835 DMPLEX Specific creation options 836 + -dm_plex_filename <str> - File containing a mesh 837 . -dm_plex_boundary_filename <str> - File containing a mesh boundary 838 . -dm_plex_shape <shape> - The domain shape, such as DM_SHAPE_BOX, DM_SHAPE_SPHERE, etc. 839 . -dm_plex_cell <ct> - Cell shape 840 . -dm_plex_reference_cell_domain <bool> - Use a reference cell domain 841 . -dm_plex_dim <dim> - Set the topological dimension 842 . -dm_plex_simplex <bool> - PETSC_TRUE for simplex elements, PETSC_FALSE for tensor elements 843 . -dm_plex_interpolate <bool> - PETSC_TRUE turns on topological interpolation (creating edges and faces) 844 . -dm_plex_scale <sc> - Scale factor for mesh coordinates 845 . -dm_plex_box_faces <m,n,p> - Number of faces along each dimension 846 . -dm_plex_box_lower <x,y,z> - Specify lower-left-bottom coordinates for the box 847 . -dm_plex_box_upper <x,y,z> - Specify upper-right-top coordinates for the box 848 . -dm_plex_box_bd <bx,by,bz> - Specify the DMBoundaryType for each direction 849 . -dm_plex_sphere_radius <r> - The sphere radius 850 . -dm_plex_ball_radius <r> - Radius of the ball 851 . -dm_plex_cylinder_bd <bz> - Boundary type in the z direction 852 . -dm_plex_cylinder_num_wedges <n> - Number of wedges around the cylinder 853 . -dm_refine_pre <n> - The number of refinements before distribution 854 . -dm_refine_uniform_pre <bool> - Flag for uniform refinement before distribution 855 . -dm_refine_volume_limit_pre <v> - The maximum cell volume after refinement before distribution 856 . -dm_refine <n> - The number of refinements after distribution 857 . -dm_extrude <l> - Acticate extrusion and apecify the number of layers to extrude 858 . -dm_plex_transform_extrude_thickness <t> - The total thickness of extruded layers 859 . -dm_plex_transform_extrude_use_tensor <bool> - Use tensor cells when extruding 860 . -dm_plex_transform_extrude_symmetric <bool> - Extrude layers symmetrically about the surface 861 . -dm_plex_transform_extrude_normal <n0,...,nd> - Specify the extrusion direction 862 . -dm_plex_transform_extrude_thicknesses <t0,...,tl> - Specify thickness of each layer 863 . -dm_plex_create_fv_ghost_cells - Flag to create finite volume ghost cells on the boundary 864 . -dm_plex_fv_ghost_cells_label <name> - Label name for ghost cells boundary 865 . -dm_distribute <bool> - Flag to redistribute a mesh among processes 866 . -dm_distribute_overlap <n> - The size of the overlap halo 867 . -dm_plex_adj_cone <bool> - Set adjacency direction 868 - -dm_plex_adj_closure <bool> - Set adjacency size 869 870 DMPLEX Specific Checks 871 + -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric - DMPlexCheckSymmetry() 872 . -dm_plex_check_skeleton - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - DMPlexCheckSkeleton() 873 . -dm_plex_check_faces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type - DMPlexCheckFaces() 874 . -dm_plex_check_geometry - Check that cells have positive volume - DMPlexCheckGeometry() 875 . -dm_plex_check_pointsf - Check some necessary conditions for PointSF - DMPlexCheckPointSF() 876 . -dm_plex_check_interface_cones - Check points on inter-partition interfaces have conforming order of cone points - DMPlexCheckInterfaceCones() 877 - -dm_plex_check_all - Perform all the checks above 878 879 Level: intermediate 880 881 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), 882 DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces(), DMPlexCheckGeometry(), DMPlexCheckPointSF(), DMPlexCheckInterfaceCones() 883 884 @*/ 885 PetscErrorCode DMSetFromOptions(DM dm) 886 { 887 char typeName[256]; 888 PetscBool flg; 889 PetscErrorCode ierr; 890 891 PetscFunctionBegin; 892 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 893 dm->setfromoptionscalled = PETSC_TRUE; 894 if (dm->sf) {ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr);} 895 if (dm->sectionSF) {ierr = PetscSFSetFromOptions(dm->sectionSF);CHKERRQ(ierr);} 896 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 897 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 898 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 899 if (flg) { 900 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 901 } 902 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 903 if (flg) { 904 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 905 } 906 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","DMSetISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 907 ierr = PetscOptionsInt("-dm_bind_below","Set the size threshold (in entries) below which the Vec is bound to the CPU","VecBindToCPU",dm->bind_below,&dm->bind_below,&flg);CHKERRQ(ierr); 908 if (dm->ops->setfromoptions) { 909 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr); 910 } 911 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 912 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr); 913 ierr = PetscOptionsEnd();CHKERRQ(ierr); 914 PetscFunctionReturn(0); 915 } 916 917 /*@C 918 DMViewFromOptions - View from Options 919 920 Collective on DM 921 922 Input Parameters: 923 + dm - the DM object 924 . obj - Optional object 925 - name - command line option 926 927 Level: intermediate 928 .seealso: DM, DMView, PetscObjectViewFromOptions(), DMCreate() 929 @*/ 930 PetscErrorCode DMViewFromOptions(DM dm,PetscObject obj,const char name[]) 931 { 932 PetscErrorCode ierr; 933 934 PetscFunctionBegin; 935 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 936 ierr = PetscObjectViewFromOptions((PetscObject)dm,obj,name);CHKERRQ(ierr); 937 PetscFunctionReturn(0); 938 } 939 940 /*@C 941 DMView - Views a DM 942 943 Collective on dm 944 945 Input Parameters: 946 + dm - the DM object to view 947 - v - the viewer 948 949 Level: beginner 950 951 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 952 953 @*/ 954 PetscErrorCode DMView(DM dm,PetscViewer v) 955 { 956 PetscErrorCode ierr; 957 PetscBool isbinary; 958 PetscMPIInt size; 959 PetscViewerFormat format; 960 961 PetscFunctionBegin; 962 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 963 if (!v) { 964 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 965 } 966 PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,2); 967 /* Ideally, we would like to have this test on. 968 However, it currently breaks socket viz via GLVis. 969 During DMView(parallel_mesh,glvis_viewer), each 970 process opens a sequential ASCII socket to visualize 971 the local mesh, and PetscObjectView(dm,local_socket) 972 is internally called inside VecView_GLVis, incurring 973 in an error here */ 974 /* PetscCheckSameComm(dm,1,v,2); */ 975 ierr = PetscViewerCheckWritable(v);CHKERRQ(ierr); 976 977 ierr = PetscViewerGetFormat(v,&format);CHKERRQ(ierr); 978 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRMPI(ierr); 979 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0); 980 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 981 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 982 if (isbinary) { 983 PetscInt classid = DM_FILE_CLASSID; 984 char type[256]; 985 986 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT);CHKERRQ(ierr); 987 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 988 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR);CHKERRQ(ierr); 989 } 990 if (dm->ops->view) { 991 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 992 } 993 PetscFunctionReturn(0); 994 } 995 996 /*@ 997 DMCreateGlobalVector - Creates a global vector from a DM object 998 999 Collective on dm 1000 1001 Input Parameter: 1002 . dm - the DM object 1003 1004 Output Parameter: 1005 . vec - the global vector 1006 1007 Level: beginner 1008 1009 .seealso DMCreateLocalVector(), DMGetGlobalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1010 1011 @*/ 1012 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 1013 { 1014 PetscErrorCode ierr; 1015 1016 PetscFunctionBegin; 1017 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1018 PetscValidPointer(vec,2); 1019 if (!dm->ops->createglobalvector) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateGlobalVector",((PetscObject)dm)->type_name); 1020 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 1021 if (PetscDefined(USE_DEBUG)) { 1022 DM vdm; 1023 1024 ierr = VecGetDM(*vec,&vdm);CHKERRQ(ierr); 1025 if (!vdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the vector\n",((PetscObject)dm)->type_name); 1026 } 1027 PetscFunctionReturn(0); 1028 } 1029 1030 /*@ 1031 DMCreateLocalVector - Creates a local vector from a DM object 1032 1033 Not Collective 1034 1035 Input Parameter: 1036 . dm - the DM object 1037 1038 Output Parameter: 1039 . vec - the local vector 1040 1041 Level: beginner 1042 1043 .seealso DMCreateGlobalVector(), DMGetLocalVector(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1044 1045 @*/ 1046 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 1047 { 1048 PetscErrorCode ierr; 1049 1050 PetscFunctionBegin; 1051 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1052 PetscValidPointer(vec,2); 1053 if (!dm->ops->createlocalvector) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateLocalVector",((PetscObject)dm)->type_name); 1054 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 1055 if (PetscDefined(USE_DEBUG)) { 1056 DM vdm; 1057 1058 ierr = VecGetDM(*vec,&vdm);CHKERRQ(ierr); 1059 if (!vdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"DM type '%s' did not attach the DM to the vector\n",((PetscObject)dm)->type_name); 1060 } 1061 PetscFunctionReturn(0); 1062 } 1063 1064 /*@ 1065 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 1066 1067 Collective on dm 1068 1069 Input Parameter: 1070 . dm - the DM that provides the mapping 1071 1072 Output Parameter: 1073 . ltog - the mapping 1074 1075 Level: intermediate 1076 1077 Notes: 1078 This mapping can then be used by VecSetLocalToGlobalMapping() or 1079 MatSetLocalToGlobalMapping(). 1080 1081 .seealso: DMCreateLocalVector() 1082 @*/ 1083 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 1084 { 1085 PetscInt bs = -1, bsLocal[2], bsMinMax[2]; 1086 PetscErrorCode ierr; 1087 1088 PetscFunctionBegin; 1089 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1090 PetscValidPointer(ltog,2); 1091 if (!dm->ltogmap) { 1092 PetscSection section, sectionGlobal; 1093 1094 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1095 if (section) { 1096 const PetscInt *cdofs; 1097 PetscInt *ltog; 1098 PetscInt pStart, pEnd, n, p, k, l; 1099 1100 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1101 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 1102 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 1103 ierr = PetscMalloc1(n, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 1104 for (p = pStart, l = 0; p < pEnd; ++p) { 1105 PetscInt bdof, cdof, dof, off, c, cind = 0; 1106 1107 /* Should probably use constrained dofs */ 1108 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 1109 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 1110 ierr = PetscSectionGetConstraintIndices(section, p, &cdofs);CHKERRQ(ierr); 1111 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 1112 /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */ 1113 bdof = cdof && (dof-cdof) ? 1 : dof; 1114 if (dof) { 1115 if (bs < 0) {bs = bdof;} 1116 else if (bs != bdof) {bs = 1;} 1117 } 1118 for (c = 0; c < dof; ++c, ++l) { 1119 if ((cind < cdof) && (c == cdofs[cind])) ltog[l] = off < 0 ? off-c : off+c; 1120 else ltog[l] = (off < 0 ? -(off+1) : off) + c; 1121 } 1122 } 1123 /* Must have same blocksize on all procs (some might have no points) */ 1124 bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 1125 ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 1126 if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 1127 else {bs = bsMinMax[0];} 1128 bs = bs < 0 ? 1 : bs; 1129 /* Must reduce indices by blocksize */ 1130 if (bs > 1) { 1131 for (l = 0, k = 0; l < n; l += bs, ++k) ltog[k] = ltog[l]/bs; 1132 n /= bs; 1133 } 1134 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 1135 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 1136 } else { 1137 if (!dm->ops->getlocaltoglobalmapping) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetLocalToGlobalMapping",((PetscObject)dm)->type_name); 1138 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 1139 } 1140 } 1141 *ltog = dm->ltogmap; 1142 PetscFunctionReturn(0); 1143 } 1144 1145 /*@ 1146 DMGetBlockSize - Gets the inherent block size associated with a DM 1147 1148 Not Collective 1149 1150 Input Parameter: 1151 . dm - the DM with block structure 1152 1153 Output Parameter: 1154 . bs - the block size, 1 implies no exploitable block structure 1155 1156 Level: intermediate 1157 1158 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 1159 @*/ 1160 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 1161 { 1162 PetscFunctionBegin; 1163 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1164 PetscValidIntPointer(bs,2); 1165 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 1166 *bs = dm->bs; 1167 PetscFunctionReturn(0); 1168 } 1169 1170 /*@C 1171 DMCreateInterpolation - Gets interpolation matrix between two DM objects 1172 1173 Collective on dmc 1174 1175 Input Parameters: 1176 + dmc - the DM object 1177 - dmf - the second, finer DM object 1178 1179 Output Parameters: 1180 + mat - the interpolation 1181 - vec - the scaling (optional) 1182 1183 Level: developer 1184 1185 Notes: 1186 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1187 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1188 1189 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 1190 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 1191 1192 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolationScale() 1193 1194 @*/ 1195 PetscErrorCode DMCreateInterpolation(DM dmc,DM dmf,Mat *mat,Vec *vec) 1196 { 1197 PetscErrorCode ierr; 1198 1199 PetscFunctionBegin; 1200 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 1201 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 1202 PetscValidPointer(mat,3); 1203 if (!dmc->ops->createinterpolation) SETERRQ1(PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInterpolation",((PetscObject)dmc)->type_name); 1204 ierr = PetscLogEventBegin(DM_CreateInterpolation,dmc,dmf,0,0);CHKERRQ(ierr); 1205 ierr = (*dmc->ops->createinterpolation)(dmc,dmf,mat,vec);CHKERRQ(ierr); 1206 ierr = PetscLogEventEnd(DM_CreateInterpolation,dmc,dmf,0,0);CHKERRQ(ierr); 1207 PetscFunctionReturn(0); 1208 } 1209 1210 /*@ 1211 DMCreateInterpolationScale - Forms L = 1/(R*1) such that diag(L)*R preserves scale and is thus suitable for state (versus residual) restriction. 1212 1213 Input Parameters: 1214 + dac - DM that defines a coarse mesh 1215 . daf - DM that defines a fine mesh 1216 - mat - the restriction (or interpolation operator) from fine to coarse 1217 1218 Output Parameter: 1219 . scale - the scaled vector 1220 1221 Level: developer 1222 1223 .seealso: DMCreateInterpolation() 1224 1225 @*/ 1226 PetscErrorCode DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale) 1227 { 1228 PetscErrorCode ierr; 1229 Vec fine; 1230 PetscScalar one = 1.0; 1231 #if defined(PETSC_HAVE_CUDA) 1232 PetscBool flg; 1233 #endif 1234 1235 PetscFunctionBegin; 1236 ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr); 1237 ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr); 1238 ierr = VecSet(fine,one);CHKERRQ(ierr); 1239 #if defined(PETSC_HAVE_CUDA) 1240 /* If the 'fine' Vec is bound to the CPU, it makes sense to bind 'mat' as well. 1241 * Note that we only do this for the CUDA case, right now, but if we add support for MatMultTranspose() via ViennaCL, 1242 * we'll need to do it for that case, too.*/ 1243 if (fine->bindingpropagates) { 1244 ierr = VecBoundToCPU(fine,&flg);CHKERRQ(ierr); 1245 ierr = MatSetBindingPropagates(mat,PETSC_TRUE);CHKERRQ(ierr); 1246 ierr = MatBindToCPU(mat,flg);CHKERRQ(ierr); 1247 } 1248 #endif 1249 ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr); 1250 ierr = VecDestroy(&fine);CHKERRQ(ierr); 1251 ierr = VecReciprocal(*scale);CHKERRQ(ierr); 1252 PetscFunctionReturn(0); 1253 } 1254 1255 /*@ 1256 DMCreateRestriction - Gets restriction matrix between two DM objects 1257 1258 Collective on dmc 1259 1260 Input Parameters: 1261 + dmc - the DM object 1262 - dmf - the second, finer DM object 1263 1264 Output Parameter: 1265 . mat - the restriction 1266 1267 Level: developer 1268 1269 Notes: 1270 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1271 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1272 1273 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation() 1274 1275 @*/ 1276 PetscErrorCode DMCreateRestriction(DM dmc,DM dmf,Mat *mat) 1277 { 1278 PetscErrorCode ierr; 1279 1280 PetscFunctionBegin; 1281 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 1282 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 1283 PetscValidPointer(mat,3); 1284 if (!dmc->ops->createrestriction) SETERRQ1(PetscObjectComm((PetscObject)dmc),PETSC_ERR_SUP,"DM type %s does not implement DMCreateRestriction",((PetscObject)dmc)->type_name); 1285 ierr = PetscLogEventBegin(DM_CreateRestriction,dmc,dmf,0,0);CHKERRQ(ierr); 1286 ierr = (*dmc->ops->createrestriction)(dmc,dmf,mat);CHKERRQ(ierr); 1287 ierr = PetscLogEventEnd(DM_CreateRestriction,dmc,dmf,0,0);CHKERRQ(ierr); 1288 PetscFunctionReturn(0); 1289 } 1290 1291 /*@ 1292 DMCreateInjection - Gets injection matrix between two DM objects 1293 1294 Collective on dac 1295 1296 Input Parameters: 1297 + dac - the DM object 1298 - daf - the second, finer DM object 1299 1300 Output Parameter: 1301 . mat - the injection 1302 1303 Level: developer 1304 1305 Notes: 1306 For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1307 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 1308 1309 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 1310 1311 @*/ 1312 PetscErrorCode DMCreateInjection(DM dac,DM daf,Mat *mat) 1313 { 1314 PetscErrorCode ierr; 1315 1316 PetscFunctionBegin; 1317 PetscValidHeaderSpecific(dac,DM_CLASSID,1); 1318 PetscValidHeaderSpecific(daf,DM_CLASSID,2); 1319 PetscValidPointer(mat,3); 1320 if (!dac->ops->createinjection) SETERRQ1(PetscObjectComm((PetscObject)dac),PETSC_ERR_SUP,"DM type %s does not implement DMCreateInjection",((PetscObject)dac)->type_name); 1321 ierr = PetscLogEventBegin(DM_CreateInjection,dac,daf,0,0);CHKERRQ(ierr); 1322 ierr = (*dac->ops->createinjection)(dac,daf,mat);CHKERRQ(ierr); 1323 ierr = PetscLogEventEnd(DM_CreateInjection,dac,daf,0,0);CHKERRQ(ierr); 1324 PetscFunctionReturn(0); 1325 } 1326 1327 /*@ 1328 DMCreateMassMatrix - Gets mass matrix between two DM objects, M_ij = \int \phi_i \psi_j 1329 1330 Collective on dac 1331 1332 Input Parameters: 1333 + dac - the DM object 1334 - daf - the second, finer DM object 1335 1336 Output Parameter: 1337 . mat - the interpolation 1338 1339 Level: developer 1340 1341 .seealso DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction(), DMCreateInterpolation(), DMCreateInjection() 1342 @*/ 1343 PetscErrorCode DMCreateMassMatrix(DM dac, DM daf, Mat *mat) 1344 { 1345 PetscErrorCode ierr; 1346 1347 PetscFunctionBegin; 1348 PetscValidHeaderSpecific(dac, DM_CLASSID, 1); 1349 PetscValidHeaderSpecific(daf, DM_CLASSID, 2); 1350 PetscValidPointer(mat,3); 1351 if (!dac->ops->createmassmatrix) SETERRQ1(PetscObjectComm((PetscObject)dac),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMassMatrix",((PetscObject)dac)->type_name); 1352 ierr = (*dac->ops->createmassmatrix)(dac, daf, mat);CHKERRQ(ierr); 1353 PetscFunctionReturn(0); 1354 } 1355 1356 /*@ 1357 DMCreateColoring - Gets coloring for a DM 1358 1359 Collective on dm 1360 1361 Input Parameters: 1362 + dm - the DM object 1363 - ctype - IS_COLORING_LOCAL or IS_COLORING_GLOBAL 1364 1365 Output Parameter: 1366 . coloring - the coloring 1367 1368 Notes: 1369 Coloring of matrices can be computed directly from the sparse matrix nonzero structure via the MatColoring object or from the mesh from which the 1370 matrix comes from. In general using the mesh produces a more optimal coloring (fewer colors). 1371 1372 This produces a coloring with the distance of 2, see MatSetColoringDistance() which can be used for efficiently computing Jacobians with MatFDColoringCreate() 1373 1374 Level: developer 1375 1376 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType(), MatColoring, MatFDColoringCreate() 1377 1378 @*/ 1379 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 1380 { 1381 PetscErrorCode ierr; 1382 1383 PetscFunctionBegin; 1384 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1385 PetscValidPointer(coloring,3); 1386 if (!dm->ops->getcoloring) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateColoring",((PetscObject)dm)->type_name); 1387 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 1388 PetscFunctionReturn(0); 1389 } 1390 1391 /*@ 1392 DMCreateMatrix - Gets empty Jacobian for a DM 1393 1394 Collective on dm 1395 1396 Input Parameter: 1397 . dm - the DM object 1398 1399 Output Parameter: 1400 . mat - the empty Jacobian 1401 1402 Level: beginner 1403 1404 Options Database Keys: 1405 . -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 1406 1407 Notes: 1408 This properly preallocates the number of nonzeros in the sparse matrix so you 1409 do not need to do it yourself. 1410 1411 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 1412 the nonzero pattern call DMSetMatrixPreallocateOnly() 1413 1414 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 1415 internally by PETSc. 1416 1417 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 1418 the indices for the global numbering for DMDAs which is complicated. 1419 1420 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 1421 1422 @*/ 1423 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 1424 { 1425 PetscErrorCode ierr; 1426 1427 PetscFunctionBegin; 1428 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1429 PetscValidPointer(mat,2); 1430 if (!dm->ops->creatematrix) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateMatrix",((PetscObject)dm)->type_name); 1431 ierr = MatInitializePackage();CHKERRQ(ierr); 1432 ierr = PetscLogEventBegin(DM_CreateMatrix,0,0,0,0);CHKERRQ(ierr); 1433 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 1434 if (PetscDefined(USE_DEBUG)) { 1435 DM mdm; 1436 1437 ierr = MatGetDM(*mat,&mdm);CHKERRQ(ierr); 1438 if (!mdm) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"DM type '%s' did not attach the DM to the matrix\n",((PetscObject)dm)->type_name); 1439 } 1440 /* Handle nullspace and near nullspace */ 1441 if (dm->Nf) { 1442 MatNullSpace nullSpace; 1443 PetscInt Nf, f; 1444 1445 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 1446 for (f = 0; f < Nf; ++f) { 1447 if (dm->nullspaceConstructors[f]) { 1448 ierr = (*dm->nullspaceConstructors[f])(dm, f, f, &nullSpace);CHKERRQ(ierr); 1449 ierr = MatSetNullSpace(*mat, nullSpace);CHKERRQ(ierr); 1450 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1451 break; 1452 } 1453 } 1454 for (f = 0; f < Nf; ++f) { 1455 if (dm->nearnullspaceConstructors[f]) { 1456 ierr = (*dm->nearnullspaceConstructors[f])(dm, f, f, &nullSpace);CHKERRQ(ierr); 1457 ierr = MatSetNearNullSpace(*mat, nullSpace);CHKERRQ(ierr); 1458 ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1459 } 1460 } 1461 } 1462 ierr = PetscLogEventEnd(DM_CreateMatrix,0,0,0,0);CHKERRQ(ierr); 1463 PetscFunctionReturn(0); 1464 } 1465 1466 /*@ 1467 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 1468 preallocated but the nonzero structure and zero values will not be set. 1469 1470 Logically Collective on dm 1471 1472 Input Parameters: 1473 + dm - the DM 1474 - only - PETSC_TRUE if only want preallocation 1475 1476 Level: developer 1477 1478 Options Database Keys: 1479 . -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 1480 1481 .seealso DMCreateMatrix(), DMSetMatrixStructureOnly() 1482 @*/ 1483 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 1484 { 1485 PetscFunctionBegin; 1486 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1487 dm->prealloc_only = only; 1488 PetscFunctionReturn(0); 1489 } 1490 1491 /*@ 1492 DMSetMatrixStructureOnly - When DMCreateMatrix() is called, the matrix structure will be created 1493 but the array for values will not be allocated. 1494 1495 Logically Collective on dm 1496 1497 Input Parameters: 1498 + dm - the DM 1499 - only - PETSC_TRUE if only want matrix stucture 1500 1501 Level: developer 1502 .seealso DMCreateMatrix(), DMSetMatrixPreallocateOnly() 1503 @*/ 1504 PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only) 1505 { 1506 PetscFunctionBegin; 1507 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1508 dm->structure_only = only; 1509 PetscFunctionReturn(0); 1510 } 1511 1512 /*@C 1513 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1514 1515 Not Collective 1516 1517 Input Parameters: 1518 + dm - the DM object 1519 . count - The minimum size 1520 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT) 1521 1522 Output Parameter: 1523 . array - the work array 1524 1525 Level: developer 1526 1527 .seealso DMDestroy(), DMCreate() 1528 @*/ 1529 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem) 1530 { 1531 PetscErrorCode ierr; 1532 DMWorkLink link; 1533 PetscMPIInt dsize; 1534 1535 PetscFunctionBegin; 1536 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1537 PetscValidPointer(mem,4); 1538 if (dm->workin) { 1539 link = dm->workin; 1540 dm->workin = dm->workin->next; 1541 } else { 1542 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1543 } 1544 ierr = MPI_Type_size(dtype,&dsize);CHKERRMPI(ierr); 1545 if (((size_t)dsize*count) > link->bytes) { 1546 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1547 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr); 1548 link->bytes = dsize*count; 1549 } 1550 link->next = dm->workout; 1551 dm->workout = link; 1552 #if defined(PETSC_HAVE_VALGRIND) 1553 VALGRIND_MAKE_MEM_NOACCESS((char*)link->mem + (size_t)dsize*count, link->bytes - (size_t)dsize*count); 1554 VALGRIND_MAKE_MEM_UNDEFINED(link->mem, (size_t)dsize*count); 1555 #endif 1556 *(void**)mem = link->mem; 1557 PetscFunctionReturn(0); 1558 } 1559 1560 /*@C 1561 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1562 1563 Not Collective 1564 1565 Input Parameters: 1566 + dm - the DM object 1567 . count - The minimum size 1568 - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT 1569 1570 Output Parameter: 1571 . array - the work array 1572 1573 Level: developer 1574 1575 Developer Notes: 1576 count and dtype are ignored, they are only needed for DMGetWorkArray() 1577 .seealso DMDestroy(), DMCreate() 1578 @*/ 1579 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,MPI_Datatype dtype,void *mem) 1580 { 1581 DMWorkLink *p,link; 1582 1583 PetscFunctionBegin; 1584 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1585 PetscValidPointer(mem,4); 1586 for (p=&dm->workout; (link=*p); p=&link->next) { 1587 if (link->mem == *(void**)mem) { 1588 *p = link->next; 1589 link->next = dm->workin; 1590 dm->workin = link; 1591 *(void**)mem = NULL; 1592 PetscFunctionReturn(0); 1593 } 1594 } 1595 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1596 } 1597 1598 /*@C 1599 DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field 1600 1601 Logically collective on DM 1602 1603 Input Parameters: 1604 + dm - The DM 1605 . field - The field number for the nullspace 1606 - nullsp - A callback to create the nullspace 1607 1608 Notes: 1609 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1610 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1611 $ dm - The present DM 1612 $ origField - The field number given above, in the original DM 1613 $ field - The field number in dm 1614 $ nullSpace - The nullspace for the given field 1615 1616 This function is currently not available from Fortran. 1617 1618 .seealso: DMGetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1619 */ 1620 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1621 { 1622 PetscFunctionBegin; 1623 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1624 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1625 dm->nullspaceConstructors[field] = nullsp; 1626 PetscFunctionReturn(0); 1627 } 1628 1629 /*@C 1630 DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, or NULL 1631 1632 Not collective 1633 1634 Input Parameters: 1635 + dm - The DM 1636 - field - The field number for the nullspace 1637 1638 Output Parameter: 1639 . nullsp - A callback to create the nullspace 1640 1641 Notes: 1642 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1643 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1644 $ dm - The present DM 1645 $ origField - The field number given above, in the original DM 1646 $ field - The field number in dm 1647 $ nullSpace - The nullspace for the given field 1648 1649 This function is currently not available from Fortran. 1650 1651 .seealso: DMSetNullSpaceConstructor(), DMSetNearNullSpaceConstructor(), DMGetNearNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1652 */ 1653 PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1654 { 1655 PetscFunctionBegin; 1656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1657 PetscValidPointer(nullsp, 3); 1658 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1659 *nullsp = dm->nullspaceConstructors[field]; 1660 PetscFunctionReturn(0); 1661 } 1662 1663 /*@C 1664 DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field 1665 1666 Logically collective on DM 1667 1668 Input Parameters: 1669 + dm - The DM 1670 . field - The field number for the nullspace 1671 - nullsp - A callback to create the near-nullspace 1672 1673 Notes: 1674 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1675 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1676 $ dm - The present DM 1677 $ origField - The field number given above, in the original DM 1678 $ field - The field number in dm 1679 $ nullSpace - The nullspace for the given field 1680 1681 This function is currently not available from Fortran. 1682 1683 .seealso: DMGetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1684 */ 1685 PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1686 { 1687 PetscFunctionBegin; 1688 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1689 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1690 dm->nearnullspaceConstructors[field] = nullsp; 1691 PetscFunctionReturn(0); 1692 } 1693 1694 /*@C 1695 DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, or NULL 1696 1697 Not collective 1698 1699 Input Parameters: 1700 + dm - The DM 1701 - field - The field number for the nullspace 1702 1703 Output Parameter: 1704 . nullsp - A callback to create the near-nullspace 1705 1706 Notes: 1707 The callback is intended to provide nullspaces when function spaces are joined or split, such as in DMCreateSubDM(). The calling sequence is 1708 $ PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace) 1709 $ dm - The present DM 1710 $ origField - The field number given above, in the original DM 1711 $ field - The field number in dm 1712 $ nullSpace - The nullspace for the given field 1713 1714 This function is currently not available from Fortran. 1715 1716 .seealso: DMSetNearNullSpaceConstructor(), DMSetNullSpaceConstructor(), DMGetNullSpaceConstructor(), DMCreateSubDM(), DMCreateSuperDM() 1717 */ 1718 PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)) 1719 { 1720 PetscFunctionBegin; 1721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1722 PetscValidPointer(nullsp, 3); 1723 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1724 *nullsp = dm->nearnullspaceConstructors[field]; 1725 PetscFunctionReturn(0); 1726 } 1727 1728 /*@C 1729 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1730 1731 Not collective 1732 1733 Input Parameter: 1734 . dm - the DM object 1735 1736 Output Parameters: 1737 + numFields - The number of fields (or NULL if not requested) 1738 . fieldNames - The name for each field (or NULL if not requested) 1739 - fields - The global indices for each field (or NULL if not requested) 1740 1741 Level: intermediate 1742 1743 Notes: 1744 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1745 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1746 PetscFree(). 1747 1748 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1749 @*/ 1750 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1751 { 1752 PetscSection section, sectionGlobal; 1753 PetscErrorCode ierr; 1754 1755 PetscFunctionBegin; 1756 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1757 if (numFields) { 1758 PetscValidIntPointer(numFields,2); 1759 *numFields = 0; 1760 } 1761 if (fieldNames) { 1762 PetscValidPointer(fieldNames,3); 1763 *fieldNames = NULL; 1764 } 1765 if (fields) { 1766 PetscValidPointer(fields,4); 1767 *fields = NULL; 1768 } 1769 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1770 if (section) { 1771 PetscInt *fieldSizes, *fieldNc, **fieldIndices; 1772 PetscInt nF, f, pStart, pEnd, p; 1773 1774 ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1775 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1776 ierr = PetscMalloc3(nF,&fieldSizes,nF,&fieldNc,nF,&fieldIndices);CHKERRQ(ierr); 1777 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1778 for (f = 0; f < nF; ++f) { 1779 fieldSizes[f] = 0; 1780 ierr = PetscSectionGetFieldComponents(section, f, &fieldNc[f]);CHKERRQ(ierr); 1781 } 1782 for (p = pStart; p < pEnd; ++p) { 1783 PetscInt gdof; 1784 1785 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1786 if (gdof > 0) { 1787 for (f = 0; f < nF; ++f) { 1788 PetscInt fdof, fcdof, fpdof; 1789 1790 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1791 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1792 fpdof = fdof-fcdof; 1793 if (fpdof && fpdof != fieldNc[f]) { 1794 /* Layout does not admit a pointwise block size */ 1795 fieldNc[f] = 1; 1796 } 1797 fieldSizes[f] += fpdof; 1798 } 1799 } 1800 } 1801 for (f = 0; f < nF; ++f) { 1802 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1803 fieldSizes[f] = 0; 1804 } 1805 for (p = pStart; p < pEnd; ++p) { 1806 PetscInt gdof, goff; 1807 1808 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1809 if (gdof > 0) { 1810 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1811 for (f = 0; f < nF; ++f) { 1812 PetscInt fdof, fcdof, fc; 1813 1814 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1815 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1816 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1817 fieldIndices[f][fieldSizes[f]] = goff++; 1818 } 1819 } 1820 } 1821 } 1822 if (numFields) *numFields = nF; 1823 if (fieldNames) { 1824 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1825 for (f = 0; f < nF; ++f) { 1826 const char *fieldName; 1827 1828 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1829 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1830 } 1831 } 1832 if (fields) { 1833 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1834 for (f = 0; f < nF; ++f) { 1835 PetscInt bs, in[2], out[2]; 1836 1837 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1838 in[0] = -fieldNc[f]; 1839 in[1] = fieldNc[f]; 1840 ierr = MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 1841 bs = (-out[0] == out[1]) ? out[1] : 1; 1842 ierr = ISSetBlockSize((*fields)[f], bs);CHKERRQ(ierr); 1843 } 1844 } 1845 ierr = PetscFree3(fieldSizes,fieldNc,fieldIndices);CHKERRQ(ierr); 1846 } else if (dm->ops->createfieldis) { 1847 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1848 } 1849 PetscFunctionReturn(0); 1850 } 1851 1852 /*@C 1853 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1854 corresponding to different fields: each IS contains the global indices of the dofs of the 1855 corresponding field. The optional list of DMs define the DM for each subproblem. 1856 Generalizes DMCreateFieldIS(). 1857 1858 Not collective 1859 1860 Input Parameter: 1861 . dm - the DM object 1862 1863 Output Parameters: 1864 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1865 . namelist - The name for each field (or NULL if not requested) 1866 . islist - The global indices for each field (or NULL if not requested) 1867 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1868 1869 Level: intermediate 1870 1871 Notes: 1872 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1873 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1874 and all of the arrays should be freed with PetscFree(). 1875 1876 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1877 @*/ 1878 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1879 { 1880 PetscErrorCode ierr; 1881 1882 PetscFunctionBegin; 1883 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1884 if (len) { 1885 PetscValidIntPointer(len,2); 1886 *len = 0; 1887 } 1888 if (namelist) { 1889 PetscValidPointer(namelist,3); 1890 *namelist = NULL; 1891 } 1892 if (islist) { 1893 PetscValidPointer(islist,4); 1894 *islist = NULL; 1895 } 1896 if (dmlist) { 1897 PetscValidPointer(dmlist,5); 1898 *dmlist = NULL; 1899 } 1900 /* 1901 Is it a good idea to apply the following check across all impls? 1902 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1903 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1904 */ 1905 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1906 if (!dm->ops->createfielddecomposition) { 1907 PetscSection section; 1908 PetscInt numFields, f; 1909 1910 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1911 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1912 if (section && numFields && dm->ops->createsubdm) { 1913 if (len) *len = numFields; 1914 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1915 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1916 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1917 for (f = 0; f < numFields; ++f) { 1918 const char *fieldName; 1919 1920 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1921 if (namelist) { 1922 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1923 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1924 } 1925 } 1926 } else { 1927 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1928 /* By default there are no DMs associated with subproblems. */ 1929 if (dmlist) *dmlist = NULL; 1930 } 1931 } else { 1932 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1933 } 1934 PetscFunctionReturn(0); 1935 } 1936 1937 /*@ 1938 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1939 The fields are defined by DMCreateFieldIS(). 1940 1941 Not collective 1942 1943 Input Parameters: 1944 + dm - The DM object 1945 . numFields - The number of fields in this subproblem 1946 - fields - The field numbers of the selected fields 1947 1948 Output Parameters: 1949 + is - The global indices for the subproblem 1950 - subdm - The DM for the subproblem 1951 1952 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed 1953 1954 Level: intermediate 1955 1956 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1957 @*/ 1958 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 1959 { 1960 PetscErrorCode ierr; 1961 1962 PetscFunctionBegin; 1963 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1964 PetscValidPointer(fields,3); 1965 if (is) PetscValidPointer(is,4); 1966 if (subdm) PetscValidPointer(subdm,5); 1967 if (!dm->ops->createsubdm) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSubDM",((PetscObject)dm)->type_name); 1968 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1969 PetscFunctionReturn(0); 1970 } 1971 1972 /*@C 1973 DMCreateSuperDM - Returns an arrays of ISes and DM encapsulating a superproblem defined by the DMs passed in. 1974 1975 Not collective 1976 1977 Input Parameters: 1978 + dms - The DM objects 1979 - len - The number of DMs 1980 1981 Output Parameters: 1982 + is - The global indices for the subproblem, or NULL 1983 - superdm - The DM for the superproblem 1984 1985 Note: You need to call DMPlexSetMigrationSF() on the original DM if you want the Global-To-Natural map to be automatically constructed 1986 1987 Level: intermediate 1988 1989 .seealso DMPlexSetMigrationSF(), DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1990 @*/ 1991 PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt len, IS **is, DM *superdm) 1992 { 1993 PetscInt i; 1994 PetscErrorCode ierr; 1995 1996 PetscFunctionBegin; 1997 PetscValidPointer(dms,1); 1998 for (i = 0; i < len; ++i) {PetscValidHeaderSpecific(dms[i],DM_CLASSID,1);} 1999 if (is) PetscValidPointer(is,3); 2000 PetscValidPointer(superdm,4); 2001 if (len < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %D", len); 2002 if (len) { 2003 DM dm = dms[0]; 2004 if (!dm->ops->createsuperdm) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateSuperDM",((PetscObject)dm)->type_name); 2005 ierr = (*dm->ops->createsuperdm)(dms, len, is, superdm);CHKERRQ(ierr); 2006 } 2007 PetscFunctionReturn(0); 2008 } 2009 2010 /*@C 2011 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 2012 corresponding to restrictions to pairs nested subdomains: each IS contains the global 2013 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 2014 define a nonoverlapping covering, while outer subdomains can overlap. 2015 The optional list of DMs define the DM for each subproblem. 2016 2017 Not collective 2018 2019 Input Parameter: 2020 . dm - the DM object 2021 2022 Output Parameters: 2023 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 2024 . namelist - The name for each subdomain (or NULL if not requested) 2025 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 2026 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 2027 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 2028 2029 Level: intermediate 2030 2031 Notes: 2032 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 2033 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 2034 and all of the arrays should be freed with PetscFree(). 2035 2036 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldDecomposition() 2037 @*/ 2038 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 2039 { 2040 PetscErrorCode ierr; 2041 DMSubDomainHookLink link; 2042 PetscInt i,l; 2043 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2046 if (len) {PetscValidPointer(len,2); *len = 0;} 2047 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 2048 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 2049 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 2050 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 2051 /* 2052 Is it a good idea to apply the following check across all impls? 2053 Perhaps some impls can have a well-defined decomposition before DMSetUp? 2054 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 2055 */ 2056 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 2057 if (dm->ops->createdomaindecomposition) { 2058 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 2059 /* copy subdomain hooks and context over to the subdomain DMs */ 2060 if (dmlist && *dmlist) { 2061 for (i = 0; i < l; i++) { 2062 for (link=dm->subdomainhook; link; link=link->next) { 2063 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 2064 } 2065 if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx; 2066 } 2067 } 2068 if (len) *len = l; 2069 } 2070 PetscFunctionReturn(0); 2071 } 2072 2073 /*@C 2074 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 2075 2076 Not collective 2077 2078 Input Parameters: 2079 + dm - the DM object 2080 . n - the number of subdomain scatters 2081 - subdms - the local subdomains 2082 2083 Output Parameters: 2084 + iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 2085 . oscat - scatter from global vector to overlapping global vector entries on subdomain 2086 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 2087 2088 Notes: 2089 This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 2090 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 2091 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 2092 solution and residual data. 2093 2094 Level: developer 2095 2096 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 2097 @*/ 2098 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 2099 { 2100 PetscErrorCode ierr; 2101 2102 PetscFunctionBegin; 2103 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2104 PetscValidPointer(subdms,3); 2105 if (!dm->ops->createddscatters) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCreateDomainDecompositionScatters",((PetscObject)dm)->type_name); 2106 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 2107 PetscFunctionReturn(0); 2108 } 2109 2110 /*@ 2111 DMRefine - Refines a DM object 2112 2113 Collective on dm 2114 2115 Input Parameters: 2116 + dm - the DM object 2117 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2118 2119 Output Parameter: 2120 . dmf - the refined DM, or NULL 2121 2122 Options Database Keys: 2123 . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex 2124 2125 Note: If no refinement was done, the return value is NULL 2126 2127 Level: developer 2128 2129 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2130 @*/ 2131 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 2132 { 2133 PetscErrorCode ierr; 2134 DMRefineHookLink link; 2135 2136 PetscFunctionBegin; 2137 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2138 if (!dm->ops->refine) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMRefine",((PetscObject)dm)->type_name); 2139 ierr = PetscLogEventBegin(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 2140 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 2141 if (*dmf) { 2142 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 2143 2144 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 2145 2146 (*dmf)->ctx = dm->ctx; 2147 (*dmf)->leveldown = dm->leveldown; 2148 (*dmf)->levelup = dm->levelup + 1; 2149 2150 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 2151 for (link=dm->refinehook; link; link=link->next) { 2152 if (link->refinehook) { 2153 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 2154 } 2155 } 2156 } 2157 ierr = PetscLogEventEnd(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 2158 PetscFunctionReturn(0); 2159 } 2160 2161 /*@C 2162 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 2163 2164 Logically Collective 2165 2166 Input Parameters: 2167 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 2168 . refinehook - function to run when setting up a coarser level 2169 . interphook - function to run to update data on finer levels (once per SNESSolve()) 2170 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2171 2172 Calling sequence of refinehook: 2173 $ refinehook(DM coarse,DM fine,void *ctx); 2174 2175 + coarse - coarse level DM 2176 . fine - fine level DM to interpolate problem to 2177 - ctx - optional user-defined function context 2178 2179 Calling sequence for interphook: 2180 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 2181 2182 + coarse - coarse level DM 2183 . interp - matrix interpolating a coarse-level solution to the finer grid 2184 . fine - fine level DM to update 2185 - ctx - optional user-defined function context 2186 2187 Level: advanced 2188 2189 Notes: 2190 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 2191 2192 If this function is called multiple times, the hooks will be run in the order they are added. 2193 2194 This function is currently not available from Fortran. 2195 2196 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2197 @*/ 2198 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 2199 { 2200 PetscErrorCode ierr; 2201 DMRefineHookLink link,*p; 2202 2203 PetscFunctionBegin; 2204 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 2205 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2206 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2207 } 2208 ierr = PetscNew(&link);CHKERRQ(ierr); 2209 link->refinehook = refinehook; 2210 link->interphook = interphook; 2211 link->ctx = ctx; 2212 link->next = NULL; 2213 *p = link; 2214 PetscFunctionReturn(0); 2215 } 2216 2217 /*@C 2218 DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid 2219 2220 Logically Collective 2221 2222 Input Parameters: 2223 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 2224 . refinehook - function to run when setting up a coarser level 2225 . interphook - function to run to update data on finer levels (once per SNESSolve()) 2226 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2227 2228 Level: advanced 2229 2230 Notes: 2231 This function does nothing if the hook is not in the list. 2232 2233 This function is currently not available from Fortran. 2234 2235 .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2236 @*/ 2237 PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 2238 { 2239 PetscErrorCode ierr; 2240 DMRefineHookLink link,*p; 2241 2242 PetscFunctionBegin; 2243 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 2244 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2245 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) { 2246 link = *p; 2247 *p = link->next; 2248 ierr = PetscFree(link);CHKERRQ(ierr); 2249 break; 2250 } 2251 } 2252 PetscFunctionReturn(0); 2253 } 2254 2255 /*@ 2256 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 2257 2258 Collective if any hooks are 2259 2260 Input Parameters: 2261 + coarse - coarser DM to use as a base 2262 . interp - interpolation matrix, apply using MatInterpolate() 2263 - fine - finer DM to update 2264 2265 Level: developer 2266 2267 .seealso: DMRefineHookAdd(), MatInterpolate() 2268 @*/ 2269 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 2270 { 2271 PetscErrorCode ierr; 2272 DMRefineHookLink link; 2273 2274 PetscFunctionBegin; 2275 for (link=fine->refinehook; link; link=link->next) { 2276 if (link->interphook) { 2277 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 2278 } 2279 } 2280 PetscFunctionReturn(0); 2281 } 2282 2283 /*@ 2284 DMInterpolateSolution - Interpolates a solution from a coarse mesh to a fine mesh. 2285 2286 Collective on DM 2287 2288 Input Parameters: 2289 + coarse - coarse DM 2290 . fine - fine DM 2291 . interp - (optional) the matrix computed by DMCreateInterpolation(). Implementations may not need this, but if it 2292 is available it can avoid some recomputation. If it is provided, MatInterpolate() will be used if 2293 the coarse DM does not have a specialized implementation. 2294 - coarseSol - solution on the coarse mesh 2295 2296 Output Parameter: 2297 . fineSol - the interpolation of coarseSol to the fine mesh 2298 2299 Level: developer 2300 2301 Note: This function exists because the interpolation of a solution vector between meshes is not always a linear 2302 map. For example, if a boundary value problem has an inhomogeneous Dirichlet boundary condition that is compressed 2303 out of the solution vector. Or if interpolation is inherently a nonlinear operation, such as a method using 2304 slope-limiting reconstruction. 2305 2306 .seealso DMInterpolate(), DMCreateInterpolation() 2307 @*/ 2308 PetscErrorCode DMInterpolateSolution(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 2309 { 2310 PetscErrorCode (*interpsol)(DM,DM,Mat,Vec,Vec) = NULL; 2311 PetscErrorCode ierr; 2312 2313 PetscFunctionBegin; 2314 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 2315 if (interp) PetscValidHeaderSpecific(interp,MAT_CLASSID,3); 2316 PetscValidHeaderSpecific(coarseSol,VEC_CLASSID,4); 2317 PetscValidHeaderSpecific(fineSol,VEC_CLASSID,5); 2318 2319 ierr = PetscObjectQueryFunction((PetscObject)coarse,"DMInterpolateSolution_C", &interpsol);CHKERRQ(ierr); 2320 if (interpsol) { 2321 ierr = (*interpsol)(coarse, fine, interp, coarseSol, fineSol);CHKERRQ(ierr); 2322 } else if (interp) { 2323 ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr); 2324 } else SETERRQ1(PetscObjectComm((PetscObject)coarse), PETSC_ERR_SUP, "DM %s does not implement DMInterpolateSolution()", ((PetscObject)coarse)->type_name); 2325 PetscFunctionReturn(0); 2326 } 2327 2328 /*@ 2329 DMGetRefineLevel - Gets the number of refinements that have generated this DM. 2330 2331 Not Collective 2332 2333 Input Parameter: 2334 . dm - the DM object 2335 2336 Output Parameter: 2337 . level - number of refinements 2338 2339 Level: developer 2340 2341 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2342 2343 @*/ 2344 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 2345 { 2346 PetscFunctionBegin; 2347 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2348 *level = dm->levelup; 2349 PetscFunctionReturn(0); 2350 } 2351 2352 /*@ 2353 DMSetRefineLevel - Sets the number of refinements that have generated this DM. 2354 2355 Not Collective 2356 2357 Input Parameters: 2358 + dm - the DM object 2359 - level - number of refinements 2360 2361 Level: advanced 2362 2363 Notes: 2364 This value is used by PCMG to determine how many multigrid levels to use 2365 2366 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2367 2368 @*/ 2369 PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level) 2370 { 2371 PetscFunctionBegin; 2372 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2373 dm->levelup = level; 2374 PetscFunctionReturn(0); 2375 } 2376 2377 /*@ 2378 DMExtrude - Extrude a DM object from a surface 2379 2380 Collective on dm 2381 2382 Input Parameter: 2383 + dm - the DM object 2384 - layers - the number of extruded cell layers 2385 2386 Output Parameter: 2387 . dme - the extruded DM, or NULL 2388 2389 Note: If no extrusion was done, the return value is NULL 2390 2391 Level: developer 2392 2393 .seealso DMRefine(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector() 2394 @*/ 2395 PetscErrorCode DMExtrude(DM dm, PetscInt layers, DM *dme) 2396 { 2397 PetscErrorCode ierr; 2398 2399 PetscFunctionBegin; 2400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2401 if (!dm->ops->extrude) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "DM type %s does not implement DMExtrude", ((PetscObject) dm)->type_name); 2402 ierr = (*dm->ops->extrude)(dm, layers, dme);CHKERRQ(ierr); 2403 if (*dme) { 2404 (*dme)->ops->creatematrix = dm->ops->creatematrix; 2405 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject) dm, (PetscObject) *dme);CHKERRQ(ierr); 2406 (*dme)->ctx = dm->ctx; 2407 ierr = DMSetMatType(*dme, dm->mattype);CHKERRQ(ierr); 2408 } 2409 PetscFunctionReturn(0); 2410 } 2411 2412 PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm) 2413 { 2414 PetscFunctionBegin; 2415 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2416 PetscValidPointer(tdm, 2); 2417 *tdm = dm->transformDM; 2418 PetscFunctionReturn(0); 2419 } 2420 2421 PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv) 2422 { 2423 PetscFunctionBegin; 2424 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2425 PetscValidPointer(tv, 2); 2426 *tv = dm->transform; 2427 PetscFunctionReturn(0); 2428 } 2429 2430 /*@ 2431 DMHasBasisTransform - Whether we employ a basis transformation from functions in global vectors to functions in local vectors 2432 2433 Input Parameter: 2434 . dm - The DM 2435 2436 Output Parameter: 2437 . flg - PETSC_TRUE if a basis transformation should be done 2438 2439 Level: developer 2440 2441 .seealso: DMPlexGlobalToLocalBasis(), DMPlexLocalToGlobalBasis(), DMPlexCreateBasisRotation() 2442 @*/ 2443 PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg) 2444 { 2445 Vec tv; 2446 PetscErrorCode ierr; 2447 2448 PetscFunctionBegin; 2449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2450 PetscValidBoolPointer(flg, 2); 2451 ierr = DMGetBasisTransformVec_Internal(dm, &tv);CHKERRQ(ierr); 2452 *flg = tv ? PETSC_TRUE : PETSC_FALSE; 2453 PetscFunctionReturn(0); 2454 } 2455 2456 PetscErrorCode DMConstructBasisTransform_Internal(DM dm) 2457 { 2458 PetscSection s, ts; 2459 PetscScalar *ta; 2460 PetscInt cdim, pStart, pEnd, p, Nf, f, Nc, dof; 2461 PetscErrorCode ierr; 2462 2463 PetscFunctionBegin; 2464 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 2465 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 2466 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2467 ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 2468 ierr = DMClone(dm, &dm->transformDM);CHKERRQ(ierr); 2469 ierr = DMGetLocalSection(dm->transformDM, &ts);CHKERRQ(ierr); 2470 ierr = PetscSectionSetNumFields(ts, Nf);CHKERRQ(ierr); 2471 ierr = PetscSectionSetChart(ts, pStart, pEnd);CHKERRQ(ierr); 2472 for (f = 0; f < Nf; ++f) { 2473 ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 2474 /* We could start to label fields by their transformation properties */ 2475 if (Nc != cdim) continue; 2476 for (p = pStart; p < pEnd; ++p) { 2477 ierr = PetscSectionGetFieldDof(s, p, f, &dof);CHKERRQ(ierr); 2478 if (!dof) continue; 2479 ierr = PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim));CHKERRQ(ierr); 2480 ierr = PetscSectionAddDof(ts, p, PetscSqr(cdim));CHKERRQ(ierr); 2481 } 2482 } 2483 ierr = PetscSectionSetUp(ts);CHKERRQ(ierr); 2484 ierr = DMCreateLocalVector(dm->transformDM, &dm->transform);CHKERRQ(ierr); 2485 ierr = VecGetArray(dm->transform, &ta);CHKERRQ(ierr); 2486 for (p = pStart; p < pEnd; ++p) { 2487 for (f = 0; f < Nf; ++f) { 2488 ierr = PetscSectionGetFieldDof(ts, p, f, &dof);CHKERRQ(ierr); 2489 if (dof) { 2490 PetscReal x[3] = {0.0, 0.0, 0.0}; 2491 PetscScalar *tva; 2492 const PetscScalar *A; 2493 2494 /* TODO Get quadrature point for this dual basis vector for coordinate */ 2495 ierr = (*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx);CHKERRQ(ierr); 2496 ierr = DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *) &tva);CHKERRQ(ierr); 2497 ierr = PetscArraycpy(tva, A, PetscSqr(cdim));CHKERRQ(ierr); 2498 } 2499 } 2500 } 2501 ierr = VecRestoreArray(dm->transform, &ta);CHKERRQ(ierr); 2502 PetscFunctionReturn(0); 2503 } 2504 2505 PetscErrorCode DMCopyTransform(DM dm, DM newdm) 2506 { 2507 PetscErrorCode ierr; 2508 2509 PetscFunctionBegin; 2510 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2511 PetscValidHeaderSpecific(newdm, DM_CLASSID, 2); 2512 newdm->transformCtx = dm->transformCtx; 2513 newdm->transformSetUp = dm->transformSetUp; 2514 newdm->transformDestroy = NULL; 2515 newdm->transformGetMatrix = dm->transformGetMatrix; 2516 if (newdm->transformSetUp) {ierr = DMConstructBasisTransform_Internal(newdm);CHKERRQ(ierr);} 2517 PetscFunctionReturn(0); 2518 } 2519 2520 /*@C 2521 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 2522 2523 Logically Collective 2524 2525 Input Parameters: 2526 + dm - the DM 2527 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 2528 . endhook - function to run after DMGlobalToLocalEnd() has completed 2529 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2530 2531 Calling sequence for beginhook: 2532 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2533 2534 + dm - global DM 2535 . g - global vector 2536 . mode - mode 2537 . l - local vector 2538 - ctx - optional user-defined function context 2539 2540 Calling sequence for endhook: 2541 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2542 2543 + global - global DM 2544 - ctx - optional user-defined function context 2545 2546 Level: advanced 2547 2548 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2549 @*/ 2550 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2551 { 2552 PetscErrorCode ierr; 2553 DMGlobalToLocalHookLink link,*p; 2554 2555 PetscFunctionBegin; 2556 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2557 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2558 ierr = PetscNew(&link);CHKERRQ(ierr); 2559 link->beginhook = beginhook; 2560 link->endhook = endhook; 2561 link->ctx = ctx; 2562 link->next = NULL; 2563 *p = link; 2564 PetscFunctionReturn(0); 2565 } 2566 2567 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 2568 { 2569 Mat cMat; 2570 Vec cVec; 2571 PetscSection section, cSec; 2572 PetscInt pStart, pEnd, p, dof; 2573 PetscErrorCode ierr; 2574 2575 PetscFunctionBegin; 2576 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2577 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2578 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 2579 PetscInt nRows; 2580 2581 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2582 if (nRows <= 0) PetscFunctionReturn(0); 2583 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2584 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2585 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 2586 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2587 for (p = pStart; p < pEnd; p++) { 2588 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2589 if (dof) { 2590 PetscScalar *vals; 2591 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 2592 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 2593 } 2594 } 2595 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2596 } 2597 PetscFunctionReturn(0); 2598 } 2599 2600 /*@ 2601 DMGlobalToLocal - update local vectors from global vector 2602 2603 Neighbor-wise Collective on dm 2604 2605 Input Parameters: 2606 + dm - the DM object 2607 . g - the global vector 2608 . mode - INSERT_VALUES or ADD_VALUES 2609 - l - the local vector 2610 2611 Notes: 2612 The communication involved in this update can be overlapped with computation by using 2613 DMGlobalToLocalBegin() and DMGlobalToLocalEnd(). 2614 2615 Level: beginner 2616 2617 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2618 2619 @*/ 2620 PetscErrorCode DMGlobalToLocal(DM dm,Vec g,InsertMode mode,Vec l) 2621 { 2622 PetscErrorCode ierr; 2623 2624 PetscFunctionBegin; 2625 ierr = DMGlobalToLocalBegin(dm,g,mode,l);CHKERRQ(ierr); 2626 ierr = DMGlobalToLocalEnd(dm,g,mode,l);CHKERRQ(ierr); 2627 PetscFunctionReturn(0); 2628 } 2629 2630 /*@ 2631 DMGlobalToLocalBegin - Begins updating local vectors from global vector 2632 2633 Neighbor-wise Collective on dm 2634 2635 Input Parameters: 2636 + dm - the DM object 2637 . g - the global vector 2638 . mode - INSERT_VALUES or ADD_VALUES 2639 - l - the local vector 2640 2641 Level: intermediate 2642 2643 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2644 2645 @*/ 2646 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2647 { 2648 PetscSF sf; 2649 PetscErrorCode ierr; 2650 DMGlobalToLocalHookLink link; 2651 2652 PetscFunctionBegin; 2653 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2654 for (link=dm->gtolhook; link; link=link->next) { 2655 if (link->beginhook) { 2656 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 2657 } 2658 } 2659 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 2660 if (sf) { 2661 const PetscScalar *gArray; 2662 PetscScalar *lArray; 2663 PetscMemType lmtype,gmtype; 2664 2665 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2666 ierr = VecGetArrayAndMemType(l, &lArray, &lmtype);CHKERRQ(ierr); 2667 ierr = VecGetArrayReadAndMemType(g, &gArray, &gmtype);CHKERRQ(ierr); 2668 ierr = PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray, MPI_REPLACE);CHKERRQ(ierr); 2669 ierr = VecRestoreArrayAndMemType(l, &lArray);CHKERRQ(ierr); 2670 ierr = VecRestoreArrayReadAndMemType(g, &gArray);CHKERRQ(ierr); 2671 } else { 2672 if (!dm->ops->globaltolocalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalBegin() for type %s",((PetscObject)dm)->type_name); 2673 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2674 } 2675 PetscFunctionReturn(0); 2676 } 2677 2678 /*@ 2679 DMGlobalToLocalEnd - Ends updating local vectors from global vector 2680 2681 Neighbor-wise Collective on dm 2682 2683 Input Parameters: 2684 + dm - the DM object 2685 . g - the global vector 2686 . mode - INSERT_VALUES or ADD_VALUES 2687 - l - the local vector 2688 2689 Level: intermediate 2690 2691 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMLocalToGlobalBegin(), DMLocalToGlobal(), DMLocalToGlobalBegin(), DMLocalToGlobalEnd() 2692 2693 @*/ 2694 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2695 { 2696 PetscSF sf; 2697 PetscErrorCode ierr; 2698 const PetscScalar *gArray; 2699 PetscScalar *lArray; 2700 PetscBool transform; 2701 DMGlobalToLocalHookLink link; 2702 PetscMemType lmtype,gmtype; 2703 2704 PetscFunctionBegin; 2705 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2706 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 2707 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 2708 if (sf) { 2709 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2710 2711 ierr = VecGetArrayAndMemType(l, &lArray, &lmtype);CHKERRQ(ierr); 2712 ierr = VecGetArrayReadAndMemType(g, &gArray, &gmtype);CHKERRQ(ierr); 2713 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray,MPI_REPLACE);CHKERRQ(ierr); 2714 ierr = VecRestoreArrayAndMemType(l, &lArray);CHKERRQ(ierr); 2715 ierr = VecRestoreArrayReadAndMemType(g, &gArray);CHKERRQ(ierr); 2716 if (transform) {ierr = DMPlexGlobalToLocalBasis(dm, l);CHKERRQ(ierr);} 2717 } else { 2718 if (!dm->ops->globaltolocalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMGlobalToLocalEnd() for type %s",((PetscObject)dm)->type_name); 2719 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2720 } 2721 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 2722 for (link=dm->gtolhook; link; link=link->next) { 2723 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2724 } 2725 PetscFunctionReturn(0); 2726 } 2727 2728 /*@C 2729 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 2730 2731 Logically Collective 2732 2733 Input Parameters: 2734 + dm - the DM 2735 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 2736 . endhook - function to run after DMLocalToGlobalEnd() has completed 2737 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2738 2739 Calling sequence for beginhook: 2740 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2741 2742 + dm - global DM 2743 . l - local vector 2744 . mode - mode 2745 . g - global vector 2746 - ctx - optional user-defined function context 2747 2748 Calling sequence for endhook: 2749 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2750 2751 + global - global DM 2752 . l - local vector 2753 . mode - mode 2754 . g - global vector 2755 - ctx - optional user-defined function context 2756 2757 Level: advanced 2758 2759 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2760 @*/ 2761 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2762 { 2763 PetscErrorCode ierr; 2764 DMLocalToGlobalHookLink link,*p; 2765 2766 PetscFunctionBegin; 2767 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2768 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2769 ierr = PetscNew(&link);CHKERRQ(ierr); 2770 link->beginhook = beginhook; 2771 link->endhook = endhook; 2772 link->ctx = ctx; 2773 link->next = NULL; 2774 *p = link; 2775 PetscFunctionReturn(0); 2776 } 2777 2778 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 2779 { 2780 Mat cMat; 2781 Vec cVec; 2782 PetscSection section, cSec; 2783 PetscInt pStart, pEnd, p, dof; 2784 PetscErrorCode ierr; 2785 2786 PetscFunctionBegin; 2787 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2788 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2789 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 2790 PetscInt nRows; 2791 2792 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2793 if (nRows <= 0) PetscFunctionReturn(0); 2794 ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 2795 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2796 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2797 for (p = pStart; p < pEnd; p++) { 2798 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2799 if (dof) { 2800 PetscInt d; 2801 PetscScalar *vals; 2802 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 2803 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 2804 /* for this to be the true transpose, we have to zero the values that 2805 * we just extracted */ 2806 for (d = 0; d < dof; d++) { 2807 vals[d] = 0.; 2808 } 2809 } 2810 } 2811 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 2812 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2813 } 2814 PetscFunctionReturn(0); 2815 } 2816 /*@ 2817 DMLocalToGlobal - updates global vectors from local vectors 2818 2819 Neighbor-wise Collective on dm 2820 2821 Input Parameters: 2822 + dm - the DM object 2823 . l - the local vector 2824 . 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. 2825 - g - the global vector 2826 2827 Notes: 2828 The communication involved in this update can be overlapped with computation by using 2829 DMLocalToGlobalBegin() and DMLocalToGlobalEnd(). 2830 2831 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2832 INSERT_VALUES is not supported for DMDA; in that case simply compute the values directly into a global vector instead of a local one. 2833 2834 Level: beginner 2835 2836 .seealso DMLocalToGlobalBegin(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2837 2838 @*/ 2839 PetscErrorCode DMLocalToGlobal(DM dm,Vec l,InsertMode mode,Vec g) 2840 { 2841 PetscErrorCode ierr; 2842 2843 PetscFunctionBegin; 2844 ierr = DMLocalToGlobalBegin(dm,l,mode,g);CHKERRQ(ierr); 2845 ierr = DMLocalToGlobalEnd(dm,l,mode,g);CHKERRQ(ierr); 2846 PetscFunctionReturn(0); 2847 } 2848 2849 /*@ 2850 DMLocalToGlobalBegin - begins updating global vectors from local vectors 2851 2852 Neighbor-wise Collective on dm 2853 2854 Input Parameters: 2855 + dm - the DM object 2856 . l - the local vector 2857 . 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. 2858 - g - the global vector 2859 2860 Notes: 2861 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2862 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 2863 2864 Level: intermediate 2865 2866 .seealso DMLocalToGlobal(), DMLocalToGlobalEnd(), DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocal(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2867 2868 @*/ 2869 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 2870 { 2871 PetscSF sf; 2872 PetscSection s, gs; 2873 DMLocalToGlobalHookLink link; 2874 Vec tmpl; 2875 const PetscScalar *lArray; 2876 PetscScalar *gArray; 2877 PetscBool isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE; 2878 PetscErrorCode ierr; 2879 PetscMemType lmtype=PETSC_MEMTYPE_HOST,gmtype=PETSC_MEMTYPE_HOST; 2880 2881 PetscFunctionBegin; 2882 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2883 for (link=dm->ltoghook; link; link=link->next) { 2884 if (link->beginhook) { 2885 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 2886 } 2887 } 2888 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 2889 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 2890 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 2891 switch (mode) { 2892 case INSERT_VALUES: 2893 case INSERT_ALL_VALUES: 2894 case INSERT_BC_VALUES: 2895 isInsert = PETSC_TRUE; break; 2896 case ADD_VALUES: 2897 case ADD_ALL_VALUES: 2898 case ADD_BC_VALUES: 2899 isInsert = PETSC_FALSE; break; 2900 default: 2901 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2902 } 2903 if ((sf && !isInsert) || (s && isInsert)) { 2904 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 2905 if (transform) { 2906 ierr = DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 2907 ierr = VecCopy(l, tmpl);CHKERRQ(ierr); 2908 ierr = DMPlexLocalToGlobalBasis(dm, tmpl);CHKERRQ(ierr); 2909 ierr = VecGetArrayRead(tmpl, &lArray);CHKERRQ(ierr); 2910 } else if (isInsert) { 2911 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2912 } else { 2913 ierr = VecGetArrayReadAndMemType(l, &lArray, &lmtype);CHKERRQ(ierr); 2914 l_inplace = PETSC_TRUE; 2915 } 2916 if (s && isInsert) { 2917 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2918 } else { 2919 ierr = VecGetArrayAndMemType(g, &gArray, &gmtype);CHKERRQ(ierr); 2920 g_inplace = PETSC_TRUE; 2921 } 2922 if (sf && !isInsert) { 2923 ierr = PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM);CHKERRQ(ierr); 2924 } else if (s && isInsert) { 2925 PetscInt gStart, pStart, pEnd, p; 2926 2927 ierr = DMGetGlobalSection(dm, &gs);CHKERRQ(ierr); 2928 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2929 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2930 for (p = pStart; p < pEnd; ++p) { 2931 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2932 2933 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2934 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2935 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2936 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2937 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2938 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2939 /* Ignore off-process data and points with no global data */ 2940 if (!gdof || goff < 0) continue; 2941 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); 2942 /* If no constraints are enforced in the global vector */ 2943 if (!gcdof) { 2944 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2945 /* If constraints are enforced in the global vector */ 2946 } else if (cdof == gcdof) { 2947 const PetscInt *cdofs; 2948 PetscInt cind = 0; 2949 2950 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2951 for (d = 0, e = 0; d < dof; ++d) { 2952 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2953 gArray[goff-gStart+e++] = lArray[off+d]; 2954 } 2955 } 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); 2956 } 2957 } 2958 if (g_inplace) { 2959 ierr = VecRestoreArrayAndMemType(g, &gArray);CHKERRQ(ierr); 2960 } else { 2961 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2962 } 2963 if (transform) { 2964 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr); 2965 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 2966 } else if (l_inplace) { 2967 ierr = VecRestoreArrayReadAndMemType(l, &lArray);CHKERRQ(ierr); 2968 } else { 2969 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2970 } 2971 } else { 2972 if (!dm->ops->localtoglobalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalBegin() for type %s",((PetscObject)dm)->type_name); 2973 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2974 } 2975 PetscFunctionReturn(0); 2976 } 2977 2978 /*@ 2979 DMLocalToGlobalEnd - updates global vectors from local vectors 2980 2981 Neighbor-wise Collective on dm 2982 2983 Input Parameters: 2984 + dm - the DM object 2985 . l - the local vector 2986 . mode - INSERT_VALUES or ADD_VALUES 2987 - g - the global vector 2988 2989 Level: intermediate 2990 2991 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2992 2993 @*/ 2994 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2995 { 2996 PetscSF sf; 2997 PetscSection s; 2998 DMLocalToGlobalHookLink link; 2999 PetscBool isInsert, transform; 3000 PetscErrorCode ierr; 3001 3002 PetscFunctionBegin; 3003 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3004 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 3005 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 3006 switch (mode) { 3007 case INSERT_VALUES: 3008 case INSERT_ALL_VALUES: 3009 isInsert = PETSC_TRUE; break; 3010 case ADD_VALUES: 3011 case ADD_ALL_VALUES: 3012 isInsert = PETSC_FALSE; break; 3013 default: 3014 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 3015 } 3016 if (sf && !isInsert) { 3017 const PetscScalar *lArray; 3018 PetscScalar *gArray; 3019 Vec tmpl; 3020 3021 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 3022 if (transform) { 3023 ierr = DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 3024 ierr = VecGetArrayRead(tmpl, &lArray);CHKERRQ(ierr); 3025 } else { 3026 ierr = VecGetArrayReadAndMemType(l, &lArray, NULL);CHKERRQ(ierr); 3027 } 3028 ierr = VecGetArrayAndMemType(g, &gArray, NULL);CHKERRQ(ierr); 3029 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 3030 if (transform) { 3031 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr); 3032 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 3033 } else { 3034 ierr = VecRestoreArrayReadAndMemType(l, &lArray);CHKERRQ(ierr); 3035 } 3036 ierr = VecRestoreArrayAndMemType(g, &gArray);CHKERRQ(ierr); 3037 } else if (s && isInsert) { 3038 } else { 3039 if (!dm->ops->localtoglobalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalEnd() for type %s",((PetscObject)dm)->type_name); 3040 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 3041 } 3042 for (link=dm->ltoghook; link; link=link->next) { 3043 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 3044 } 3045 PetscFunctionReturn(0); 3046 } 3047 3048 /*@ 3049 DMLocalToLocalBegin - Maps from a local vector (including ghost points 3050 that contain irrelevant values) to another local vector where the ghost 3051 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 3052 3053 Neighbor-wise Collective on dm 3054 3055 Input Parameters: 3056 + dm - the DM object 3057 . g - the original local vector 3058 - mode - one of INSERT_VALUES or ADD_VALUES 3059 3060 Output Parameter: 3061 . l - the local vector with correct ghost values 3062 3063 Level: intermediate 3064 3065 Notes: 3066 The local vectors used here need not be the same as those 3067 obtained from DMCreateLocalVector(), BUT they 3068 must have the same parallel data layout; they could, for example, be 3069 obtained with VecDuplicate() from the DM originating vectors. 3070 3071 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 3072 3073 @*/ 3074 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 3075 { 3076 PetscErrorCode ierr; 3077 3078 PetscFunctionBegin; 3079 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3080 if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 3081 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 3082 PetscFunctionReturn(0); 3083 } 3084 3085 /*@ 3086 DMLocalToLocalEnd - Maps from a local vector (including ghost points 3087 that contain irrelevant values) to another local vector where the ghost 3088 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 3089 3090 Neighbor-wise Collective on dm 3091 3092 Input Parameters: 3093 + da - the DM object 3094 . g - the original local vector 3095 - mode - one of INSERT_VALUES or ADD_VALUES 3096 3097 Output Parameter: 3098 . l - the local vector with correct ghost values 3099 3100 Level: intermediate 3101 3102 Notes: 3103 The local vectors used here need not be the same as those 3104 obtained from DMCreateLocalVector(), BUT they 3105 must have the same parallel data layout; they could, for example, be 3106 obtained with VecDuplicate() from the DM originating vectors. 3107 3108 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 3109 3110 @*/ 3111 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 3112 { 3113 PetscErrorCode ierr; 3114 3115 PetscFunctionBegin; 3116 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3117 if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 3118 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 3119 PetscFunctionReturn(0); 3120 } 3121 3122 /*@ 3123 DMCoarsen - Coarsens a DM object 3124 3125 Collective on dm 3126 3127 Input Parameters: 3128 + dm - the DM object 3129 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 3130 3131 Output Parameter: 3132 . dmc - the coarsened DM 3133 3134 Level: developer 3135 3136 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3137 3138 @*/ 3139 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 3140 { 3141 PetscErrorCode ierr; 3142 DMCoarsenHookLink link; 3143 3144 PetscFunctionBegin; 3145 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3146 if (!dm->ops->coarsen) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCoarsen",((PetscObject)dm)->type_name); 3147 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 3148 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 3149 if (*dmc) { 3150 (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */ 3151 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 3152 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 3153 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 3154 (*dmc)->ctx = dm->ctx; 3155 (*dmc)->levelup = dm->levelup; 3156 (*dmc)->leveldown = dm->leveldown + 1; 3157 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 3158 for (link=dm->coarsenhook; link; link=link->next) { 3159 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 3160 } 3161 } 3162 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 3163 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 3164 PetscFunctionReturn(0); 3165 } 3166 3167 /*@C 3168 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 3169 3170 Logically Collective 3171 3172 Input Parameters: 3173 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 3174 . coarsenhook - function to run when setting up a coarser level 3175 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 3176 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3177 3178 Calling sequence of coarsenhook: 3179 $ coarsenhook(DM fine,DM coarse,void *ctx); 3180 3181 + fine - fine level DM 3182 . coarse - coarse level DM to restrict problem to 3183 - ctx - optional user-defined function context 3184 3185 Calling sequence for restricthook: 3186 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 3187 3188 + fine - fine level DM 3189 . mrestrict - matrix restricting a fine-level solution to the coarse grid 3190 . rscale - scaling vector for restriction 3191 . inject - matrix restricting by injection 3192 . coarse - coarse level DM to update 3193 - ctx - optional user-defined function context 3194 3195 Level: advanced 3196 3197 Notes: 3198 This function is only needed if auxiliary data needs to be set up on coarse grids. 3199 3200 If this function is called multiple times, the hooks will be run in the order they are added. 3201 3202 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 3203 extract the finest level information from its context (instead of from the SNES). 3204 3205 This function is currently not available from Fortran. 3206 3207 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3208 @*/ 3209 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 3210 { 3211 PetscErrorCode ierr; 3212 DMCoarsenHookLink link,*p; 3213 3214 PetscFunctionBegin; 3215 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 3216 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 3217 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 3218 } 3219 ierr = PetscNew(&link);CHKERRQ(ierr); 3220 link->coarsenhook = coarsenhook; 3221 link->restricthook = restricthook; 3222 link->ctx = ctx; 3223 link->next = NULL; 3224 *p = link; 3225 PetscFunctionReturn(0); 3226 } 3227 3228 /*@C 3229 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid 3230 3231 Logically Collective 3232 3233 Input Parameters: 3234 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 3235 . coarsenhook - function to run when setting up a coarser level 3236 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 3237 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3238 3239 Level: advanced 3240 3241 Notes: 3242 This function does nothing if the hook is not in the list. 3243 3244 This function is currently not available from Fortran. 3245 3246 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3247 @*/ 3248 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 3249 { 3250 PetscErrorCode ierr; 3251 DMCoarsenHookLink link,*p; 3252 3253 PetscFunctionBegin; 3254 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 3255 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 3256 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 3257 link = *p; 3258 *p = link->next; 3259 ierr = PetscFree(link);CHKERRQ(ierr); 3260 break; 3261 } 3262 } 3263 PetscFunctionReturn(0); 3264 } 3265 3266 /*@ 3267 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 3268 3269 Collective if any hooks are 3270 3271 Input Parameters: 3272 + fine - finer DM to use as a base 3273 . restrct - restriction matrix, apply using MatRestrict() 3274 . rscale - scaling vector for restriction 3275 . inject - injection matrix, also use MatRestrict() 3276 - coarse - coarser DM to update 3277 3278 Level: developer 3279 3280 .seealso: DMCoarsenHookAdd(), MatRestrict() 3281 @*/ 3282 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 3283 { 3284 PetscErrorCode ierr; 3285 DMCoarsenHookLink link; 3286 3287 PetscFunctionBegin; 3288 for (link=fine->coarsenhook; link; link=link->next) { 3289 if (link->restricthook) { 3290 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 3291 } 3292 } 3293 PetscFunctionReturn(0); 3294 } 3295 3296 /*@C 3297 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 3298 3299 Logically Collective on global 3300 3301 Input Parameters: 3302 + global - global DM 3303 . ddhook - function to run to pass data to the decomposition DM upon its creation 3304 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 3305 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3306 3307 Calling sequence for ddhook: 3308 $ ddhook(DM global,DM block,void *ctx) 3309 3310 + global - global DM 3311 . block - block DM 3312 - ctx - optional user-defined function context 3313 3314 Calling sequence for restricthook: 3315 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 3316 3317 + global - global DM 3318 . out - scatter to the outer (with ghost and overlap points) block vector 3319 . in - scatter to block vector values only owned locally 3320 . block - block DM 3321 - ctx - optional user-defined function context 3322 3323 Level: advanced 3324 3325 Notes: 3326 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 3327 3328 If this function is called multiple times, the hooks will be run in the order they are added. 3329 3330 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 3331 extract the global information from its context (instead of from the SNES). 3332 3333 This function is currently not available from Fortran. 3334 3335 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3336 @*/ 3337 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 3338 { 3339 PetscErrorCode ierr; 3340 DMSubDomainHookLink link,*p; 3341 3342 PetscFunctionBegin; 3343 PetscValidHeaderSpecific(global,DM_CLASSID,1); 3344 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 3345 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 3346 } 3347 ierr = PetscNew(&link);CHKERRQ(ierr); 3348 link->restricthook = restricthook; 3349 link->ddhook = ddhook; 3350 link->ctx = ctx; 3351 link->next = NULL; 3352 *p = link; 3353 PetscFunctionReturn(0); 3354 } 3355 3356 /*@C 3357 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid 3358 3359 Logically Collective 3360 3361 Input Parameters: 3362 + global - global DM 3363 . ddhook - function to run to pass data to the decomposition DM upon its creation 3364 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 3365 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3366 3367 Level: advanced 3368 3369 Notes: 3370 3371 This function is currently not available from Fortran. 3372 3373 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3374 @*/ 3375 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 3376 { 3377 PetscErrorCode ierr; 3378 DMSubDomainHookLink link,*p; 3379 3380 PetscFunctionBegin; 3381 PetscValidHeaderSpecific(global,DM_CLASSID,1); 3382 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 3383 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 3384 link = *p; 3385 *p = link->next; 3386 ierr = PetscFree(link);CHKERRQ(ierr); 3387 break; 3388 } 3389 } 3390 PetscFunctionReturn(0); 3391 } 3392 3393 /*@ 3394 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 3395 3396 Collective if any hooks are 3397 3398 Input Parameters: 3399 + fine - finer DM to use as a base 3400 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 3401 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 3402 - coarse - coarer DM to update 3403 3404 Level: developer 3405 3406 .seealso: DMCoarsenHookAdd(), MatRestrict() 3407 @*/ 3408 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 3409 { 3410 PetscErrorCode ierr; 3411 DMSubDomainHookLink link; 3412 3413 PetscFunctionBegin; 3414 for (link=global->subdomainhook; link; link=link->next) { 3415 if (link->restricthook) { 3416 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 3417 } 3418 } 3419 PetscFunctionReturn(0); 3420 } 3421 3422 /*@ 3423 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 3424 3425 Not Collective 3426 3427 Input Parameter: 3428 . dm - the DM object 3429 3430 Output Parameter: 3431 . level - number of coarsenings 3432 3433 Level: developer 3434 3435 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3436 3437 @*/ 3438 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 3439 { 3440 PetscFunctionBegin; 3441 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3442 PetscValidIntPointer(level,2); 3443 *level = dm->leveldown; 3444 PetscFunctionReturn(0); 3445 } 3446 3447 /*@ 3448 DMSetCoarsenLevel - Sets the number of coarsenings that have generated this DM. 3449 3450 Not Collective 3451 3452 Input Parameters: 3453 + dm - the DM object 3454 - level - number of coarsenings 3455 3456 Level: developer 3457 3458 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3459 @*/ 3460 PetscErrorCode DMSetCoarsenLevel(DM dm,PetscInt level) 3461 { 3462 PetscFunctionBegin; 3463 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3464 dm->leveldown = level; 3465 PetscFunctionReturn(0); 3466 } 3467 3468 /*@C 3469 DMRefineHierarchy - Refines a DM object, all levels at once 3470 3471 Collective on dm 3472 3473 Input Parameters: 3474 + dm - the DM object 3475 - nlevels - the number of levels of refinement 3476 3477 Output Parameter: 3478 . dmf - the refined DM hierarchy 3479 3480 Level: developer 3481 3482 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3483 3484 @*/ 3485 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 3486 { 3487 PetscErrorCode ierr; 3488 3489 PetscFunctionBegin; 3490 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3491 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 3492 if (nlevels == 0) PetscFunctionReturn(0); 3493 PetscValidPointer(dmf,3); 3494 if (dm->ops->refinehierarchy) { 3495 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 3496 } else if (dm->ops->refine) { 3497 PetscInt i; 3498 3499 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 3500 for (i=1; i<nlevels; i++) { 3501 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 3502 } 3503 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 3504 PetscFunctionReturn(0); 3505 } 3506 3507 /*@C 3508 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 3509 3510 Collective on dm 3511 3512 Input Parameters: 3513 + dm - the DM object 3514 - nlevels - the number of levels of coarsening 3515 3516 Output Parameter: 3517 . dmc - the coarsened DM hierarchy 3518 3519 Level: developer 3520 3521 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3522 3523 @*/ 3524 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 3525 { 3526 PetscErrorCode ierr; 3527 3528 PetscFunctionBegin; 3529 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3530 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 3531 if (nlevels == 0) PetscFunctionReturn(0); 3532 PetscValidPointer(dmc,3); 3533 if (dm->ops->coarsenhierarchy) { 3534 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 3535 } else if (dm->ops->coarsen) { 3536 PetscInt i; 3537 3538 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 3539 for (i=1; i<nlevels; i++) { 3540 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 3541 } 3542 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 3543 PetscFunctionReturn(0); 3544 } 3545 3546 /*@C 3547 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 3548 3549 Not Collective 3550 3551 Input Parameters: 3552 + dm - the DM object 3553 - destroy - the destroy function 3554 3555 Level: intermediate 3556 3557 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3558 3559 @*/ 3560 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 3561 { 3562 PetscFunctionBegin; 3563 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3564 dm->ctxdestroy = destroy; 3565 PetscFunctionReturn(0); 3566 } 3567 3568 /*@ 3569 DMSetApplicationContext - Set a user context into a DM object 3570 3571 Not Collective 3572 3573 Input Parameters: 3574 + dm - the DM object 3575 - ctx - the user context 3576 3577 Level: intermediate 3578 3579 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3580 3581 @*/ 3582 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 3583 { 3584 PetscFunctionBegin; 3585 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3586 dm->ctx = ctx; 3587 PetscFunctionReturn(0); 3588 } 3589 3590 /*@ 3591 DMGetApplicationContext - Gets a user context from a DM object 3592 3593 Not Collective 3594 3595 Input Parameter: 3596 . dm - the DM object 3597 3598 Output Parameter: 3599 . ctx - the user context 3600 3601 Level: intermediate 3602 3603 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3604 3605 @*/ 3606 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 3607 { 3608 PetscFunctionBegin; 3609 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3610 *(void**)ctx = dm->ctx; 3611 PetscFunctionReturn(0); 3612 } 3613 3614 /*@C 3615 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 3616 3617 Logically Collective on dm 3618 3619 Input Parameters: 3620 + dm - the DM object 3621 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 3622 3623 Level: intermediate 3624 3625 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 3626 DMSetJacobian() 3627 3628 @*/ 3629 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 3630 { 3631 PetscFunctionBegin; 3632 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3633 dm->ops->computevariablebounds = f; 3634 PetscFunctionReturn(0); 3635 } 3636 3637 /*@ 3638 DMHasVariableBounds - does the DM object have a variable bounds function? 3639 3640 Not Collective 3641 3642 Input Parameter: 3643 . dm - the DM object to destroy 3644 3645 Output Parameter: 3646 . flg - PETSC_TRUE if the variable bounds function exists 3647 3648 Level: developer 3649 3650 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3651 3652 @*/ 3653 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 3654 { 3655 PetscFunctionBegin; 3656 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3657 PetscValidBoolPointer(flg,2); 3658 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 3659 PetscFunctionReturn(0); 3660 } 3661 3662 /*@C 3663 DMComputeVariableBounds - compute variable bounds used by SNESVI. 3664 3665 Logically Collective on dm 3666 3667 Input Parameter: 3668 . dm - the DM object 3669 3670 Output parameters: 3671 + xl - lower bound 3672 - xu - upper bound 3673 3674 Level: advanced 3675 3676 Notes: 3677 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 3678 3679 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3680 3681 @*/ 3682 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 3683 { 3684 PetscErrorCode ierr; 3685 3686 PetscFunctionBegin; 3687 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3688 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 3689 PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 3690 if (!dm->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeVariableBounds",((PetscObject)dm)->type_name); 3691 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 3692 PetscFunctionReturn(0); 3693 } 3694 3695 /*@ 3696 DMHasColoring - does the DM object have a method of providing a coloring? 3697 3698 Not Collective 3699 3700 Input Parameter: 3701 . dm - the DM object 3702 3703 Output Parameter: 3704 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 3705 3706 Level: developer 3707 3708 .seealso DMCreateColoring() 3709 3710 @*/ 3711 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 3712 { 3713 PetscFunctionBegin; 3714 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3715 PetscValidBoolPointer(flg,2); 3716 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 3717 PetscFunctionReturn(0); 3718 } 3719 3720 /*@ 3721 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 3722 3723 Not Collective 3724 3725 Input Parameter: 3726 . dm - the DM object 3727 3728 Output Parameter: 3729 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 3730 3731 Level: developer 3732 3733 .seealso DMCreateRestriction() 3734 3735 @*/ 3736 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 3737 { 3738 PetscFunctionBegin; 3739 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3740 PetscValidBoolPointer(flg,2); 3741 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 3742 PetscFunctionReturn(0); 3743 } 3744 3745 /*@ 3746 DMHasCreateInjection - does the DM object have a method of providing an injection? 3747 3748 Not Collective 3749 3750 Input Parameter: 3751 . dm - the DM object 3752 3753 Output Parameter: 3754 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection(). 3755 3756 Level: developer 3757 3758 .seealso DMCreateInjection() 3759 3760 @*/ 3761 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg) 3762 { 3763 PetscErrorCode ierr; 3764 3765 PetscFunctionBegin; 3766 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3767 PetscValidBoolPointer(flg,2); 3768 if (dm->ops->hascreateinjection) { 3769 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr); 3770 } else { 3771 *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE; 3772 } 3773 PetscFunctionReturn(0); 3774 } 3775 3776 PetscFunctionList DMList = NULL; 3777 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3778 3779 /*@C 3780 DMSetType - Builds a DM, for a particular DM implementation. 3781 3782 Collective on dm 3783 3784 Input Parameters: 3785 + dm - The DM object 3786 - method - The name of the DM type 3787 3788 Options Database Key: 3789 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3790 3791 Notes: 3792 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3793 3794 Level: intermediate 3795 3796 .seealso: DMGetType(), DMCreate() 3797 @*/ 3798 PetscErrorCode DMSetType(DM dm, DMType method) 3799 { 3800 PetscErrorCode (*r)(DM); 3801 PetscBool match; 3802 PetscErrorCode ierr; 3803 3804 PetscFunctionBegin; 3805 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3806 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3807 if (match) PetscFunctionReturn(0); 3808 3809 ierr = DMRegisterAll();CHKERRQ(ierr); 3810 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3811 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3812 3813 if (dm->ops->destroy) { 3814 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3815 } 3816 ierr = PetscMemzero(dm->ops,sizeof(*dm->ops));CHKERRQ(ierr); 3817 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3818 ierr = (*r)(dm);CHKERRQ(ierr); 3819 PetscFunctionReturn(0); 3820 } 3821 3822 /*@C 3823 DMGetType - Gets the DM type name (as a string) from the DM. 3824 3825 Not Collective 3826 3827 Input Parameter: 3828 . dm - The DM 3829 3830 Output Parameter: 3831 . type - The DM type name 3832 3833 Level: intermediate 3834 3835 .seealso: DMSetType(), DMCreate() 3836 @*/ 3837 PetscErrorCode DMGetType(DM dm, DMType *type) 3838 { 3839 PetscErrorCode ierr; 3840 3841 PetscFunctionBegin; 3842 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3843 PetscValidPointer(type,2); 3844 ierr = DMRegisterAll();CHKERRQ(ierr); 3845 *type = ((PetscObject)dm)->type_name; 3846 PetscFunctionReturn(0); 3847 } 3848 3849 /*@C 3850 DMConvert - Converts a DM to another DM, either of the same or different type. 3851 3852 Collective on dm 3853 3854 Input Parameters: 3855 + dm - the DM 3856 - newtype - new DM type (use "same" for the same type) 3857 3858 Output Parameter: 3859 . M - pointer to new DM 3860 3861 Notes: 3862 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3863 the MPI communicator of the generated DM is always the same as the communicator 3864 of the input DM. 3865 3866 Level: intermediate 3867 3868 .seealso: DMCreate() 3869 @*/ 3870 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3871 { 3872 DM B; 3873 char convname[256]; 3874 PetscBool sametype/*, issame */; 3875 PetscErrorCode ierr; 3876 3877 PetscFunctionBegin; 3878 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3879 PetscValidType(dm,1); 3880 PetscValidPointer(M,3); 3881 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3882 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3883 if (sametype) { 3884 *M = dm; 3885 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3886 PetscFunctionReturn(0); 3887 } else { 3888 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3889 3890 /* 3891 Order of precedence: 3892 1) See if a specialized converter is known to the current DM. 3893 2) See if a specialized converter is known to the desired DM class. 3894 3) See if a good general converter is registered for the desired class 3895 4) See if a good general converter is known for the current matrix. 3896 5) Use a really basic converter. 3897 */ 3898 3899 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3900 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3901 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3902 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3903 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3904 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3905 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3906 if (conv) goto foundconv; 3907 3908 /* 2) See if a specialized converter is known to the desired DM class. */ 3909 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3910 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3911 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3912 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3913 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3914 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3915 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3916 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3917 if (conv) { 3918 ierr = DMDestroy(&B);CHKERRQ(ierr); 3919 goto foundconv; 3920 } 3921 3922 #if 0 3923 /* 3) See if a good general converter is registered for the desired class */ 3924 conv = B->ops->convertfrom; 3925 ierr = DMDestroy(&B);CHKERRQ(ierr); 3926 if (conv) goto foundconv; 3927 3928 /* 4) See if a good general converter is known for the current matrix */ 3929 if (dm->ops->convert) { 3930 conv = dm->ops->convert; 3931 } 3932 if (conv) goto foundconv; 3933 #endif 3934 3935 /* 5) Use a really basic converter. */ 3936 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3937 3938 foundconv: 3939 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3940 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3941 /* Things that are independent of DM type: We should consult DMClone() here */ 3942 { 3943 PetscBool isper; 3944 const PetscReal *maxCell, *L; 3945 const DMBoundaryType *bd; 3946 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3947 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3948 (*M)->prealloc_only = dm->prealloc_only; 3949 ierr = PetscFree((*M)->vectype);CHKERRQ(ierr); 3950 ierr = PetscStrallocpy(dm->vectype,(char**)&(*M)->vectype);CHKERRQ(ierr); 3951 ierr = PetscFree((*M)->mattype);CHKERRQ(ierr); 3952 ierr = PetscStrallocpy(dm->mattype,(char**)&(*M)->mattype);CHKERRQ(ierr); 3953 } 3954 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3955 } 3956 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3957 PetscFunctionReturn(0); 3958 } 3959 3960 /*--------------------------------------------------------------------------------------------------------------------*/ 3961 3962 /*@C 3963 DMRegister - Adds a new DM component implementation 3964 3965 Not Collective 3966 3967 Input Parameters: 3968 + name - The name of a new user-defined creation routine 3969 - create_func - The creation routine itself 3970 3971 Notes: 3972 DMRegister() may be called multiple times to add several user-defined DMs 3973 3974 Sample usage: 3975 .vb 3976 DMRegister("my_da", MyDMCreate); 3977 .ve 3978 3979 Then, your DM type can be chosen with the procedural interface via 3980 .vb 3981 DMCreate(MPI_Comm, DM *); 3982 DMSetType(DM,"my_da"); 3983 .ve 3984 or at runtime via the option 3985 .vb 3986 -da_type my_da 3987 .ve 3988 3989 Level: advanced 3990 3991 .seealso: DMRegisterAll(), DMRegisterDestroy() 3992 3993 @*/ 3994 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3995 { 3996 PetscErrorCode ierr; 3997 3998 PetscFunctionBegin; 3999 ierr = DMInitializePackage();CHKERRQ(ierr); 4000 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 4001 PetscFunctionReturn(0); 4002 } 4003 4004 /*@C 4005 DMLoad - Loads a DM that has been stored in binary with DMView(). 4006 4007 Collective on viewer 4008 4009 Input Parameters: 4010 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 4011 some related function before a call to DMLoad(). 4012 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 4013 HDF5 file viewer, obtained from PetscViewerHDF5Open() 4014 4015 Level: intermediate 4016 4017 Notes: 4018 The type is determined by the data in the file, any type set into the DM before this call is ignored. 4019 4020 Notes for advanced users: 4021 Most users should not need to know the details of the binary storage 4022 format, since DMLoad() and DMView() completely hide these details. 4023 But for anyone who's interested, the standard binary matrix storage 4024 format is 4025 .vb 4026 has not yet been determined 4027 .ve 4028 4029 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 4030 @*/ 4031 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 4032 { 4033 PetscBool isbinary, ishdf5; 4034 PetscErrorCode ierr; 4035 4036 PetscFunctionBegin; 4037 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 4038 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4039 ierr = PetscViewerCheckReadable(viewer);CHKERRQ(ierr); 4040 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 4041 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 4042 ierr = PetscLogEventBegin(DM_Load,viewer,0,0,0);CHKERRQ(ierr); 4043 if (isbinary) { 4044 PetscInt classid; 4045 char type[256]; 4046 4047 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 4048 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 4049 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 4050 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 4051 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 4052 } else if (ishdf5) { 4053 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 4054 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 4055 ierr = PetscLogEventEnd(DM_Load,viewer,0,0,0);CHKERRQ(ierr); 4056 PetscFunctionReturn(0); 4057 } 4058 4059 /*@ 4060 DMGetLocalBoundingBox - Returns the bounding box for the piece of the DM on this process. 4061 4062 Not collective 4063 4064 Input Parameter: 4065 . dm - the DM 4066 4067 Output Parameters: 4068 + lmin - local minimum coordinates (length coord dim, optional) 4069 - lmax - local maximim coordinates (length coord dim, optional) 4070 4071 Level: beginner 4072 4073 Note: If the DM is a DMDA and has no coordinates, the index bounds are returned instead. 4074 4075 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetBoundingBox() 4076 @*/ 4077 PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[]) 4078 { 4079 Vec coords = NULL; 4080 PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 4081 PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 4082 const PetscScalar *local_coords; 4083 PetscInt N, Ni; 4084 PetscInt cdim, i, j; 4085 PetscErrorCode ierr; 4086 4087 PetscFunctionBegin; 4088 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4089 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 4090 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 4091 if (coords) { 4092 ierr = VecGetArrayRead(coords, &local_coords);CHKERRQ(ierr); 4093 ierr = VecGetLocalSize(coords, &N);CHKERRQ(ierr); 4094 Ni = N/cdim; 4095 for (i = 0; i < Ni; ++i) { 4096 for (j = 0; j < 3; ++j) { 4097 min[j] = j < cdim ? PetscMin(min[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 4098 max[j] = j < cdim ? PetscMax(max[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 4099 } 4100 } 4101 ierr = VecRestoreArrayRead(coords, &local_coords);CHKERRQ(ierr); 4102 } else { 4103 PetscBool isda; 4104 4105 ierr = PetscObjectTypeCompare((PetscObject) dm, DMDA, &isda);CHKERRQ(ierr); 4106 if (isda) {ierr = DMGetLocalBoundingIndices_DMDA(dm, min, max);CHKERRQ(ierr);} 4107 } 4108 if (lmin) {ierr = PetscArraycpy(lmin, min, cdim);CHKERRQ(ierr);} 4109 if (lmax) {ierr = PetscArraycpy(lmax, max, cdim);CHKERRQ(ierr);} 4110 PetscFunctionReturn(0); 4111 } 4112 4113 /*@ 4114 DMGetBoundingBox - Returns the global bounding box for the DM. 4115 4116 Collective 4117 4118 Input Parameter: 4119 . dm - the DM 4120 4121 Output Parameters: 4122 + gmin - global minimum coordinates (length coord dim, optional) 4123 - gmax - global maximim coordinates (length coord dim, optional) 4124 4125 Level: beginner 4126 4127 .seealso: DMGetLocalBoundingBox(), DMGetCoordinates(), DMGetCoordinatesLocal() 4128 @*/ 4129 PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[]) 4130 { 4131 PetscReal lmin[3], lmax[3]; 4132 PetscInt cdim; 4133 PetscMPIInt count; 4134 PetscErrorCode ierr; 4135 4136 PetscFunctionBegin; 4137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4138 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 4139 ierr = PetscMPIIntCast(cdim, &count);CHKERRQ(ierr); 4140 ierr = DMGetLocalBoundingBox(dm, lmin, lmax);CHKERRQ(ierr); 4141 if (gmin) {ierr = MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);} 4142 if (gmax) {ierr = MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);} 4143 PetscFunctionReturn(0); 4144 } 4145 4146 /******************************** FEM Support **********************************/ 4147 4148 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 4149 { 4150 PetscInt f; 4151 PetscErrorCode ierr; 4152 4153 PetscFunctionBegin; 4154 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 4155 for (f = 0; f < len; ++f) { 4156 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 4157 } 4158 PetscFunctionReturn(0); 4159 } 4160 4161 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 4162 { 4163 PetscInt f, g; 4164 PetscErrorCode ierr; 4165 4166 PetscFunctionBegin; 4167 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 4168 for (f = 0; f < rows; ++f) { 4169 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 4170 for (g = 0; g < cols; ++g) { 4171 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 4172 } 4173 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 4174 } 4175 PetscFunctionReturn(0); 4176 } 4177 4178 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 4179 { 4180 PetscInt localSize, bs; 4181 PetscMPIInt size; 4182 Vec x, xglob; 4183 const PetscScalar *xarray; 4184 PetscErrorCode ierr; 4185 4186 PetscFunctionBegin; 4187 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRMPI(ierr); 4188 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 4189 ierr = VecCopy(X, x);CHKERRQ(ierr); 4190 ierr = VecChop(x, tol);CHKERRQ(ierr); 4191 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 4192 if (size > 1) { 4193 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 4194 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 4195 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 4196 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 4197 } else { 4198 xglob = x; 4199 } 4200 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 4201 if (size > 1) { 4202 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 4203 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 4204 } 4205 ierr = VecDestroy(&x);CHKERRQ(ierr); 4206 PetscFunctionReturn(0); 4207 } 4208 4209 /*@ 4210 DMGetSection - Get the PetscSection encoding the local data layout for the DM. This is equivalent to DMGetLocalSection(). Deprecated in v3.12 4211 4212 Input Parameter: 4213 . dm - The DM 4214 4215 Output Parameter: 4216 . section - The PetscSection 4217 4218 Options Database Keys: 4219 . -dm_petscsection_view - View the Section created by the DM 4220 4221 Level: advanced 4222 4223 Notes: 4224 Use DMGetLocalSection() in new code. 4225 4226 This gets a borrowed reference, so the user should not destroy this PetscSection. 4227 4228 .seealso: DMGetLocalSection(), DMSetLocalSection(), DMGetGlobalSection() 4229 @*/ 4230 PetscErrorCode DMGetSection(DM dm, PetscSection *section) 4231 { 4232 PetscErrorCode ierr; 4233 4234 PetscFunctionBegin; 4235 ierr = DMGetLocalSection(dm,section);CHKERRQ(ierr); 4236 PetscFunctionReturn(0); 4237 } 4238 4239 /*@ 4240 DMGetLocalSection - Get the PetscSection encoding the local data layout for the DM. 4241 4242 Input Parameter: 4243 . dm - The DM 4244 4245 Output Parameter: 4246 . section - The PetscSection 4247 4248 Options Database Keys: 4249 . -dm_petscsection_view - View the Section created by the DM 4250 4251 Level: intermediate 4252 4253 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4254 4255 .seealso: DMSetLocalSection(), DMGetGlobalSection() 4256 @*/ 4257 PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section) 4258 { 4259 PetscErrorCode ierr; 4260 4261 PetscFunctionBegin; 4262 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4263 PetscValidPointer(section, 2); 4264 if (!dm->localSection && dm->ops->createlocalsection) { 4265 PetscInt d; 4266 4267 if (dm->setfromoptionscalled) { 4268 PetscObject obj = (PetscObject) dm; 4269 PetscViewer viewer; 4270 PetscViewerFormat format; 4271 PetscBool flg; 4272 4273 ierr = PetscOptionsGetViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg);CHKERRQ(ierr); 4274 if (flg) {ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr);} 4275 for (d = 0; d < dm->Nds; ++d) { 4276 ierr = PetscDSSetFromOptions(dm->probs[d].ds);CHKERRQ(ierr); 4277 if (flg) {ierr = PetscDSView(dm->probs[d].ds, viewer);CHKERRQ(ierr);} 4278 } 4279 if (flg) { 4280 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 4281 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 4282 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4283 } 4284 } 4285 ierr = (*dm->ops->createlocalsection)(dm);CHKERRQ(ierr); 4286 if (dm->localSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->localSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 4287 } 4288 *section = dm->localSection; 4289 PetscFunctionReturn(0); 4290 } 4291 4292 /*@ 4293 DMSetSection - Set the PetscSection encoding the local data layout for the DM. This is equivalent to DMSetLocalSection(). Deprecated in v3.12 4294 4295 Input Parameters: 4296 + dm - The DM 4297 - section - The PetscSection 4298 4299 Level: advanced 4300 4301 Notes: 4302 Use DMSetLocalSection() in new code. 4303 4304 Any existing Section will be destroyed 4305 4306 .seealso: DMSetLocalSection(), DMGetLocalSection(), DMSetGlobalSection() 4307 @*/ 4308 PetscErrorCode DMSetSection(DM dm, PetscSection section) 4309 { 4310 PetscErrorCode ierr; 4311 4312 PetscFunctionBegin; 4313 ierr = DMSetLocalSection(dm,section);CHKERRQ(ierr); 4314 PetscFunctionReturn(0); 4315 } 4316 4317 /*@ 4318 DMSetLocalSection - Set the PetscSection encoding the local data layout for the DM. 4319 4320 Input Parameters: 4321 + dm - The DM 4322 - section - The PetscSection 4323 4324 Level: intermediate 4325 4326 Note: Any existing Section will be destroyed 4327 4328 .seealso: DMGetLocalSection(), DMSetGlobalSection() 4329 @*/ 4330 PetscErrorCode DMSetLocalSection(DM dm, PetscSection section) 4331 { 4332 PetscInt numFields = 0; 4333 PetscInt f; 4334 PetscErrorCode ierr; 4335 4336 PetscFunctionBegin; 4337 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4338 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4339 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4340 ierr = PetscSectionDestroy(&dm->localSection);CHKERRQ(ierr); 4341 dm->localSection = section; 4342 if (section) {ierr = PetscSectionGetNumFields(dm->localSection, &numFields);CHKERRQ(ierr);} 4343 if (numFields) { 4344 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 4345 for (f = 0; f < numFields; ++f) { 4346 PetscObject disc; 4347 const char *name; 4348 4349 ierr = PetscSectionGetFieldName(dm->localSection, f, &name);CHKERRQ(ierr); 4350 ierr = DMGetField(dm, f, NULL, &disc);CHKERRQ(ierr); 4351 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 4352 } 4353 } 4354 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */ 4355 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4356 PetscFunctionReturn(0); 4357 } 4358 4359 /*@ 4360 DMGetDefaultConstraints - Get the PetscSection and Mat that specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 4361 4362 not collective 4363 4364 Input Parameter: 4365 . dm - The DM 4366 4367 Output Parameters: 4368 + 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. 4369 - 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. 4370 4371 Level: advanced 4372 4373 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 4374 4375 .seealso: DMSetDefaultConstraints() 4376 @*/ 4377 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 4378 { 4379 PetscErrorCode ierr; 4380 4381 PetscFunctionBegin; 4382 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4383 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 4384 if (section) {*section = dm->defaultConstraintSection;} 4385 if (mat) {*mat = dm->defaultConstraintMat;} 4386 PetscFunctionReturn(0); 4387 } 4388 4389 /*@ 4390 DMSetDefaultConstraints - Set the PetscSection and Mat that specify the local constraint interpolation. 4391 4392 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(). 4393 4394 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. 4395 4396 collective on dm 4397 4398 Input Parameters: 4399 + dm - The DM 4400 + 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). 4401 - 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). 4402 4403 Level: advanced 4404 4405 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 4406 4407 .seealso: DMGetDefaultConstraints() 4408 @*/ 4409 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 4410 { 4411 PetscMPIInt result; 4412 PetscErrorCode ierr; 4413 4414 PetscFunctionBegin; 4415 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4416 if (section) { 4417 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4418 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRMPI(ierr); 4419 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 4420 } 4421 if (mat) { 4422 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 4423 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRMPI(ierr); 4424 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 4425 } 4426 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4427 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 4428 dm->defaultConstraintSection = section; 4429 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 4430 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 4431 dm->defaultConstraintMat = mat; 4432 PetscFunctionReturn(0); 4433 } 4434 4435 #if defined(PETSC_USE_DEBUG) 4436 /* 4437 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 4438 4439 Input Parameters: 4440 + dm - The DM 4441 . localSection - PetscSection describing the local data layout 4442 - globalSection - PetscSection describing the global data layout 4443 4444 Level: intermediate 4445 4446 .seealso: DMGetSectionSF(), DMSetSectionSF() 4447 */ 4448 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 4449 { 4450 MPI_Comm comm; 4451 PetscLayout layout; 4452 const PetscInt *ranges; 4453 PetscInt pStart, pEnd, p, nroots; 4454 PetscMPIInt size, rank; 4455 PetscBool valid = PETSC_TRUE, gvalid; 4456 PetscErrorCode ierr; 4457 4458 PetscFunctionBegin; 4459 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4461 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 4462 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 4463 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4464 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4465 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4466 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4467 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4468 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4469 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4470 for (p = pStart; p < pEnd; ++p) { 4471 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 4472 4473 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4474 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4475 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4476 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4477 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4478 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4479 if (!gdof) continue; /* Censored point */ 4480 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;} 4481 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;} 4482 if (gdof < 0) { 4483 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4484 for (d = 0; d < gsize; ++d) { 4485 PetscInt offset = -(goff+1) + d, r; 4486 4487 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4488 if (r < 0) r = -(r+2); 4489 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;} 4490 } 4491 } 4492 } 4493 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4494 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 4495 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRMPI(ierr); 4496 if (!gvalid) { 4497 ierr = DMView(dm, NULL);CHKERRQ(ierr); 4498 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 4499 } 4500 PetscFunctionReturn(0); 4501 } 4502 #endif 4503 4504 /*@ 4505 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM. 4506 4507 Collective on dm 4508 4509 Input Parameter: 4510 . dm - The DM 4511 4512 Output Parameter: 4513 . section - The PetscSection 4514 4515 Level: intermediate 4516 4517 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4518 4519 .seealso: DMSetLocalSection(), DMGetLocalSection() 4520 @*/ 4521 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section) 4522 { 4523 PetscErrorCode ierr; 4524 4525 PetscFunctionBegin; 4526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4527 PetscValidPointer(section, 2); 4528 if (!dm->globalSection) { 4529 PetscSection s; 4530 4531 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 4532 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 4533 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection"); 4534 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection);CHKERRQ(ierr); 4535 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 4536 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map);CHKERRQ(ierr); 4537 ierr = PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view");CHKERRQ(ierr); 4538 } 4539 *section = dm->globalSection; 4540 PetscFunctionReturn(0); 4541 } 4542 4543 /*@ 4544 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM. 4545 4546 Input Parameters: 4547 + dm - The DM 4548 - section - The PetscSection, or NULL 4549 4550 Level: intermediate 4551 4552 Note: Any existing Section will be destroyed 4553 4554 .seealso: DMGetGlobalSection(), DMSetLocalSection() 4555 @*/ 4556 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section) 4557 { 4558 PetscErrorCode ierr; 4559 4560 PetscFunctionBegin; 4561 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4562 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4563 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4564 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4565 dm->globalSection = section; 4566 #if defined(PETSC_USE_DEBUG) 4567 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section);CHKERRQ(ierr);} 4568 #endif 4569 PetscFunctionReturn(0); 4570 } 4571 4572 /*@ 4573 DMGetSectionSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 4574 it is created from the default PetscSection layouts in the DM. 4575 4576 Input Parameter: 4577 . dm - The DM 4578 4579 Output Parameter: 4580 . sf - The PetscSF 4581 4582 Level: intermediate 4583 4584 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4585 4586 .seealso: DMSetSectionSF(), DMCreateSectionSF() 4587 @*/ 4588 PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf) 4589 { 4590 PetscInt nroots; 4591 PetscErrorCode ierr; 4592 4593 PetscFunctionBegin; 4594 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4595 PetscValidPointer(sf, 2); 4596 if (!dm->sectionSF) { 4597 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->sectionSF);CHKERRQ(ierr); 4598 } 4599 ierr = PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 4600 if (nroots < 0) { 4601 PetscSection section, gSection; 4602 4603 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 4604 if (section) { 4605 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr); 4606 ierr = DMCreateSectionSF(dm, section, gSection);CHKERRQ(ierr); 4607 } else { 4608 *sf = NULL; 4609 PetscFunctionReturn(0); 4610 } 4611 } 4612 *sf = dm->sectionSF; 4613 PetscFunctionReturn(0); 4614 } 4615 4616 /*@ 4617 DMSetSectionSF - Set the PetscSF encoding the parallel dof overlap for the DM 4618 4619 Input Parameters: 4620 + dm - The DM 4621 - sf - The PetscSF 4622 4623 Level: intermediate 4624 4625 Note: Any previous SF is destroyed 4626 4627 .seealso: DMGetSectionSF(), DMCreateSectionSF() 4628 @*/ 4629 PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf) 4630 { 4631 PetscErrorCode ierr; 4632 4633 PetscFunctionBegin; 4634 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4635 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4636 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4637 ierr = PetscSFDestroy(&dm->sectionSF);CHKERRQ(ierr); 4638 dm->sectionSF = sf; 4639 PetscFunctionReturn(0); 4640 } 4641 4642 /*@C 4643 DMCreateSectionSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 4644 describing the data layout. 4645 4646 Input Parameters: 4647 + dm - The DM 4648 . localSection - PetscSection describing the local data layout 4649 - globalSection - PetscSection describing the global data layout 4650 4651 Notes: One usually uses DMGetSectionSF() to obtain the PetscSF 4652 4653 Level: developer 4654 4655 Developer Note: Since this routine has for arguments the two sections from the DM and puts the resulting PetscSF 4656 directly into the DM, perhaps this function should not take the local and global sections as 4657 input and should just obtain them from the DM? 4658 4659 .seealso: DMGetSectionSF(), DMSetSectionSF(), DMGetLocalSection(), DMGetGlobalSection() 4660 @*/ 4661 PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection) 4662 { 4663 PetscErrorCode ierr; 4664 4665 PetscFunctionBegin; 4666 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4667 ierr = PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection);CHKERRQ(ierr); 4668 PetscFunctionReturn(0); 4669 } 4670 4671 /*@ 4672 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 4673 4674 Input Parameter: 4675 . dm - The DM 4676 4677 Output Parameter: 4678 . sf - The PetscSF 4679 4680 Level: intermediate 4681 4682 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4683 4684 .seealso: DMSetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4685 @*/ 4686 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 4687 { 4688 PetscFunctionBegin; 4689 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4690 PetscValidPointer(sf, 2); 4691 *sf = dm->sf; 4692 PetscFunctionReturn(0); 4693 } 4694 4695 /*@ 4696 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 4697 4698 Input Parameters: 4699 + dm - The DM 4700 - sf - The PetscSF 4701 4702 Level: intermediate 4703 4704 .seealso: DMGetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4705 @*/ 4706 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 4707 { 4708 PetscErrorCode ierr; 4709 4710 PetscFunctionBegin; 4711 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4712 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4713 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4714 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4715 dm->sf = sf; 4716 PetscFunctionReturn(0); 4717 } 4718 4719 /*@ 4720 DMGetNaturalSF - Get the PetscSF encoding the map back to the original mesh ordering 4721 4722 Input Parameter: 4723 . dm - The DM 4724 4725 Output Parameter: 4726 . sf - The PetscSF 4727 4728 Level: intermediate 4729 4730 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4731 4732 .seealso: DMSetNaturalSF(), DMSetUseNatural(), DMGetUseNatural(), DMPlexCreateGlobalToNaturalSF(), DMPlexDistribute() 4733 @*/ 4734 PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf) 4735 { 4736 PetscFunctionBegin; 4737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4738 PetscValidPointer(sf, 2); 4739 *sf = dm->sfNatural; 4740 PetscFunctionReturn(0); 4741 } 4742 4743 /*@ 4744 DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering 4745 4746 Input Parameters: 4747 + dm - The DM 4748 - sf - The PetscSF 4749 4750 Level: intermediate 4751 4752 .seealso: DMGetNaturalSF(), DMSetUseNatural(), DMGetUseNatural(), DMPlexCreateGlobalToNaturalSF(), DMPlexDistribute() 4753 @*/ 4754 PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf) 4755 { 4756 PetscErrorCode ierr; 4757 4758 PetscFunctionBegin; 4759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4760 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4761 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4762 ierr = PetscSFDestroy(&dm->sfNatural);CHKERRQ(ierr); 4763 dm->sfNatural = sf; 4764 PetscFunctionReturn(0); 4765 } 4766 4767 static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc) 4768 { 4769 PetscClassId id; 4770 PetscErrorCode ierr; 4771 4772 PetscFunctionBegin; 4773 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 4774 if (id == PETSCFE_CLASSID) { 4775 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4776 } else if (id == PETSCFV_CLASSID) { 4777 ierr = DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 4778 } else { 4779 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4780 } 4781 PetscFunctionReturn(0); 4782 } 4783 4784 static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew) 4785 { 4786 RegionField *tmpr; 4787 PetscInt Nf = dm->Nf, f; 4788 PetscErrorCode ierr; 4789 4790 PetscFunctionBegin; 4791 if (Nf >= NfNew) PetscFunctionReturn(0); 4792 ierr = PetscMalloc1(NfNew, &tmpr);CHKERRQ(ierr); 4793 for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f]; 4794 for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL; tmpr[f].avoidTensor = PETSC_FALSE;} 4795 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4796 dm->Nf = NfNew; 4797 dm->fields = tmpr; 4798 PetscFunctionReturn(0); 4799 } 4800 4801 /*@ 4802 DMClearFields - Remove all fields from the DM 4803 4804 Logically collective on dm 4805 4806 Input Parameter: 4807 . dm - The DM 4808 4809 Level: intermediate 4810 4811 .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField() 4812 @*/ 4813 PetscErrorCode DMClearFields(DM dm) 4814 { 4815 PetscInt f; 4816 PetscErrorCode ierr; 4817 4818 PetscFunctionBegin; 4819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4820 for (f = 0; f < dm->Nf; ++f) { 4821 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4822 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4823 } 4824 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4825 dm->fields = NULL; 4826 dm->Nf = 0; 4827 PetscFunctionReturn(0); 4828 } 4829 4830 /*@ 4831 DMGetNumFields - Get the number of fields in the DM 4832 4833 Not collective 4834 4835 Input Parameter: 4836 . dm - The DM 4837 4838 Output Parameter: 4839 . Nf - The number of fields 4840 4841 Level: intermediate 4842 4843 .seealso: DMSetNumFields(), DMSetField() 4844 @*/ 4845 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4846 { 4847 PetscFunctionBegin; 4848 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4849 PetscValidIntPointer(numFields, 2); 4850 *numFields = dm->Nf; 4851 PetscFunctionReturn(0); 4852 } 4853 4854 /*@ 4855 DMSetNumFields - Set the number of fields in the DM 4856 4857 Logically collective on dm 4858 4859 Input Parameters: 4860 + dm - The DM 4861 - Nf - The number of fields 4862 4863 Level: intermediate 4864 4865 .seealso: DMGetNumFields(), DMSetField() 4866 @*/ 4867 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4868 { 4869 PetscInt Nf, f; 4870 PetscErrorCode ierr; 4871 4872 PetscFunctionBegin; 4873 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4874 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4875 for (f = Nf; f < numFields; ++f) { 4876 PetscContainer obj; 4877 4878 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4879 ierr = DMAddField(dm, NULL, (PetscObject) obj);CHKERRQ(ierr); 4880 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4881 } 4882 PetscFunctionReturn(0); 4883 } 4884 4885 /*@ 4886 DMGetField - Return the discretization object for a given DM field 4887 4888 Not collective 4889 4890 Input Parameters: 4891 + dm - The DM 4892 - f - The field number 4893 4894 Output Parameters: 4895 + label - The label indicating the support of the field, or NULL for the entire mesh 4896 - field - The discretization object 4897 4898 Level: intermediate 4899 4900 .seealso: DMAddField(), DMSetField() 4901 @*/ 4902 PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field) 4903 { 4904 PetscFunctionBegin; 4905 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4906 PetscValidPointer(field, 4); 4907 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); 4908 if (label) *label = dm->fields[f].label; 4909 if (field) *field = dm->fields[f].disc; 4910 PetscFunctionReturn(0); 4911 } 4912 4913 /* Does not clear the DS */ 4914 PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject field) 4915 { 4916 PetscErrorCode ierr; 4917 4918 PetscFunctionBegin; 4919 ierr = DMFieldEnlarge_Static(dm, f+1);CHKERRQ(ierr); 4920 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4921 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4922 dm->fields[f].label = label; 4923 dm->fields[f].disc = field; 4924 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4925 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4926 PetscFunctionReturn(0); 4927 } 4928 4929 /*@ 4930 DMSetField - Set the discretization object for a given DM field 4931 4932 Logically collective on dm 4933 4934 Input Parameters: 4935 + dm - The DM 4936 . f - The field number 4937 . label - The label indicating the support of the field, or NULL for the entire mesh 4938 - field - The discretization object 4939 4940 Level: intermediate 4941 4942 .seealso: DMAddField(), DMGetField() 4943 @*/ 4944 PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field) 4945 { 4946 PetscErrorCode ierr; 4947 4948 PetscFunctionBegin; 4949 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4950 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4951 PetscValidHeader(field, 4); 4952 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 4953 ierr = DMSetField_Internal(dm, f, label, field);CHKERRQ(ierr); 4954 ierr = DMSetDefaultAdjacency_Private(dm, f, field);CHKERRQ(ierr); 4955 ierr = DMClearDS(dm);CHKERRQ(ierr); 4956 PetscFunctionReturn(0); 4957 } 4958 4959 /*@ 4960 DMAddField - Add the discretization object for the given DM field 4961 4962 Logically collective on dm 4963 4964 Input Parameters: 4965 + dm - The DM 4966 . label - The label indicating the support of the field, or NULL for the entire mesh 4967 - field - The discretization object 4968 4969 Level: intermediate 4970 4971 .seealso: DMSetField(), DMGetField() 4972 @*/ 4973 PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field) 4974 { 4975 PetscInt Nf = dm->Nf; 4976 PetscErrorCode ierr; 4977 4978 PetscFunctionBegin; 4979 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4980 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 4981 PetscValidHeader(field, 3); 4982 ierr = DMFieldEnlarge_Static(dm, Nf+1);CHKERRQ(ierr); 4983 dm->fields[Nf].label = label; 4984 dm->fields[Nf].disc = field; 4985 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4986 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4987 ierr = DMSetDefaultAdjacency_Private(dm, Nf, field);CHKERRQ(ierr); 4988 ierr = DMClearDS(dm);CHKERRQ(ierr); 4989 PetscFunctionReturn(0); 4990 } 4991 4992 /*@ 4993 DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells 4994 4995 Logically collective on dm 4996 4997 Input Parameters: 4998 + dm - The DM 4999 . f - The field index 5000 - avoidTensor - The flag to avoid defining the field on tensor cells 5001 5002 Level: intermediate 5003 5004 .seealso: DMGetFieldAvoidTensor(), DMSetField(), DMGetField() 5005 @*/ 5006 PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor) 5007 { 5008 PetscFunctionBegin; 5009 if ((f < 0) || (f >= dm->Nf)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Field %D is not in [0, %D)", f, dm->Nf); 5010 dm->fields[f].avoidTensor = avoidTensor; 5011 PetscFunctionReturn(0); 5012 } 5013 5014 /*@ 5015 DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells 5016 5017 Logically collective on dm 5018 5019 Input Parameters: 5020 + dm - The DM 5021 - f - The field index 5022 5023 Output Parameter: 5024 . avoidTensor - The flag to avoid defining the field on tensor cells 5025 5026 Level: intermediate 5027 5028 .seealso: DMSetFieldAvoidTensor(), DMSetField(), DMGetField() 5029 @*/ 5030 PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor) 5031 { 5032 PetscFunctionBegin; 5033 if ((f < 0) || (f >= dm->Nf)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Field %D is not in [0, %D)", f, dm->Nf); 5034 *avoidTensor = dm->fields[f].avoidTensor; 5035 PetscFunctionReturn(0); 5036 } 5037 5038 /*@ 5039 DMCopyFields - Copy the discretizations for the DM into another DM 5040 5041 Collective on dm 5042 5043 Input Parameter: 5044 . dm - The DM 5045 5046 Output Parameter: 5047 . newdm - The DM 5048 5049 Level: advanced 5050 5051 .seealso: DMGetField(), DMSetField(), DMAddField(), DMCopyDS(), DMGetDS(), DMGetCellDS() 5052 @*/ 5053 PetscErrorCode DMCopyFields(DM dm, DM newdm) 5054 { 5055 PetscInt Nf, f; 5056 PetscErrorCode ierr; 5057 5058 PetscFunctionBegin; 5059 if (dm == newdm) PetscFunctionReturn(0); 5060 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5061 ierr = DMClearFields(newdm);CHKERRQ(ierr); 5062 for (f = 0; f < Nf; ++f) { 5063 DMLabel label; 5064 PetscObject field; 5065 PetscBool useCone, useClosure; 5066 5067 ierr = DMGetField(dm, f, &label, &field);CHKERRQ(ierr); 5068 ierr = DMSetField(newdm, f, label, field);CHKERRQ(ierr); 5069 ierr = DMGetAdjacency(dm, f, &useCone, &useClosure);CHKERRQ(ierr); 5070 ierr = DMSetAdjacency(newdm, f, useCone, useClosure);CHKERRQ(ierr); 5071 } 5072 PetscFunctionReturn(0); 5073 } 5074 5075 /*@ 5076 DMGetAdjacency - Returns the flags for determining variable influence 5077 5078 Not collective 5079 5080 Input Parameters: 5081 + dm - The DM object 5082 - f - The field number, or PETSC_DEFAULT for the default adjacency 5083 5084 Output Parameters: 5085 + useCone - Flag for variable influence starting with the cone operation 5086 - useClosure - Flag for variable influence using transitive closure 5087 5088 Notes: 5089 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5090 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5091 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5092 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 5093 5094 Level: developer 5095 5096 .seealso: DMSetAdjacency(), DMGetField(), DMSetField() 5097 @*/ 5098 PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure) 5099 { 5100 PetscFunctionBegin; 5101 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5102 if (useCone) PetscValidBoolPointer(useCone, 3); 5103 if (useClosure) PetscValidBoolPointer(useClosure, 4); 5104 if (f < 0) { 5105 if (useCone) *useCone = dm->adjacency[0]; 5106 if (useClosure) *useClosure = dm->adjacency[1]; 5107 } else { 5108 PetscInt Nf; 5109 PetscErrorCode ierr; 5110 5111 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5112 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 5113 if (useCone) *useCone = dm->fields[f].adjacency[0]; 5114 if (useClosure) *useClosure = dm->fields[f].adjacency[1]; 5115 } 5116 PetscFunctionReturn(0); 5117 } 5118 5119 /*@ 5120 DMSetAdjacency - Set the flags for determining variable influence 5121 5122 Not collective 5123 5124 Input Parameters: 5125 + dm - The DM object 5126 . f - The field number 5127 . useCone - Flag for variable influence starting with the cone operation 5128 - useClosure - Flag for variable influence using transitive closure 5129 5130 Notes: 5131 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5132 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5133 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5134 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 5135 5136 Level: developer 5137 5138 .seealso: DMGetAdjacency(), DMGetField(), DMSetField() 5139 @*/ 5140 PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure) 5141 { 5142 PetscFunctionBegin; 5143 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5144 if (f < 0) { 5145 dm->adjacency[0] = useCone; 5146 dm->adjacency[1] = useClosure; 5147 } else { 5148 PetscInt Nf; 5149 PetscErrorCode ierr; 5150 5151 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5152 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 5153 dm->fields[f].adjacency[0] = useCone; 5154 dm->fields[f].adjacency[1] = useClosure; 5155 } 5156 PetscFunctionReturn(0); 5157 } 5158 5159 /*@ 5160 DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined 5161 5162 Not collective 5163 5164 Input Parameter: 5165 . dm - The DM object 5166 5167 Output Parameters: 5168 + useCone - Flag for variable influence starting with the cone operation 5169 - useClosure - Flag for variable influence using transitive closure 5170 5171 Notes: 5172 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5173 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5174 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5175 5176 Level: developer 5177 5178 .seealso: DMSetBasicAdjacency(), DMGetField(), DMSetField() 5179 @*/ 5180 PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure) 5181 { 5182 PetscInt Nf; 5183 PetscErrorCode ierr; 5184 5185 PetscFunctionBegin; 5186 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5187 if (useCone) PetscValidBoolPointer(useCone, 2); 5188 if (useClosure) PetscValidBoolPointer(useClosure, 3); 5189 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5190 if (!Nf) { 5191 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 5192 } else { 5193 ierr = DMGetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 5194 } 5195 PetscFunctionReturn(0); 5196 } 5197 5198 /*@ 5199 DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined 5200 5201 Not collective 5202 5203 Input Parameters: 5204 + dm - The DM object 5205 . useCone - Flag for variable influence starting with the cone operation 5206 - useClosure - Flag for variable influence using transitive closure 5207 5208 Notes: 5209 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 5210 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 5211 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 5212 5213 Level: developer 5214 5215 .seealso: DMGetBasicAdjacency(), DMGetField(), DMSetField() 5216 @*/ 5217 PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure) 5218 { 5219 PetscInt Nf; 5220 PetscErrorCode ierr; 5221 5222 PetscFunctionBegin; 5223 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5224 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5225 if (!Nf) { 5226 ierr = DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 5227 } else { 5228 ierr = DMSetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 5229 } 5230 PetscFunctionReturn(0); 5231 } 5232 5233 /* Complete labels that are being used for FEM BC */ 5234 static PetscErrorCode DMCompleteBoundaryLabel_Internal(DM dm, PetscDS ds, PetscInt field, PetscInt bdNum, DMLabel label) 5235 { 5236 PetscObject obj; 5237 PetscClassId id; 5238 PetscInt Nbd, bd; 5239 PetscBool isFE = PETSC_FALSE; 5240 PetscBool duplicate = PETSC_FALSE; 5241 PetscErrorCode ierr; 5242 5243 PetscFunctionBegin; 5244 ierr = DMGetField(dm, field, NULL, &obj);CHKERRQ(ierr); 5245 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5246 if (id == PETSCFE_CLASSID) isFE = PETSC_TRUE; 5247 if (isFE && label) { 5248 /* Only want to modify label once */ 5249 ierr = PetscDSGetNumBoundary(ds, &Nbd);CHKERRQ(ierr); 5250 for (bd = 0; bd < PetscMin(Nbd, bdNum); ++bd) { 5251 DMLabel l; 5252 5253 ierr = PetscDSGetBoundary(ds, bd, NULL, NULL, NULL, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5254 duplicate = l == label ? PETSC_TRUE : PETSC_FALSE; 5255 if (duplicate) break; 5256 } 5257 if (!duplicate) { 5258 DM plex; 5259 5260 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5261 if (plex) {ierr = DMPlexLabelComplete(plex, label);CHKERRQ(ierr);} 5262 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5263 } 5264 } 5265 PetscFunctionReturn(0); 5266 } 5267 5268 static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew) 5269 { 5270 DMSpace *tmpd; 5271 PetscInt Nds = dm->Nds, s; 5272 PetscErrorCode ierr; 5273 5274 PetscFunctionBegin; 5275 if (Nds >= NdsNew) PetscFunctionReturn(0); 5276 ierr = PetscMalloc1(NdsNew, &tmpd);CHKERRQ(ierr); 5277 for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s]; 5278 for (s = Nds; s < NdsNew; ++s) {tmpd[s].ds = NULL; tmpd[s].label = NULL; tmpd[s].fields = NULL;} 5279 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 5280 dm->Nds = NdsNew; 5281 dm->probs = tmpd; 5282 PetscFunctionReturn(0); 5283 } 5284 5285 /*@ 5286 DMGetNumDS - Get the number of discrete systems in the DM 5287 5288 Not collective 5289 5290 Input Parameter: 5291 . dm - The DM 5292 5293 Output Parameter: 5294 . Nds - The number of PetscDS objects 5295 5296 Level: intermediate 5297 5298 .seealso: DMGetDS(), DMGetCellDS() 5299 @*/ 5300 PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds) 5301 { 5302 PetscFunctionBegin; 5303 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5304 PetscValidIntPointer(Nds, 2); 5305 *Nds = dm->Nds; 5306 PetscFunctionReturn(0); 5307 } 5308 5309 /*@ 5310 DMClearDS - Remove all discrete systems from the DM 5311 5312 Logically collective on dm 5313 5314 Input Parameter: 5315 . dm - The DM 5316 5317 Level: intermediate 5318 5319 .seealso: DMGetNumDS(), DMGetDS(), DMSetField() 5320 @*/ 5321 PetscErrorCode DMClearDS(DM dm) 5322 { 5323 PetscInt s; 5324 PetscErrorCode ierr; 5325 5326 PetscFunctionBegin; 5327 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5328 for (s = 0; s < dm->Nds; ++s) { 5329 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 5330 ierr = DMLabelDestroy(&dm->probs[s].label);CHKERRQ(ierr); 5331 ierr = ISDestroy(&dm->probs[s].fields);CHKERRQ(ierr); 5332 } 5333 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 5334 dm->probs = NULL; 5335 dm->Nds = 0; 5336 PetscFunctionReturn(0); 5337 } 5338 5339 /*@ 5340 DMGetDS - Get the default PetscDS 5341 5342 Not collective 5343 5344 Input Parameter: 5345 . dm - The DM 5346 5347 Output Parameter: 5348 . prob - The default PetscDS 5349 5350 Level: intermediate 5351 5352 .seealso: DMGetCellDS(), DMGetRegionDS() 5353 @*/ 5354 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 5355 { 5356 PetscErrorCode ierr; 5357 5358 PetscFunctionBeginHot; 5359 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5360 PetscValidPointer(prob, 2); 5361 if (dm->Nds <= 0) { 5362 PetscDS ds; 5363 5364 ierr = PetscDSCreate(PETSC_COMM_SELF, &ds);CHKERRQ(ierr); 5365 ierr = DMSetRegionDS(dm, NULL, NULL, ds);CHKERRQ(ierr); 5366 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 5367 } 5368 *prob = dm->probs[0].ds; 5369 PetscFunctionReturn(0); 5370 } 5371 5372 /*@ 5373 DMGetCellDS - Get the PetscDS defined on a given cell 5374 5375 Not collective 5376 5377 Input Parameters: 5378 + dm - The DM 5379 - point - Cell for the DS 5380 5381 Output Parameter: 5382 . prob - The PetscDS defined on the given cell 5383 5384 Level: developer 5385 5386 .seealso: DMGetDS(), DMSetRegionDS() 5387 @*/ 5388 PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob) 5389 { 5390 PetscDS probDef = NULL; 5391 PetscInt s; 5392 PetscErrorCode ierr; 5393 5394 PetscFunctionBeginHot; 5395 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5396 PetscValidPointer(prob, 3); 5397 if (point < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %D", point); 5398 *prob = NULL; 5399 for (s = 0; s < dm->Nds; ++s) { 5400 PetscInt val; 5401 5402 if (!dm->probs[s].label) {probDef = dm->probs[s].ds;} 5403 else { 5404 ierr = DMLabelGetValue(dm->probs[s].label, point, &val);CHKERRQ(ierr); 5405 if (val >= 0) {*prob = dm->probs[s].ds; break;} 5406 } 5407 } 5408 if (!*prob) *prob = probDef; 5409 PetscFunctionReturn(0); 5410 } 5411 5412 /*@ 5413 DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel 5414 5415 Not collective 5416 5417 Input Parameters: 5418 + dm - The DM 5419 - label - The DMLabel defining the mesh region, or NULL for the entire mesh 5420 5421 Output Parameters: 5422 + fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5423 - prob - The PetscDS defined on the given region, or NULL 5424 5425 Note: If the label is missing, this function returns an error 5426 5427 Level: advanced 5428 5429 .seealso: DMGetRegionNumDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5430 @*/ 5431 PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds) 5432 { 5433 PetscInt Nds = dm->Nds, s; 5434 5435 PetscFunctionBegin; 5436 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5437 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5438 if (fields) {PetscValidPointer(fields, 3); *fields = NULL;} 5439 if (ds) {PetscValidPointer(ds, 4); *ds = NULL;} 5440 for (s = 0; s < Nds; ++s) { 5441 if (dm->probs[s].label == label) { 5442 if (fields) *fields = dm->probs[s].fields; 5443 if (ds) *ds = dm->probs[s].ds; 5444 PetscFunctionReturn(0); 5445 } 5446 } 5447 PetscFunctionReturn(0); 5448 } 5449 5450 /*@ 5451 DMSetRegionDS - Set the PetscDS for a given mesh region, defined by a DMLabel 5452 5453 Collective on dm 5454 5455 Input Parameters: 5456 + dm - The DM 5457 . label - The DMLabel defining the mesh region, or NULL for the entire mesh 5458 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL for all fields 5459 - prob - The PetscDS defined on the given cell 5460 5461 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. If DS is replaced, 5462 the fields argument is ignored. 5463 5464 Level: advanced 5465 5466 .seealso: DMGetRegionDS(), DMSetRegionNumDS(), DMGetDS(), DMGetCellDS() 5467 @*/ 5468 PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds) 5469 { 5470 PetscInt Nds = dm->Nds, s; 5471 PetscErrorCode ierr; 5472 5473 PetscFunctionBegin; 5474 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5475 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5476 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4); 5477 for (s = 0; s < Nds; ++s) { 5478 if (dm->probs[s].label == label) { 5479 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 5480 dm->probs[s].ds = ds; 5481 PetscFunctionReturn(0); 5482 } 5483 } 5484 ierr = DMDSEnlarge_Static(dm, Nds+1);CHKERRQ(ierr); 5485 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 5486 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr); 5487 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr); 5488 if (!label) { 5489 /* Put the NULL label at the front, so it is returned as the default */ 5490 for (s = Nds-1; s >=0; --s) dm->probs[s+1] = dm->probs[s]; 5491 Nds = 0; 5492 } 5493 dm->probs[Nds].label = label; 5494 dm->probs[Nds].fields = fields; 5495 dm->probs[Nds].ds = ds; 5496 PetscFunctionReturn(0); 5497 } 5498 5499 /*@ 5500 DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number 5501 5502 Not collective 5503 5504 Input Parameters: 5505 + dm - The DM 5506 - num - The region number, in [0, Nds) 5507 5508 Output Parameters: 5509 + label - The region label, or NULL 5510 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5511 - ds - The PetscDS defined on the given region, or NULL 5512 5513 Level: advanced 5514 5515 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5516 @*/ 5517 PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds) 5518 { 5519 PetscInt Nds; 5520 PetscErrorCode ierr; 5521 5522 PetscFunctionBegin; 5523 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5524 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5525 if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds); 5526 if (label) { 5527 PetscValidPointer(label, 3); 5528 *label = dm->probs[num].label; 5529 } 5530 if (fields) { 5531 PetscValidPointer(fields, 4); 5532 *fields = dm->probs[num].fields; 5533 } 5534 if (ds) { 5535 PetscValidPointer(ds, 5); 5536 *ds = dm->probs[num].ds; 5537 } 5538 PetscFunctionReturn(0); 5539 } 5540 5541 /*@ 5542 DMSetRegionNumDS - Set the PetscDS for a given mesh region, defined by the region number 5543 5544 Not collective 5545 5546 Input Parameters: 5547 + dm - The DM 5548 . num - The region number, in [0, Nds) 5549 . label - The region label, or NULL 5550 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL to prevent setting 5551 - ds - The PetscDS defined on the given region, or NULL to prevent setting 5552 5553 Level: advanced 5554 5555 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5556 @*/ 5557 PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds) 5558 { 5559 PetscInt Nds; 5560 PetscErrorCode ierr; 5561 5562 PetscFunctionBegin; 5563 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5564 if (label) {PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);} 5565 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5566 if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds); 5567 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 5568 ierr = DMLabelDestroy(&dm->probs[num].label);CHKERRQ(ierr); 5569 dm->probs[num].label = label; 5570 if (fields) { 5571 PetscValidHeaderSpecific(fields, IS_CLASSID, 4); 5572 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr); 5573 ierr = ISDestroy(&dm->probs[num].fields);CHKERRQ(ierr); 5574 dm->probs[num].fields = fields; 5575 } 5576 if (ds) { 5577 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5); 5578 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr); 5579 ierr = PetscDSDestroy(&dm->probs[num].ds);CHKERRQ(ierr); 5580 dm->probs[num].ds = ds; 5581 } 5582 PetscFunctionReturn(0); 5583 } 5584 5585 /*@ 5586 DMFindRegionNum - Find the region number for a given PetscDS, or -1 if it is not found. 5587 5588 Not collective 5589 5590 Input Parameters: 5591 + dm - The DM 5592 - ds - The PetscDS defined on the given region 5593 5594 Output Parameter: 5595 . num - The region number, in [0, Nds), or -1 if not found 5596 5597 Level: advanced 5598 5599 .seealso: DMGetRegionNumDS(), DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5600 @*/ 5601 PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num) 5602 { 5603 PetscInt Nds, n; 5604 PetscErrorCode ierr; 5605 5606 PetscFunctionBegin; 5607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5608 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2); 5609 PetscValidPointer(num, 3); 5610 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5611 for (n = 0; n < Nds; ++n) if (ds == dm->probs[n].ds) break; 5612 if (n >= Nds) *num = -1; 5613 else *num = n; 5614 PetscFunctionReturn(0); 5615 } 5616 5617 /*@ 5618 DMCreateDS - Create the discrete systems for the DM based upon the fields added to the DM 5619 5620 Collective on dm 5621 5622 Input Parameter: 5623 . dm - The DM 5624 5625 Options Database Keys: 5626 . -dm_petscds_view - View all the PetscDS objects in this DM 5627 5628 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. 5629 5630 Level: intermediate 5631 5632 .seealso: DMSetField, DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5633 @*/ 5634 PetscErrorCode DMCreateDS(DM dm) 5635 { 5636 MPI_Comm comm; 5637 PetscDS dsDef; 5638 DMLabel *labelSet; 5639 PetscInt dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k; 5640 PetscBool doSetup = PETSC_TRUE, flg; 5641 PetscErrorCode ierr; 5642 5643 PetscFunctionBegin; 5644 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5645 if (!dm->fields) PetscFunctionReturn(0); 5646 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 5647 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 5648 /* Determine how many regions we have */ 5649 ierr = PetscMalloc1(Nf, &labelSet);CHKERRQ(ierr); 5650 Nl = 0; 5651 Ndef = 0; 5652 for (f = 0; f < Nf; ++f) { 5653 DMLabel label = dm->fields[f].label; 5654 PetscInt l; 5655 5656 #ifdef PETSC_HAVE_LIBCEED 5657 /* Move CEED context to discretizations */ 5658 { 5659 PetscClassId id; 5660 5661 ierr = PetscObjectGetClassId(dm->fields[f].disc, &id);CHKERRQ(ierr); 5662 if (id == PETSCFE_CLASSID) { 5663 Ceed ceed; 5664 5665 ierr = DMGetCeed(dm, &ceed);CHKERRQ(ierr); 5666 ierr = PetscFESetCeed((PetscFE) dm->fields[f].disc, ceed);CHKERRQ(ierr); 5667 } 5668 } 5669 #endif 5670 if (!label) {++Ndef; continue;} 5671 for (l = 0; l < Nl; ++l) if (label == labelSet[l]) break; 5672 if (l < Nl) continue; 5673 labelSet[Nl++] = label; 5674 } 5675 /* Create default DS if there are no labels to intersect with */ 5676 ierr = DMGetRegionDS(dm, NULL, NULL, &dsDef);CHKERRQ(ierr); 5677 if (!dsDef && Ndef && !Nl) { 5678 IS fields; 5679 PetscInt *fld, nf; 5680 5681 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) ++nf; 5682 if (nf) { 5683 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr); 5684 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) fld[nf++] = f; 5685 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5686 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5687 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5688 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5689 5690 ierr = PetscDSCreate(PETSC_COMM_SELF, &dsDef);CHKERRQ(ierr); 5691 ierr = DMSetRegionDS(dm, NULL, fields, dsDef);CHKERRQ(ierr); 5692 ierr = PetscDSDestroy(&dsDef);CHKERRQ(ierr); 5693 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5694 } 5695 } 5696 ierr = DMGetRegionDS(dm, NULL, NULL, &dsDef);CHKERRQ(ierr); 5697 if (dsDef) {ierr = PetscDSSetCoordinateDimension(dsDef, dE);CHKERRQ(ierr);} 5698 /* Intersect labels with default fields */ 5699 if (Ndef && Nl) { 5700 DM plex; 5701 DMLabel cellLabel; 5702 IS fieldIS, allcellIS, defcellIS = NULL; 5703 PetscInt *fields; 5704 const PetscInt *cells; 5705 PetscInt depth, nf = 0, n, c; 5706 5707 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5708 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 5709 ierr = DMGetStratumIS(plex, "dim", depth, &allcellIS);CHKERRQ(ierr); 5710 if (!allcellIS) {ierr = DMGetStratumIS(plex, "depth", depth, &allcellIS);CHKERRQ(ierr);} 5711 for (l = 0; l < Nl; ++l) { 5712 DMLabel label = labelSet[l]; 5713 IS pointIS; 5714 5715 ierr = ISDestroy(&defcellIS);CHKERRQ(ierr); 5716 ierr = DMLabelGetStratumIS(label, 1, &pointIS);CHKERRQ(ierr); 5717 ierr = ISDifference(allcellIS, pointIS, &defcellIS);CHKERRQ(ierr); 5718 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 5719 } 5720 ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 5721 5722 ierr = DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel);CHKERRQ(ierr); 5723 ierr = ISGetLocalSize(defcellIS, &n);CHKERRQ(ierr); 5724 ierr = ISGetIndices(defcellIS, &cells);CHKERRQ(ierr); 5725 for (c = 0; c < n; ++c) {ierr = DMLabelSetValue(cellLabel, cells[c], 1);CHKERRQ(ierr);} 5726 ierr = ISRestoreIndices(defcellIS, &cells);CHKERRQ(ierr); 5727 ierr = ISDestroy(&defcellIS);CHKERRQ(ierr); 5728 ierr = DMPlexLabelComplete(plex, cellLabel);CHKERRQ(ierr); 5729 5730 ierr = PetscMalloc1(Ndef, &fields);CHKERRQ(ierr); 5731 for (f = 0; f < Nf; ++f) if (!dm->fields[f].label) fields[nf++] = f; 5732 ierr = ISCreate(PETSC_COMM_SELF, &fieldIS);CHKERRQ(ierr); 5733 ierr = PetscObjectSetOptionsPrefix((PetscObject) fieldIS, "dm_fields_");CHKERRQ(ierr); 5734 ierr = ISSetType(fieldIS, ISGENERAL);CHKERRQ(ierr); 5735 ierr = ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER);CHKERRQ(ierr); 5736 5737 ierr = PetscDSCreate(PETSC_COMM_SELF, &dsDef);CHKERRQ(ierr); 5738 ierr = DMSetRegionDS(dm, cellLabel, fieldIS, dsDef);CHKERRQ(ierr); 5739 ierr = DMLabelDestroy(&cellLabel);CHKERRQ(ierr); 5740 ierr = PetscDSSetCoordinateDimension(dsDef, dE);CHKERRQ(ierr); 5741 ierr = PetscDSDestroy(&dsDef);CHKERRQ(ierr); 5742 ierr = ISDestroy(&fieldIS);CHKERRQ(ierr); 5743 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5744 } 5745 /* Create label DSes 5746 - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS 5747 */ 5748 /* TODO Should check that labels are disjoint */ 5749 for (l = 0; l < Nl; ++l) { 5750 DMLabel label = labelSet[l]; 5751 PetscDS ds; 5752 IS fields; 5753 PetscInt *fld, nf; 5754 5755 ierr = PetscDSCreate(PETSC_COMM_SELF, &ds);CHKERRQ(ierr); 5756 for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) ++nf; 5757 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr); 5758 for (f = 0, nf = 0; f < Nf; ++f) if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f; 5759 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5760 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5761 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5762 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5763 ierr = DMSetRegionDS(dm, label, fields, ds);CHKERRQ(ierr); 5764 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5765 ierr = PetscDSSetCoordinateDimension(ds, dE);CHKERRQ(ierr); 5766 { 5767 DMPolytopeType ct; 5768 PetscInt lStart, lEnd; 5769 PetscBool isHybridLocal = PETSC_FALSE, isHybrid; 5770 5771 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr); 5772 if (lStart >= 0) { 5773 ierr = DMPlexGetCellType(dm, lStart, &ct);CHKERRQ(ierr); 5774 switch (ct) { 5775 case DM_POLYTOPE_POINT_PRISM_TENSOR: 5776 case DM_POLYTOPE_SEG_PRISM_TENSOR: 5777 case DM_POLYTOPE_TRI_PRISM_TENSOR: 5778 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 5779 isHybridLocal = PETSC_TRUE;break; 5780 default: break; 5781 } 5782 } 5783 ierr = MPI_Allreduce(&isHybridLocal, &isHybrid, 1, MPIU_BOOL, MPI_LOR, comm);CHKERRMPI(ierr); 5784 ierr = PetscDSSetHybrid(ds, isHybrid);CHKERRQ(ierr); 5785 } 5786 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 5787 } 5788 ierr = PetscFree(labelSet);CHKERRQ(ierr); 5789 /* Set fields in DSes */ 5790 for (s = 0; s < dm->Nds; ++s) { 5791 PetscDS ds = dm->probs[s].ds; 5792 IS fields = dm->probs[s].fields; 5793 const PetscInt *fld; 5794 PetscInt nf; 5795 5796 ierr = ISGetLocalSize(fields, &nf);CHKERRQ(ierr); 5797 ierr = ISGetIndices(fields, &fld);CHKERRQ(ierr); 5798 for (f = 0; f < nf; ++f) { 5799 PetscObject disc = dm->fields[fld[f]].disc; 5800 PetscBool isHybrid; 5801 PetscClassId id; 5802 5803 ierr = PetscDSGetHybrid(ds, &isHybrid);CHKERRQ(ierr); 5804 /* If this is a cohesive cell, then it needs the lower dimensional discretization */ 5805 if (isHybrid && f < nf-1) {ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, (PetscFE *) &disc);CHKERRQ(ierr);} 5806 ierr = PetscDSSetDiscretization(ds, f, disc);CHKERRQ(ierr); 5807 /* We allow people to have placeholder fields and construct the Section by hand */ 5808 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 5809 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE; 5810 } 5811 ierr = ISRestoreIndices(fields, &fld);CHKERRQ(ierr); 5812 } 5813 /* Allow k-jet tabulation */ 5814 ierr = PetscOptionsGetInt(NULL, ((PetscObject) dm)->prefix, "-dm_ds_jet_degree", &k, &flg);CHKERRQ(ierr); 5815 if (flg) { 5816 for (s = 0; s < dm->Nds; ++s) { 5817 PetscDS ds = dm->probs[s].ds; 5818 PetscInt Nf, f; 5819 5820 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 5821 for (f = 0; f < Nf; ++f) {ierr = PetscDSSetJetDegree(ds, f, k);CHKERRQ(ierr);} 5822 } 5823 } 5824 /* Setup DSes */ 5825 if (doSetup) { 5826 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 5827 } 5828 PetscFunctionReturn(0); 5829 } 5830 5831 /*@ 5832 DMComputeExactSolution - Compute the exact solution for a given DM, using the PetscDS information. 5833 5834 Collective on DM 5835 5836 Input Parameters: 5837 + dm - The DM 5838 - time - The time 5839 5840 Output Parameters: 5841 + u - The vector will be filled with exact solution values, or NULL 5842 - u_t - The vector will be filled with the time derivative of exact solution values, or NULL 5843 5844 Note: The user must call PetscDSSetExactSolution() beforehand 5845 5846 Level: developer 5847 5848 .seealso: PetscDSSetExactSolution() 5849 @*/ 5850 PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t) 5851 { 5852 PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 5853 void **ectxs; 5854 PetscInt Nf, Nds, s; 5855 PetscErrorCode ierr; 5856 5857 PetscFunctionBegin; 5858 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5859 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 5860 if (u_t) PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4); 5861 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5862 ierr = PetscMalloc2(Nf, &exacts, Nf, &ectxs);CHKERRQ(ierr); 5863 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5864 for (s = 0; s < Nds; ++s) { 5865 PetscDS ds; 5866 DMLabel label; 5867 IS fieldIS; 5868 const PetscInt *fields, id = 1; 5869 PetscInt dsNf, f; 5870 5871 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 5872 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 5873 ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 5874 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 5875 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 5876 if (u) { 5877 for (f = 0; f < dsNf; ++f) { 5878 const PetscInt field = fields[f]; 5879 ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 5880 } 5881 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 5882 if (label) { 5883 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 5884 } else { 5885 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 5886 } 5887 } 5888 if (u_t) { 5889 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 5890 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 5891 for (f = 0; f < dsNf; ++f) { 5892 const PetscInt field = fields[f]; 5893 ierr = PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 5894 } 5895 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 5896 if (label) { 5897 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 5898 } else { 5899 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 5900 } 5901 } 5902 } 5903 if (u) { 5904 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution");CHKERRQ(ierr); 5905 ierr = PetscObjectSetOptionsPrefix((PetscObject) u, "exact_");CHKERRQ(ierr); 5906 } 5907 if (u_t) { 5908 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution Time Derivative");CHKERRQ(ierr); 5909 ierr = PetscObjectSetOptionsPrefix((PetscObject) u_t, "exact_t_");CHKERRQ(ierr); 5910 } 5911 ierr = PetscFree2(exacts, ectxs);CHKERRQ(ierr); 5912 PetscFunctionReturn(0); 5913 } 5914 5915 PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds) 5916 { 5917 PetscDS dsNew; 5918 DSBoundary b; 5919 PetscInt cdim, Nf, f; 5920 PetscBool isHybrid; 5921 void *ctx; 5922 PetscErrorCode ierr; 5923 5924 PetscFunctionBegin; 5925 ierr = PetscDSCreate(PetscObjectComm((PetscObject) ds), &dsNew);CHKERRQ(ierr); 5926 ierr = PetscDSCopyConstants(ds, dsNew);CHKERRQ(ierr); 5927 ierr = PetscDSCopyExactSolutions(ds, dsNew);CHKERRQ(ierr); 5928 ierr = PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 5929 ierr = PetscDSCopyEquations(ds, dsNew);CHKERRQ(ierr); 5930 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 5931 for (f = 0; f < Nf; ++f) { 5932 ierr = PetscDSGetContext(ds, f, &ctx);CHKERRQ(ierr); 5933 ierr = PetscDSSetContext(dsNew, f, ctx);CHKERRQ(ierr); 5934 } 5935 if (Nf) { 5936 ierr = PetscDSGetCoordinateDimension(ds, &cdim);CHKERRQ(ierr); 5937 ierr = PetscDSSetCoordinateDimension(dsNew, cdim);CHKERRQ(ierr); 5938 } 5939 ierr = PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 5940 for (b = dsNew->boundary; b; b = b->next) { 5941 ierr = DMGetLabel(dm, b->lname, &b->label);CHKERRQ(ierr); 5942 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 5943 //if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name); 5944 } 5945 ierr = PetscDSGetHybrid(ds, &isHybrid);CHKERRQ(ierr); 5946 ierr = PetscDSSetHybrid(dsNew, isHybrid);CHKERRQ(ierr); 5947 5948 ierr = DMSetRegionDS(dm, label, fields, dsNew);CHKERRQ(ierr); 5949 ierr = PetscDSDestroy(&dsNew);CHKERRQ(ierr); 5950 PetscFunctionReturn(0); 5951 } 5952 5953 /*@ 5954 DMCopyDS - Copy the discrete systems for the DM into another DM 5955 5956 Collective on dm 5957 5958 Input Parameter: 5959 . dm - The DM 5960 5961 Output Parameter: 5962 . newdm - The DM 5963 5964 Level: advanced 5965 5966 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5967 @*/ 5968 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5969 { 5970 PetscInt Nds, s; 5971 PetscErrorCode ierr; 5972 5973 PetscFunctionBegin; 5974 if (dm == newdm) PetscFunctionReturn(0); 5975 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5976 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5977 for (s = 0; s < Nds; ++s) { 5978 DMLabel label; 5979 IS fields; 5980 PetscDS ds, newds; 5981 PetscInt Nbd, bd; 5982 5983 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5984 /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */ 5985 ierr = DMTransferDS_Internal(newdm, label, fields, ds);CHKERRQ(ierr); 5986 /* Commplete new labels in the new DS */ 5987 ierr = DMGetRegionDS(newdm, label, NULL, &newds);CHKERRQ(ierr); 5988 ierr = PetscDSGetNumBoundary(newds, &Nbd);CHKERRQ(ierr); 5989 for (bd = 0; bd < Nbd; ++bd) { 5990 PetscWeakForm wf; 5991 DMLabel label; 5992 PetscInt field; 5993 5994 ierr = PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5995 ierr = DMCompleteBoundaryLabel_Internal(newdm, newds, field, bd, label);CHKERRQ(ierr); 5996 ierr = PetscWeakFormReplaceLabel(wf, label);CHKERRQ(ierr); 5997 } 5998 } 5999 PetscFunctionReturn(0); 6000 } 6001 6002 /*@ 6003 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 6004 6005 Collective on dm 6006 6007 Input Parameter: 6008 . dm - The DM 6009 6010 Output Parameter: 6011 . newdm - The DM 6012 6013 Level: advanced 6014 6015 .seealso: DMCopyFields(), DMCopyDS() 6016 @*/ 6017 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 6018 { 6019 PetscErrorCode ierr; 6020 6021 PetscFunctionBegin; 6022 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 6023 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 6024 PetscFunctionReturn(0); 6025 } 6026 6027 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 6028 { 6029 DM dm_coord,dmc_coord; 6030 PetscErrorCode ierr; 6031 Vec coords,ccoords; 6032 Mat inject; 6033 PetscFunctionBegin; 6034 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 6035 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 6036 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 6037 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 6038 if (coords && !ccoords) { 6039 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 6040 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 6041 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 6042 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 6043 ierr = MatDestroy(&inject);CHKERRQ(ierr); 6044 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 6045 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 6046 } 6047 PetscFunctionReturn(0); 6048 } 6049 6050 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 6051 { 6052 DM dm_coord,subdm_coord; 6053 PetscErrorCode ierr; 6054 Vec coords,ccoords,clcoords; 6055 VecScatter *scat_i,*scat_g; 6056 PetscFunctionBegin; 6057 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 6058 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 6059 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 6060 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 6061 if (coords && !ccoords) { 6062 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 6063 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 6064 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 6065 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 6066 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 6067 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6068 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6069 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6070 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 6071 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 6072 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 6073 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 6074 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 6075 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 6076 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 6077 ierr = PetscFree(scat_i);CHKERRQ(ierr); 6078 ierr = PetscFree(scat_g);CHKERRQ(ierr); 6079 } 6080 PetscFunctionReturn(0); 6081 } 6082 6083 /*@ 6084 DMGetDimension - Return the topological dimension of the DM 6085 6086 Not collective 6087 6088 Input Parameter: 6089 . dm - The DM 6090 6091 Output Parameter: 6092 . dim - The topological dimension 6093 6094 Level: beginner 6095 6096 .seealso: DMSetDimension(), DMCreate() 6097 @*/ 6098 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 6099 { 6100 PetscFunctionBegin; 6101 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6102 PetscValidIntPointer(dim, 2); 6103 *dim = dm->dim; 6104 PetscFunctionReturn(0); 6105 } 6106 6107 /*@ 6108 DMSetDimension - Set the topological dimension of the DM 6109 6110 Collective on dm 6111 6112 Input Parameters: 6113 + dm - The DM 6114 - dim - The topological dimension 6115 6116 Level: beginner 6117 6118 .seealso: DMGetDimension(), DMCreate() 6119 @*/ 6120 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 6121 { 6122 PetscDS ds; 6123 PetscInt Nds, n; 6124 PetscErrorCode ierr; 6125 6126 PetscFunctionBegin; 6127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6128 PetscValidLogicalCollectiveInt(dm, dim, 2); 6129 dm->dim = dim; 6130 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6131 for (n = 0; n < Nds; ++n) { 6132 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 6133 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr);} 6134 } 6135 PetscFunctionReturn(0); 6136 } 6137 6138 /*@ 6139 DMGetDimPoints - Get the half-open interval for all points of a given dimension 6140 6141 Collective on dm 6142 6143 Input Parameters: 6144 + dm - the DM 6145 - dim - the dimension 6146 6147 Output Parameters: 6148 + pStart - The first point of the given dimension 6149 - pEnd - The first point following points of the given dimension 6150 6151 Note: 6152 The points are vertices in the Hasse diagram encoding the topology. This is explained in 6153 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 6154 then the interval is empty. 6155 6156 Level: intermediate 6157 6158 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 6159 @*/ 6160 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 6161 { 6162 PetscInt d; 6163 PetscErrorCode ierr; 6164 6165 PetscFunctionBegin; 6166 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6167 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 6168 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 6169 if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name); 6170 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 6171 PetscFunctionReturn(0); 6172 } 6173 6174 /*@ 6175 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 6176 6177 Collective on dm 6178 6179 Input Parameters: 6180 + dm - the DM 6181 - c - coordinate vector 6182 6183 Notes: 6184 The coordinates do include those for ghost points, which are in the local vector. 6185 6186 The vector c should be destroyed by the caller. 6187 6188 Level: intermediate 6189 6190 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6191 @*/ 6192 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 6193 { 6194 PetscErrorCode ierr; 6195 6196 PetscFunctionBegin; 6197 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6198 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6199 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6200 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6201 dm->coordinates = c; 6202 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6203 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6204 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6205 PetscFunctionReturn(0); 6206 } 6207 6208 /*@ 6209 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 6210 6211 Not collective 6212 6213 Input Parameters: 6214 + dm - the DM 6215 - c - coordinate vector 6216 6217 Notes: 6218 The coordinates of ghost points can be set using DMSetCoordinates() 6219 followed by DMGetCoordinatesLocal(). This is intended to enable the 6220 setting of ghost coordinates outside of the domain. 6221 6222 The vector c should be destroyed by the caller. 6223 6224 Level: intermediate 6225 6226 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 6227 @*/ 6228 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 6229 { 6230 PetscErrorCode ierr; 6231 6232 PetscFunctionBegin; 6233 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6234 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6235 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6236 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6237 6238 dm->coordinatesLocal = c; 6239 6240 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6241 PetscFunctionReturn(0); 6242 } 6243 6244 /*@ 6245 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 6246 6247 Collective on dm 6248 6249 Input Parameter: 6250 . dm - the DM 6251 6252 Output Parameter: 6253 . c - global coordinate vector 6254 6255 Note: 6256 This is a borrowed reference, so the user should NOT destroy this vector. When the DM is 6257 destroyed the array will no longer be valid. 6258 6259 Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates). 6260 6261 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6262 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6263 6264 Level: intermediate 6265 6266 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6267 @*/ 6268 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 6269 { 6270 PetscErrorCode ierr; 6271 6272 PetscFunctionBegin; 6273 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6274 PetscValidPointer(c,2); 6275 if (!dm->coordinates && dm->coordinatesLocal) { 6276 DM cdm = NULL; 6277 PetscBool localized; 6278 6279 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6280 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 6281 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6282 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 6283 if (localized) { 6284 PetscInt cdim; 6285 6286 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6287 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6288 } 6289 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 6290 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6291 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6292 } 6293 *c = dm->coordinates; 6294 PetscFunctionReturn(0); 6295 } 6296 6297 /*@ 6298 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 6299 6300 Collective on dm 6301 6302 Input Parameter: 6303 . dm - the DM 6304 6305 Level: advanced 6306 6307 .seealso: DMGetCoordinatesLocalNoncollective() 6308 @*/ 6309 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 6310 { 6311 PetscErrorCode ierr; 6312 6313 PetscFunctionBegin; 6314 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6315 if (!dm->coordinatesLocal && dm->coordinates) { 6316 DM cdm = NULL; 6317 PetscBool localized; 6318 6319 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6320 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 6321 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6322 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 6323 if (localized) { 6324 PetscInt cdim; 6325 6326 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6327 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6328 } 6329 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 6330 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6331 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6332 } 6333 PetscFunctionReturn(0); 6334 } 6335 6336 /*@ 6337 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 6338 6339 Collective on dm 6340 6341 Input Parameter: 6342 . dm - the DM 6343 6344 Output Parameter: 6345 . c - coordinate vector 6346 6347 Note: 6348 This is a borrowed reference, so the user should NOT destroy this vector 6349 6350 Each process has the local and ghost coordinates 6351 6352 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6353 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6354 6355 Level: intermediate 6356 6357 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 6358 @*/ 6359 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 6360 { 6361 PetscErrorCode ierr; 6362 6363 PetscFunctionBegin; 6364 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6365 PetscValidPointer(c,2); 6366 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 6367 *c = dm->coordinatesLocal; 6368 PetscFunctionReturn(0); 6369 } 6370 6371 /*@ 6372 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 6373 6374 Not collective 6375 6376 Input Parameter: 6377 . dm - the DM 6378 6379 Output Parameter: 6380 . c - coordinate vector 6381 6382 Level: advanced 6383 6384 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6385 @*/ 6386 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 6387 { 6388 PetscFunctionBegin; 6389 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6390 PetscValidPointer(c,2); 6391 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 6392 *c = dm->coordinatesLocal; 6393 PetscFunctionReturn(0); 6394 } 6395 6396 /*@ 6397 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 6398 6399 Not collective 6400 6401 Input Parameters: 6402 + dm - the DM 6403 - p - the IS of points whose coordinates will be returned 6404 6405 Output Parameters: 6406 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 6407 - pCoord - the Vec with coordinates of points in p 6408 6409 Note: 6410 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 6411 6412 This creates a new vector, so the user SHOULD destroy this vector 6413 6414 Each process has the local and ghost coordinates 6415 6416 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6417 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6418 6419 Level: advanced 6420 6421 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6422 @*/ 6423 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 6424 { 6425 PetscSection cs, newcs; 6426 Vec coords; 6427 const PetscScalar *arr; 6428 PetscScalar *newarr=NULL; 6429 PetscInt n; 6430 PetscErrorCode ierr; 6431 6432 PetscFunctionBegin; 6433 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6434 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 6435 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 6436 if (pCoord) PetscValidPointer(pCoord, 4); 6437 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 6438 if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 6439 cs = dm->coordinateDM->localSection; 6440 coords = dm->coordinatesLocal; 6441 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 6442 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 6443 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 6444 if (pCoord) { 6445 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 6446 /* set array in two steps to mimic PETSC_OWN_POINTER */ 6447 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 6448 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 6449 } else { 6450 ierr = PetscFree(newarr);CHKERRQ(ierr); 6451 } 6452 if (pCoordSection) {*pCoordSection = newcs;} 6453 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 6454 PetscFunctionReturn(0); 6455 } 6456 6457 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 6458 { 6459 PetscErrorCode ierr; 6460 6461 PetscFunctionBegin; 6462 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6463 PetscValidPointer(field,2); 6464 if (!dm->coordinateField) { 6465 if (dm->ops->createcoordinatefield) { 6466 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 6467 } 6468 } 6469 *field = dm->coordinateField; 6470 PetscFunctionReturn(0); 6471 } 6472 6473 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 6474 { 6475 PetscErrorCode ierr; 6476 6477 PetscFunctionBegin; 6478 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6479 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 6480 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 6481 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 6482 dm->coordinateField = field; 6483 PetscFunctionReturn(0); 6484 } 6485 6486 /*@ 6487 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 6488 6489 Collective on dm 6490 6491 Input Parameter: 6492 . dm - the DM 6493 6494 Output Parameter: 6495 . cdm - coordinate DM 6496 6497 Level: intermediate 6498 6499 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6500 @*/ 6501 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 6502 { 6503 PetscErrorCode ierr; 6504 6505 PetscFunctionBegin; 6506 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6507 PetscValidPointer(cdm,2); 6508 if (!dm->coordinateDM) { 6509 DM cdm; 6510 6511 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 6512 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 6513 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 6514 * until the call to CreateCoordinateDM) */ 6515 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6516 dm->coordinateDM = cdm; 6517 } 6518 *cdm = dm->coordinateDM; 6519 PetscFunctionReturn(0); 6520 } 6521 6522 /*@ 6523 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 6524 6525 Logically Collective on dm 6526 6527 Input Parameters: 6528 + dm - the DM 6529 - cdm - coordinate DM 6530 6531 Level: intermediate 6532 6533 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6534 @*/ 6535 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 6536 { 6537 PetscErrorCode ierr; 6538 6539 PetscFunctionBegin; 6540 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6541 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 6542 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6543 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6544 dm->coordinateDM = cdm; 6545 PetscFunctionReturn(0); 6546 } 6547 6548 /*@ 6549 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 6550 6551 Not Collective 6552 6553 Input Parameter: 6554 . dm - The DM object 6555 6556 Output Parameter: 6557 . dim - The embedding dimension 6558 6559 Level: intermediate 6560 6561 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6562 @*/ 6563 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 6564 { 6565 PetscFunctionBegin; 6566 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6567 PetscValidIntPointer(dim, 2); 6568 if (dm->dimEmbed == PETSC_DEFAULT) { 6569 dm->dimEmbed = dm->dim; 6570 } 6571 *dim = dm->dimEmbed; 6572 PetscFunctionReturn(0); 6573 } 6574 6575 /*@ 6576 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 6577 6578 Not Collective 6579 6580 Input Parameters: 6581 + dm - The DM object 6582 - dim - The embedding dimension 6583 6584 Level: intermediate 6585 6586 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6587 @*/ 6588 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 6589 { 6590 PetscDS ds; 6591 PetscInt Nds, n; 6592 PetscErrorCode ierr; 6593 6594 PetscFunctionBegin; 6595 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6596 dm->dimEmbed = dim; 6597 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6598 for (n = 0; n < Nds; ++n) { 6599 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 6600 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 6601 } 6602 PetscFunctionReturn(0); 6603 } 6604 6605 /*@ 6606 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6607 6608 Collective on dm 6609 6610 Input Parameter: 6611 . dm - The DM object 6612 6613 Output Parameter: 6614 . section - The PetscSection object 6615 6616 Level: intermediate 6617 6618 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6619 @*/ 6620 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 6621 { 6622 DM cdm; 6623 PetscErrorCode ierr; 6624 6625 PetscFunctionBegin; 6626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6627 PetscValidPointer(section, 2); 6628 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6629 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr); 6630 PetscFunctionReturn(0); 6631 } 6632 6633 /*@ 6634 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 6635 6636 Not Collective 6637 6638 Input Parameters: 6639 + dm - The DM object 6640 . dim - The embedding dimension, or PETSC_DETERMINE 6641 - section - The PetscSection object 6642 6643 Level: intermediate 6644 6645 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6646 @*/ 6647 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 6648 { 6649 DM cdm; 6650 PetscErrorCode ierr; 6651 6652 PetscFunctionBegin; 6653 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6654 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 6655 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6656 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr); 6657 if (dim == PETSC_DETERMINE) { 6658 PetscInt d = PETSC_DEFAULT; 6659 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 6660 6661 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6662 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6663 pStart = PetscMax(vStart, pStart); 6664 pEnd = PetscMin(vEnd, pEnd); 6665 for (v = pStart; v < pEnd; ++v) { 6666 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 6667 if (dd) {d = dd; break;} 6668 } 6669 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 6670 } 6671 PetscFunctionReturn(0); 6672 } 6673 6674 /*@ 6675 DMProjectCoordinates - Project coordinates to a different space 6676 6677 Input Parameters: 6678 + dm - The DM object 6679 - disc - The new coordinate discretization 6680 6681 Level: intermediate 6682 6683 .seealso: DMGetCoordinateField() 6684 @*/ 6685 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc) 6686 { 6687 PetscObject discOld; 6688 PetscClassId classid; 6689 DM cdmOld,cdmNew; 6690 Vec coordsOld,coordsNew; 6691 Mat matInterp; 6692 PetscErrorCode ierr; 6693 6694 PetscFunctionBegin; 6695 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6696 PetscValidHeaderSpecific(disc,PETSCFE_CLASSID,2); 6697 6698 ierr = DMGetCoordinateDM(dm, &cdmOld);CHKERRQ(ierr); 6699 /* Check current discretization is compatible */ 6700 ierr = DMGetField(cdmOld, 0, NULL, &discOld);CHKERRQ(ierr); 6701 ierr = PetscObjectGetClassId(discOld, &classid);CHKERRQ(ierr); 6702 if (classid != PETSCFE_CLASSID) { 6703 if (classid == PETSC_CONTAINER_CLASSID) { 6704 PetscFE feLinear; 6705 DMPolytopeType ct; 6706 PetscInt dim, dE, cStart; 6707 PetscBool simplex; 6708 6709 /* Assume linear vertex coordinates */ 6710 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6711 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 6712 ierr = DMPlexGetHeightStratum(cdmOld, 0, &cStart, NULL);CHKERRQ(ierr); 6713 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 6714 switch (ct) { 6715 case DM_POLYTOPE_TRI_PRISM: 6716 case DM_POLYTOPE_TRI_PRISM_TENSOR: 6717 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot autoamtically create coordinate space for prisms"); 6718 default: break; 6719 } 6720 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 6721 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, 1, -1, &feLinear);CHKERRQ(ierr); 6722 ierr = DMSetField(cdmOld, 0, NULL, (PetscObject) feLinear);CHKERRQ(ierr); 6723 ierr = PetscFEDestroy(&feLinear);CHKERRQ(ierr); 6724 ierr = DMCreateDS(cdmOld);CHKERRQ(ierr); 6725 } else { 6726 const char *discname; 6727 6728 ierr = PetscObjectGetType(discOld, &discname);CHKERRQ(ierr); 6729 SETERRQ1(PetscObjectComm(discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname); 6730 } 6731 } 6732 /* Make a fresh clone of the coordinate DM */ 6733 ierr = DMClone(cdmOld, &cdmNew);CHKERRQ(ierr); 6734 ierr = DMSetField(cdmNew, 0, NULL, (PetscObject) disc);CHKERRQ(ierr); 6735 ierr = DMCreateDS(cdmNew);CHKERRQ(ierr); 6736 /* Project the coordinate vector from old to new space */ 6737 ierr = DMGetCoordinates(dm, &coordsOld);CHKERRQ(ierr); 6738 ierr = DMCreateGlobalVector(cdmNew, &coordsNew);CHKERRQ(ierr); 6739 ierr = DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL);CHKERRQ(ierr); 6740 ierr = MatInterpolate(matInterp, coordsOld, coordsNew);CHKERRQ(ierr); 6741 ierr = MatDestroy(&matInterp);CHKERRQ(ierr); 6742 /* Set new coordinate structures */ 6743 ierr = DMSetCoordinateField(dm, NULL);CHKERRQ(ierr); 6744 ierr = DMSetCoordinateDM(dm, cdmNew);CHKERRQ(ierr); 6745 ierr = DMSetCoordinates(dm, coordsNew);CHKERRQ(ierr); 6746 ierr = VecDestroy(&coordsNew);CHKERRQ(ierr); 6747 ierr = DMDestroy(&cdmNew);CHKERRQ(ierr); 6748 PetscFunctionReturn(0); 6749 } 6750 6751 /*@C 6752 DMGetPeriodicity - Get the description of mesh periodicity 6753 6754 Input Parameter: 6755 . dm - The DM object 6756 6757 Output Parameters: 6758 + per - Whether the DM is periodic or not 6759 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6760 . L - If we assume the mesh is a torus, this is the length of each coordinate 6761 - bd - This describes the type of periodicity in each topological dimension 6762 6763 Level: developer 6764 6765 .seealso: DMGetPeriodicity() 6766 @*/ 6767 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 6768 { 6769 PetscFunctionBegin; 6770 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6771 if (per) *per = dm->periodic; 6772 if (L) *L = dm->L; 6773 if (maxCell) *maxCell = dm->maxCell; 6774 if (bd) *bd = dm->bdtype; 6775 PetscFunctionReturn(0); 6776 } 6777 6778 /*@C 6779 DMSetPeriodicity - Set the description of mesh periodicity 6780 6781 Input Parameters: 6782 + dm - The DM object 6783 . per - Whether the DM is periodic or not. 6784 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates. Pass NULL to remove such information. 6785 . L - If we assume the mesh is a torus, this is the length of each coordinate 6786 - bd - This describes the type of periodicity in each topological dimension 6787 6788 Notes: If per is PETSC_TRUE and maxCell is not provided, coordinates need to be already localized, or must be localized by hand by the user. 6789 6790 Level: developer 6791 6792 .seealso: DMGetPeriodicity() 6793 @*/ 6794 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6795 { 6796 PetscInt dim, d; 6797 PetscErrorCode ierr; 6798 6799 PetscFunctionBegin; 6800 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6801 PetscValidLogicalCollectiveBool(dm,per,2); 6802 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6803 if (L) {PetscValidRealPointer(L,4);} 6804 if (bd) {PetscValidPointer(bd,5);} 6805 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6806 if (maxCell) { 6807 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6808 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6809 } else { /* remove maxCell information to disable automatic computation of localized vertices */ 6810 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr); 6811 } 6812 6813 if (L) { 6814 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6815 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6816 } 6817 if (bd) { 6818 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6819 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6820 } 6821 dm->periodic = per; 6822 PetscFunctionReturn(0); 6823 } 6824 6825 /*@ 6826 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. 6827 6828 Input Parameters: 6829 + dm - The DM 6830 . in - The input coordinate point (dim numbers) 6831 - endpoint - Include the endpoint L_i 6832 6833 Output Parameter: 6834 . out - The localized coordinate point 6835 6836 Level: developer 6837 6838 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6839 @*/ 6840 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6841 { 6842 PetscInt dim, d; 6843 PetscErrorCode ierr; 6844 6845 PetscFunctionBegin; 6846 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6847 if (!dm->maxCell) { 6848 for (d = 0; d < dim; ++d) out[d] = in[d]; 6849 } else { 6850 if (endpoint) { 6851 for (d = 0; d < dim; ++d) { 6852 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)) { 6853 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6854 } else { 6855 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6856 } 6857 } 6858 } else { 6859 for (d = 0; d < dim; ++d) { 6860 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6861 } 6862 } 6863 } 6864 PetscFunctionReturn(0); 6865 } 6866 6867 /* 6868 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. 6869 6870 Input Parameters: 6871 + dm - The DM 6872 . dim - The spatial dimension 6873 . anchor - The anchor point, the input point can be no more than maxCell away from it 6874 - in - The input coordinate point (dim numbers) 6875 6876 Output Parameter: 6877 . out - The localized coordinate point 6878 6879 Level: developer 6880 6881 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 6882 6883 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6884 */ 6885 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6886 { 6887 PetscInt d; 6888 6889 PetscFunctionBegin; 6890 if (!dm->maxCell) { 6891 for (d = 0; d < dim; ++d) out[d] = in[d]; 6892 } else { 6893 for (d = 0; d < dim; ++d) { 6894 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6895 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6896 } else { 6897 out[d] = in[d]; 6898 } 6899 } 6900 } 6901 PetscFunctionReturn(0); 6902 } 6903 6904 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6905 { 6906 PetscInt d; 6907 6908 PetscFunctionBegin; 6909 if (!dm->maxCell) { 6910 for (d = 0; d < dim; ++d) out[d] = in[d]; 6911 } else { 6912 for (d = 0; d < dim; ++d) { 6913 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6914 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6915 } else { 6916 out[d] = in[d]; 6917 } 6918 } 6919 } 6920 PetscFunctionReturn(0); 6921 } 6922 6923 /* 6924 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. 6925 6926 Input Parameters: 6927 + dm - The DM 6928 . dim - The spatial dimension 6929 . anchor - The anchor point, the input point can be no more than maxCell away from it 6930 . in - The input coordinate delta (dim numbers) 6931 - out - The input coordinate point (dim numbers) 6932 6933 Output Parameter: 6934 . out - The localized coordinate in + out 6935 6936 Level: developer 6937 6938 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 6939 6940 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6941 */ 6942 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6943 { 6944 PetscInt d; 6945 6946 PetscFunctionBegin; 6947 if (!dm->maxCell) { 6948 for (d = 0; d < dim; ++d) out[d] += in[d]; 6949 } else { 6950 for (d = 0; d < dim; ++d) { 6951 const PetscReal maxC = dm->maxCell[d]; 6952 6953 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 6954 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6955 6956 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 6957 SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "%D-Coordinate %g more than %g away from anchor %g", d, (double) PetscRealPart(in[d]), (double) maxC, (double) PetscRealPart(anchor[d])); 6958 out[d] += newCoord; 6959 } else { 6960 out[d] += in[d]; 6961 } 6962 } 6963 } 6964 PetscFunctionReturn(0); 6965 } 6966 6967 /*@ 6968 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6969 6970 Not collective 6971 6972 Input Parameter: 6973 . dm - The DM 6974 6975 Output Parameter: 6976 areLocalized - True if localized 6977 6978 Level: developer 6979 6980 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6981 @*/ 6982 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6983 { 6984 DM cdm; 6985 PetscSection coordSection; 6986 PetscInt depth, cStart, cEnd, sStart, sEnd, c, dof; 6987 PetscBool isPlex, alreadyLocalized; 6988 PetscErrorCode ierr; 6989 6990 PetscFunctionBegin; 6991 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6992 PetscValidBoolPointer(areLocalized, 2); 6993 *areLocalized = PETSC_FALSE; 6994 6995 /* We need some generic way of refering to cells/vertices */ 6996 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6997 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6998 if (!isPlex) PetscFunctionReturn(0); 6999 ierr = DMPlexGetDepth(cdm, &depth);CHKERRQ(ierr); 7000 if (!depth) PetscFunctionReturn(0); 7001 7002 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7003 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7004 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 7005 alreadyLocalized = PETSC_FALSE; 7006 for (c = cStart; c < cEnd; ++c) { 7007 if (c < sStart || c >= sEnd) continue; 7008 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 7009 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 7010 } 7011 *areLocalized = alreadyLocalized; 7012 PetscFunctionReturn(0); 7013 } 7014 7015 /*@ 7016 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 7017 7018 Collective on dm 7019 7020 Input Parameter: 7021 . dm - The DM 7022 7023 Output Parameter: 7024 areLocalized - True if localized 7025 7026 Level: developer 7027 7028 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 7029 @*/ 7030 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 7031 { 7032 PetscBool localized; 7033 PetscErrorCode ierr; 7034 7035 PetscFunctionBegin; 7036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7037 PetscValidBoolPointer(areLocalized, 2); 7038 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 7039 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 7040 PetscFunctionReturn(0); 7041 } 7042 7043 /*@ 7044 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 7045 7046 Collective on dm 7047 7048 Input Parameter: 7049 . dm - The DM 7050 7051 Level: developer 7052 7053 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 7054 @*/ 7055 PetscErrorCode DMLocalizeCoordinates(DM dm) 7056 { 7057 DM cdm; 7058 PetscSection coordSection, cSection; 7059 Vec coordinates, cVec; 7060 PetscScalar *coords, *coords2, *anchor, *localized; 7061 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 7062 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 7063 PetscInt maxHeight = 0, h; 7064 PetscInt *pStart = NULL, *pEnd = NULL; 7065 PetscErrorCode ierr; 7066 7067 PetscFunctionBegin; 7068 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7069 if (!dm->periodic) PetscFunctionReturn(0); 7070 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 7071 if (alreadyLocalized) PetscFunctionReturn(0); 7072 7073 /* We need some generic way of refering to cells/vertices */ 7074 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7075 { 7076 PetscBool isplex; 7077 7078 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 7079 if (isplex) { 7080 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7081 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 7082 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7083 pEnd = &pStart[maxHeight + 1]; 7084 newStart = vStart; 7085 newEnd = vEnd; 7086 for (h = 0; h <= maxHeight; h++) { 7087 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 7088 newStart = PetscMin(newStart,pStart[h]); 7089 newEnd = PetscMax(newEnd,pEnd[h]); 7090 } 7091 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 7092 } 7093 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 7094 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 7095 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7096 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 7097 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 7098 7099 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 7100 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 7101 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 7102 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 7103 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 7104 7105 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7106 localized = &anchor[bs]; 7107 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 7108 for (h = 0; h <= maxHeight; h++) { 7109 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7110 7111 for (c = cStart; c < cEnd; ++c) { 7112 PetscScalar *cellCoords = NULL; 7113 PetscInt b; 7114 7115 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 7116 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7117 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7118 for (d = 0; d < dof/bs; ++d) { 7119 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 7120 for (b = 0; b < bs; b++) { 7121 if (cellCoords[d*bs + b] != localized[b]) break; 7122 } 7123 if (b < bs) break; 7124 } 7125 if (d < dof/bs) { 7126 if (c >= sStart && c < sEnd) { 7127 PetscInt cdof; 7128 7129 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 7130 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 7131 } 7132 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 7133 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 7134 } 7135 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7136 } 7137 } 7138 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 7139 if (alreadyLocalizedGlobal) { 7140 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7141 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7142 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7143 PetscFunctionReturn(0); 7144 } 7145 for (v = vStart; v < vEnd; ++v) { 7146 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7147 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 7148 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 7149 } 7150 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 7151 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 7152 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 7153 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 7154 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 7155 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 7156 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 7157 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7158 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 7159 for (v = vStart; v < vEnd; ++v) { 7160 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7161 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 7162 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 7163 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 7164 } 7165 for (h = 0; h <= maxHeight; h++) { 7166 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7167 7168 for (c = cStart; c < cEnd; ++c) { 7169 PetscScalar *cellCoords = NULL; 7170 PetscInt b, cdof; 7171 7172 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 7173 if (!cdof) continue; 7174 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7175 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 7176 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7177 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 7178 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7179 } 7180 } 7181 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7182 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7183 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7184 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 7185 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 7186 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 7187 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 7188 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7189 PetscFunctionReturn(0); 7190 } 7191 7192 /*@ 7193 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 7194 7195 Collective on v (see explanation below) 7196 7197 Input Parameters: 7198 + dm - The DM 7199 - ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 7200 7201 Input/Output Parameters: 7202 + v - The Vec of points, on output contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 7203 - cellSF - Points to either NULL, or a PetscSF with guesses for which cells contain each point; 7204 on output, the PetscSF containing the ranks and local indices of the containing points 7205 7206 Level: developer 7207 7208 Notes: 7209 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 7210 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 7211 7212 If *cellSF is NULL on input, a PetscSF will be created. 7213 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 7214 7215 An array that maps each point to its containing cell can be obtained with 7216 7217 $ const PetscSFNode *cells; 7218 $ PetscInt nFound; 7219 $ const PetscInt *found; 7220 $ 7221 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 7222 7223 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 7224 the index of the cell in its rank's local numbering. 7225 7226 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 7227 @*/ 7228 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 7229 { 7230 PetscErrorCode ierr; 7231 7232 PetscFunctionBegin; 7233 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7234 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 7235 PetscValidPointer(cellSF,4); 7236 if (*cellSF) { 7237 PetscMPIInt result; 7238 7239 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 7240 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRMPI(ierr); 7241 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 7242 } else { 7243 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 7244 } 7245 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 7246 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7247 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 7248 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7249 PetscFunctionReturn(0); 7250 } 7251 7252 /*@ 7253 DMGetOutputDM - Retrieve the DM associated with the layout for output 7254 7255 Collective on dm 7256 7257 Input Parameter: 7258 . dm - The original DM 7259 7260 Output Parameter: 7261 . odm - The DM which provides the layout for output 7262 7263 Level: intermediate 7264 7265 .seealso: VecView(), DMGetGlobalSection() 7266 @*/ 7267 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 7268 { 7269 PetscSection section; 7270 PetscBool hasConstraints, ghasConstraints; 7271 PetscErrorCode ierr; 7272 7273 PetscFunctionBegin; 7274 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7275 PetscValidPointer(odm,2); 7276 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 7277 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 7278 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7279 if (!ghasConstraints) { 7280 *odm = dm; 7281 PetscFunctionReturn(0); 7282 } 7283 if (!dm->dmBC) { 7284 PetscSection newSection, gsection; 7285 PetscSF sf; 7286 7287 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 7288 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 7289 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 7290 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 7291 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 7292 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 7293 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 7294 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 7295 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 7296 } 7297 *odm = dm->dmBC; 7298 PetscFunctionReturn(0); 7299 } 7300 7301 /*@ 7302 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 7303 7304 Input Parameter: 7305 . dm - The original DM 7306 7307 Output Parameters: 7308 + num - The output sequence number 7309 - val - The output sequence value 7310 7311 Level: intermediate 7312 7313 Note: This is intended for output that should appear in sequence, for instance 7314 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7315 7316 .seealso: VecView() 7317 @*/ 7318 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 7319 { 7320 PetscFunctionBegin; 7321 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7322 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 7323 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 7324 PetscFunctionReturn(0); 7325 } 7326 7327 /*@ 7328 DMSetOutputSequenceNumber - Set the sequence number/value for output 7329 7330 Input Parameters: 7331 + dm - The original DM 7332 . num - The output sequence number 7333 - val - The output sequence value 7334 7335 Level: intermediate 7336 7337 Note: This is intended for output that should appear in sequence, for instance 7338 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7339 7340 .seealso: VecView() 7341 @*/ 7342 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 7343 { 7344 PetscFunctionBegin; 7345 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7346 dm->outputSequenceNum = num; 7347 dm->outputSequenceVal = val; 7348 PetscFunctionReturn(0); 7349 } 7350 7351 /*@C 7352 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 7353 7354 Input Parameters: 7355 + dm - The original DM 7356 . name - The sequence name 7357 - num - The output sequence number 7358 7359 Output Parameter: 7360 . val - The output sequence value 7361 7362 Level: intermediate 7363 7364 Note: This is intended for output that should appear in sequence, for instance 7365 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7366 7367 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 7368 @*/ 7369 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 7370 { 7371 PetscBool ishdf5; 7372 PetscErrorCode ierr; 7373 7374 PetscFunctionBegin; 7375 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7376 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 7377 PetscValidRealPointer(val,5); 7378 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 7379 if (ishdf5) { 7380 #if defined(PETSC_HAVE_HDF5) 7381 PetscScalar value; 7382 7383 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 7384 *val = PetscRealPart(value); 7385 #endif 7386 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 7387 PetscFunctionReturn(0); 7388 } 7389 7390 /*@ 7391 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 7392 7393 Not collective 7394 7395 Input Parameter: 7396 . dm - The DM 7397 7398 Output Parameter: 7399 . useNatural - The flag to build the mapping to a natural order during distribution 7400 7401 Level: beginner 7402 7403 .seealso: DMSetUseNatural(), DMCreate() 7404 @*/ 7405 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 7406 { 7407 PetscFunctionBegin; 7408 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7409 PetscValidBoolPointer(useNatural, 2); 7410 *useNatural = dm->useNatural; 7411 PetscFunctionReturn(0); 7412 } 7413 7414 /*@ 7415 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 7416 7417 Collective on dm 7418 7419 Input Parameters: 7420 + dm - The DM 7421 - useNatural - The flag to build the mapping to a natural order during distribution 7422 7423 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 7424 7425 Level: beginner 7426 7427 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 7428 @*/ 7429 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 7430 { 7431 PetscFunctionBegin; 7432 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7433 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 7434 dm->useNatural = useNatural; 7435 PetscFunctionReturn(0); 7436 } 7437 7438 /*@C 7439 DMCreateLabel - Create a label of the given name if it does not already exist 7440 7441 Not Collective 7442 7443 Input Parameters: 7444 + dm - The DM object 7445 - name - The label name 7446 7447 Level: intermediate 7448 7449 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7450 @*/ 7451 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 7452 { 7453 PetscBool flg; 7454 DMLabel label; 7455 PetscErrorCode ierr; 7456 7457 PetscFunctionBegin; 7458 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7459 PetscValidCharPointer(name, 2); 7460 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7461 if (!flg) { 7462 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7463 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7464 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7465 } 7466 PetscFunctionReturn(0); 7467 } 7468 7469 /*@C 7470 DMCreateLabelAtIndex - Create a label of the given name at the iven index. If it already exists, move it to this index. 7471 7472 Not Collective 7473 7474 Input Parameters: 7475 + dm - The DM object 7476 . l - The index for the label 7477 - name - The label name 7478 7479 Level: intermediate 7480 7481 .seealso: DMCreateLabel(), DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7482 @*/ 7483 PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[]) 7484 { 7485 DMLabelLink orig, prev = NULL; 7486 DMLabel label; 7487 PetscInt Nl, m; 7488 PetscBool flg, match; 7489 const char *lname; 7490 PetscErrorCode ierr; 7491 7492 PetscFunctionBegin; 7493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7494 PetscValidCharPointer(name, 3); 7495 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7496 if (!flg) { 7497 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7498 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7499 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7500 } 7501 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 7502 if (l >= Nl) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %D must be in [0, %D)", l, Nl); 7503 for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) { 7504 ierr = PetscObjectGetName((PetscObject) orig->label, &lname);CHKERRQ(ierr); 7505 ierr = PetscStrcmp(name, lname, &match);CHKERRQ(ierr); 7506 if (match) break; 7507 } 7508 if (m == l) PetscFunctionReturn(0); 7509 if (!m) dm->labels = orig->next; 7510 else prev->next = orig->next; 7511 if (!l) { 7512 orig->next = dm->labels; 7513 dm->labels = orig; 7514 } else { 7515 for (m = 0, prev = dm->labels; m < l-1; ++m, prev = prev->next); 7516 orig->next = prev->next; 7517 prev->next = orig; 7518 } 7519 PetscFunctionReturn(0); 7520 } 7521 7522 /*@C 7523 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 7524 7525 Not Collective 7526 7527 Input Parameters: 7528 + dm - The DM object 7529 . name - The label name 7530 - point - The mesh point 7531 7532 Output Parameter: 7533 . value - The label value for this point, or -1 if the point is not in the label 7534 7535 Level: beginner 7536 7537 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 7538 @*/ 7539 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 7540 { 7541 DMLabel label; 7542 PetscErrorCode ierr; 7543 7544 PetscFunctionBegin; 7545 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7546 PetscValidCharPointer(name, 2); 7547 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7548 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 7549 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 7550 PetscFunctionReturn(0); 7551 } 7552 7553 /*@C 7554 DMSetLabelValue - Add a point to a Sieve Label with given value 7555 7556 Not Collective 7557 7558 Input Parameters: 7559 + dm - The DM object 7560 . name - The label name 7561 . point - The mesh point 7562 - value - The label value for this point 7563 7564 Output Parameter: 7565 7566 Level: beginner 7567 7568 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 7569 @*/ 7570 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7571 { 7572 DMLabel label; 7573 PetscErrorCode ierr; 7574 7575 PetscFunctionBegin; 7576 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7577 PetscValidCharPointer(name, 2); 7578 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7579 if (!label) { 7580 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 7581 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7582 } 7583 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 7584 PetscFunctionReturn(0); 7585 } 7586 7587 /*@C 7588 DMClearLabelValue - Remove a point from a Sieve Label with given value 7589 7590 Not Collective 7591 7592 Input Parameters: 7593 + dm - The DM object 7594 . name - The label name 7595 . point - The mesh point 7596 - value - The label value for this point 7597 7598 Output Parameter: 7599 7600 Level: beginner 7601 7602 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 7603 @*/ 7604 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7605 { 7606 DMLabel label; 7607 PetscErrorCode ierr; 7608 7609 PetscFunctionBegin; 7610 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7611 PetscValidCharPointer(name, 2); 7612 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7613 if (!label) PetscFunctionReturn(0); 7614 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 7615 PetscFunctionReturn(0); 7616 } 7617 7618 /*@C 7619 DMGetLabelSize - Get the number of different integer ids in a Label 7620 7621 Not Collective 7622 7623 Input Parameters: 7624 + dm - The DM object 7625 - name - The label name 7626 7627 Output Parameter: 7628 . size - The number of different integer ids, or 0 if the label does not exist 7629 7630 Level: beginner 7631 7632 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 7633 @*/ 7634 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 7635 { 7636 DMLabel label; 7637 PetscErrorCode ierr; 7638 7639 PetscFunctionBegin; 7640 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7641 PetscValidCharPointer(name, 2); 7642 PetscValidIntPointer(size, 3); 7643 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7644 *size = 0; 7645 if (!label) PetscFunctionReturn(0); 7646 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 7647 PetscFunctionReturn(0); 7648 } 7649 7650 /*@C 7651 DMGetLabelIdIS - Get the integer ids in a label 7652 7653 Not Collective 7654 7655 Input Parameters: 7656 + mesh - The DM object 7657 - name - The label name 7658 7659 Output Parameter: 7660 . ids - The integer ids, or NULL if the label does not exist 7661 7662 Level: beginner 7663 7664 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 7665 @*/ 7666 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 7667 { 7668 DMLabel label; 7669 PetscErrorCode ierr; 7670 7671 PetscFunctionBegin; 7672 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7673 PetscValidCharPointer(name, 2); 7674 PetscValidPointer(ids, 3); 7675 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7676 *ids = NULL; 7677 if (label) { 7678 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 7679 } else { 7680 /* returning an empty IS */ 7681 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 7682 } 7683 PetscFunctionReturn(0); 7684 } 7685 7686 /*@C 7687 DMGetStratumSize - Get the number of points in a label stratum 7688 7689 Not Collective 7690 7691 Input Parameters: 7692 + dm - The DM object 7693 . name - The label name 7694 - value - The stratum value 7695 7696 Output Parameter: 7697 . size - The stratum size 7698 7699 Level: beginner 7700 7701 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 7702 @*/ 7703 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 7704 { 7705 DMLabel label; 7706 PetscErrorCode ierr; 7707 7708 PetscFunctionBegin; 7709 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7710 PetscValidCharPointer(name, 2); 7711 PetscValidIntPointer(size, 4); 7712 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7713 *size = 0; 7714 if (!label) PetscFunctionReturn(0); 7715 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 7716 PetscFunctionReturn(0); 7717 } 7718 7719 /*@C 7720 DMGetStratumIS - Get the points in a label stratum 7721 7722 Not Collective 7723 7724 Input Parameters: 7725 + dm - The DM object 7726 . name - The label name 7727 - value - The stratum value 7728 7729 Output Parameter: 7730 . points - The stratum points, or NULL if the label does not exist or does not have that value 7731 7732 Level: beginner 7733 7734 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 7735 @*/ 7736 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 7737 { 7738 DMLabel label; 7739 PetscErrorCode ierr; 7740 7741 PetscFunctionBegin; 7742 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7743 PetscValidCharPointer(name, 2); 7744 PetscValidPointer(points, 4); 7745 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7746 *points = NULL; 7747 if (!label) PetscFunctionReturn(0); 7748 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 7749 PetscFunctionReturn(0); 7750 } 7751 7752 /*@C 7753 DMSetStratumIS - Set the points in a label stratum 7754 7755 Not Collective 7756 7757 Input Parameters: 7758 + dm - The DM object 7759 . name - The label name 7760 . value - The stratum value 7761 - points - The stratum points 7762 7763 Level: beginner 7764 7765 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 7766 @*/ 7767 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 7768 { 7769 DMLabel label; 7770 PetscErrorCode ierr; 7771 7772 PetscFunctionBegin; 7773 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7774 PetscValidCharPointer(name, 2); 7775 PetscValidPointer(points, 4); 7776 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7777 if (!label) PetscFunctionReturn(0); 7778 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 7779 PetscFunctionReturn(0); 7780 } 7781 7782 /*@C 7783 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 7784 7785 Not Collective 7786 7787 Input Parameters: 7788 + dm - The DM object 7789 . name - The label name 7790 - value - The label value for this point 7791 7792 Output Parameter: 7793 7794 Level: beginner 7795 7796 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7797 @*/ 7798 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7799 { 7800 DMLabel label; 7801 PetscErrorCode ierr; 7802 7803 PetscFunctionBegin; 7804 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7805 PetscValidCharPointer(name, 2); 7806 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7807 if (!label) PetscFunctionReturn(0); 7808 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7809 PetscFunctionReturn(0); 7810 } 7811 7812 /*@ 7813 DMGetNumLabels - Return the number of labels defined by the mesh 7814 7815 Not Collective 7816 7817 Input Parameter: 7818 . dm - The DM object 7819 7820 Output Parameter: 7821 . numLabels - the number of Labels 7822 7823 Level: intermediate 7824 7825 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7826 @*/ 7827 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7828 { 7829 DMLabelLink next = dm->labels; 7830 PetscInt n = 0; 7831 7832 PetscFunctionBegin; 7833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7834 PetscValidIntPointer(numLabels, 2); 7835 while (next) {++n; next = next->next;} 7836 *numLabels = n; 7837 PetscFunctionReturn(0); 7838 } 7839 7840 /*@C 7841 DMGetLabelName - Return the name of nth label 7842 7843 Not Collective 7844 7845 Input Parameters: 7846 + dm - The DM object 7847 - n - the label number 7848 7849 Output Parameter: 7850 . name - the label name 7851 7852 Level: intermediate 7853 7854 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7855 @*/ 7856 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7857 { 7858 DMLabelLink next = dm->labels; 7859 PetscInt l = 0; 7860 PetscErrorCode ierr; 7861 7862 PetscFunctionBegin; 7863 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7864 PetscValidPointer(name, 3); 7865 while (next) { 7866 if (l == n) { 7867 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7868 PetscFunctionReturn(0); 7869 } 7870 ++l; 7871 next = next->next; 7872 } 7873 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7874 } 7875 7876 /*@C 7877 DMHasLabel - Determine whether the mesh has a label of a given name 7878 7879 Not Collective 7880 7881 Input Parameters: 7882 + dm - The DM object 7883 - name - The label name 7884 7885 Output Parameter: 7886 . hasLabel - PETSC_TRUE if the label is present 7887 7888 Level: intermediate 7889 7890 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7891 @*/ 7892 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7893 { 7894 DMLabelLink next = dm->labels; 7895 const char *lname; 7896 PetscErrorCode ierr; 7897 7898 PetscFunctionBegin; 7899 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7900 PetscValidCharPointer(name, 2); 7901 PetscValidBoolPointer(hasLabel, 3); 7902 *hasLabel = PETSC_FALSE; 7903 while (next) { 7904 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7905 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7906 if (*hasLabel) break; 7907 next = next->next; 7908 } 7909 PetscFunctionReturn(0); 7910 } 7911 7912 /*@C 7913 DMGetLabel - Return the label of a given name, or NULL 7914 7915 Not Collective 7916 7917 Input Parameters: 7918 + dm - The DM object 7919 - name - The label name 7920 7921 Output Parameter: 7922 . label - The DMLabel, or NULL if the label is absent 7923 7924 Note: Some of the default labels in a DMPlex will be 7925 $ "depth" - Holds the depth (co-dimension) of each mesh point 7926 $ "celltype" - Holds the topological type of each cell 7927 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 7928 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 7929 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 7930 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 7931 7932 Level: intermediate 7933 7934 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 7935 @*/ 7936 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7937 { 7938 DMLabelLink next = dm->labels; 7939 PetscBool hasLabel; 7940 const char *lname; 7941 PetscErrorCode ierr; 7942 7943 PetscFunctionBegin; 7944 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7945 PetscValidCharPointer(name, 2); 7946 PetscValidPointer(label, 3); 7947 *label = NULL; 7948 while (next) { 7949 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7950 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7951 if (hasLabel) { 7952 *label = next->label; 7953 break; 7954 } 7955 next = next->next; 7956 } 7957 PetscFunctionReturn(0); 7958 } 7959 7960 /*@C 7961 DMGetLabelByNum - Return the nth label 7962 7963 Not Collective 7964 7965 Input Parameters: 7966 + dm - The DM object 7967 - n - the label number 7968 7969 Output Parameter: 7970 . label - the label 7971 7972 Level: intermediate 7973 7974 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7975 @*/ 7976 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7977 { 7978 DMLabelLink next = dm->labels; 7979 PetscInt l = 0; 7980 7981 PetscFunctionBegin; 7982 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7983 PetscValidPointer(label, 3); 7984 while (next) { 7985 if (l == n) { 7986 *label = next->label; 7987 PetscFunctionReturn(0); 7988 } 7989 ++l; 7990 next = next->next; 7991 } 7992 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7993 } 7994 7995 /*@C 7996 DMAddLabel - Add the label to this mesh 7997 7998 Not Collective 7999 8000 Input Parameters: 8001 + dm - The DM object 8002 - label - The DMLabel 8003 8004 Level: developer 8005 8006 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8007 @*/ 8008 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 8009 { 8010 DMLabelLink l, *p, tmpLabel; 8011 PetscBool hasLabel; 8012 const char *lname; 8013 PetscBool flg; 8014 PetscErrorCode ierr; 8015 8016 PetscFunctionBegin; 8017 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8018 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 8019 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 8020 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 8021 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 8022 tmpLabel->label = label; 8023 tmpLabel->output = PETSC_TRUE; 8024 for (p=&dm->labels; (l=*p); p=&l->next) {} 8025 *p = tmpLabel; 8026 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 8027 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 8028 if (flg) dm->depthLabel = label; 8029 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 8030 if (flg) dm->celltypeLabel = label; 8031 PetscFunctionReturn(0); 8032 } 8033 8034 /*@C 8035 DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present 8036 8037 Not Collective 8038 8039 Input Parameters: 8040 + dm - The DM object 8041 - label - The DMLabel, having the same name, to substitute 8042 8043 Note: Some of the default labels in a DMPlex will be 8044 $ "depth" - Holds the depth (co-dimension) of each mesh point 8045 $ "celltype" - Holds the topological type of each cell 8046 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 8047 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 8048 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 8049 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 8050 8051 Level: intermediate 8052 8053 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 8054 @*/ 8055 PetscErrorCode DMSetLabel(DM dm, DMLabel label) 8056 { 8057 DMLabelLink next = dm->labels; 8058 PetscBool hasLabel, flg; 8059 const char *name, *lname; 8060 PetscErrorCode ierr; 8061 8062 PetscFunctionBegin; 8063 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8064 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 8065 ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 8066 while (next) { 8067 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8068 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8069 if (hasLabel) { 8070 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 8071 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 8072 if (flg) dm->depthLabel = label; 8073 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 8074 if (flg) dm->celltypeLabel = label; 8075 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 8076 next->label = label; 8077 break; 8078 } 8079 next = next->next; 8080 } 8081 PetscFunctionReturn(0); 8082 } 8083 8084 /*@C 8085 DMRemoveLabel - Remove the label given by name from this mesh 8086 8087 Not Collective 8088 8089 Input Parameters: 8090 + dm - The DM object 8091 - name - The label name 8092 8093 Output Parameter: 8094 . label - The DMLabel, or NULL if the label is absent 8095 8096 Level: developer 8097 8098 Notes: 8099 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 8100 DMLabelDestroy() on the label. 8101 8102 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 8103 call DMLabelDestroy(). Instead, the label is returned and the user is 8104 responsible of calling DMLabelDestroy() at some point. 8105 8106 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 8107 @*/ 8108 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 8109 { 8110 DMLabelLink link, *pnext; 8111 PetscBool hasLabel; 8112 const char *lname; 8113 PetscErrorCode ierr; 8114 8115 PetscFunctionBegin; 8116 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8117 PetscValidCharPointer(name, 2); 8118 if (label) { 8119 PetscValidPointer(label, 3); 8120 *label = NULL; 8121 } 8122 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8123 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 8124 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8125 if (hasLabel) { 8126 *pnext = link->next; /* Remove from list */ 8127 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 8128 if (hasLabel) dm->depthLabel = NULL; 8129 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 8130 if (hasLabel) dm->celltypeLabel = NULL; 8131 if (label) *label = link->label; 8132 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 8133 ierr = PetscFree(link);CHKERRQ(ierr); 8134 break; 8135 } 8136 } 8137 PetscFunctionReturn(0); 8138 } 8139 8140 /*@ 8141 DMRemoveLabelBySelf - Remove the label from this mesh 8142 8143 Not Collective 8144 8145 Input Parameters: 8146 + dm - The DM object 8147 . label - The DMLabel to be removed from the DM 8148 - failNotFound - Should it fail if the label is not found in the DM? 8149 8150 Level: developer 8151 8152 Notes: 8153 Only exactly the same instance is removed if found, name match is ignored. 8154 If the DM has an exclusive reference to the label, it gets destroyed and 8155 *label nullified. 8156 8157 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 8158 @*/ 8159 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 8160 { 8161 DMLabelLink link, *pnext; 8162 PetscBool hasLabel = PETSC_FALSE; 8163 PetscErrorCode ierr; 8164 8165 PetscFunctionBegin; 8166 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8167 PetscValidPointer(label, 2); 8168 if (!*label && !failNotFound) PetscFunctionReturn(0); 8169 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 8170 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 8171 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8172 if (*label == link->label) { 8173 hasLabel = PETSC_TRUE; 8174 *pnext = link->next; /* Remove from list */ 8175 if (*label == dm->depthLabel) dm->depthLabel = NULL; 8176 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 8177 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 8178 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 8179 ierr = PetscFree(link);CHKERRQ(ierr); 8180 break; 8181 } 8182 } 8183 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 8184 PetscFunctionReturn(0); 8185 } 8186 8187 /*@C 8188 DMGetLabelOutput - Get the output flag for a given label 8189 8190 Not Collective 8191 8192 Input Parameters: 8193 + dm - The DM object 8194 - name - The label name 8195 8196 Output Parameter: 8197 . output - The flag for output 8198 8199 Level: developer 8200 8201 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8202 @*/ 8203 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 8204 { 8205 DMLabelLink next = dm->labels; 8206 const char *lname; 8207 PetscErrorCode ierr; 8208 8209 PetscFunctionBegin; 8210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8211 PetscValidPointer(name, 2); 8212 PetscValidPointer(output, 3); 8213 while (next) { 8214 PetscBool flg; 8215 8216 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8217 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8218 if (flg) {*output = next->output; PetscFunctionReturn(0);} 8219 next = next->next; 8220 } 8221 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8222 } 8223 8224 /*@C 8225 DMSetLabelOutput - Set the output flag for a given label 8226 8227 Not Collective 8228 8229 Input Parameters: 8230 + dm - The DM object 8231 . name - The label name 8232 - output - The flag for output 8233 8234 Level: developer 8235 8236 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8237 @*/ 8238 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 8239 { 8240 DMLabelLink next = dm->labels; 8241 const char *lname; 8242 PetscErrorCode ierr; 8243 8244 PetscFunctionBegin; 8245 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8246 PetscValidCharPointer(name, 2); 8247 while (next) { 8248 PetscBool flg; 8249 8250 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8251 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8252 if (flg) {next->output = output; PetscFunctionReturn(0);} 8253 next = next->next; 8254 } 8255 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8256 } 8257 8258 /*@ 8259 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 8260 8261 Collective on dmA 8262 8263 Input Parameters: 8264 + dmA - The DM object with initial labels 8265 . dmB - The DM object to which labels are copied 8266 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 8267 . all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 8268 - emode - How to behave when a DMLabel in the source and destination DMs with the same name is encountered (see DMCopyLabelsMode) 8269 8270 Level: intermediate 8271 8272 Notes: 8273 This is typically used when interpolating or otherwise adding to a mesh, or testing. 8274 8275 .seealso: DMAddLabel(), DMCopyLabelsMode 8276 @*/ 8277 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode) 8278 { 8279 DMLabel label, labelNew, labelOld; 8280 const char *name; 8281 PetscBool flg; 8282 DMLabelLink link; 8283 PetscErrorCode ierr; 8284 8285 PetscFunctionBegin; 8286 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 8287 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 8288 PetscValidLogicalCollectiveEnum(dmA, mode,3); 8289 PetscValidLogicalCollectiveBool(dmA, all, 4); 8290 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 8291 if (dmA == dmB) PetscFunctionReturn(0); 8292 for (link=dmA->labels; link; link=link->next) { 8293 label=link->label; 8294 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 8295 if (!all) { 8296 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 8297 if (flg) continue; 8298 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 8299 if (flg) continue; 8300 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 8301 if (flg) continue; 8302 } 8303 ierr = DMGetLabel(dmB, name, &labelOld);CHKERRQ(ierr); 8304 if (labelOld) { 8305 switch (emode) { 8306 case DM_COPY_LABELS_KEEP: 8307 continue; 8308 case DM_COPY_LABELS_REPLACE: 8309 ierr = DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE);CHKERRQ(ierr); 8310 break; 8311 case DM_COPY_LABELS_FAIL: 8312 SETERRQ1(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name); 8313 default: 8314 SETERRQ1(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", emode); 8315 } 8316 } 8317 if (mode==PETSC_COPY_VALUES) { 8318 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 8319 } else { 8320 labelNew = label; 8321 } 8322 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 8323 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 8324 } 8325 PetscFunctionReturn(0); 8326 } 8327 8328 /*@C 8329 DMCompareLabels - Compare labels of two DMPlex meshes 8330 8331 Collective on dmA 8332 8333 Input Parameters: 8334 + dm0 - First DM object 8335 - dm1 - Second DM object 8336 8337 Output Parameters 8338 + same - (Optional) Flag whether labels of dm0 and dm1 are the same 8339 - message - (Optional) Message describing the difference, or NULL if there is no difference 8340 8341 Level: intermediate 8342 8343 Notes: 8344 If both same and message is passed as NULL, and difference is found, an error is thrown with a message describing the difference. 8345 8346 Message must be freed by user. 8347 8348 Labels are matched by name. If the number of labels and their names are equal, 8349 DMLabelCompare() is used to compare each pair of labels with the same name. 8350 8351 Fortran Notes: 8352 This function is currently not available from Fortran. 8353 8354 .seealso: DMAddLabel(), DMCopyLabelsMode, DMLabelCompare() 8355 @*/ 8356 PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *same, char **message) 8357 { 8358 PetscInt n0, n1, i; 8359 char msg[PETSC_MAX_PATH_LEN] = ""; 8360 MPI_Comm comm; 8361 PetscErrorCode ierr; 8362 8363 PetscFunctionBegin; 8364 PetscValidHeaderSpecific(dm0,DM_CLASSID,1); 8365 PetscValidHeaderSpecific(dm1,DM_CLASSID,2); 8366 PetscCheckSameComm(dm0,1,dm1,2); 8367 if (same) PetscValidBoolPointer(same,3); 8368 if (message) PetscValidPointer(message, 4); 8369 ierr = PetscObjectGetComm((PetscObject)dm0, &comm);CHKERRQ(ierr); 8370 ierr = DMGetNumLabels(dm0, &n0);CHKERRQ(ierr); 8371 ierr = DMGetNumLabels(dm1, &n1);CHKERRQ(ierr); 8372 if (n0 != n1) { 8373 ierr = PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %D != %D = Number of labels in dm1", n0, n1);CHKERRQ(ierr); 8374 goto finish; 8375 } 8376 for (i=0; i<n0; i++) { 8377 DMLabel l0, l1; 8378 const char *name; 8379 char *msgInner; 8380 8381 /* Ignore label order */ 8382 ierr = DMGetLabelByNum(dm0, i, &l0);CHKERRQ(ierr); 8383 ierr = PetscObjectGetName((PetscObject)l0, &name);CHKERRQ(ierr); 8384 ierr = DMGetLabel(dm1, name, &l1);CHKERRQ(ierr); 8385 if (!l1) { 8386 ierr = PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%D in dm0) not found in dm1", name, i);CHKERRQ(ierr); 8387 goto finish; 8388 } 8389 ierr = DMLabelCompare(l0, l1, NULL, &msgInner);CHKERRQ(ierr); 8390 ierr = PetscStrncpy(msg, msgInner, sizeof(msg));CHKERRQ(ierr); 8391 ierr = PetscFree(msgInner);CHKERRQ(ierr); 8392 if (msg[0]) goto finish; 8393 } 8394 finish: 8395 if (msg[0] && !same && !message) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, msg); 8396 if (same) *same = (PetscBool) !msg[0]; 8397 if (message) { 8398 *message = NULL; 8399 if (msg[0]) { 8400 ierr = PetscStrallocpy(msg, message);CHKERRQ(ierr); 8401 } 8402 } 8403 PetscFunctionReturn(0); 8404 } 8405 8406 PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value) 8407 { 8408 PetscErrorCode ierr; 8409 8410 PetscFunctionBegin; 8411 PetscValidPointer(label,2); 8412 if (!*label) { 8413 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 8414 ierr = DMGetLabel(dm, name, label);CHKERRQ(ierr); 8415 } 8416 ierr = DMLabelSetValue(*label, point, value);CHKERRQ(ierr); 8417 PetscFunctionReturn(0); 8418 } 8419 8420 /* 8421 Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would 8422 like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every 8423 (label, id) pair in the DM. 8424 8425 However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to 8426 each label. 8427 */ 8428 PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal) 8429 { 8430 DMUniversalLabel ul; 8431 PetscBool *active; 8432 PetscInt pStart, pEnd, p, Nl, l, m; 8433 PetscErrorCode ierr; 8434 8435 PetscFunctionBegin; 8436 ierr = PetscMalloc1(1, &ul);CHKERRQ(ierr); 8437 ierr = DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label);CHKERRQ(ierr); 8438 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 8439 ierr = PetscCalloc1(Nl, &active);CHKERRQ(ierr); 8440 ul->Nl = 0; 8441 for (l = 0; l < Nl; ++l) { 8442 PetscBool isdepth, iscelltype; 8443 const char *name; 8444 8445 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8446 ierr = PetscStrncmp(name, "depth", 6, &isdepth);CHKERRQ(ierr); 8447 ierr = PetscStrncmp(name, "celltype", 9, &iscelltype);CHKERRQ(ierr); 8448 active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE; 8449 if (active[l]) ++ul->Nl; 8450 } 8451 ierr = PetscCalloc5(ul->Nl, &ul->names, ul->Nl, &ul->indices, ul->Nl+1, &ul->offsets, ul->Nl+1, &ul->bits, ul->Nl, &ul->masks);CHKERRQ(ierr); 8452 ul->Nv = 0; 8453 for (l = 0, m = 0; l < Nl; ++l) { 8454 DMLabel label; 8455 PetscInt nv; 8456 const char *name; 8457 8458 if (!active[l]) continue; 8459 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8460 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8461 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8462 ierr = PetscStrallocpy(name, &ul->names[m]);CHKERRQ(ierr); 8463 ul->indices[m] = l; 8464 ul->Nv += nv; 8465 ul->offsets[m+1] = nv; 8466 ul->bits[m+1] = PetscCeilReal(PetscLog2Real(nv+1)); 8467 ++m; 8468 } 8469 for (l = 1; l <= ul->Nl; ++l) { 8470 ul->offsets[l] = ul->offsets[l-1] + ul->offsets[l]; 8471 ul->bits[l] = ul->bits[l-1] + ul->bits[l]; 8472 } 8473 for (l = 0; l < ul->Nl; ++l) { 8474 PetscInt b; 8475 8476 ul->masks[l] = 0; 8477 for (b = ul->bits[l]; b < ul->bits[l+1]; ++b) ul->masks[l] |= 1 << b; 8478 } 8479 ierr = PetscMalloc1(ul->Nv, &ul->values);CHKERRQ(ierr); 8480 for (l = 0, m = 0; l < Nl; ++l) { 8481 DMLabel label; 8482 IS valueIS; 8483 const PetscInt *varr; 8484 PetscInt nv, v; 8485 8486 if (!active[l]) continue; 8487 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8488 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8489 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 8490 ierr = ISGetIndices(valueIS, &varr);CHKERRQ(ierr); 8491 for (v = 0; v < nv; ++v) { 8492 ul->values[ul->offsets[m]+v] = varr[v]; 8493 } 8494 ierr = ISRestoreIndices(valueIS, &varr);CHKERRQ(ierr); 8495 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 8496 ierr = PetscSortInt(nv, &ul->values[ul->offsets[m]]);CHKERRQ(ierr); 8497 ++m; 8498 } 8499 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8500 for (p = pStart; p < pEnd; ++p) { 8501 PetscInt uval = 0; 8502 PetscBool marked = PETSC_FALSE; 8503 8504 for (l = 0, m = 0; l < Nl; ++l) { 8505 DMLabel label; 8506 PetscInt val, defval, loc, nv; 8507 8508 if (!active[l]) continue; 8509 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8510 ierr = DMLabelGetValue(label, p, &val);CHKERRQ(ierr); 8511 ierr = DMLabelGetDefaultValue(label, &defval);CHKERRQ(ierr); 8512 if (val == defval) {++m; continue;} 8513 nv = ul->offsets[m+1]-ul->offsets[m]; 8514 marked = PETSC_TRUE; 8515 ierr = PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc);CHKERRQ(ierr); 8516 if (loc < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %D not found in compression array", val); 8517 uval += (loc+1) << ul->bits[m]; 8518 ++m; 8519 } 8520 if (marked) {ierr = DMLabelSetValue(ul->label, p, uval);CHKERRQ(ierr);} 8521 } 8522 ierr = PetscFree(active);CHKERRQ(ierr); 8523 *universal = ul; 8524 PetscFunctionReturn(0); 8525 } 8526 8527 PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal) 8528 { 8529 PetscInt l; 8530 PetscErrorCode ierr; 8531 8532 PetscFunctionBegin; 8533 for (l = 0; l < (*universal)->Nl; ++l) {ierr = PetscFree((*universal)->names[l]);CHKERRQ(ierr);} 8534 ierr = DMLabelDestroy(&(*universal)->label);CHKERRQ(ierr); 8535 ierr = PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks);CHKERRQ(ierr); 8536 ierr = PetscFree((*universal)->values);CHKERRQ(ierr); 8537 ierr = PetscFree(*universal);CHKERRQ(ierr); 8538 *universal = NULL; 8539 PetscFunctionReturn(0); 8540 } 8541 8542 PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel) 8543 { 8544 PetscFunctionBegin; 8545 PetscValidPointer(ulabel, 2); 8546 *ulabel = ul->label; 8547 PetscFunctionReturn(0); 8548 } 8549 8550 PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm) 8551 { 8552 PetscInt Nl = ul->Nl, l; 8553 PetscErrorCode ierr; 8554 8555 PetscFunctionBegin; 8556 PetscValidHeaderSpecific(dm, DM_CLASSID, 3); 8557 for (l = 0; l < Nl; ++l) { 8558 if (preserveOrder) {ierr = DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]);CHKERRQ(ierr);} 8559 else {ierr = DMCreateLabel(dm, ul->names[l]);CHKERRQ(ierr);} 8560 } 8561 if (preserveOrder) { 8562 for (l = 0; l < ul->Nl; ++l) { 8563 const char *name; 8564 PetscBool match; 8565 8566 ierr = DMGetLabelName(dm, ul->indices[l], &name);CHKERRQ(ierr); 8567 ierr = PetscStrcmp(name, ul->names[l], &match);CHKERRQ(ierr); 8568 if (!match) SETERRQ3(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %D name %s does not match new name %s", l, name, ul->names[l]); 8569 } 8570 } 8571 PetscFunctionReturn(0); 8572 } 8573 8574 PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value) 8575 { 8576 PetscInt l; 8577 PetscErrorCode ierr; 8578 8579 PetscFunctionBegin; 8580 for (l = 0; l < ul->Nl; ++l) { 8581 DMLabel label; 8582 PetscInt lval = (value & ul->masks[l]) >> ul->bits[l]; 8583 8584 if (lval) { 8585 if (useIndex) {ierr = DMGetLabelByNum(dm, ul->indices[l], &label);CHKERRQ(ierr);} 8586 else {ierr = DMGetLabel(dm, ul->names[l], &label);CHKERRQ(ierr);} 8587 ierr = DMLabelSetValue(label, p, ul->values[ul->offsets[l]+lval-1]);CHKERRQ(ierr); 8588 } 8589 } 8590 PetscFunctionReturn(0); 8591 } 8592 8593 /*@ 8594 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 8595 8596 Input Parameter: 8597 . dm - The DM object 8598 8599 Output Parameter: 8600 . cdm - The coarse DM 8601 8602 Level: intermediate 8603 8604 .seealso: DMSetCoarseDM() 8605 @*/ 8606 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 8607 { 8608 PetscFunctionBegin; 8609 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8610 PetscValidPointer(cdm, 2); 8611 *cdm = dm->coarseMesh; 8612 PetscFunctionReturn(0); 8613 } 8614 8615 /*@ 8616 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 8617 8618 Input Parameters: 8619 + dm - The DM object 8620 - cdm - The coarse DM 8621 8622 Level: intermediate 8623 8624 .seealso: DMGetCoarseDM() 8625 @*/ 8626 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 8627 { 8628 PetscErrorCode ierr; 8629 8630 PetscFunctionBegin; 8631 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8632 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 8633 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 8634 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 8635 dm->coarseMesh = cdm; 8636 PetscFunctionReturn(0); 8637 } 8638 8639 /*@ 8640 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 8641 8642 Input Parameter: 8643 . dm - The DM object 8644 8645 Output Parameter: 8646 . fdm - The fine DM 8647 8648 Level: intermediate 8649 8650 .seealso: DMSetFineDM() 8651 @*/ 8652 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 8653 { 8654 PetscFunctionBegin; 8655 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8656 PetscValidPointer(fdm, 2); 8657 *fdm = dm->fineMesh; 8658 PetscFunctionReturn(0); 8659 } 8660 8661 /*@ 8662 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 8663 8664 Input Parameters: 8665 + dm - The DM object 8666 - fdm - The fine DM 8667 8668 Level: intermediate 8669 8670 .seealso: DMGetFineDM() 8671 @*/ 8672 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 8673 { 8674 PetscErrorCode ierr; 8675 8676 PetscFunctionBegin; 8677 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8678 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 8679 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 8680 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 8681 dm->fineMesh = fdm; 8682 PetscFunctionReturn(0); 8683 } 8684 8685 /*=== DMBoundary code ===*/ 8686 8687 /*@C 8688 DMAddBoundary - Add a boundary condition to the model 8689 8690 Collective on dm 8691 8692 Input Parameters: 8693 + dm - The DM, with a PetscDS that matches the problem being constrained 8694 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 8695 . name - The BC name 8696 . label - The label defining constrained points 8697 . Nv - The number of DMLabel values for constrained points 8698 . values - An array of values for constrained points 8699 . field - The field to constrain 8700 . Nc - The number of constrained field components (0 will constrain all fields) 8701 . comps - An array of constrained component numbers 8702 . bcFunc - A pointwise function giving boundary values 8703 . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL 8704 - ctx - An optional user context for bcFunc 8705 8706 Output Parameter: 8707 . bd - (Optional) Boundary number 8708 8709 Options Database Keys: 8710 + -bc_<boundary name> <num> - Overrides the boundary ids 8711 - -bc_<boundary name>_comp <num> - Overrides the boundary components 8712 8713 Note: 8714 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 8715 8716 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 8717 8718 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 8719 8720 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8721 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8722 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8723 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 8724 8725 + dim - the spatial dimension 8726 . Nf - the number of fields 8727 . uOff - the offset into u[] and u_t[] for each field 8728 . uOff_x - the offset into u_x[] for each field 8729 . u - each field evaluated at the current point 8730 . u_t - the time derivative of each field evaluated at the current point 8731 . u_x - the gradient of each field evaluated at the current point 8732 . aOff - the offset into a[] and a_t[] for each auxiliary field 8733 . aOff_x - the offset into a_x[] for each auxiliary field 8734 . a - each auxiliary field evaluated at the current point 8735 . a_t - the time derivative of each auxiliary field evaluated at the current point 8736 . a_x - the gradient of auxiliary each field evaluated at the current point 8737 . t - current time 8738 . x - coordinates of the current point 8739 . numConstants - number of constant parameters 8740 . constants - constant parameters 8741 - bcval - output values at the current point 8742 8743 Level: developer 8744 8745 .seealso: DSGetBoundary(), PetscDSAddBoundary() 8746 @*/ 8747 PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd) 8748 { 8749 PetscDS ds; 8750 PetscErrorCode ierr; 8751 8752 PetscFunctionBegin; 8753 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8754 PetscValidLogicalCollectiveEnum(dm, type, 2); 8755 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 8756 PetscValidLogicalCollectiveInt(dm, Nv, 5); 8757 PetscValidLogicalCollectiveInt(dm, field, 7); 8758 PetscValidLogicalCollectiveInt(dm, Nc, 8); 8759 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8760 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, label);CHKERRQ(ierr); 8761 ierr = PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd);CHKERRQ(ierr); 8762 PetscFunctionReturn(0); 8763 } 8764 8765 /* TODO Remove this since now the structures are the same */ 8766 static PetscErrorCode DMPopulateBoundary(DM dm) 8767 { 8768 PetscDS ds; 8769 DMBoundary *lastnext; 8770 DSBoundary dsbound; 8771 PetscErrorCode ierr; 8772 8773 PetscFunctionBegin; 8774 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8775 dsbound = ds->boundary; 8776 if (dm->boundary) { 8777 DMBoundary next = dm->boundary; 8778 8779 /* quick check to see if the PetscDS has changed */ 8780 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 8781 /* the PetscDS has changed: tear down and rebuild */ 8782 while (next) { 8783 DMBoundary b = next; 8784 8785 next = b->next; 8786 ierr = PetscFree(b);CHKERRQ(ierr); 8787 } 8788 dm->boundary = NULL; 8789 } 8790 8791 lastnext = &(dm->boundary); 8792 while (dsbound) { 8793 DMBoundary dmbound; 8794 8795 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 8796 dmbound->dsboundary = dsbound; 8797 dmbound->label = dsbound->label; 8798 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 8799 *lastnext = dmbound; 8800 lastnext = &(dmbound->next); 8801 dsbound = dsbound->next; 8802 } 8803 PetscFunctionReturn(0); 8804 } 8805 8806 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 8807 { 8808 DMBoundary b; 8809 PetscErrorCode ierr; 8810 8811 PetscFunctionBegin; 8812 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8813 PetscValidBoolPointer(isBd, 3); 8814 *isBd = PETSC_FALSE; 8815 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 8816 b = dm->boundary; 8817 while (b && !(*isBd)) { 8818 DMLabel label = b->label; 8819 DSBoundary dsb = b->dsboundary; 8820 PetscInt i; 8821 8822 if (label) { 8823 for (i = 0; i < dsb->Nv && !(*isBd); ++i) {ierr = DMLabelStratumHasPoint(label, dsb->values[i], point, isBd);CHKERRQ(ierr);} 8824 } 8825 b = b->next; 8826 } 8827 PetscFunctionReturn(0); 8828 } 8829 8830 /*@C 8831 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 8832 8833 Collective on DM 8834 8835 Input Parameters: 8836 + dm - The DM 8837 . time - The time 8838 . funcs - The coordinate functions to evaluate, one per field 8839 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8840 - mode - The insertion mode for values 8841 8842 Output Parameter: 8843 . X - vector 8844 8845 Calling sequence of func: 8846 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 8847 8848 + dim - The spatial dimension 8849 . time - The time at which to sample 8850 . x - The coordinates 8851 . Nc - The number of components 8852 . u - The output field values 8853 - ctx - optional user-defined function context 8854 8855 Level: developer 8856 8857 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8858 @*/ 8859 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 8860 { 8861 Vec localX; 8862 PetscErrorCode ierr; 8863 8864 PetscFunctionBegin; 8865 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8866 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8867 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8868 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8869 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8870 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8871 PetscFunctionReturn(0); 8872 } 8873 8874 /*@C 8875 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 8876 8877 Not collective 8878 8879 Input Parameters: 8880 + dm - The DM 8881 . time - The time 8882 . funcs - The coordinate functions to evaluate, one per field 8883 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8884 - mode - The insertion mode for values 8885 8886 Output Parameter: 8887 . localX - vector 8888 8889 Calling sequence of func: 8890 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 8891 8892 + dim - The spatial dimension 8893 . x - The coordinates 8894 . Nc - The number of components 8895 . u - The output field values 8896 - ctx - optional user-defined function context 8897 8898 Level: developer 8899 8900 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 8901 @*/ 8902 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 8903 { 8904 PetscErrorCode ierr; 8905 8906 PetscFunctionBegin; 8907 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8908 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 8909 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 8910 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8911 PetscFunctionReturn(0); 8912 } 8913 8914 /*@C 8915 DMProjectFunctionLabel - This projects the given function into the function space provided, putting the coefficients in a global vector, setting values only for points in the given label. 8916 8917 Collective on DM 8918 8919 Input Parameters: 8920 + dm - The DM 8921 . time - The time 8922 . label - The DMLabel selecting the portion of the mesh for projection 8923 . funcs - The coordinate functions to evaluate, one per field 8924 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8925 - mode - The insertion mode for values 8926 8927 Output Parameter: 8928 . X - vector 8929 8930 Calling sequence of func: 8931 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 8932 8933 + dim - The spatial dimension 8934 . x - The coordinates 8935 . Nc - The number of components 8936 . u - The output field values 8937 - ctx - optional user-defined function context 8938 8939 Level: developer 8940 8941 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 8942 @*/ 8943 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) 8944 { 8945 Vec localX; 8946 PetscErrorCode ierr; 8947 8948 PetscFunctionBegin; 8949 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8950 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8951 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8952 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8953 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8954 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8955 PetscFunctionReturn(0); 8956 } 8957 8958 /*@C 8959 DMProjectFunctionLabelLocal - This projects the given function into the function space provided, putting the coefficients in a local vector, setting values only for points in the given label. 8960 8961 Not collective 8962 8963 Input Parameters: 8964 + dm - The DM 8965 . time - The time 8966 . label - The DMLabel selecting the portion of the mesh for projection 8967 . funcs - The coordinate functions to evaluate, one per field 8968 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8969 - mode - The insertion mode for values 8970 8971 Output Parameter: 8972 . localX - vector 8973 8974 Calling sequence of func: 8975 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 8976 8977 + dim - The spatial dimension 8978 . x - The coordinates 8979 . Nc - The number of components 8980 . u - The output field values 8981 - ctx - optional user-defined function context 8982 8983 Level: developer 8984 8985 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8986 @*/ 8987 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) 8988 { 8989 PetscErrorCode ierr; 8990 8991 PetscFunctionBegin; 8992 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8993 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 8994 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 8995 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8996 PetscFunctionReturn(0); 8997 } 8998 8999 /*@C 9000 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 9001 9002 Not collective 9003 9004 Input Parameters: 9005 + dm - The DM 9006 . time - The time 9007 . localU - The input field vector 9008 . funcs - The functions to evaluate, one per field 9009 - mode - The insertion mode for values 9010 9011 Output Parameter: 9012 . localX - The output vector 9013 9014 Calling sequence of func: 9015 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9016 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9017 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9018 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9019 9020 + dim - The spatial dimension 9021 . Nf - The number of input fields 9022 . NfAux - The number of input auxiliary fields 9023 . uOff - The offset of each field in u[] 9024 . uOff_x - The offset of each field in u_x[] 9025 . u - The field values at this point in space 9026 . u_t - The field time derivative at this point in space (or NULL) 9027 . u_x - The field derivatives at this point in space 9028 . aOff - The offset of each auxiliary field in u[] 9029 . aOff_x - The offset of each auxiliary field in u_x[] 9030 . a - The auxiliary field values at this point in space 9031 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9032 . a_x - The auxiliary field derivatives at this point in space 9033 . t - The current time 9034 . x - The coordinates of this point 9035 . numConstants - The number of constants 9036 . constants - The value of each constant 9037 - f - The value of the function at this point in space 9038 9039 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 9040 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or 9041 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9042 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9043 9044 Level: intermediate 9045 9046 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9047 @*/ 9048 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 9049 void (**funcs)(PetscInt, PetscInt, PetscInt, 9050 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9051 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9052 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9053 InsertMode mode, Vec localX) 9054 { 9055 PetscErrorCode ierr; 9056 9057 PetscFunctionBegin; 9058 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9059 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 9060 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 9061 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 9062 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 9063 PetscFunctionReturn(0); 9064 } 9065 9066 /*@C 9067 DMProjectFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain specified by the label. 9068 9069 Not collective 9070 9071 Input Parameters: 9072 + dm - The DM 9073 . time - The time 9074 . label - The DMLabel marking the portion of the domain to output 9075 . numIds - The number of label ids to use 9076 . ids - The label ids to use for marking 9077 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 9078 . comps - The components to set in the output, or NULL for all components 9079 . localU - The input field vector 9080 . funcs - The functions to evaluate, one per field 9081 - mode - The insertion mode for values 9082 9083 Output Parameter: 9084 . localX - The output vector 9085 9086 Calling sequence of func: 9087 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9088 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9089 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9090 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9091 9092 + dim - The spatial dimension 9093 . Nf - The number of input fields 9094 . NfAux - The number of input auxiliary fields 9095 . uOff - The offset of each field in u[] 9096 . uOff_x - The offset of each field in u_x[] 9097 . u - The field values at this point in space 9098 . u_t - The field time derivative at this point in space (or NULL) 9099 . u_x - The field derivatives at this point in space 9100 . aOff - The offset of each auxiliary field in u[] 9101 . aOff_x - The offset of each auxiliary field in u_x[] 9102 . a - The auxiliary field values at this point in space 9103 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9104 . a_x - The auxiliary field derivatives at this point in space 9105 . t - The current time 9106 . x - The coordinates of this point 9107 . numConstants - The number of constants 9108 . constants - The value of each constant 9109 - f - The value of the function at this point in space 9110 9111 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 9112 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or 9113 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9114 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9115 9116 Level: intermediate 9117 9118 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9119 @*/ 9120 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 9121 void (**funcs)(PetscInt, PetscInt, PetscInt, 9122 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9123 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9124 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9125 InsertMode mode, Vec localX) 9126 { 9127 PetscErrorCode ierr; 9128 9129 PetscFunctionBegin; 9130 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9131 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 9132 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9133 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name); 9134 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 9135 PetscFunctionReturn(0); 9136 } 9137 9138 /*@C 9139 DMProjectBdFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain boundary specified by the label. 9140 9141 Not collective 9142 9143 Input Parameters: 9144 + dm - The DM 9145 . time - The time 9146 . label - The DMLabel marking the portion of the domain boundary to output 9147 . numIds - The number of label ids to use 9148 . ids - The label ids to use for marking 9149 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 9150 . comps - The components to set in the output, or NULL for all components 9151 . localU - The input field vector 9152 . funcs - The functions to evaluate, one per field 9153 - mode - The insertion mode for values 9154 9155 Output Parameter: 9156 . localX - The output vector 9157 9158 Calling sequence of func: 9159 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9160 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9161 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9162 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9163 9164 + dim - The spatial dimension 9165 . Nf - The number of input fields 9166 . NfAux - The number of input auxiliary fields 9167 . uOff - The offset of each field in u[] 9168 . uOff_x - The offset of each field in u_x[] 9169 . u - The field values at this point in space 9170 . u_t - The field time derivative at this point in space (or NULL) 9171 . u_x - The field derivatives at this point in space 9172 . aOff - The offset of each auxiliary field in u[] 9173 . aOff_x - The offset of each auxiliary field in u_x[] 9174 . a - The auxiliary field values at this point in space 9175 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9176 . a_x - The auxiliary field derivatives at this point in space 9177 . t - The current time 9178 . x - The coordinates of this point 9179 . n - The face normal 9180 . numConstants - The number of constants 9181 . constants - The value of each constant 9182 - f - The value of the function at this point in space 9183 9184 Note: 9185 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 9186 The input DM, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or 9187 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9188 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9189 9190 Level: intermediate 9191 9192 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9193 @*/ 9194 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 9195 void (**funcs)(PetscInt, PetscInt, PetscInt, 9196 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9197 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9198 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9199 InsertMode mode, Vec localX) 9200 { 9201 PetscErrorCode ierr; 9202 9203 PetscFunctionBegin; 9204 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9205 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 9206 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9207 if (!dm->ops->projectbdfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name); 9208 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 9209 PetscFunctionReturn(0); 9210 } 9211 9212 /*@C 9213 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9214 9215 Input Parameters: 9216 + dm - The DM 9217 . time - The time 9218 . funcs - The functions to evaluate for each field component 9219 . ctxs - Optional array of contexts to pass to each function, or NULL. 9220 - X - The coefficient vector u_h, a global vector 9221 9222 Output Parameter: 9223 . diff - The diff ||u - u_h||_2 9224 9225 Level: developer 9226 9227 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9228 @*/ 9229 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 9230 { 9231 PetscErrorCode ierr; 9232 9233 PetscFunctionBegin; 9234 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9235 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9236 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 9237 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9238 PetscFunctionReturn(0); 9239 } 9240 9241 /*@C 9242 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 9243 9244 Collective on dm 9245 9246 Input Parameters: 9247 + dm - The DM 9248 , time - The time 9249 . funcs - The gradient functions to evaluate for each field component 9250 . ctxs - Optional array of contexts to pass to each function, or NULL. 9251 . X - The coefficient vector u_h, a global vector 9252 - n - The vector to project along 9253 9254 Output Parameter: 9255 . diff - The diff ||(grad u - grad u_h) . n||_2 9256 9257 Level: developer 9258 9259 .seealso: DMProjectFunction(), DMComputeL2Diff() 9260 @*/ 9261 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) 9262 { 9263 PetscErrorCode ierr; 9264 9265 PetscFunctionBegin; 9266 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9267 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9268 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 9269 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 9270 PetscFunctionReturn(0); 9271 } 9272 9273 /*@C 9274 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 9275 9276 Collective on dm 9277 9278 Input Parameters: 9279 + dm - The DM 9280 . time - The time 9281 . funcs - The functions to evaluate for each field component 9282 . ctxs - Optional array of contexts to pass to each function, or NULL. 9283 - X - The coefficient vector u_h, a global vector 9284 9285 Output Parameter: 9286 . diff - The array of differences, ||u^f - u^f_h||_2 9287 9288 Level: developer 9289 9290 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9291 @*/ 9292 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 9293 { 9294 PetscErrorCode ierr; 9295 9296 PetscFunctionBegin; 9297 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9298 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9299 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 9300 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9301 PetscFunctionReturn(0); 9302 } 9303 9304 /*@C 9305 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 9306 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 9307 9308 Collective on dm 9309 9310 Input parameters: 9311 + dm - the pre-adaptation DM object 9312 - label - label with the flags 9313 9314 Output parameters: 9315 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 9316 9317 Level: intermediate 9318 9319 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 9320 @*/ 9321 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 9322 { 9323 PetscErrorCode ierr; 9324 9325 PetscFunctionBegin; 9326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9327 PetscValidPointer(label,2); 9328 PetscValidPointer(dmAdapt,3); 9329 *dmAdapt = NULL; 9330 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 9331 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 9332 if (*dmAdapt) { 9333 (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */ 9334 ierr = PetscFree((*dmAdapt)->vectype);CHKERRQ(ierr); 9335 ierr = PetscStrallocpy(dm->vectype,(char**)&(*dmAdapt)->vectype);CHKERRQ(ierr); 9336 ierr = PetscFree((*dmAdapt)->mattype);CHKERRQ(ierr); 9337 ierr = PetscStrallocpy(dm->mattype,(char**)&(*dmAdapt)->mattype);CHKERRQ(ierr); 9338 } 9339 PetscFunctionReturn(0); 9340 } 9341 9342 /*@C 9343 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 9344 9345 Input Parameters: 9346 + dm - The DM object 9347 . metric - The metric to which the mesh is adapted, defined vertex-wise. 9348 - 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_". 9349 9350 Output Parameter: 9351 . dmAdapt - Pointer to the DM object containing the adapted mesh 9352 9353 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 9354 9355 Level: advanced 9356 9357 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 9358 @*/ 9359 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 9360 { 9361 PetscErrorCode ierr; 9362 9363 PetscFunctionBegin; 9364 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9365 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 9366 if (bdLabel) PetscValidPointer(bdLabel, 3); 9367 PetscValidPointer(dmAdapt, 4); 9368 *dmAdapt = NULL; 9369 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 9370 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 9371 PetscFunctionReturn(0); 9372 } 9373 9374 /*@C 9375 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 9376 9377 Not Collective 9378 9379 Input Parameter: 9380 . dm - The DM 9381 9382 Output Parameters: 9383 + nranks - the number of neighbours 9384 - ranks - the neighbors ranks 9385 9386 Notes: 9387 Do not free the array, it is freed when the DM is destroyed. 9388 9389 Level: beginner 9390 9391 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 9392 @*/ 9393 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 9394 { 9395 PetscErrorCode ierr; 9396 9397 PetscFunctionBegin; 9398 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9399 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 9400 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 9401 PetscFunctionReturn(0); 9402 } 9403 9404 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 9405 9406 /* 9407 Converts the input vector to a ghosted vector and then calls the standard coloring code. 9408 This has be a different function because it requires DM which is not defined in the Mat library 9409 */ 9410 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 9411 { 9412 PetscErrorCode ierr; 9413 9414 PetscFunctionBegin; 9415 if (coloring->ctype == IS_COLORING_LOCAL) { 9416 Vec x1local; 9417 DM dm; 9418 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9419 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 9420 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 9421 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9422 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9423 x1 = x1local; 9424 } 9425 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 9426 if (coloring->ctype == IS_COLORING_LOCAL) { 9427 DM dm; 9428 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9429 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 9430 } 9431 PetscFunctionReturn(0); 9432 } 9433 9434 /*@ 9435 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 9436 9437 Input Parameter: 9438 . coloring - the MatFDColoring object 9439 9440 Developer Notes: 9441 this routine exists because the PETSc Mat library does not know about the DM objects 9442 9443 Level: advanced 9444 9445 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 9446 @*/ 9447 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 9448 { 9449 PetscFunctionBegin; 9450 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 9451 PetscFunctionReturn(0); 9452 } 9453 9454 /*@ 9455 DMGetCompatibility - determine if two DMs are compatible 9456 9457 Collective 9458 9459 Input Parameters: 9460 + dm1 - the first DM 9461 - dm2 - the second DM 9462 9463 Output Parameters: 9464 + compatible - whether or not the two DMs are compatible 9465 - set - whether or not the compatible value was set 9466 9467 Notes: 9468 Two DMs are deemed compatible if they represent the same parallel decomposition 9469 of the same topology. This implies that the section (field data) on one 9470 "makes sense" with respect to the topology and parallel decomposition of the other. 9471 Loosely speaking, compatible DMs represent the same domain and parallel 9472 decomposition, but hold different data. 9473 9474 Typically, one would confirm compatibility if intending to simultaneously iterate 9475 over a pair of vectors obtained from different DMs. 9476 9477 For example, two DMDA objects are compatible if they have the same local 9478 and global sizes and the same stencil width. They can have different numbers 9479 of degrees of freedom per node. Thus, one could use the node numbering from 9480 either DM in bounds for a loop over vectors derived from either DM. 9481 9482 Consider the operation of summing data living on a 2-dof DMDA to data living 9483 on a 1-dof DMDA, which should be compatible, as in the following snippet. 9484 .vb 9485 ... 9486 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 9487 if (set && compatible) { 9488 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9489 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9490 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 9491 for (j=y; j<y+n; ++j) { 9492 for (i=x; i<x+m, ++i) { 9493 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 9494 } 9495 } 9496 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9497 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9498 } else { 9499 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 9500 } 9501 ... 9502 .ve 9503 9504 Checking compatibility might be expensive for a given implementation of DM, 9505 or might be impossible to unambiguously confirm or deny. For this reason, 9506 this function may decline to determine compatibility, and hence users should 9507 always check the "set" output parameter. 9508 9509 A DM is always compatible with itself. 9510 9511 In the current implementation, DMs which live on "unequal" communicators 9512 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 9513 incompatible. 9514 9515 This function is labeled "Collective," as information about all subdomains 9516 is required on each rank. However, in DM implementations which store all this 9517 information locally, this function may be merely "Logically Collective". 9518 9519 Developer Notes: 9520 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 9521 iff B is compatible with A. Thus, this function checks the implementations 9522 of both dm and dmc (if they are of different types), attempting to determine 9523 compatibility. It is left to DM implementers to ensure that symmetry is 9524 preserved. The simplest way to do this is, when implementing type-specific 9525 logic for this function, is to check for existing logic in the implementation 9526 of other DM types and let *set = PETSC_FALSE if found. 9527 9528 Level: advanced 9529 9530 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 9531 @*/ 9532 9533 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 9534 { 9535 PetscErrorCode ierr; 9536 PetscMPIInt compareResult; 9537 DMType type,type2; 9538 PetscBool sameType; 9539 9540 PetscFunctionBegin; 9541 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 9542 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 9543 9544 /* Declare a DM compatible with itself */ 9545 if (dm1 == dm2) { 9546 *set = PETSC_TRUE; 9547 *compatible = PETSC_TRUE; 9548 PetscFunctionReturn(0); 9549 } 9550 9551 /* Declare a DM incompatible with a DM that lives on an "unequal" 9552 communicator. Note that this does not preclude compatibility with 9553 DMs living on "congruent" or "similar" communicators, but this must be 9554 determined by the implementation-specific logic */ 9555 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRMPI(ierr); 9556 if (compareResult == MPI_UNEQUAL) { 9557 *set = PETSC_TRUE; 9558 *compatible = PETSC_FALSE; 9559 PetscFunctionReturn(0); 9560 } 9561 9562 /* Pass to the implementation-specific routine, if one exists. */ 9563 if (dm1->ops->getcompatibility) { 9564 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 9565 if (*set) PetscFunctionReturn(0); 9566 } 9567 9568 /* If dm1 and dm2 are of different types, then attempt to check compatibility 9569 with an implementation of this function from dm2 */ 9570 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 9571 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 9572 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 9573 if (!sameType && dm2->ops->getcompatibility) { 9574 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 9575 } else { 9576 *set = PETSC_FALSE; 9577 } 9578 PetscFunctionReturn(0); 9579 } 9580 9581 /*@C 9582 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 9583 9584 Logically Collective on DM 9585 9586 Input Parameters: 9587 + DM - the DM 9588 . f - the monitor function 9589 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 9590 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 9591 9592 Options Database Keys: 9593 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 9594 does not cancel those set via the options database. 9595 9596 Notes: 9597 Several different monitoring routines may be set by calling 9598 DMMonitorSet() multiple times; all will be called in the 9599 order in which they were set. 9600 9601 Fortran Notes: 9602 Only a single monitor function can be set for each DM object 9603 9604 Level: intermediate 9605 9606 .seealso: DMMonitorCancel() 9607 @*/ 9608 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 9609 { 9610 PetscInt m; 9611 PetscErrorCode ierr; 9612 9613 PetscFunctionBegin; 9614 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9615 for (m = 0; m < dm->numbermonitors; ++m) { 9616 PetscBool identical; 9617 9618 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 9619 if (identical) PetscFunctionReturn(0); 9620 } 9621 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 9622 dm->monitor[dm->numbermonitors] = f; 9623 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 9624 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 9625 PetscFunctionReturn(0); 9626 } 9627 9628 /*@ 9629 DMMonitorCancel - Clears all the monitor functions for a DM object. 9630 9631 Logically Collective on DM 9632 9633 Input Parameter: 9634 . dm - the DM 9635 9636 Options Database Key: 9637 . -dm_monitor_cancel - cancels all monitors that have been hardwired 9638 into a code by calls to DMonitorSet(), but does not cancel those 9639 set via the options database 9640 9641 Notes: 9642 There is no way to clear one specific monitor from a DM object. 9643 9644 Level: intermediate 9645 9646 .seealso: DMMonitorSet() 9647 @*/ 9648 PetscErrorCode DMMonitorCancel(DM dm) 9649 { 9650 PetscErrorCode ierr; 9651 PetscInt m; 9652 9653 PetscFunctionBegin; 9654 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9655 for (m = 0; m < dm->numbermonitors; ++m) { 9656 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 9657 } 9658 dm->numbermonitors = 0; 9659 PetscFunctionReturn(0); 9660 } 9661 9662 /*@C 9663 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 9664 9665 Collective on DM 9666 9667 Input Parameters: 9668 + dm - DM object you wish to monitor 9669 . name - the monitor type one is seeking 9670 . help - message indicating what monitoring is done 9671 . manual - manual page for the monitor 9672 . monitor - the monitor function 9673 - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the DM or PetscViewer objects 9674 9675 Output Parameter: 9676 . flg - Flag set if the monitor was created 9677 9678 Level: developer 9679 9680 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 9681 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 9682 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 9683 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 9684 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 9685 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 9686 PetscOptionsFList(), PetscOptionsEList() 9687 @*/ 9688 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 9689 { 9690 PetscViewer viewer; 9691 PetscViewerFormat format; 9692 PetscErrorCode ierr; 9693 9694 PetscFunctionBegin; 9695 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9696 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 9697 if (*flg) { 9698 PetscViewerAndFormat *vf; 9699 9700 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 9701 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 9702 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 9703 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 9704 } 9705 PetscFunctionReturn(0); 9706 } 9707 9708 /*@ 9709 DMMonitor - runs the user provided monitor routines, if they exist 9710 9711 Collective on DM 9712 9713 Input Parameters: 9714 . dm - The DM 9715 9716 Level: developer 9717 9718 .seealso: DMMonitorSet() 9719 @*/ 9720 PetscErrorCode DMMonitor(DM dm) 9721 { 9722 PetscInt m; 9723 PetscErrorCode ierr; 9724 9725 PetscFunctionBegin; 9726 if (!dm) PetscFunctionReturn(0); 9727 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9728 for (m = 0; m < dm->numbermonitors; ++m) { 9729 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 9730 } 9731 PetscFunctionReturn(0); 9732 } 9733 9734 /*@ 9735 DMComputeError - Computes the error assuming the user has given exact solution functions 9736 9737 Collective on DM 9738 9739 Input Parameters: 9740 + dm - The DM 9741 - sol - The solution vector 9742 9743 Input/Output Parameter: 9744 . errors - An array of length Nf, the number of fields, or NULL for no output; on output 9745 contains the error in each field 9746 9747 Output Parameter: 9748 . errorVec - A vector to hold the cellwise error (may be NULL) 9749 9750 Note: The exact solutions come from the PetscDS object, and the time comes from DMGetOutputSequenceNumber(). 9751 9752 Level: developer 9753 9754 .seealso: DMMonitorSet(), DMGetRegionNumDS(), PetscDSGetExactSolution(), DMGetOutputSequenceNumber() 9755 @*/ 9756 PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec) 9757 { 9758 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 9759 void **ctxs; 9760 PetscReal time; 9761 PetscInt Nf, f, Nds, s; 9762 PetscErrorCode ierr; 9763 9764 PetscFunctionBegin; 9765 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9766 ierr = PetscCalloc2(Nf, &exactSol, Nf, &ctxs);CHKERRQ(ierr); 9767 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 9768 for (s = 0; s < Nds; ++s) { 9769 PetscDS ds; 9770 DMLabel label; 9771 IS fieldIS; 9772 const PetscInt *fields; 9773 PetscInt dsNf; 9774 9775 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 9776 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 9777 if (fieldIS) {ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);} 9778 for (f = 0; f < dsNf; ++f) { 9779 const PetscInt field = fields[f]; 9780 ierr = PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]);CHKERRQ(ierr); 9781 } 9782 if (fieldIS) {ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);} 9783 } 9784 for (f = 0; f < Nf; ++f) { 9785 if (!exactSol[f]) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "DS must contain exact solution functions in order to calculate error, missing for field %D", f); 9786 } 9787 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 9788 if (errors) {ierr = DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors);CHKERRQ(ierr);} 9789 if (errorVec) { 9790 DM edm; 9791 DMPolytopeType ct; 9792 PetscBool simplex; 9793 PetscInt dim, cStart, Nf; 9794 9795 ierr = DMClone(dm, &edm);CHKERRQ(ierr); 9796 ierr = DMGetDimension(edm, &dim);CHKERRQ(ierr); 9797 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 9798 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 9799 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 9800 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9801 for (f = 0; f < Nf; ++f) { 9802 PetscFE fe, efe; 9803 PetscQuadrature q; 9804 const char *name; 9805 9806 ierr = DMGetField(dm, f, NULL, (PetscObject *) &fe);CHKERRQ(ierr); 9807 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe);CHKERRQ(ierr); 9808 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 9809 ierr = PetscObjectSetName((PetscObject) efe, name);CHKERRQ(ierr); 9810 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 9811 ierr = PetscFESetQuadrature(efe, q);CHKERRQ(ierr); 9812 ierr = DMSetField(edm, f, NULL, (PetscObject) efe);CHKERRQ(ierr); 9813 ierr = PetscFEDestroy(&efe);CHKERRQ(ierr); 9814 } 9815 ierr = DMCreateDS(edm);CHKERRQ(ierr); 9816 9817 ierr = DMCreateGlobalVector(edm, errorVec);CHKERRQ(ierr); 9818 ierr = PetscObjectSetName((PetscObject) *errorVec, "Error");CHKERRQ(ierr); 9819 ierr = DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec);CHKERRQ(ierr); 9820 ierr = DMDestroy(&edm);CHKERRQ(ierr); 9821 } 9822 ierr = PetscFree2(exactSol, ctxs);CHKERRQ(ierr); 9823 PetscFunctionReturn(0); 9824 } 9825 9826 /*@ 9827 DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this DM 9828 9829 Not collective 9830 9831 Input Parameter: 9832 . dm - The DM 9833 9834 Output Parameter: 9835 . numAux - The number of auxiliary data vectors 9836 9837 Level: advanced 9838 9839 .seealso: DMGetAuxiliaryLabels(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9840 @*/ 9841 PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux) 9842 { 9843 PetscErrorCode ierr; 9844 9845 PetscFunctionBegin; 9846 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9847 ierr = PetscHMapAuxGetSize(dm->auxData, numAux);CHKERRQ(ierr); 9848 PetscFunctionReturn(0); 9849 } 9850 9851 /*@ 9852 DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value 9853 9854 Not collective 9855 9856 Input Parameters: 9857 + dm - The DM 9858 . label - The DMLabel 9859 - value - The label value indicating the region 9860 9861 Output Parameter: 9862 . aux - The Vec holding auxiliary field data 9863 9864 Note: If no auxiliary vector is found for this (label, value), (NULL, 0) is checked as well. 9865 9866 Level: advanced 9867 9868 .seealso: DMSetAuxiliaryVec(), DMGetNumAuxiliaryVec() 9869 @*/ 9870 PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec *aux) 9871 { 9872 PetscHashAuxKey key, wild = {NULL, 0}; 9873 PetscBool has; 9874 PetscErrorCode ierr; 9875 9876 PetscFunctionBegin; 9877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9878 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9879 key.label = label; 9880 key.value = value; 9881 ierr = PetscHMapAuxHas(dm->auxData, key, &has);CHKERRQ(ierr); 9882 if (has) {ierr = PetscHMapAuxGet(dm->auxData, key, aux);CHKERRQ(ierr);} 9883 else {ierr = PetscHMapAuxGet(dm->auxData, wild, aux);CHKERRQ(ierr);} 9884 PetscFunctionReturn(0); 9885 } 9886 9887 /*@ 9888 DMSetAuxiliaryVec - Set the auxiliary vector for region specified by the given label and value 9889 9890 Not collective 9891 9892 Input Parameters: 9893 + dm - The DM 9894 . label - The DMLabel 9895 . value - The label value indicating the region 9896 - aux - The Vec holding auxiliary field data 9897 9898 Level: advanced 9899 9900 .seealso: DMGetAuxiliaryVec() 9901 @*/ 9902 PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec aux) 9903 { 9904 Vec old; 9905 PetscHashAuxKey key; 9906 PetscErrorCode ierr; 9907 9908 PetscFunctionBegin; 9909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9910 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9911 key.label = label; 9912 key.value = value; 9913 ierr = PetscHMapAuxGet(dm->auxData, key, &old);CHKERRQ(ierr); 9914 ierr = PetscObjectReference((PetscObject) aux);CHKERRQ(ierr); 9915 ierr = PetscObjectDereference((PetscObject) old);CHKERRQ(ierr); 9916 if (!aux) {ierr = PetscHMapAuxDel(dm->auxData, key);CHKERRQ(ierr);} 9917 else {ierr = PetscHMapAuxSet(dm->auxData, key, aux);CHKERRQ(ierr);} 9918 PetscFunctionReturn(0); 9919 } 9920 9921 /*@C 9922 DMGetAuxiliaryLabels - Get the labels and values for all auxiliary vectors in this DM 9923 9924 Not collective 9925 9926 Input Parameter: 9927 . dm - The DM 9928 9929 Output Parameters: 9930 + labels - The DMLabels for each Vec 9931 - values - The label values for each Vec 9932 9933 Note: The arrays passed in must be at least as large as DMGetNumAuxiliaryVec(). 9934 9935 Level: advanced 9936 9937 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9938 @*/ 9939 PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[]) 9940 { 9941 PetscHashAuxKey *keys; 9942 PetscInt n, i, off = 0; 9943 PetscErrorCode ierr; 9944 9945 PetscFunctionBegin; 9946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9947 PetscValidPointer(labels, 2); 9948 PetscValidPointer(values, 3); 9949 ierr = DMGetNumAuxiliaryVec(dm, &n);CHKERRQ(ierr); 9950 ierr = PetscMalloc1(n, &keys);CHKERRQ(ierr); 9951 ierr = PetscHMapAuxGetKeys(dm->auxData, &off, keys);CHKERRQ(ierr); 9952 for (i = 0; i < n; ++i) {labels[i] = keys[i].label; values[i] = keys[i].value;} 9953 ierr = PetscFree(keys);CHKERRQ(ierr); 9954 PetscFunctionReturn(0); 9955 } 9956 9957 /*@ 9958 DMCopyAuxiliaryVec - Copy the auxiliary data to a new DM 9959 9960 Not collective 9961 9962 Input Parameter: 9963 . dm - The DM 9964 9965 Output Parameter: 9966 . dmNew - The new DM, now with the same auxiliary data 9967 9968 Level: advanced 9969 9970 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9971 @*/ 9972 PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew) 9973 { 9974 PetscErrorCode ierr; 9975 9976 PetscFunctionBegin; 9977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9978 ierr = PetscHMapAuxDestroy(&dmNew->auxData);CHKERRQ(ierr); 9979 ierr = PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData);CHKERRQ(ierr); 9980 PetscFunctionReturn(0); 9981 } 9982 9983 /*@C 9984 DMPolytopeMatchOrientation - Determine an orientation that takes the source face arrangement to the target face arrangement 9985 9986 Not collective 9987 9988 Input Parameters: 9989 + ct - The DMPolytopeType 9990 . sourceCone - The source arrangement of faces 9991 - targetCone - The target arrangement of faces 9992 9993 Output Parameters: 9994 + ornt - The orientation which will take the source arrangement to the target arrangement 9995 - found - Flag indicating that a suitable orientation was found 9996 9997 Level: advanced 9998 9999 .seealso: DMPolytopeGetOrientation(), DMPolytopeMatchVertexOrientation() 10000 @*/ 10001 PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found) 10002 { 10003 const PetscInt cS = DMPolytopeTypeGetConeSize(ct); 10004 const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct)/2; 10005 PetscInt o, c; 10006 10007 PetscFunctionBegin; 10008 if (!nO) {*ornt = 0; *found = PETSC_TRUE; PetscFunctionReturn(0);} 10009 for (o = -nO; o < nO; ++o) { 10010 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 10011 10012 for (c = 0; c < cS; ++c) if (sourceCone[arr[c*2]] != targetCone[c]) break; 10013 if (c == cS) {*ornt = o; break;} 10014 } 10015 *found = o == nO ? PETSC_FALSE : PETSC_TRUE; 10016 PetscFunctionReturn(0); 10017 } 10018 10019 /*@C 10020 DMPolytopeGetOrientation - Determine an orientation that takes the source face arrangement to the target face arrangement 10021 10022 Not collective 10023 10024 Input Parameters: 10025 + ct - The DMPolytopeType 10026 . sourceCone - The source arrangement of faces 10027 - targetCone - The target arrangement of faces 10028 10029 Output Parameters: 10030 . ornt - The orientation which will take the source arrangement to the target arrangement 10031 10032 Note: This function will fail if no suitable orientation can be found. 10033 10034 Level: advanced 10035 10036 .seealso: DMPolytopeMatchOrientation(), DMPolytopeGetVertexOrientation() 10037 @*/ 10038 PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt) 10039 { 10040 PetscBool found; 10041 PetscErrorCode ierr; 10042 10043 PetscFunctionBegin; 10044 ierr = DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found);CHKERRQ(ierr); 10045 if (!found) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]); 10046 PetscFunctionReturn(0); 10047 } 10048 10049 /*@C 10050 DMPolytopeMatchVertexOrientation - Determine an orientation that takes the source vertex arrangement to the target vertex arrangement 10051 10052 Not collective 10053 10054 Input Parameters: 10055 + ct - The DMPolytopeType 10056 . sourceVert - The source arrangement of vertices 10057 - targetVert - The target arrangement of vertices 10058 10059 Output Parameters: 10060 + ornt - The orientation which will take the source arrangement to the target arrangement 10061 - found - Flag indicating that a suitable orientation was found 10062 10063 Level: advanced 10064 10065 .seealso: DMPolytopeGetOrientation(), DMPolytopeMatchOrientation() 10066 @*/ 10067 PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found) 10068 { 10069 const PetscInt cS = DMPolytopeTypeGetNumVertices(ct); 10070 const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct)/2; 10071 PetscInt o, c; 10072 10073 PetscFunctionBegin; 10074 if (!nO) {*ornt = 0; *found = PETSC_TRUE; PetscFunctionReturn(0);} 10075 for (o = -nO; o < nO; ++o) { 10076 const PetscInt *arr = DMPolytopeTypeGetVertexArrangment(ct, o); 10077 10078 for (c = 0; c < cS; ++c) if (sourceVert[arr[c]] != targetVert[c]) break; 10079 if (c == cS) {*ornt = o; break;} 10080 } 10081 *found = o == nO ? PETSC_FALSE : PETSC_TRUE; 10082 PetscFunctionReturn(0); 10083 } 10084 10085 /*@C 10086 DMPolytopeGetVertexOrientation - Determine an orientation that takes the source vertex arrangement to the target vertex arrangement 10087 10088 Not collective 10089 10090 Input Parameters: 10091 + ct - The DMPolytopeType 10092 . sourceCone - The source arrangement of vertices 10093 - targetCone - The target arrangement of vertices 10094 10095 Output Parameters: 10096 . ornt - The orientation which will take the source arrangement to the target arrangement 10097 10098 Note: This function will fail if no suitable orientation can be found. 10099 10100 Level: advanced 10101 10102 .seealso: DMPolytopeMatchVertexOrientation(), DMPolytopeGetOrientation() 10103 @*/ 10104 PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt) 10105 { 10106 PetscBool found; 10107 PetscErrorCode ierr; 10108 10109 PetscFunctionBegin; 10110 ierr = DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found);CHKERRQ(ierr); 10111 if (!found) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]); 10112 PetscFunctionReturn(0); 10113 } 10114 10115 /*@C 10116 DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type 10117 10118 Not collective 10119 10120 Input Parameters: 10121 + ct - The DMPolytopeType 10122 - point - Coordinates of the point 10123 10124 Output Parameters: 10125 . inside - Flag indicating whether the point is inside the reference cell of given type 10126 10127 Level: advanced 10128 10129 .seealso: DMLocatePoints() 10130 @*/ 10131 PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside) 10132 { 10133 PetscReal sum = 0.0; 10134 PetscInt d; 10135 10136 PetscFunctionBegin; 10137 *inside = PETSC_TRUE; 10138 switch (ct) { 10139 case DM_POLYTOPE_TRIANGLE: 10140 case DM_POLYTOPE_TETRAHEDRON: 10141 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) { 10142 if (point[d] < -1.0) {*inside = PETSC_FALSE; break;} 10143 sum += point[d]; 10144 } 10145 if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;} 10146 break; 10147 case DM_POLYTOPE_QUADRILATERAL: 10148 case DM_POLYTOPE_HEXAHEDRON: 10149 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) 10150 if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;} 10151 break; 10152 default: 10153 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]); 10154 } 10155 PetscFunctionReturn(0); 10156 } 10157