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