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