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