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