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