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