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