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