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