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; 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: DMDestry(), 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 if (isbinary) { 3759 PetscInt classid; 3760 char type[256]; 3761 3762 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3763 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3764 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3765 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3766 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3767 } else if (ishdf5) { 3768 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3769 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3770 PetscFunctionReturn(0); 3771 } 3772 3773 /*@ 3774 DMGetLocalBoundingBox - Returns the bounding box for the piece of the DM on this process. 3775 3776 Not collective 3777 3778 Input Parameter: 3779 . dm - the DM 3780 3781 Output Parameters: 3782 + lmin - local minimum coordinates (length coord dim, optional) 3783 - lmax - local maximim coordinates (length coord dim, optional) 3784 3785 Level: beginner 3786 3787 Note: If the DM is a DMDA and has no coordinates, the index bounds are returned instead. 3788 3789 3790 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetBoundingBox() 3791 @*/ 3792 PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[]) 3793 { 3794 Vec coords = NULL; 3795 PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 3796 PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 3797 const PetscScalar *local_coords; 3798 PetscInt N, Ni; 3799 PetscInt cdim, i, j; 3800 PetscErrorCode ierr; 3801 3802 PetscFunctionBegin; 3803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3804 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3805 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 3806 if (coords) { 3807 ierr = VecGetArrayRead(coords, &local_coords);CHKERRQ(ierr); 3808 ierr = VecGetLocalSize(coords, &N);CHKERRQ(ierr); 3809 Ni = N/cdim; 3810 for (i = 0; i < Ni; ++i) { 3811 for (j = 0; j < 3; ++j) { 3812 min[j] = j < cdim ? PetscMin(min[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 3813 max[j] = j < cdim ? PetscMax(max[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 3814 } 3815 } 3816 ierr = VecRestoreArrayRead(coords, &local_coords);CHKERRQ(ierr); 3817 } else { 3818 PetscBool isda; 3819 3820 ierr = PetscObjectTypeCompare((PetscObject) dm, DMDA, &isda);CHKERRQ(ierr); 3821 if (isda) {ierr = DMGetLocalBoundingIndices_DMDA(dm, min, max);CHKERRQ(ierr);} 3822 } 3823 if (lmin) {ierr = PetscArraycpy(lmin, min, cdim);CHKERRQ(ierr);} 3824 if (lmax) {ierr = PetscArraycpy(lmax, max, cdim);CHKERRQ(ierr);} 3825 PetscFunctionReturn(0); 3826 } 3827 3828 /*@ 3829 DMGetBoundingBox - Returns the global bounding box for the DM. 3830 3831 Collective 3832 3833 Input Parameter: 3834 . dm - the DM 3835 3836 Output Parameters: 3837 + gmin - global minimum coordinates (length coord dim, optional) 3838 - gmax - global maximim coordinates (length coord dim, optional) 3839 3840 Level: beginner 3841 3842 .seealso: DMGetLocalBoundingBox(), DMGetCoordinates(), DMGetCoordinatesLocal() 3843 @*/ 3844 PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[]) 3845 { 3846 PetscReal lmin[3], lmax[3]; 3847 PetscInt cdim; 3848 PetscMPIInt count; 3849 PetscErrorCode ierr; 3850 3851 PetscFunctionBegin; 3852 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3853 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3854 ierr = PetscMPIIntCast(cdim, &count);CHKERRQ(ierr); 3855 ierr = DMGetLocalBoundingBox(dm, lmin, lmax);CHKERRQ(ierr); 3856 if (gmin) {ierr = MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);} 3857 if (gmax) {ierr = MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);} 3858 PetscFunctionReturn(0); 3859 } 3860 3861 /******************************** FEM Support **********************************/ 3862 3863 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3864 { 3865 PetscInt f; 3866 PetscErrorCode ierr; 3867 3868 PetscFunctionBegin; 3869 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3870 for (f = 0; f < len; ++f) { 3871 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3872 } 3873 PetscFunctionReturn(0); 3874 } 3875 3876 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3877 { 3878 PetscInt f, g; 3879 PetscErrorCode ierr; 3880 3881 PetscFunctionBegin; 3882 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3883 for (f = 0; f < rows; ++f) { 3884 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3885 for (g = 0; g < cols; ++g) { 3886 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3887 } 3888 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3889 } 3890 PetscFunctionReturn(0); 3891 } 3892 3893 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3894 { 3895 PetscInt localSize, bs; 3896 PetscMPIInt size; 3897 Vec x, xglob; 3898 const PetscScalar *xarray; 3899 PetscErrorCode ierr; 3900 3901 PetscFunctionBegin; 3902 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr); 3903 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3904 ierr = VecCopy(X, x);CHKERRQ(ierr); 3905 ierr = VecChop(x, tol);CHKERRQ(ierr); 3906 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 3907 if (size > 1) { 3908 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 3909 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 3910 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 3911 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 3912 } else { 3913 xglob = x; 3914 } 3915 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 3916 if (size > 1) { 3917 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 3918 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 3919 } 3920 ierr = VecDestroy(&x);CHKERRQ(ierr); 3921 PetscFunctionReturn(0); 3922 } 3923 3924 /*@ 3925 DMGetSection - Get the PetscSection encoding the local data layout for the DM. This is equivalent to DMGetLocalSection(). Deprecated in v3.12 3926 3927 Input Parameter: 3928 . dm - The DM 3929 3930 Output Parameter: 3931 . section - The PetscSection 3932 3933 Options Database Keys: 3934 . -dm_petscsection_view - View the Section created by the DM 3935 3936 Level: advanced 3937 3938 Notes: 3939 Use DMGetLocalSection() in new code. 3940 3941 This gets a borrowed reference, so the user should not destroy this PetscSection. 3942 3943 .seealso: DMGetLocalSection(), DMSetLocalSection(), DMGetGlobalSection() 3944 @*/ 3945 PetscErrorCode DMGetSection(DM dm, PetscSection *section) 3946 { 3947 PetscErrorCode ierr; 3948 3949 PetscFunctionBegin; 3950 ierr = DMGetLocalSection(dm,section);CHKERRQ(ierr); 3951 PetscFunctionReturn(0); 3952 } 3953 3954 /*@ 3955 DMGetLocalSection - Get the PetscSection encoding the local data layout for the DM. 3956 3957 Input Parameter: 3958 . dm - The DM 3959 3960 Output Parameter: 3961 . section - The PetscSection 3962 3963 Options Database Keys: 3964 . -dm_petscsection_view - View the Section created by the DM 3965 3966 Level: intermediate 3967 3968 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3969 3970 .seealso: DMSetLocalSection(), DMGetGlobalSection() 3971 @*/ 3972 PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section) 3973 { 3974 PetscErrorCode ierr; 3975 3976 PetscFunctionBegin; 3977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3978 PetscValidPointer(section, 2); 3979 if (!dm->localSection && dm->ops->createlocalsection) { 3980 PetscInt d; 3981 3982 if (dm->setfromoptionscalled) for (d = 0; d < dm->Nds; ++d) {ierr = PetscDSSetFromOptions(dm->probs[d].ds);CHKERRQ(ierr);} 3983 ierr = (*dm->ops->createlocalsection)(dm);CHKERRQ(ierr); 3984 if (dm->localSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->localSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3985 } 3986 *section = dm->localSection; 3987 PetscFunctionReturn(0); 3988 } 3989 3990 /*@ 3991 DMSetSection - Set the PetscSection encoding the local data layout for the DM. This is equivalent to DMSetLocalSection(). Deprecated in v3.12 3992 3993 Input Parameters: 3994 + dm - The DM 3995 - section - The PetscSection 3996 3997 Level: advanced 3998 3999 Notes: 4000 Use DMSetLocalSection() in new code. 4001 4002 Any existing Section will be destroyed 4003 4004 .seealso: DMSetLocalSection(), DMGetLocalSection(), DMSetGlobalSection() 4005 @*/ 4006 PetscErrorCode DMSetSection(DM dm, PetscSection section) 4007 { 4008 PetscErrorCode ierr; 4009 4010 PetscFunctionBegin; 4011 ierr = DMSetLocalSection(dm,section);CHKERRQ(ierr); 4012 PetscFunctionReturn(0); 4013 } 4014 4015 /*@ 4016 DMSetLocalSection - Set the PetscSection encoding the local data layout for the DM. 4017 4018 Input Parameters: 4019 + dm - The DM 4020 - section - The PetscSection 4021 4022 Level: intermediate 4023 4024 Note: Any existing Section will be destroyed 4025 4026 .seealso: DMGetLocalSection(), DMSetGlobalSection() 4027 @*/ 4028 PetscErrorCode DMSetLocalSection(DM dm, PetscSection section) 4029 { 4030 PetscInt numFields = 0; 4031 PetscInt f; 4032 PetscErrorCode ierr; 4033 4034 PetscFunctionBegin; 4035 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4036 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4037 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4038 ierr = PetscSectionDestroy(&dm->localSection);CHKERRQ(ierr); 4039 dm->localSection = section; 4040 if (section) {ierr = PetscSectionGetNumFields(dm->localSection, &numFields);CHKERRQ(ierr);} 4041 if (numFields) { 4042 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 4043 for (f = 0; f < numFields; ++f) { 4044 PetscObject disc; 4045 const char *name; 4046 4047 ierr = PetscSectionGetFieldName(dm->localSection, f, &name);CHKERRQ(ierr); 4048 ierr = DMGetField(dm, f, NULL, &disc);CHKERRQ(ierr); 4049 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 4050 } 4051 } 4052 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */ 4053 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4054 PetscFunctionReturn(0); 4055 } 4056 4057 /*@ 4058 DMGetDefaultConstraints - Get the PetscSection and Mat that specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 4059 4060 not collective 4061 4062 Input Parameter: 4063 . dm - The DM 4064 4065 Output Parameter: 4066 + 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. 4067 - 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. 4068 4069 Level: advanced 4070 4071 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 4072 4073 .seealso: DMSetDefaultConstraints() 4074 @*/ 4075 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 4076 { 4077 PetscErrorCode ierr; 4078 4079 PetscFunctionBegin; 4080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4081 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 4082 if (section) {*section = dm->defaultConstraintSection;} 4083 if (mat) {*mat = dm->defaultConstraintMat;} 4084 PetscFunctionReturn(0); 4085 } 4086 4087 /*@ 4088 DMSetDefaultConstraints - Set the PetscSection and Mat that specify the local constraint interpolation. 4089 4090 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(). 4091 4092 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. 4093 4094 collective on dm 4095 4096 Input Parameters: 4097 + dm - The DM 4098 + 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). 4099 - 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). 4100 4101 Level: advanced 4102 4103 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 4104 4105 .seealso: DMGetDefaultConstraints() 4106 @*/ 4107 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 4108 { 4109 PetscMPIInt result; 4110 PetscErrorCode ierr; 4111 4112 PetscFunctionBegin; 4113 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4114 if (section) { 4115 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4116 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 4117 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 4118 } 4119 if (mat) { 4120 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 4121 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 4122 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 4123 } 4124 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4125 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 4126 dm->defaultConstraintSection = section; 4127 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 4128 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 4129 dm->defaultConstraintMat = mat; 4130 PetscFunctionReturn(0); 4131 } 4132 4133 #if defined(PETSC_USE_DEBUG) 4134 /* 4135 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 4136 4137 Input Parameters: 4138 + dm - The DM 4139 . localSection - PetscSection describing the local data layout 4140 - globalSection - PetscSection describing the global data layout 4141 4142 Level: intermediate 4143 4144 .seealso: DMGetSectionSF(), DMSetSectionSF() 4145 */ 4146 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 4147 { 4148 MPI_Comm comm; 4149 PetscLayout layout; 4150 const PetscInt *ranges; 4151 PetscInt pStart, pEnd, p, nroots; 4152 PetscMPIInt size, rank; 4153 PetscBool valid = PETSC_TRUE, gvalid; 4154 PetscErrorCode ierr; 4155 4156 PetscFunctionBegin; 4157 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4158 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4159 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 4160 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4161 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4162 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4163 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4164 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4165 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4166 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4167 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4168 for (p = pStart; p < pEnd; ++p) { 4169 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 4170 4171 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4172 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4173 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4174 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4175 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4176 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4177 if (!gdof) continue; /* Censored point */ 4178 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;} 4179 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;} 4180 if (gdof < 0) { 4181 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4182 for (d = 0; d < gsize; ++d) { 4183 PetscInt offset = -(goff+1) + d, r; 4184 4185 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4186 if (r < 0) r = -(r+2); 4187 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;} 4188 } 4189 } 4190 } 4191 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4192 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 4193 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 4194 if (!gvalid) { 4195 ierr = DMView(dm, NULL);CHKERRQ(ierr); 4196 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 4197 } 4198 PetscFunctionReturn(0); 4199 } 4200 #endif 4201 4202 /*@ 4203 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM. 4204 4205 Collective on dm 4206 4207 Input Parameter: 4208 . dm - The DM 4209 4210 Output Parameter: 4211 . section - The PetscSection 4212 4213 Level: intermediate 4214 4215 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4216 4217 .seealso: DMSetLocalSection(), DMGetLocalSection() 4218 @*/ 4219 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section) 4220 { 4221 PetscErrorCode ierr; 4222 4223 PetscFunctionBegin; 4224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4225 PetscValidPointer(section, 2); 4226 if (!dm->globalSection) { 4227 PetscSection s; 4228 4229 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 4230 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 4231 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection"); 4232 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection);CHKERRQ(ierr); 4233 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 4234 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map);CHKERRQ(ierr); 4235 ierr = PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view");CHKERRQ(ierr); 4236 } 4237 *section = dm->globalSection; 4238 PetscFunctionReturn(0); 4239 } 4240 4241 /*@ 4242 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM. 4243 4244 Input Parameters: 4245 + dm - The DM 4246 - section - The PetscSection, or NULL 4247 4248 Level: intermediate 4249 4250 Note: Any existing Section will be destroyed 4251 4252 .seealso: DMGetGlobalSection(), DMSetLocalSection() 4253 @*/ 4254 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section) 4255 { 4256 PetscErrorCode ierr; 4257 4258 PetscFunctionBegin; 4259 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4260 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4261 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4262 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4263 dm->globalSection = section; 4264 #if defined(PETSC_USE_DEBUG) 4265 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section);CHKERRQ(ierr);} 4266 #endif 4267 PetscFunctionReturn(0); 4268 } 4269 4270 /*@ 4271 DMGetSectionSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 4272 it is created from the default PetscSection layouts in the DM. 4273 4274 Input Parameter: 4275 . dm - The DM 4276 4277 Output Parameter: 4278 . sf - The PetscSF 4279 4280 Level: intermediate 4281 4282 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4283 4284 .seealso: DMSetSectionSF(), DMCreateSectionSF() 4285 @*/ 4286 PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf) 4287 { 4288 PetscInt nroots; 4289 PetscErrorCode ierr; 4290 4291 PetscFunctionBegin; 4292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4293 PetscValidPointer(sf, 2); 4294 if (!dm->sectionSF) { 4295 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->sectionSF);CHKERRQ(ierr); 4296 } 4297 ierr = PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 4298 if (nroots < 0) { 4299 PetscSection section, gSection; 4300 4301 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 4302 if (section) { 4303 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr); 4304 ierr = DMCreateSectionSF(dm, section, gSection);CHKERRQ(ierr); 4305 } else { 4306 *sf = NULL; 4307 PetscFunctionReturn(0); 4308 } 4309 } 4310 *sf = dm->sectionSF; 4311 PetscFunctionReturn(0); 4312 } 4313 4314 /*@ 4315 DMSetSectionSF - Set the PetscSF encoding the parallel dof overlap for the DM 4316 4317 Input Parameters: 4318 + dm - The DM 4319 - sf - The PetscSF 4320 4321 Level: intermediate 4322 4323 Note: Any previous SF is destroyed 4324 4325 .seealso: DMGetSectionSF(), DMCreateSectionSF() 4326 @*/ 4327 PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf) 4328 { 4329 PetscErrorCode ierr; 4330 4331 PetscFunctionBegin; 4332 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4333 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4334 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4335 ierr = PetscSFDestroy(&dm->sectionSF);CHKERRQ(ierr); 4336 dm->sectionSF = sf; 4337 PetscFunctionReturn(0); 4338 } 4339 4340 /*@C 4341 DMCreateSectionSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 4342 describing the data layout. 4343 4344 Input Parameters: 4345 + dm - The DM 4346 . localSection - PetscSection describing the local data layout 4347 - globalSection - PetscSection describing the global data layout 4348 4349 Notes: One usually uses DMGetSectionSF() to obtain the PetscSF 4350 4351 Level: developer 4352 4353 Developer Note: Since this routine has for arguments the two sections from the DM and puts the resulting PetscSF 4354 directly into the DM, perhaps this function should not take the local and global sections as 4355 input and should just obtain them from the DM? 4356 4357 .seealso: DMGetSectionSF(), DMSetSectionSF(), DMGetLocalSection(), DMGetGlobalSection() 4358 @*/ 4359 PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection) 4360 { 4361 MPI_Comm comm; 4362 PetscLayout layout; 4363 const PetscInt *ranges; 4364 PetscInt *local; 4365 PetscSFNode *remote; 4366 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 4367 PetscMPIInt size, rank; 4368 PetscErrorCode ierr; 4369 4370 PetscFunctionBegin; 4371 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4372 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4373 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 4374 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4375 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4376 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4377 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4378 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4379 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4380 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4381 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4382 for (p = pStart; p < pEnd; ++p) { 4383 PetscInt gdof, gcdof; 4384 4385 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4386 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4387 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)); 4388 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4389 } 4390 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 4391 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 4392 for (p = pStart, l = 0; p < pEnd; ++p) { 4393 const PetscInt *cind; 4394 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 4395 4396 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4397 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4398 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4399 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 4400 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4401 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4402 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4403 if (!gdof) continue; /* Censored point */ 4404 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4405 if (gsize != dof-cdof) { 4406 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); 4407 cdof = 0; /* Ignore constraints */ 4408 } 4409 for (d = 0, c = 0; d < dof; ++d) { 4410 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 4411 local[l+d-c] = off+d; 4412 } 4413 if (gdof < 0) { 4414 for (d = 0; d < gsize; ++d, ++l) { 4415 PetscInt offset = -(goff+1) + d, r; 4416 4417 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4418 if (r < 0) r = -(r+2); 4419 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); 4420 remote[l].rank = r; 4421 remote[l].index = offset - ranges[r]; 4422 } 4423 } else { 4424 for (d = 0; d < gsize; ++d, ++l) { 4425 remote[l].rank = rank; 4426 remote[l].index = goff+d - ranges[rank]; 4427 } 4428 } 4429 } 4430 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 4431 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4432 ierr = PetscSFSetGraph(dm->sectionSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 4433 PetscFunctionReturn(0); 4434 } 4435 4436 /*@ 4437 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 4438 4439 Input Parameter: 4440 . dm - The DM 4441 4442 Output Parameter: 4443 . sf - The PetscSF 4444 4445 Level: intermediate 4446 4447 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4448 4449 .seealso: DMSetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4450 @*/ 4451 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 4452 { 4453 PetscFunctionBegin; 4454 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4455 PetscValidPointer(sf, 2); 4456 *sf = dm->sf; 4457 PetscFunctionReturn(0); 4458 } 4459 4460 /*@ 4461 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 4462 4463 Input Parameters: 4464 + dm - The DM 4465 - sf - The PetscSF 4466 4467 Level: intermediate 4468 4469 .seealso: DMGetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4470 @*/ 4471 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 4472 { 4473 PetscErrorCode ierr; 4474 4475 PetscFunctionBegin; 4476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4477 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4478 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4479 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4480 dm->sf = sf; 4481 PetscFunctionReturn(0); 4482 } 4483 4484 static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc) 4485 { 4486 PetscClassId id; 4487 PetscErrorCode ierr; 4488 4489 PetscFunctionBegin; 4490 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 4491 if (id == PETSCFE_CLASSID) { 4492 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4493 } else if (id == PETSCFV_CLASSID) { 4494 ierr = DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 4495 } else { 4496 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4497 } 4498 PetscFunctionReturn(0); 4499 } 4500 4501 static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew) 4502 { 4503 RegionField *tmpr; 4504 PetscInt Nf = dm->Nf, f; 4505 PetscErrorCode ierr; 4506 4507 PetscFunctionBegin; 4508 if (Nf >= NfNew) PetscFunctionReturn(0); 4509 ierr = PetscMalloc1(NfNew, &tmpr);CHKERRQ(ierr); 4510 for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f]; 4511 for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL;} 4512 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4513 dm->Nf = NfNew; 4514 dm->fields = tmpr; 4515 PetscFunctionReturn(0); 4516 } 4517 4518 /*@ 4519 DMClearFields - Remove all fields from the DM 4520 4521 Logically collective on dm 4522 4523 Input Parameter: 4524 . dm - The DM 4525 4526 Level: intermediate 4527 4528 .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField() 4529 @*/ 4530 PetscErrorCode DMClearFields(DM dm) 4531 { 4532 PetscInt f; 4533 PetscErrorCode ierr; 4534 4535 PetscFunctionBegin; 4536 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4537 for (f = 0; f < dm->Nf; ++f) { 4538 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4539 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4540 } 4541 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4542 dm->fields = NULL; 4543 dm->Nf = 0; 4544 PetscFunctionReturn(0); 4545 } 4546 4547 /*@ 4548 DMGetNumFields - Get the number of fields in the DM 4549 4550 Not collective 4551 4552 Input Parameter: 4553 . dm - The DM 4554 4555 Output Parameter: 4556 . Nf - The number of fields 4557 4558 Level: intermediate 4559 4560 .seealso: DMSetNumFields(), DMSetField() 4561 @*/ 4562 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4563 { 4564 PetscFunctionBegin; 4565 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4566 PetscValidIntPointer(numFields, 2); 4567 *numFields = dm->Nf; 4568 PetscFunctionReturn(0); 4569 } 4570 4571 /*@ 4572 DMSetNumFields - Set the number of fields in the DM 4573 4574 Logically collective on dm 4575 4576 Input Parameters: 4577 + dm - The DM 4578 - Nf - The number of fields 4579 4580 Level: intermediate 4581 4582 .seealso: DMGetNumFields(), DMSetField() 4583 @*/ 4584 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4585 { 4586 PetscInt Nf, f; 4587 PetscErrorCode ierr; 4588 4589 PetscFunctionBegin; 4590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4591 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4592 for (f = Nf; f < numFields; ++f) { 4593 PetscContainer obj; 4594 4595 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4596 ierr = DMAddField(dm, NULL, (PetscObject) obj);CHKERRQ(ierr); 4597 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4598 } 4599 PetscFunctionReturn(0); 4600 } 4601 4602 /*@ 4603 DMGetField - Return the discretization object for a given DM field 4604 4605 Not collective 4606 4607 Input Parameters: 4608 + dm - The DM 4609 - f - The field number 4610 4611 Output Parameters: 4612 + label - The label indicating the support of the field, or NULL for the entire mesh 4613 - field - The discretization object 4614 4615 Level: intermediate 4616 4617 .seealso: DMAddField(), DMSetField() 4618 @*/ 4619 PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field) 4620 { 4621 PetscFunctionBegin; 4622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4623 PetscValidPointer(field, 3); 4624 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); 4625 if (label) *label = dm->fields[f].label; 4626 if (field) *field = dm->fields[f].disc; 4627 PetscFunctionReturn(0); 4628 } 4629 4630 /*@ 4631 DMSetField - Set the discretization object for a given DM field 4632 4633 Logically collective on dm 4634 4635 Input Parameters: 4636 + dm - The DM 4637 . f - The field number 4638 . label - The label indicating the support of the field, or NULL for the entire mesh 4639 - field - The discretization object 4640 4641 Level: intermediate 4642 4643 .seealso: DMAddField(), DMGetField() 4644 @*/ 4645 PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field) 4646 { 4647 PetscErrorCode ierr; 4648 4649 PetscFunctionBegin; 4650 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4651 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4652 PetscValidHeader(field, 4); 4653 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 4654 ierr = DMFieldEnlarge_Static(dm, f+1);CHKERRQ(ierr); 4655 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4656 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4657 dm->fields[f].label = label; 4658 dm->fields[f].disc = field; 4659 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4660 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4661 ierr = DMSetDefaultAdjacency_Private(dm, f, field);CHKERRQ(ierr); 4662 ierr = DMClearDS(dm);CHKERRQ(ierr); 4663 PetscFunctionReturn(0); 4664 } 4665 4666 /*@ 4667 DMAddField - Add the discretization object for the given DM field 4668 4669 Logically collective on dm 4670 4671 Input Parameters: 4672 + dm - The DM 4673 . label - The label indicating the support of the field, or NULL for the entire mesh 4674 - field - The discretization object 4675 4676 Level: intermediate 4677 4678 .seealso: DMSetField(), DMGetField() 4679 @*/ 4680 PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field) 4681 { 4682 PetscInt Nf = dm->Nf; 4683 PetscErrorCode ierr; 4684 4685 PetscFunctionBegin; 4686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4687 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4688 PetscValidHeader(field, 3); 4689 ierr = DMFieldEnlarge_Static(dm, Nf+1);CHKERRQ(ierr); 4690 dm->fields[Nf].label = label; 4691 dm->fields[Nf].disc = field; 4692 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4693 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4694 ierr = DMSetDefaultAdjacency_Private(dm, Nf, field);CHKERRQ(ierr); 4695 ierr = DMClearDS(dm);CHKERRQ(ierr); 4696 PetscFunctionReturn(0); 4697 } 4698 4699 /*@ 4700 DMCopyFields - Copy the discretizations for the DM into another DM 4701 4702 Collective on dm 4703 4704 Input Parameter: 4705 . dm - The DM 4706 4707 Output Parameter: 4708 . newdm - The DM 4709 4710 Level: advanced 4711 4712 .seealso: DMGetField(), DMSetField(), DMAddField(), DMCopyDS(), DMGetDS(), DMGetCellDS() 4713 @*/ 4714 PetscErrorCode DMCopyFields(DM dm, DM newdm) 4715 { 4716 PetscInt Nf, f; 4717 PetscErrorCode ierr; 4718 4719 PetscFunctionBegin; 4720 if (dm == newdm) PetscFunctionReturn(0); 4721 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4722 ierr = DMClearFields(newdm);CHKERRQ(ierr); 4723 for (f = 0; f < Nf; ++f) { 4724 DMLabel label; 4725 PetscObject field; 4726 PetscBool useCone, useClosure; 4727 4728 ierr = DMGetField(dm, f, &label, &field);CHKERRQ(ierr); 4729 ierr = DMSetField(newdm, f, label, field);CHKERRQ(ierr); 4730 ierr = DMGetAdjacency(dm, f, &useCone, &useClosure);CHKERRQ(ierr); 4731 ierr = DMSetAdjacency(newdm, f, useCone, useClosure);CHKERRQ(ierr); 4732 } 4733 PetscFunctionReturn(0); 4734 } 4735 4736 /*@ 4737 DMGetAdjacency - Returns the flags for determining variable influence 4738 4739 Not collective 4740 4741 Input Parameters: 4742 + dm - The DM object 4743 - f - The field number, or PETSC_DEFAULT for the default adjacency 4744 4745 Output Parameter: 4746 + useCone - Flag for variable influence starting with the cone operation 4747 - useClosure - Flag for variable influence using transitive closure 4748 4749 Notes: 4750 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4751 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4752 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4753 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 4754 4755 Level: developer 4756 4757 .seealso: DMSetAdjacency(), DMGetField(), DMSetField() 4758 @*/ 4759 PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure) 4760 { 4761 PetscFunctionBegin; 4762 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4763 if (useCone) PetscValidBoolPointer(useCone, 3); 4764 if (useClosure) PetscValidBoolPointer(useClosure, 4); 4765 if (f < 0) { 4766 if (useCone) *useCone = dm->adjacency[0]; 4767 if (useClosure) *useClosure = dm->adjacency[1]; 4768 } else { 4769 PetscInt Nf; 4770 PetscErrorCode ierr; 4771 4772 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4773 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 4774 if (useCone) *useCone = dm->fields[f].adjacency[0]; 4775 if (useClosure) *useClosure = dm->fields[f].adjacency[1]; 4776 } 4777 PetscFunctionReturn(0); 4778 } 4779 4780 /*@ 4781 DMSetAdjacency - Set the flags for determining variable influence 4782 4783 Not collective 4784 4785 Input Parameters: 4786 + dm - The DM object 4787 . f - The field number 4788 . useCone - Flag for variable influence starting with the cone operation 4789 - useClosure - Flag for variable influence using transitive closure 4790 4791 Notes: 4792 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4793 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4794 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4795 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 4796 4797 Level: developer 4798 4799 .seealso: DMGetAdjacency(), DMGetField(), DMSetField() 4800 @*/ 4801 PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure) 4802 { 4803 PetscFunctionBegin; 4804 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4805 if (f < 0) { 4806 dm->adjacency[0] = useCone; 4807 dm->adjacency[1] = useClosure; 4808 } else { 4809 PetscInt Nf; 4810 PetscErrorCode ierr; 4811 4812 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4813 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 4814 dm->fields[f].adjacency[0] = useCone; 4815 dm->fields[f].adjacency[1] = useClosure; 4816 } 4817 PetscFunctionReturn(0); 4818 } 4819 4820 /*@ 4821 DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined 4822 4823 Not collective 4824 4825 Input Parameters: 4826 . dm - The DM object 4827 4828 Output Parameter: 4829 + useCone - Flag for variable influence starting with the cone operation 4830 - useClosure - Flag for variable influence using transitive closure 4831 4832 Notes: 4833 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4834 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4835 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4836 4837 Level: developer 4838 4839 .seealso: DMSetBasicAdjacency(), DMGetField(), DMSetField() 4840 @*/ 4841 PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure) 4842 { 4843 PetscInt Nf; 4844 PetscErrorCode ierr; 4845 4846 PetscFunctionBegin; 4847 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4848 if (useCone) PetscValidBoolPointer(useCone, 3); 4849 if (useClosure) PetscValidBoolPointer(useClosure, 4); 4850 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4851 if (!Nf) { 4852 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 4853 } else { 4854 ierr = DMGetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 4855 } 4856 PetscFunctionReturn(0); 4857 } 4858 4859 /*@ 4860 DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined 4861 4862 Not collective 4863 4864 Input Parameters: 4865 + dm - The DM object 4866 . useCone - Flag for variable influence starting with the cone operation 4867 - useClosure - Flag for variable influence using transitive closure 4868 4869 Notes: 4870 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4871 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4872 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4873 4874 Level: developer 4875 4876 .seealso: DMGetBasicAdjacency(), DMGetField(), DMSetField() 4877 @*/ 4878 PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure) 4879 { 4880 PetscInt Nf; 4881 PetscErrorCode ierr; 4882 4883 PetscFunctionBegin; 4884 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4885 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4886 if (!Nf) { 4887 ierr = DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 4888 } else { 4889 ierr = DMSetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 4890 } 4891 PetscFunctionReturn(0); 4892 } 4893 4894 static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew) 4895 { 4896 DMSpace *tmpd; 4897 PetscInt Nds = dm->Nds, s; 4898 PetscErrorCode ierr; 4899 4900 PetscFunctionBegin; 4901 if (Nds >= NdsNew) PetscFunctionReturn(0); 4902 ierr = PetscMalloc1(NdsNew, &tmpd);CHKERRQ(ierr); 4903 for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s]; 4904 for (s = Nds; s < NdsNew; ++s) {tmpd[s].ds = NULL; tmpd[s].label = NULL; tmpd[s].fields = NULL;} 4905 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 4906 dm->Nds = NdsNew; 4907 dm->probs = tmpd; 4908 PetscFunctionReturn(0); 4909 } 4910 4911 /*@ 4912 DMGetNumDS - Get the number of discrete systems in the DM 4913 4914 Not collective 4915 4916 Input Parameter: 4917 . dm - The DM 4918 4919 Output Parameter: 4920 . Nds - The number of PetscDS objects 4921 4922 Level: intermediate 4923 4924 .seealso: DMGetDS(), DMGetCellDS() 4925 @*/ 4926 PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds) 4927 { 4928 PetscFunctionBegin; 4929 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4930 PetscValidIntPointer(Nds, 2); 4931 *Nds = dm->Nds; 4932 PetscFunctionReturn(0); 4933 } 4934 4935 /*@ 4936 DMClearDS - Remove all discrete systems from the DM 4937 4938 Logically collective on dm 4939 4940 Input Parameter: 4941 . dm - The DM 4942 4943 Level: intermediate 4944 4945 .seealso: DMGetNumDS(), DMGetDS(), DMSetField() 4946 @*/ 4947 PetscErrorCode DMClearDS(DM dm) 4948 { 4949 PetscInt s; 4950 PetscErrorCode ierr; 4951 4952 PetscFunctionBegin; 4953 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4954 for (s = 0; s < dm->Nds; ++s) { 4955 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 4956 ierr = DMLabelDestroy(&dm->probs[s].label);CHKERRQ(ierr); 4957 ierr = ISDestroy(&dm->probs[s].fields);CHKERRQ(ierr); 4958 } 4959 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 4960 dm->probs = NULL; 4961 dm->Nds = 0; 4962 PetscFunctionReturn(0); 4963 } 4964 4965 /*@ 4966 DMGetDS - Get the default PetscDS 4967 4968 Not collective 4969 4970 Input Parameter: 4971 . dm - The DM 4972 4973 Output Parameter: 4974 . prob - The default PetscDS 4975 4976 Level: intermediate 4977 4978 .seealso: DMGetCellDS(), DMGetRegionDS() 4979 @*/ 4980 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 4981 { 4982 PetscErrorCode ierr; 4983 4984 PetscFunctionBeginHot; 4985 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4986 PetscValidPointer(prob, 2); 4987 if (dm->Nds <= 0) { 4988 PetscDS ds; 4989 4990 ierr = PetscDSCreate(PetscObjectComm((PetscObject) dm), &ds);CHKERRQ(ierr); 4991 ierr = DMSetRegionDS(dm, NULL, NULL, ds);CHKERRQ(ierr); 4992 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 4993 } 4994 *prob = dm->probs[0].ds; 4995 PetscFunctionReturn(0); 4996 } 4997 4998 /*@ 4999 DMGetCellDS - Get the PetscDS defined on a given cell 5000 5001 Not collective 5002 5003 Input Parameters: 5004 + dm - The DM 5005 - point - Cell for the DS 5006 5007 Output Parameter: 5008 . prob - The PetscDS defined on the given cell 5009 5010 Level: developer 5011 5012 .seealso: DMGetDS(), DMSetRegionDS() 5013 @*/ 5014 PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob) 5015 { 5016 PetscDS probDef = NULL; 5017 PetscInt s; 5018 PetscErrorCode ierr; 5019 5020 PetscFunctionBeginHot; 5021 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5022 PetscValidPointer(prob, 3); 5023 *prob = NULL; 5024 for (s = 0; s < dm->Nds; ++s) { 5025 PetscInt val; 5026 5027 if (!dm->probs[s].label) {probDef = dm->probs[s].ds;} 5028 else { 5029 ierr = DMLabelGetValue(dm->probs[s].label, point, &val);CHKERRQ(ierr); 5030 if (val >= 0) {*prob = dm->probs[s].ds; break;} 5031 } 5032 } 5033 if (!*prob) *prob = probDef; 5034 PetscFunctionReturn(0); 5035 } 5036 5037 /*@ 5038 DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel 5039 5040 Not collective 5041 5042 Input Parameters: 5043 + dm - The DM 5044 - label - The DMLabel defining the mesh region, or NULL for the entire mesh 5045 5046 Output Parameters: 5047 + fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5048 - prob - The PetscDS defined on the given region, or NULL 5049 5050 Note: If the label is missing, this function returns an error 5051 5052 Level: advanced 5053 5054 .seealso: DMGetRegionNumDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5055 @*/ 5056 PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds) 5057 { 5058 PetscInt Nds = dm->Nds, s; 5059 5060 PetscFunctionBegin; 5061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5062 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5063 if (fields) {PetscValidPointer(fields, 3); *fields = NULL;} 5064 if (ds) {PetscValidPointer(ds, 4); *ds = NULL;} 5065 for (s = 0; s < Nds; ++s) { 5066 if (dm->probs[s].label == label) { 5067 if (fields) *fields = dm->probs[s].fields; 5068 if (ds) *ds = dm->probs[s].ds; 5069 PetscFunctionReturn(0); 5070 } 5071 } 5072 PetscFunctionReturn(0); 5073 } 5074 5075 /*@ 5076 DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number 5077 5078 Not collective 5079 5080 Input Parameters: 5081 + dm - The DM 5082 - num - The region number, in [0, Nds) 5083 5084 Output Parameters: 5085 + label - The region label, or NULL 5086 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5087 - prob - The PetscDS defined on the given region, or NULL 5088 5089 Level: advanced 5090 5091 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5092 @*/ 5093 PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds) 5094 { 5095 PetscInt Nds; 5096 PetscErrorCode ierr; 5097 5098 PetscFunctionBegin; 5099 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5100 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5101 if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds); 5102 if (label) { 5103 PetscValidPointer(label, 3); 5104 *label = dm->probs[num].label; 5105 } 5106 if (fields) { 5107 PetscValidPointer(fields, 4); 5108 *fields = dm->probs[num].fields; 5109 } 5110 if (ds) { 5111 PetscValidPointer(ds, 5); 5112 *ds = dm->probs[num].ds; 5113 } 5114 PetscFunctionReturn(0); 5115 } 5116 5117 /*@ 5118 DMSetRegionDS - Set the PetscDS for a given mesh region, defined by a DMLabel 5119 5120 Collective on dm 5121 5122 Input Parameters: 5123 + dm - The DM 5124 . label - The DMLabel defining the mesh region, or NULL for the entire mesh 5125 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL for all fields 5126 - prob - The PetscDS defined on the given cell 5127 5128 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. If DS is replaced, 5129 the fields argument is ignored. 5130 5131 Level: advanced 5132 5133 .seealso: DMGetRegionDS(), DMGetDS(), DMGetCellDS() 5134 @*/ 5135 PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds) 5136 { 5137 PetscInt Nds = dm->Nds, s; 5138 PetscErrorCode ierr; 5139 5140 PetscFunctionBegin; 5141 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5142 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5143 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 3); 5144 for (s = 0; s < Nds; ++s) { 5145 if (dm->probs[s].label == label) { 5146 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 5147 dm->probs[s].ds = ds; 5148 PetscFunctionReturn(0); 5149 } 5150 } 5151 ierr = DMDSEnlarge_Static(dm, Nds+1);CHKERRQ(ierr); 5152 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 5153 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr); 5154 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr); 5155 if (!label) { 5156 /* Put the NULL label at the front, so it is returned as the default */ 5157 for (s = Nds-1; s >=0; --s) dm->probs[s+1] = dm->probs[s]; 5158 Nds = 0; 5159 } 5160 dm->probs[Nds].label = label; 5161 dm->probs[Nds].fields = fields; 5162 dm->probs[Nds].ds = ds; 5163 PetscFunctionReturn(0); 5164 } 5165 5166 /*@ 5167 DMCreateDS - Create the discrete systems for the DM based upon the fields added to the DM 5168 5169 Collective on dm 5170 5171 Input Parameter: 5172 . dm - The DM 5173 5174 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. 5175 5176 Level: intermediate 5177 5178 .seealso: DMSetField, DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5179 @*/ 5180 PetscErrorCode DMCreateDS(DM dm) 5181 { 5182 MPI_Comm comm; 5183 PetscDS prob, probh = NULL; 5184 PetscInt dimEmbed, Nf = dm->Nf, f, s, field = 0, fieldh = 0; 5185 PetscBool doSetup = PETSC_TRUE; 5186 PetscErrorCode ierr; 5187 5188 PetscFunctionBegin; 5189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5190 if (!dm->fields) PetscFunctionReturn(0); 5191 /* Can only handle two label cases right now: 5192 1) NULL 5193 2) Hybrid cells 5194 */ 5195 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 5196 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 5197 /* Create default DS */ 5198 ierr = DMGetRegionDS(dm, NULL, NULL, &prob);CHKERRQ(ierr); 5199 if (!prob) { 5200 IS fields; 5201 PetscInt *fld, nf; 5202 5203 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) ++nf; 5204 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr); 5205 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) fld[nf++] = f; 5206 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5207 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5208 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5209 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5210 5211 ierr = PetscDSCreate(comm, &prob);CHKERRQ(ierr); 5212 ierr = DMSetRegionDS(dm, NULL, fields, prob);CHKERRQ(ierr); 5213 ierr = PetscDSDestroy(&prob);CHKERRQ(ierr); 5214 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5215 ierr = DMGetRegionDS(dm, NULL, NULL, &prob);CHKERRQ(ierr); 5216 } 5217 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 5218 /* Optionally create hybrid DS */ 5219 for (f = 0; f < Nf; ++f) { 5220 DMLabel label = dm->fields[f].label; 5221 PetscInt lStart, lEnd; 5222 5223 if (label) { 5224 DM plex; 5225 IS fields; 5226 PetscInt *fld; 5227 PetscInt depth, pMax[4]; 5228 5229 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5230 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 5231 ierr = DMPlexGetHybridBounds(plex, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 5232 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5233 5234 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr); 5235 if (lStart < pMax[depth]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support labels over hybrid cells right now"); 5236 ierr = PetscDSCreate(comm, &probh);CHKERRQ(ierr); 5237 ierr = PetscMalloc1(1, &fld);CHKERRQ(ierr); 5238 fld[0] = f; 5239 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5240 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5241 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5242 ierr = ISGeneralSetIndices(fields, 1, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5243 ierr = DMSetRegionDS(dm, label, fields, probh);CHKERRQ(ierr); 5244 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5245 ierr = PetscDSSetHybrid(probh, PETSC_TRUE);CHKERRQ(ierr); 5246 ierr = PetscDSSetCoordinateDimension(probh, dimEmbed);CHKERRQ(ierr); 5247 break; 5248 } 5249 } 5250 /* Set fields in DSes */ 5251 for (f = 0; f < Nf; ++f) { 5252 DMLabel label = dm->fields[f].label; 5253 PetscObject disc = dm->fields[f].disc; 5254 5255 if (!label) { 5256 ierr = PetscDSSetDiscretization(prob, field++, disc);CHKERRQ(ierr); 5257 if (probh) { 5258 PetscFE subfe; 5259 5260 ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, &subfe);CHKERRQ(ierr); 5261 ierr = PetscDSSetDiscretization(probh, fieldh++, (PetscObject) subfe);CHKERRQ(ierr); 5262 } 5263 } else { 5264 ierr = PetscDSSetDiscretization(probh, fieldh++, disc);CHKERRQ(ierr); 5265 } 5266 /* We allow people to have placeholder fields and construct the Section by hand */ 5267 { 5268 PetscClassId id; 5269 5270 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 5271 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE; 5272 } 5273 } 5274 ierr = PetscDSDestroy(&probh);CHKERRQ(ierr); 5275 /* Setup DSes */ 5276 if (doSetup) { 5277 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 5278 } 5279 PetscFunctionReturn(0); 5280 } 5281 5282 /*@ 5283 DMCopyDS - Copy the discrete systems for the DM into another DM 5284 5285 Collective on dm 5286 5287 Input Parameter: 5288 . dm - The DM 5289 5290 Output Parameter: 5291 . newdm - The DM 5292 5293 Level: advanced 5294 5295 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5296 @*/ 5297 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5298 { 5299 PetscInt Nds, s; 5300 PetscErrorCode ierr; 5301 5302 PetscFunctionBegin; 5303 if (dm == newdm) PetscFunctionReturn(0); 5304 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5305 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5306 for (s = 0; s < Nds; ++s) { 5307 DMLabel label; 5308 IS fields; 5309 PetscDS ds; 5310 5311 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5312 ierr = DMSetRegionDS(newdm, label, fields, ds);CHKERRQ(ierr); 5313 } 5314 PetscFunctionReturn(0); 5315 } 5316 5317 /*@ 5318 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5319 5320 Collective on dm 5321 5322 Input Parameter: 5323 . dm - The DM 5324 5325 Output Parameter: 5326 . newdm - The DM 5327 5328 Level: advanced 5329 5330 .seealso: DMCopyFields(), DMCopyDS() 5331 @*/ 5332 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5333 { 5334 PetscErrorCode ierr; 5335 5336 PetscFunctionBegin; 5337 if (dm == newdm) PetscFunctionReturn(0); 5338 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5339 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5340 PetscFunctionReturn(0); 5341 } 5342 5343 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5344 { 5345 DM dm_coord,dmc_coord; 5346 PetscErrorCode ierr; 5347 Vec coords,ccoords; 5348 Mat inject; 5349 PetscFunctionBegin; 5350 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5351 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5352 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5353 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5354 if (coords && !ccoords) { 5355 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5356 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5357 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5358 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5359 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5360 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5361 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5362 } 5363 PetscFunctionReturn(0); 5364 } 5365 5366 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5367 { 5368 DM dm_coord,subdm_coord; 5369 PetscErrorCode ierr; 5370 Vec coords,ccoords,clcoords; 5371 VecScatter *scat_i,*scat_g; 5372 PetscFunctionBegin; 5373 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5374 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5375 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5376 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5377 if (coords && !ccoords) { 5378 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5379 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5380 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5381 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5382 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5383 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5384 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5385 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5386 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5387 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5388 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5389 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5390 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5391 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5392 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5393 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5394 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5395 } 5396 PetscFunctionReturn(0); 5397 } 5398 5399 /*@ 5400 DMGetDimension - Return the topological dimension of the DM 5401 5402 Not collective 5403 5404 Input Parameter: 5405 . dm - The DM 5406 5407 Output Parameter: 5408 . dim - The topological dimension 5409 5410 Level: beginner 5411 5412 .seealso: DMSetDimension(), DMCreate() 5413 @*/ 5414 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5415 { 5416 PetscFunctionBegin; 5417 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5418 PetscValidIntPointer(dim, 2); 5419 *dim = dm->dim; 5420 PetscFunctionReturn(0); 5421 } 5422 5423 /*@ 5424 DMSetDimension - Set the topological dimension of the DM 5425 5426 Collective on dm 5427 5428 Input Parameters: 5429 + dm - The DM 5430 - dim - The topological dimension 5431 5432 Level: beginner 5433 5434 .seealso: DMGetDimension(), DMCreate() 5435 @*/ 5436 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 5437 { 5438 PetscDS ds; 5439 PetscErrorCode ierr; 5440 5441 PetscFunctionBegin; 5442 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5443 PetscValidLogicalCollectiveInt(dm, dim, 2); 5444 dm->dim = dim; 5445 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5446 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dm->dim);CHKERRQ(ierr);} 5447 PetscFunctionReturn(0); 5448 } 5449 5450 /*@ 5451 DMGetDimPoints - Get the half-open interval for all points of a given dimension 5452 5453 Collective on dm 5454 5455 Input Parameters: 5456 + dm - the DM 5457 - dim - the dimension 5458 5459 Output Parameters: 5460 + pStart - The first point of the given dimension 5461 - pEnd - The first point following points of the given dimension 5462 5463 Note: 5464 The points are vertices in the Hasse diagram encoding the topology. This is explained in 5465 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 5466 then the interval is empty. 5467 5468 Level: intermediate 5469 5470 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 5471 @*/ 5472 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5473 { 5474 PetscInt d; 5475 PetscErrorCode ierr; 5476 5477 PetscFunctionBegin; 5478 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5479 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 5480 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 5481 if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name); 5482 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 5483 PetscFunctionReturn(0); 5484 } 5485 5486 /*@ 5487 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 5488 5489 Collective on dm 5490 5491 Input Parameters: 5492 + dm - the DM 5493 - c - coordinate vector 5494 5495 Notes: 5496 The coordinates do include those for ghost points, which are in the local vector. 5497 5498 The vector c should be destroyed by the caller. 5499 5500 Level: intermediate 5501 5502 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5503 @*/ 5504 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 5505 { 5506 PetscErrorCode ierr; 5507 5508 PetscFunctionBegin; 5509 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5510 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5511 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5512 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5513 dm->coordinates = c; 5514 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5515 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5516 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5517 PetscFunctionReturn(0); 5518 } 5519 5520 /*@ 5521 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 5522 5523 Not collective 5524 5525 Input Parameters: 5526 + dm - the DM 5527 - c - coordinate vector 5528 5529 Notes: 5530 The coordinates of ghost points can be set using DMSetCoordinates() 5531 followed by DMGetCoordinatesLocal(). This is intended to enable the 5532 setting of ghost coordinates outside of the domain. 5533 5534 The vector c should be destroyed by the caller. 5535 5536 Level: intermediate 5537 5538 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 5539 @*/ 5540 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 5541 { 5542 PetscErrorCode ierr; 5543 5544 PetscFunctionBegin; 5545 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5546 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5547 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5548 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5549 5550 dm->coordinatesLocal = c; 5551 5552 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5553 PetscFunctionReturn(0); 5554 } 5555 5556 /*@ 5557 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 5558 5559 Collective on dm 5560 5561 Input Parameter: 5562 . dm - the DM 5563 5564 Output Parameter: 5565 . c - global coordinate vector 5566 5567 Note: 5568 This is a borrowed reference, so the user should NOT destroy this vector 5569 5570 Each process has only the local coordinates (does NOT have the ghost coordinates). 5571 5572 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5573 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5574 5575 Level: intermediate 5576 5577 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5578 @*/ 5579 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 5580 { 5581 PetscErrorCode ierr; 5582 5583 PetscFunctionBegin; 5584 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5585 PetscValidPointer(c,2); 5586 if (!dm->coordinates && dm->coordinatesLocal) { 5587 DM cdm = NULL; 5588 PetscBool localized; 5589 5590 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5591 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 5592 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5593 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 5594 if (localized) { 5595 PetscInt cdim; 5596 5597 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5598 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5599 } 5600 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 5601 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5602 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5603 } 5604 *c = dm->coordinates; 5605 PetscFunctionReturn(0); 5606 } 5607 5608 /*@ 5609 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 5610 5611 Collective on dm 5612 5613 Input Parameter: 5614 . dm - the DM 5615 5616 Level: advanced 5617 5618 .seealso: DMGetCoordinatesLocalNoncollective() 5619 @*/ 5620 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 5621 { 5622 PetscErrorCode ierr; 5623 5624 PetscFunctionBegin; 5625 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5626 if (!dm->coordinatesLocal && dm->coordinates) { 5627 DM cdm = NULL; 5628 PetscBool localized; 5629 5630 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5631 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 5632 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5633 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 5634 if (localized) { 5635 PetscInt cdim; 5636 5637 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5638 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5639 } 5640 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 5641 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5642 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5643 } 5644 PetscFunctionReturn(0); 5645 } 5646 5647 /*@ 5648 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 5649 5650 Collective on dm 5651 5652 Input Parameter: 5653 . dm - the DM 5654 5655 Output Parameter: 5656 . c - coordinate vector 5657 5658 Note: 5659 This is a borrowed reference, so the user should NOT destroy this vector 5660 5661 Each process has the local and ghost coordinates 5662 5663 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5664 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5665 5666 Level: intermediate 5667 5668 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 5669 @*/ 5670 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 5671 { 5672 PetscErrorCode ierr; 5673 5674 PetscFunctionBegin; 5675 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5676 PetscValidPointer(c,2); 5677 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 5678 *c = dm->coordinatesLocal; 5679 PetscFunctionReturn(0); 5680 } 5681 5682 /*@ 5683 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 5684 5685 Not collective 5686 5687 Input Parameter: 5688 . dm - the DM 5689 5690 Output Parameter: 5691 . c - coordinate vector 5692 5693 Level: advanced 5694 5695 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5696 @*/ 5697 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 5698 { 5699 PetscFunctionBegin; 5700 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5701 PetscValidPointer(c,2); 5702 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 5703 *c = dm->coordinatesLocal; 5704 PetscFunctionReturn(0); 5705 } 5706 5707 /*@ 5708 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 5709 5710 Not collective 5711 5712 Input Parameter: 5713 + dm - the DM 5714 - p - the IS of points whose coordinates will be returned 5715 5716 Output Parameter: 5717 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 5718 - pCoord - the Vec with coordinates of points in p 5719 5720 Note: 5721 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 5722 5723 This creates a new vector, so the user SHOULD destroy this vector 5724 5725 Each process has the local and ghost coordinates 5726 5727 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5728 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5729 5730 Level: advanced 5731 5732 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5733 @*/ 5734 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 5735 { 5736 PetscSection cs, newcs; 5737 Vec coords; 5738 const PetscScalar *arr; 5739 PetscScalar *newarr=NULL; 5740 PetscInt n; 5741 PetscErrorCode ierr; 5742 5743 PetscFunctionBegin; 5744 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5745 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 5746 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 5747 if (pCoord) PetscValidPointer(pCoord, 4); 5748 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 5749 if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 5750 cs = dm->coordinateDM->localSection; 5751 coords = dm->coordinatesLocal; 5752 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 5753 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 5754 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 5755 if (pCoord) { 5756 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 5757 /* set array in two steps to mimic PETSC_OWN_POINTER */ 5758 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 5759 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 5760 } else { 5761 ierr = PetscFree(newarr);CHKERRQ(ierr); 5762 } 5763 if (pCoordSection) {*pCoordSection = newcs;} 5764 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 5765 PetscFunctionReturn(0); 5766 } 5767 5768 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 5769 { 5770 PetscErrorCode ierr; 5771 5772 PetscFunctionBegin; 5773 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5774 PetscValidPointer(field,2); 5775 if (!dm->coordinateField) { 5776 if (dm->ops->createcoordinatefield) { 5777 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 5778 } 5779 } 5780 *field = dm->coordinateField; 5781 PetscFunctionReturn(0); 5782 } 5783 5784 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 5785 { 5786 PetscErrorCode ierr; 5787 5788 PetscFunctionBegin; 5789 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5790 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 5791 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 5792 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 5793 dm->coordinateField = field; 5794 PetscFunctionReturn(0); 5795 } 5796 5797 /*@ 5798 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 5799 5800 Collective on dm 5801 5802 Input Parameter: 5803 . dm - the DM 5804 5805 Output Parameter: 5806 . cdm - coordinate DM 5807 5808 Level: intermediate 5809 5810 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5811 @*/ 5812 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 5813 { 5814 PetscErrorCode ierr; 5815 5816 PetscFunctionBegin; 5817 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5818 PetscValidPointer(cdm,2); 5819 if (!dm->coordinateDM) { 5820 DM cdm; 5821 5822 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 5823 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 5824 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 5825 * until the call to CreateCoordinateDM) */ 5826 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5827 dm->coordinateDM = cdm; 5828 } 5829 *cdm = dm->coordinateDM; 5830 PetscFunctionReturn(0); 5831 } 5832 5833 /*@ 5834 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 5835 5836 Logically Collective on dm 5837 5838 Input Parameters: 5839 + dm - the DM 5840 - cdm - coordinate DM 5841 5842 Level: intermediate 5843 5844 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5845 @*/ 5846 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 5847 { 5848 PetscErrorCode ierr; 5849 5850 PetscFunctionBegin; 5851 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5852 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 5853 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5854 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5855 dm->coordinateDM = cdm; 5856 PetscFunctionReturn(0); 5857 } 5858 5859 /*@ 5860 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 5861 5862 Not Collective 5863 5864 Input Parameter: 5865 . dm - The DM object 5866 5867 Output Parameter: 5868 . dim - The embedding dimension 5869 5870 Level: intermediate 5871 5872 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 5873 @*/ 5874 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 5875 { 5876 PetscFunctionBegin; 5877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5878 PetscValidIntPointer(dim, 2); 5879 if (dm->dimEmbed == PETSC_DEFAULT) { 5880 dm->dimEmbed = dm->dim; 5881 } 5882 *dim = dm->dimEmbed; 5883 PetscFunctionReturn(0); 5884 } 5885 5886 /*@ 5887 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 5888 5889 Not Collective 5890 5891 Input Parameters: 5892 + dm - The DM object 5893 - dim - The embedding dimension 5894 5895 Level: intermediate 5896 5897 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 5898 @*/ 5899 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 5900 { 5901 PetscDS ds; 5902 PetscErrorCode ierr; 5903 5904 PetscFunctionBegin; 5905 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5906 dm->dimEmbed = dim; 5907 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5908 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 5909 PetscFunctionReturn(0); 5910 } 5911 5912 /*@ 5913 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 5914 5915 Collective on dm 5916 5917 Input Parameter: 5918 . dm - The DM object 5919 5920 Output Parameter: 5921 . section - The PetscSection object 5922 5923 Level: intermediate 5924 5925 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 5926 @*/ 5927 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 5928 { 5929 DM cdm; 5930 PetscErrorCode ierr; 5931 5932 PetscFunctionBegin; 5933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5934 PetscValidPointer(section, 2); 5935 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5936 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr); 5937 PetscFunctionReturn(0); 5938 } 5939 5940 /*@ 5941 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 5942 5943 Not Collective 5944 5945 Input Parameters: 5946 + dm - The DM object 5947 . dim - The embedding dimension, or PETSC_DETERMINE 5948 - section - The PetscSection object 5949 5950 Level: intermediate 5951 5952 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 5953 @*/ 5954 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 5955 { 5956 DM cdm; 5957 PetscErrorCode ierr; 5958 5959 PetscFunctionBegin; 5960 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5961 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 5962 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5963 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr); 5964 if (dim == PETSC_DETERMINE) { 5965 PetscInt d = PETSC_DEFAULT; 5966 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 5967 5968 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5969 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5970 pStart = PetscMax(vStart, pStart); 5971 pEnd = PetscMin(vEnd, pEnd); 5972 for (v = pStart; v < pEnd; ++v) { 5973 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 5974 if (dd) {d = dd; break;} 5975 } 5976 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 5977 } 5978 PetscFunctionReturn(0); 5979 } 5980 5981 /*@C 5982 DMGetPeriodicity - Get the description of mesh periodicity 5983 5984 Input Parameters: 5985 . dm - The DM object 5986 5987 Output Parameters: 5988 + per - Whether the DM is periodic or not 5989 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5990 . L - If we assume the mesh is a torus, this is the length of each coordinate 5991 - bd - This describes the type of periodicity in each topological dimension 5992 5993 Level: developer 5994 5995 .seealso: DMGetPeriodicity() 5996 @*/ 5997 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 5998 { 5999 PetscFunctionBegin; 6000 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6001 if (per) *per = dm->periodic; 6002 if (L) *L = dm->L; 6003 if (maxCell) *maxCell = dm->maxCell; 6004 if (bd) *bd = dm->bdtype; 6005 PetscFunctionReturn(0); 6006 } 6007 6008 /*@C 6009 DMSetPeriodicity - Set the description of mesh periodicity 6010 6011 Input Parameters: 6012 + dm - The DM object 6013 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 6014 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6015 . L - If we assume the mesh is a torus, this is the length of each coordinate 6016 - bd - This describes the type of periodicity in each topological dimension 6017 6018 Level: developer 6019 6020 .seealso: DMGetPeriodicity() 6021 @*/ 6022 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6023 { 6024 PetscInt dim, d; 6025 PetscErrorCode ierr; 6026 6027 PetscFunctionBegin; 6028 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6029 PetscValidLogicalCollectiveBool(dm,per,2); 6030 if (maxCell) { 6031 PetscValidRealPointer(maxCell,3); 6032 PetscValidRealPointer(L,4); 6033 PetscValidPointer(bd,5); 6034 } 6035 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 6036 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6037 if (maxCell) { 6038 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 6039 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 6040 } 6041 dm->periodic = per; 6042 PetscFunctionReturn(0); 6043 } 6044 6045 /*@ 6046 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. 6047 6048 Input Parameters: 6049 + dm - The DM 6050 . in - The input coordinate point (dim numbers) 6051 - endpoint - Include the endpoint L_i 6052 6053 Output Parameter: 6054 . out - The localized coordinate point 6055 6056 Level: developer 6057 6058 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6059 @*/ 6060 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6061 { 6062 PetscInt dim, d; 6063 PetscErrorCode ierr; 6064 6065 PetscFunctionBegin; 6066 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6067 if (!dm->maxCell) { 6068 for (d = 0; d < dim; ++d) out[d] = in[d]; 6069 } else { 6070 if (endpoint) { 6071 for (d = 0; d < dim; ++d) { 6072 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)) { 6073 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6074 } else { 6075 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6076 } 6077 } 6078 } else { 6079 for (d = 0; d < dim; ++d) { 6080 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6081 } 6082 } 6083 } 6084 PetscFunctionReturn(0); 6085 } 6086 6087 /* 6088 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. 6089 6090 Input Parameters: 6091 + dm - The DM 6092 . dim - The spatial dimension 6093 . anchor - The anchor point, the input point can be no more than maxCell away from it 6094 - in - The input coordinate point (dim numbers) 6095 6096 Output Parameter: 6097 . out - The localized coordinate point 6098 6099 Level: developer 6100 6101 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 6102 6103 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6104 */ 6105 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6106 { 6107 PetscInt d; 6108 6109 PetscFunctionBegin; 6110 if (!dm->maxCell) { 6111 for (d = 0; d < dim; ++d) out[d] = in[d]; 6112 } else { 6113 for (d = 0; d < dim; ++d) { 6114 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6115 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6116 } else { 6117 out[d] = in[d]; 6118 } 6119 } 6120 } 6121 PetscFunctionReturn(0); 6122 } 6123 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6124 { 6125 PetscInt d; 6126 6127 PetscFunctionBegin; 6128 if (!dm->maxCell) { 6129 for (d = 0; d < dim; ++d) out[d] = in[d]; 6130 } else { 6131 for (d = 0; d < dim; ++d) { 6132 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6133 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6134 } else { 6135 out[d] = in[d]; 6136 } 6137 } 6138 } 6139 PetscFunctionReturn(0); 6140 } 6141 6142 /* 6143 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. 6144 6145 Input Parameters: 6146 + dm - The DM 6147 . dim - The spatial dimension 6148 . anchor - The anchor point, the input point can be no more than maxCell away from it 6149 . in - The input coordinate delta (dim numbers) 6150 - out - The input coordinate point (dim numbers) 6151 6152 Output Parameter: 6153 . out - The localized coordinate in + out 6154 6155 Level: developer 6156 6157 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 6158 6159 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6160 */ 6161 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6162 { 6163 PetscInt d; 6164 6165 PetscFunctionBegin; 6166 if (!dm->maxCell) { 6167 for (d = 0; d < dim; ++d) out[d] += in[d]; 6168 } else { 6169 for (d = 0; d < dim; ++d) { 6170 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6171 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6172 } else { 6173 out[d] += in[d]; 6174 } 6175 } 6176 } 6177 PetscFunctionReturn(0); 6178 } 6179 6180 /*@ 6181 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6182 6183 Not collective 6184 6185 Input Parameter: 6186 . dm - The DM 6187 6188 Output Parameter: 6189 areLocalized - True if localized 6190 6191 Level: developer 6192 6193 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6194 @*/ 6195 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6196 { 6197 DM cdm; 6198 PetscSection coordSection; 6199 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6200 PetscBool isPlex, alreadyLocalized; 6201 PetscErrorCode ierr; 6202 6203 PetscFunctionBegin; 6204 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6205 PetscValidBoolPointer(areLocalized, 2); 6206 *areLocalized = PETSC_FALSE; 6207 6208 /* We need some generic way of refering to cells/vertices */ 6209 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6210 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6211 if (!isPlex) PetscFunctionReturn(0); 6212 6213 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6214 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6215 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6216 alreadyLocalized = PETSC_FALSE; 6217 for (c = cStart; c < cEnd; ++c) { 6218 if (c < sStart || c >= sEnd) continue; 6219 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6220 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6221 } 6222 *areLocalized = alreadyLocalized; 6223 PetscFunctionReturn(0); 6224 } 6225 6226 /*@ 6227 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6228 6229 Collective on dm 6230 6231 Input Parameter: 6232 . dm - The DM 6233 6234 Output Parameter: 6235 areLocalized - True if localized 6236 6237 Level: developer 6238 6239 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6240 @*/ 6241 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6242 { 6243 PetscBool localized; 6244 PetscErrorCode ierr; 6245 6246 PetscFunctionBegin; 6247 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6248 PetscValidBoolPointer(areLocalized, 2); 6249 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6250 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6251 PetscFunctionReturn(0); 6252 } 6253 6254 /*@ 6255 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6256 6257 Collective on dm 6258 6259 Input Parameter: 6260 . dm - The DM 6261 6262 Level: developer 6263 6264 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6265 @*/ 6266 PetscErrorCode DMLocalizeCoordinates(DM dm) 6267 { 6268 DM cdm; 6269 PetscSection coordSection, cSection; 6270 Vec coordinates, cVec; 6271 PetscScalar *coords, *coords2, *anchor, *localized; 6272 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6273 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6274 PetscInt maxHeight = 0, h; 6275 PetscInt *pStart = NULL, *pEnd = NULL; 6276 PetscErrorCode ierr; 6277 6278 PetscFunctionBegin; 6279 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6280 if (!dm->periodic) PetscFunctionReturn(0); 6281 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6282 if (alreadyLocalized) PetscFunctionReturn(0); 6283 6284 /* We need some generic way of refering to cells/vertices */ 6285 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6286 { 6287 PetscBool isplex; 6288 6289 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6290 if (isplex) { 6291 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6292 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6293 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6294 pEnd = &pStart[maxHeight + 1]; 6295 newStart = vStart; 6296 newEnd = vEnd; 6297 for (h = 0; h <= maxHeight; h++) { 6298 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6299 newStart = PetscMin(newStart,pStart[h]); 6300 newEnd = PetscMax(newEnd,pEnd[h]); 6301 } 6302 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6303 } 6304 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6305 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6306 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6307 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6308 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6309 6310 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6311 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6312 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6313 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6314 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6315 6316 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6317 localized = &anchor[bs]; 6318 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6319 for (h = 0; h <= maxHeight; h++) { 6320 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6321 6322 for (c = cStart; c < cEnd; ++c) { 6323 PetscScalar *cellCoords = NULL; 6324 PetscInt b; 6325 6326 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6327 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6328 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6329 for (d = 0; d < dof/bs; ++d) { 6330 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6331 for (b = 0; b < bs; b++) { 6332 if (cellCoords[d*bs + b] != localized[b]) break; 6333 } 6334 if (b < bs) break; 6335 } 6336 if (d < dof/bs) { 6337 if (c >= sStart && c < sEnd) { 6338 PetscInt cdof; 6339 6340 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6341 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6342 } 6343 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6344 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6345 } 6346 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6347 } 6348 } 6349 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6350 if (alreadyLocalizedGlobal) { 6351 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6352 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6353 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6354 PetscFunctionReturn(0); 6355 } 6356 for (v = vStart; v < vEnd; ++v) { 6357 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6358 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6359 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6360 } 6361 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6362 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6363 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6364 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6365 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6366 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6367 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6368 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6369 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6370 for (v = vStart; v < vEnd; ++v) { 6371 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6372 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6373 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6374 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6375 } 6376 for (h = 0; h <= maxHeight; h++) { 6377 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6378 6379 for (c = cStart; c < cEnd; ++c) { 6380 PetscScalar *cellCoords = NULL; 6381 PetscInt b, cdof; 6382 6383 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6384 if (!cdof) continue; 6385 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6386 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6387 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6388 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6389 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6390 } 6391 } 6392 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6393 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6394 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6395 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6396 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6397 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6398 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6399 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6400 PetscFunctionReturn(0); 6401 } 6402 6403 /*@ 6404 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6405 6406 Collective on v (see explanation below) 6407 6408 Input Parameters: 6409 + dm - The DM 6410 . v - The Vec of points 6411 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6412 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6413 6414 Output Parameter: 6415 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6416 - cells - The PetscSF containing the ranks and local indices of the containing points. 6417 6418 6419 Level: developer 6420 6421 Notes: 6422 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6423 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6424 6425 If *cellSF is NULL on input, a PetscSF will be created. 6426 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6427 6428 An array that maps each point to its containing cell can be obtained with 6429 6430 $ const PetscSFNode *cells; 6431 $ PetscInt nFound; 6432 $ const PetscInt *found; 6433 $ 6434 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6435 6436 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6437 the index of the cell in its rank's local numbering. 6438 6439 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6440 @*/ 6441 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6442 { 6443 PetscErrorCode ierr; 6444 6445 PetscFunctionBegin; 6446 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6447 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6448 PetscValidPointer(cellSF,4); 6449 if (*cellSF) { 6450 PetscMPIInt result; 6451 6452 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6453 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6454 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6455 } else { 6456 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6457 } 6458 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6459 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6460 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6461 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6462 PetscFunctionReturn(0); 6463 } 6464 6465 /*@ 6466 DMGetOutputDM - Retrieve the DM associated with the layout for output 6467 6468 Collective on dm 6469 6470 Input Parameter: 6471 . dm - The original DM 6472 6473 Output Parameter: 6474 . odm - The DM which provides the layout for output 6475 6476 Level: intermediate 6477 6478 .seealso: VecView(), DMGetGlobalSection() 6479 @*/ 6480 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6481 { 6482 PetscSection section; 6483 PetscBool hasConstraints, ghasConstraints; 6484 PetscErrorCode ierr; 6485 6486 PetscFunctionBegin; 6487 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6488 PetscValidPointer(odm,2); 6489 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 6490 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6491 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6492 if (!ghasConstraints) { 6493 *odm = dm; 6494 PetscFunctionReturn(0); 6495 } 6496 if (!dm->dmBC) { 6497 PetscSection newSection, gsection; 6498 PetscSF sf; 6499 6500 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6501 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6502 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6503 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 6504 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6505 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6506 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6507 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6508 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6509 } 6510 *odm = dm->dmBC; 6511 PetscFunctionReturn(0); 6512 } 6513 6514 /*@ 6515 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6516 6517 Input Parameter: 6518 . dm - The original DM 6519 6520 Output Parameters: 6521 + num - The output sequence number 6522 - val - The output sequence value 6523 6524 Level: intermediate 6525 6526 Note: This is intended for output that should appear in sequence, for instance 6527 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6528 6529 .seealso: VecView() 6530 @*/ 6531 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6532 { 6533 PetscFunctionBegin; 6534 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6535 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 6536 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 6537 PetscFunctionReturn(0); 6538 } 6539 6540 /*@ 6541 DMSetOutputSequenceNumber - Set the sequence number/value for output 6542 6543 Input Parameters: 6544 + dm - The original DM 6545 . num - The output sequence number 6546 - val - The output sequence value 6547 6548 Level: intermediate 6549 6550 Note: This is intended for output that should appear in sequence, for instance 6551 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6552 6553 .seealso: VecView() 6554 @*/ 6555 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6556 { 6557 PetscFunctionBegin; 6558 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6559 dm->outputSequenceNum = num; 6560 dm->outputSequenceVal = val; 6561 PetscFunctionReturn(0); 6562 } 6563 6564 /*@C 6565 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6566 6567 Input Parameters: 6568 + dm - The original DM 6569 . name - The sequence name 6570 - num - The output sequence number 6571 6572 Output Parameter: 6573 . val - The output sequence value 6574 6575 Level: intermediate 6576 6577 Note: This is intended for output that should appear in sequence, for instance 6578 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6579 6580 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6581 @*/ 6582 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6583 { 6584 PetscBool ishdf5; 6585 PetscErrorCode ierr; 6586 6587 PetscFunctionBegin; 6588 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6589 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6590 PetscValidRealPointer(val,4); 6591 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6592 if (ishdf5) { 6593 #if defined(PETSC_HAVE_HDF5) 6594 PetscScalar value; 6595 6596 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6597 *val = PetscRealPart(value); 6598 #endif 6599 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6600 PetscFunctionReturn(0); 6601 } 6602 6603 /*@ 6604 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6605 6606 Not collective 6607 6608 Input Parameter: 6609 . dm - The DM 6610 6611 Output Parameter: 6612 . useNatural - The flag to build the mapping to a natural order during distribution 6613 6614 Level: beginner 6615 6616 .seealso: DMSetUseNatural(), DMCreate() 6617 @*/ 6618 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6619 { 6620 PetscFunctionBegin; 6621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6622 PetscValidBoolPointer(useNatural, 2); 6623 *useNatural = dm->useNatural; 6624 PetscFunctionReturn(0); 6625 } 6626 6627 /*@ 6628 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6629 6630 Collective on dm 6631 6632 Input Parameters: 6633 + dm - The DM 6634 - useNatural - The flag to build the mapping to a natural order during distribution 6635 6636 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6637 6638 Level: beginner 6639 6640 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6641 @*/ 6642 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6643 { 6644 PetscFunctionBegin; 6645 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6646 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6647 dm->useNatural = useNatural; 6648 PetscFunctionReturn(0); 6649 } 6650 6651 6652 /*@C 6653 DMCreateLabel - Create a label of the given name if it does not already exist 6654 6655 Not Collective 6656 6657 Input Parameters: 6658 + dm - The DM object 6659 - name - The label name 6660 6661 Level: intermediate 6662 6663 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6664 @*/ 6665 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6666 { 6667 PetscBool flg; 6668 DMLabel label; 6669 PetscErrorCode ierr; 6670 6671 PetscFunctionBegin; 6672 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6673 PetscValidCharPointer(name, 2); 6674 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 6675 if (!flg) { 6676 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 6677 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 6678 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 6679 } 6680 PetscFunctionReturn(0); 6681 } 6682 6683 /*@C 6684 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 6685 6686 Not Collective 6687 6688 Input Parameters: 6689 + dm - The DM object 6690 . name - The label name 6691 - point - The mesh point 6692 6693 Output Parameter: 6694 . value - The label value for this point, or -1 if the point is not in the label 6695 6696 Level: beginner 6697 6698 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 6699 @*/ 6700 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 6701 { 6702 DMLabel label; 6703 PetscErrorCode ierr; 6704 6705 PetscFunctionBegin; 6706 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6707 PetscValidCharPointer(name, 2); 6708 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6709 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 6710 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 6711 PetscFunctionReturn(0); 6712 } 6713 6714 /*@C 6715 DMSetLabelValue - Add a point to a Sieve Label with given value 6716 6717 Not Collective 6718 6719 Input Parameters: 6720 + dm - The DM object 6721 . name - The label name 6722 . point - The mesh point 6723 - value - The label value for this point 6724 6725 Output Parameter: 6726 6727 Level: beginner 6728 6729 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 6730 @*/ 6731 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6732 { 6733 DMLabel label; 6734 PetscErrorCode ierr; 6735 6736 PetscFunctionBegin; 6737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6738 PetscValidCharPointer(name, 2); 6739 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6740 if (!label) { 6741 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 6742 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6743 } 6744 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 6745 PetscFunctionReturn(0); 6746 } 6747 6748 /*@C 6749 DMClearLabelValue - Remove a point from a Sieve Label with given value 6750 6751 Not Collective 6752 6753 Input Parameters: 6754 + dm - The DM object 6755 . name - The label name 6756 . point - The mesh point 6757 - value - The label value for this point 6758 6759 Output Parameter: 6760 6761 Level: beginner 6762 6763 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 6764 @*/ 6765 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6766 { 6767 DMLabel label; 6768 PetscErrorCode ierr; 6769 6770 PetscFunctionBegin; 6771 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6772 PetscValidCharPointer(name, 2); 6773 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6774 if (!label) PetscFunctionReturn(0); 6775 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 6776 PetscFunctionReturn(0); 6777 } 6778 6779 /*@C 6780 DMGetLabelSize - Get the number of different integer ids in a Label 6781 6782 Not Collective 6783 6784 Input Parameters: 6785 + dm - The DM object 6786 - name - The label name 6787 6788 Output Parameter: 6789 . size - The number of different integer ids, or 0 if the label does not exist 6790 6791 Level: beginner 6792 6793 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 6794 @*/ 6795 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 6796 { 6797 DMLabel label; 6798 PetscErrorCode ierr; 6799 6800 PetscFunctionBegin; 6801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6802 PetscValidCharPointer(name, 2); 6803 PetscValidIntPointer(size, 3); 6804 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6805 *size = 0; 6806 if (!label) PetscFunctionReturn(0); 6807 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 6808 PetscFunctionReturn(0); 6809 } 6810 6811 /*@C 6812 DMGetLabelIdIS - Get the integer ids in a label 6813 6814 Not Collective 6815 6816 Input Parameters: 6817 + mesh - The DM object 6818 - name - The label name 6819 6820 Output Parameter: 6821 . ids - The integer ids, or NULL if the label does not exist 6822 6823 Level: beginner 6824 6825 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 6826 @*/ 6827 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 6828 { 6829 DMLabel label; 6830 PetscErrorCode ierr; 6831 6832 PetscFunctionBegin; 6833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6834 PetscValidCharPointer(name, 2); 6835 PetscValidPointer(ids, 3); 6836 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6837 *ids = NULL; 6838 if (label) { 6839 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 6840 } else { 6841 /* returning an empty IS */ 6842 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 6843 } 6844 PetscFunctionReturn(0); 6845 } 6846 6847 /*@C 6848 DMGetStratumSize - Get the number of points in a label stratum 6849 6850 Not Collective 6851 6852 Input Parameters: 6853 + dm - The DM object 6854 . name - The label name 6855 - value - The stratum value 6856 6857 Output Parameter: 6858 . size - The stratum size 6859 6860 Level: beginner 6861 6862 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 6863 @*/ 6864 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 6865 { 6866 DMLabel label; 6867 PetscErrorCode ierr; 6868 6869 PetscFunctionBegin; 6870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6871 PetscValidCharPointer(name, 2); 6872 PetscValidIntPointer(size, 4); 6873 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6874 *size = 0; 6875 if (!label) PetscFunctionReturn(0); 6876 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 6877 PetscFunctionReturn(0); 6878 } 6879 6880 /*@C 6881 DMGetStratumIS - Get the points in a label stratum 6882 6883 Not Collective 6884 6885 Input Parameters: 6886 + dm - The DM object 6887 . name - The label name 6888 - value - The stratum value 6889 6890 Output Parameter: 6891 . points - The stratum points, or NULL if the label does not exist or does not have that value 6892 6893 Level: beginner 6894 6895 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 6896 @*/ 6897 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 6898 { 6899 DMLabel label; 6900 PetscErrorCode ierr; 6901 6902 PetscFunctionBegin; 6903 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6904 PetscValidCharPointer(name, 2); 6905 PetscValidPointer(points, 4); 6906 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6907 *points = NULL; 6908 if (!label) PetscFunctionReturn(0); 6909 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 6910 PetscFunctionReturn(0); 6911 } 6912 6913 /*@C 6914 DMSetStratumIS - Set the points in a label stratum 6915 6916 Not Collective 6917 6918 Input Parameters: 6919 + dm - The DM object 6920 . name - The label name 6921 . value - The stratum value 6922 - points - The stratum points 6923 6924 Level: beginner 6925 6926 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 6927 @*/ 6928 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 6929 { 6930 DMLabel label; 6931 PetscErrorCode ierr; 6932 6933 PetscFunctionBegin; 6934 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6935 PetscValidCharPointer(name, 2); 6936 PetscValidPointer(points, 4); 6937 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6938 if (!label) PetscFunctionReturn(0); 6939 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 6940 PetscFunctionReturn(0); 6941 } 6942 6943 /*@C 6944 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 6945 6946 Not Collective 6947 6948 Input Parameters: 6949 + dm - The DM object 6950 . name - The label name 6951 - value - The label value for this point 6952 6953 Output Parameter: 6954 6955 Level: beginner 6956 6957 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 6958 @*/ 6959 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 6960 { 6961 DMLabel label; 6962 PetscErrorCode ierr; 6963 6964 PetscFunctionBegin; 6965 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6966 PetscValidCharPointer(name, 2); 6967 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6968 if (!label) PetscFunctionReturn(0); 6969 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 6970 PetscFunctionReturn(0); 6971 } 6972 6973 /*@ 6974 DMGetNumLabels - Return the number of labels defined by the mesh 6975 6976 Not Collective 6977 6978 Input Parameter: 6979 . dm - The DM object 6980 6981 Output Parameter: 6982 . numLabels - the number of Labels 6983 6984 Level: intermediate 6985 6986 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6987 @*/ 6988 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 6989 { 6990 DMLabelLink next = dm->labels; 6991 PetscInt n = 0; 6992 6993 PetscFunctionBegin; 6994 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6995 PetscValidIntPointer(numLabels, 2); 6996 while (next) {++n; next = next->next;} 6997 *numLabels = n; 6998 PetscFunctionReturn(0); 6999 } 7000 7001 /*@C 7002 DMGetLabelName - Return the name of nth label 7003 7004 Not Collective 7005 7006 Input Parameters: 7007 + dm - The DM object 7008 - n - the label number 7009 7010 Output Parameter: 7011 . name - the label name 7012 7013 Level: intermediate 7014 7015 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7016 @*/ 7017 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7018 { 7019 DMLabelLink next = dm->labels; 7020 PetscInt l = 0; 7021 PetscErrorCode ierr; 7022 7023 PetscFunctionBegin; 7024 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7025 PetscValidPointer(name, 3); 7026 while (next) { 7027 if (l == n) { 7028 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7029 PetscFunctionReturn(0); 7030 } 7031 ++l; 7032 next = next->next; 7033 } 7034 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7035 } 7036 7037 /*@C 7038 DMHasLabel - Determine whether the mesh has a label of a given name 7039 7040 Not Collective 7041 7042 Input Parameters: 7043 + dm - The DM object 7044 - name - The label name 7045 7046 Output Parameter: 7047 . hasLabel - PETSC_TRUE if the label is present 7048 7049 Level: intermediate 7050 7051 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7052 @*/ 7053 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7054 { 7055 DMLabelLink next = dm->labels; 7056 const char *lname; 7057 PetscErrorCode ierr; 7058 7059 PetscFunctionBegin; 7060 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7061 PetscValidCharPointer(name, 2); 7062 PetscValidBoolPointer(hasLabel, 3); 7063 *hasLabel = PETSC_FALSE; 7064 while (next) { 7065 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7066 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7067 if (*hasLabel) break; 7068 next = next->next; 7069 } 7070 PetscFunctionReturn(0); 7071 } 7072 7073 /*@C 7074 DMGetLabel - Return the label of a given name, or NULL 7075 7076 Not Collective 7077 7078 Input Parameters: 7079 + dm - The DM object 7080 - name - The label name 7081 7082 Output Parameter: 7083 . label - The DMLabel, or NULL if the label is absent 7084 7085 Level: intermediate 7086 7087 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7088 @*/ 7089 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7090 { 7091 DMLabelLink next = dm->labels; 7092 PetscBool hasLabel; 7093 const char *lname; 7094 PetscErrorCode ierr; 7095 7096 PetscFunctionBegin; 7097 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7098 PetscValidCharPointer(name, 2); 7099 PetscValidPointer(label, 3); 7100 *label = NULL; 7101 while (next) { 7102 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7103 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7104 if (hasLabel) { 7105 *label = next->label; 7106 break; 7107 } 7108 next = next->next; 7109 } 7110 PetscFunctionReturn(0); 7111 } 7112 7113 /*@C 7114 DMGetLabelByNum - Return the nth label 7115 7116 Not Collective 7117 7118 Input Parameters: 7119 + dm - The DM object 7120 - n - the label number 7121 7122 Output Parameter: 7123 . label - the label 7124 7125 Level: intermediate 7126 7127 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7128 @*/ 7129 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7130 { 7131 DMLabelLink next = dm->labels; 7132 PetscInt l = 0; 7133 7134 PetscFunctionBegin; 7135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7136 PetscValidPointer(label, 3); 7137 while (next) { 7138 if (l == n) { 7139 *label = next->label; 7140 PetscFunctionReturn(0); 7141 } 7142 ++l; 7143 next = next->next; 7144 } 7145 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7146 } 7147 7148 /*@C 7149 DMAddLabel - Add the label to this mesh 7150 7151 Not Collective 7152 7153 Input Parameters: 7154 + dm - The DM object 7155 - label - The DMLabel 7156 7157 Level: developer 7158 7159 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7160 @*/ 7161 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 7162 { 7163 DMLabelLink l, *p, tmpLabel; 7164 PetscBool hasLabel; 7165 const char *lname; 7166 PetscBool flg; 7167 PetscErrorCode ierr; 7168 7169 PetscFunctionBegin; 7170 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7171 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 7172 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 7173 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 7174 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 7175 tmpLabel->label = label; 7176 tmpLabel->output = PETSC_TRUE; 7177 for (p=&dm->labels; (l=*p); p=&l->next) {} 7178 *p = tmpLabel; 7179 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 7180 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7181 if (flg) dm->depthLabel = label; 7182 PetscFunctionReturn(0); 7183 } 7184 7185 /*@C 7186 DMRemoveLabel - Remove the label given by name from this mesh 7187 7188 Not Collective 7189 7190 Input Parameters: 7191 + dm - The DM object 7192 - name - The label name 7193 7194 Output Parameter: 7195 . label - The DMLabel, or NULL if the label is absent 7196 7197 Level: developer 7198 7199 Notes: 7200 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 7201 DMLabelDestroy() on the label. 7202 7203 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 7204 call DMLabelDestroy(). Instead, the label is returned and the user is 7205 responsible of calling DMLabelDestroy() at some point. 7206 7207 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 7208 @*/ 7209 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7210 { 7211 DMLabelLink link, *pnext; 7212 PetscBool hasLabel; 7213 const char *lname; 7214 PetscErrorCode ierr; 7215 7216 PetscFunctionBegin; 7217 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7218 PetscValidCharPointer(name, 2); 7219 if (label) { 7220 PetscValidPointer(label, 3); 7221 *label = NULL; 7222 } 7223 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7224 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 7225 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7226 if (hasLabel) { 7227 *pnext = link->next; /* Remove from list */ 7228 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7229 if (hasLabel) dm->depthLabel = NULL; 7230 if (label) *label = link->label; 7231 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 7232 ierr = PetscFree(link);CHKERRQ(ierr); 7233 break; 7234 } 7235 } 7236 PetscFunctionReturn(0); 7237 } 7238 7239 /*@ 7240 DMRemoveLabelBySelf - Remove the label from this mesh 7241 7242 Not Collective 7243 7244 Input Parameters: 7245 + dm - The DM object 7246 . label - (Optional) The DMLabel to be removed from the DM 7247 - failNotFound - Should it fail if the label is not found in the DM? 7248 7249 Level: developer 7250 7251 Notes: 7252 Only exactly the same instance is removed if found, name match is ignored. 7253 If the DM has an exclusive reference to the label, it gets destroyed and 7254 *label nullified. 7255 7256 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 7257 @*/ 7258 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 7259 { 7260 DMLabelLink link, *pnext; 7261 PetscBool hasLabel = PETSC_FALSE; 7262 PetscErrorCode ierr; 7263 7264 PetscFunctionBegin; 7265 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7266 PetscValidPointer(label, 2); 7267 if (!*label && !failNotFound) PetscFunctionReturn(0); 7268 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 7269 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 7270 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7271 if (*label == link->label) { 7272 hasLabel = PETSC_TRUE; 7273 *pnext = link->next; /* Remove from list */ 7274 if (*label == dm->depthLabel) dm->depthLabel = NULL; 7275 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 7276 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 7277 ierr = PetscFree(link);CHKERRQ(ierr); 7278 break; 7279 } 7280 } 7281 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 7282 PetscFunctionReturn(0); 7283 } 7284 7285 /*@C 7286 DMGetLabelOutput - Get the output flag for a given label 7287 7288 Not Collective 7289 7290 Input Parameters: 7291 + dm - The DM object 7292 - name - The label name 7293 7294 Output Parameter: 7295 . output - The flag for output 7296 7297 Level: developer 7298 7299 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7300 @*/ 7301 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7302 { 7303 DMLabelLink next = dm->labels; 7304 const char *lname; 7305 PetscErrorCode ierr; 7306 7307 PetscFunctionBegin; 7308 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7309 PetscValidPointer(name, 2); 7310 PetscValidPointer(output, 3); 7311 while (next) { 7312 PetscBool flg; 7313 7314 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7315 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7316 if (flg) {*output = next->output; PetscFunctionReturn(0);} 7317 next = next->next; 7318 } 7319 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7320 } 7321 7322 /*@C 7323 DMSetLabelOutput - Set the output flag for a given label 7324 7325 Not Collective 7326 7327 Input Parameters: 7328 + dm - The DM object 7329 . name - The label name 7330 - output - The flag for output 7331 7332 Level: developer 7333 7334 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7335 @*/ 7336 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7337 { 7338 DMLabelLink next = dm->labels; 7339 const char *lname; 7340 PetscErrorCode ierr; 7341 7342 PetscFunctionBegin; 7343 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7344 PetscValidCharPointer(name, 2); 7345 while (next) { 7346 PetscBool flg; 7347 7348 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7349 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7350 if (flg) {next->output = output; PetscFunctionReturn(0);} 7351 next = next->next; 7352 } 7353 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7354 } 7355 7356 /*@ 7357 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7358 7359 Collective on dmA 7360 7361 Input Parameter: 7362 + dmA - The DM object with initial labels 7363 . dmB - The DM object with copied labels 7364 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 7365 - all - Copy all labels including "depth" and "dim" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 7366 7367 Level: intermediate 7368 7369 Note: This is typically used when interpolating or otherwise adding to a mesh 7370 7371 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels() 7372 @*/ 7373 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all) 7374 { 7375 DMLabel label, labelNew; 7376 const char *name; 7377 PetscBool flg; 7378 DMLabelLink link; 7379 PetscErrorCode ierr; 7380 7381 PetscFunctionBegin; 7382 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 7383 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 7384 PetscValidLogicalCollectiveEnum(dmA, mode,3); 7385 PetscValidLogicalCollectiveBool(dmA, all, 4); 7386 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 7387 if (dmA == dmB) PetscFunctionReturn(0); 7388 for (link=dmA->labels; link; link=link->next) { 7389 label=link->label; 7390 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 7391 if (!all) { 7392 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7393 if (flg) continue; 7394 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7395 if (flg) continue; 7396 } else { 7397 dmB->depthLabel = dmA->depthLabel; 7398 } 7399 if (mode==PETSC_COPY_VALUES) { 7400 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7401 } else { 7402 labelNew = label; 7403 } 7404 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7405 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 7406 } 7407 PetscFunctionReturn(0); 7408 } 7409 7410 /*@ 7411 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7412 7413 Input Parameter: 7414 . dm - The DM object 7415 7416 Output Parameter: 7417 . cdm - The coarse DM 7418 7419 Level: intermediate 7420 7421 .seealso: DMSetCoarseDM() 7422 @*/ 7423 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7424 { 7425 PetscFunctionBegin; 7426 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7427 PetscValidPointer(cdm, 2); 7428 *cdm = dm->coarseMesh; 7429 PetscFunctionReturn(0); 7430 } 7431 7432 /*@ 7433 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7434 7435 Input Parameters: 7436 + dm - The DM object 7437 - cdm - The coarse DM 7438 7439 Level: intermediate 7440 7441 .seealso: DMGetCoarseDM() 7442 @*/ 7443 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7444 { 7445 PetscErrorCode ierr; 7446 7447 PetscFunctionBegin; 7448 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7449 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7450 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7451 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7452 dm->coarseMesh = cdm; 7453 PetscFunctionReturn(0); 7454 } 7455 7456 /*@ 7457 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7458 7459 Input Parameter: 7460 . dm - The DM object 7461 7462 Output Parameter: 7463 . fdm - The fine DM 7464 7465 Level: intermediate 7466 7467 .seealso: DMSetFineDM() 7468 @*/ 7469 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7470 { 7471 PetscFunctionBegin; 7472 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7473 PetscValidPointer(fdm, 2); 7474 *fdm = dm->fineMesh; 7475 PetscFunctionReturn(0); 7476 } 7477 7478 /*@ 7479 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7480 7481 Input Parameters: 7482 + dm - The DM object 7483 - fdm - The fine DM 7484 7485 Level: intermediate 7486 7487 .seealso: DMGetFineDM() 7488 @*/ 7489 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7490 { 7491 PetscErrorCode ierr; 7492 7493 PetscFunctionBegin; 7494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7495 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7496 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7497 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7498 dm->fineMesh = fdm; 7499 PetscFunctionReturn(0); 7500 } 7501 7502 /*=== DMBoundary code ===*/ 7503 7504 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7505 { 7506 PetscInt d; 7507 PetscErrorCode ierr; 7508 7509 PetscFunctionBegin; 7510 for (d = 0; d < dm->Nds; ++d) { 7511 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7512 } 7513 PetscFunctionReturn(0); 7514 } 7515 7516 /*@C 7517 DMAddBoundary - Add a boundary condition to the model 7518 7519 Input Parameters: 7520 + dm - The DM, with a PetscDS that matches the problem being constrained 7521 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7522 . name - The BC name 7523 . labelname - The label defining constrained points 7524 . field - The field to constrain 7525 . numcomps - The number of constrained field components (0 will constrain all fields) 7526 . comps - An array of constrained component numbers 7527 . bcFunc - A pointwise function giving boundary values 7528 . numids - The number of DMLabel ids for constrained points 7529 . ids - An array of ids for constrained points 7530 - ctx - An optional user context for bcFunc 7531 7532 Options Database Keys: 7533 + -bc_<boundary name> <num> - Overrides the boundary ids 7534 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7535 7536 Level: developer 7537 7538 .seealso: DMGetBoundary() 7539 @*/ 7540 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) 7541 { 7542 PetscDS ds; 7543 PetscErrorCode ierr; 7544 7545 PetscFunctionBegin; 7546 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7547 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7548 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, numids, ids, ctx);CHKERRQ(ierr); 7549 PetscFunctionReturn(0); 7550 } 7551 7552 /*@ 7553 DMGetNumBoundary - Get the number of registered BC 7554 7555 Input Parameters: 7556 . dm - The mesh object 7557 7558 Output Parameters: 7559 . numBd - The number of BC 7560 7561 Level: intermediate 7562 7563 .seealso: DMAddBoundary(), DMGetBoundary() 7564 @*/ 7565 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7566 { 7567 PetscDS ds; 7568 PetscErrorCode ierr; 7569 7570 PetscFunctionBegin; 7571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7572 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7573 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7574 PetscFunctionReturn(0); 7575 } 7576 7577 /*@C 7578 DMGetBoundary - Get a model boundary condition 7579 7580 Input Parameters: 7581 + dm - The mesh object 7582 - bd - The BC number 7583 7584 Output Parameters: 7585 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7586 . name - The BC name 7587 . labelname - The label defining constrained points 7588 . field - The field to constrain 7589 . numcomps - The number of constrained field components 7590 . comps - An array of constrained component numbers 7591 . bcFunc - A pointwise function giving boundary values 7592 . numids - The number of DMLabel ids for constrained points 7593 . ids - An array of ids for constrained points 7594 - ctx - An optional user context for bcFunc 7595 7596 Options Database Keys: 7597 + -bc_<boundary name> <num> - Overrides the boundary ids 7598 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7599 7600 Level: developer 7601 7602 .seealso: DMAddBoundary() 7603 @*/ 7604 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) 7605 { 7606 PetscDS ds; 7607 PetscErrorCode ierr; 7608 7609 PetscFunctionBegin; 7610 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7611 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7612 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, numids, ids, ctx);CHKERRQ(ierr); 7613 PetscFunctionReturn(0); 7614 } 7615 7616 static PetscErrorCode DMPopulateBoundary(DM dm) 7617 { 7618 PetscDS ds; 7619 DMBoundary *lastnext; 7620 DSBoundary dsbound; 7621 PetscErrorCode ierr; 7622 7623 PetscFunctionBegin; 7624 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7625 dsbound = ds->boundary; 7626 if (dm->boundary) { 7627 DMBoundary next = dm->boundary; 7628 7629 /* quick check to see if the PetscDS has changed */ 7630 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 7631 /* the PetscDS has changed: tear down and rebuild */ 7632 while (next) { 7633 DMBoundary b = next; 7634 7635 next = b->next; 7636 ierr = PetscFree(b);CHKERRQ(ierr); 7637 } 7638 dm->boundary = NULL; 7639 } 7640 7641 lastnext = &(dm->boundary); 7642 while (dsbound) { 7643 DMBoundary dmbound; 7644 7645 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 7646 dmbound->dsboundary = dsbound; 7647 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 7648 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 7649 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 7650 *lastnext = dmbound; 7651 lastnext = &(dmbound->next); 7652 dsbound = dsbound->next; 7653 } 7654 PetscFunctionReturn(0); 7655 } 7656 7657 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 7658 { 7659 DMBoundary b; 7660 PetscErrorCode ierr; 7661 7662 PetscFunctionBegin; 7663 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7664 PetscValidBoolPointer(isBd, 3); 7665 *isBd = PETSC_FALSE; 7666 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 7667 b = dm->boundary; 7668 while (b && !(*isBd)) { 7669 DMLabel label = b->label; 7670 DSBoundary dsb = b->dsboundary; 7671 7672 if (label) { 7673 PetscInt i; 7674 7675 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 7676 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 7677 } 7678 } 7679 b = b->next; 7680 } 7681 PetscFunctionReturn(0); 7682 } 7683 7684 /*@C 7685 DMProjectFunction - This projects the given function into the function space provided. 7686 7687 Input Parameters: 7688 + dm - The DM 7689 . time - The time 7690 . funcs - The coordinate functions to evaluate, one per field 7691 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7692 - mode - The insertion mode for values 7693 7694 Output Parameter: 7695 . X - vector 7696 7697 Calling sequence of func: 7698 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7699 7700 + dim - The spatial dimension 7701 . x - The coordinates 7702 . Nf - The number of fields 7703 . u - The output field values 7704 - ctx - optional user-defined function context 7705 7706 Level: developer 7707 7708 .seealso: DMComputeL2Diff() 7709 @*/ 7710 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 7711 { 7712 Vec localX; 7713 PetscErrorCode ierr; 7714 7715 PetscFunctionBegin; 7716 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7717 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7718 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7719 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7720 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7721 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7722 PetscFunctionReturn(0); 7723 } 7724 7725 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 7726 { 7727 PetscErrorCode ierr; 7728 7729 PetscFunctionBegin; 7730 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7731 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7732 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 7733 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7734 PetscFunctionReturn(0); 7735 } 7736 7737 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) 7738 { 7739 Vec localX; 7740 PetscErrorCode ierr; 7741 7742 PetscFunctionBegin; 7743 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7744 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7745 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7746 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7747 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7748 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7749 PetscFunctionReturn(0); 7750 } 7751 7752 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) 7753 { 7754 PetscErrorCode ierr; 7755 7756 PetscFunctionBegin; 7757 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7758 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7759 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 7760 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7761 PetscFunctionReturn(0); 7762 } 7763 7764 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 7765 void (**funcs)(PetscInt, PetscInt, PetscInt, 7766 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7767 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7768 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7769 InsertMode mode, Vec localX) 7770 { 7771 PetscErrorCode ierr; 7772 7773 PetscFunctionBegin; 7774 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7775 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 7776 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 7777 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7778 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 7779 PetscFunctionReturn(0); 7780 } 7781 7782 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 7783 void (**funcs)(PetscInt, PetscInt, PetscInt, 7784 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7785 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7786 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7787 InsertMode mode, Vec localX) 7788 { 7789 PetscErrorCode ierr; 7790 7791 PetscFunctionBegin; 7792 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7793 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 7794 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 7795 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7796 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 7797 PetscFunctionReturn(0); 7798 } 7799 7800 /*@C 7801 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 7802 7803 Input Parameters: 7804 + dm - The DM 7805 . time - The time 7806 . funcs - The functions to evaluate for each field component 7807 . ctxs - Optional array of contexts to pass to each function, or NULL. 7808 - X - The coefficient vector u_h, a global vector 7809 7810 Output Parameter: 7811 . diff - The diff ||u - u_h||_2 7812 7813 Level: developer 7814 7815 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7816 @*/ 7817 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 7818 { 7819 PetscErrorCode ierr; 7820 7821 PetscFunctionBegin; 7822 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7823 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7824 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 7825 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7826 PetscFunctionReturn(0); 7827 } 7828 7829 /*@C 7830 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 7831 7832 Collective on dm 7833 7834 Input Parameters: 7835 + dm - The DM 7836 , time - The time 7837 . funcs - The gradient functions to evaluate for each field component 7838 . ctxs - Optional array of contexts to pass to each function, or NULL. 7839 . X - The coefficient vector u_h, a global vector 7840 - n - The vector to project along 7841 7842 Output Parameter: 7843 . diff - The diff ||(grad u - grad u_h) . n||_2 7844 7845 Level: developer 7846 7847 .seealso: DMProjectFunction(), DMComputeL2Diff() 7848 @*/ 7849 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) 7850 { 7851 PetscErrorCode ierr; 7852 7853 PetscFunctionBegin; 7854 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7855 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7856 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 7857 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 7858 PetscFunctionReturn(0); 7859 } 7860 7861 /*@C 7862 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 7863 7864 Collective on dm 7865 7866 Input Parameters: 7867 + dm - The DM 7868 . time - The time 7869 . funcs - The functions to evaluate for each field component 7870 . ctxs - Optional array of contexts to pass to each function, or NULL. 7871 - X - The coefficient vector u_h, a global vector 7872 7873 Output Parameter: 7874 . diff - The array of differences, ||u^f - u^f_h||_2 7875 7876 Level: developer 7877 7878 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7879 @*/ 7880 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 7881 { 7882 PetscErrorCode ierr; 7883 7884 PetscFunctionBegin; 7885 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7886 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7887 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 7888 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7889 PetscFunctionReturn(0); 7890 } 7891 7892 /*@C 7893 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 7894 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 7895 7896 Collective on dm 7897 7898 Input parameters: 7899 + dm - the pre-adaptation DM object 7900 - label - label with the flags 7901 7902 Output parameters: 7903 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 7904 7905 Level: intermediate 7906 7907 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 7908 @*/ 7909 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 7910 { 7911 PetscErrorCode ierr; 7912 7913 PetscFunctionBegin; 7914 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7915 PetscValidPointer(label,2); 7916 PetscValidPointer(dmAdapt,3); 7917 *dmAdapt = NULL; 7918 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 7919 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 7920 PetscFunctionReturn(0); 7921 } 7922 7923 /*@C 7924 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 7925 7926 Input Parameters: 7927 + dm - The DM object 7928 . metric - The metric to which the mesh is adapted, defined vertex-wise. 7929 - 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_". 7930 7931 Output Parameter: 7932 . dmAdapt - Pointer to the DM object containing the adapted mesh 7933 7934 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 7935 7936 Level: advanced 7937 7938 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 7939 @*/ 7940 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 7941 { 7942 PetscErrorCode ierr; 7943 7944 PetscFunctionBegin; 7945 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7946 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 7947 if (bdLabel) PetscValidPointer(bdLabel, 3); 7948 PetscValidPointer(dmAdapt, 4); 7949 *dmAdapt = NULL; 7950 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 7951 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 7952 PetscFunctionReturn(0); 7953 } 7954 7955 /*@C 7956 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 7957 7958 Not Collective 7959 7960 Input Parameter: 7961 . dm - The DM 7962 7963 Output Parameter: 7964 . nranks - the number of neighbours 7965 . ranks - the neighbors ranks 7966 7967 Notes: 7968 Do not free the array, it is freed when the DM is destroyed. 7969 7970 Level: beginner 7971 7972 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 7973 @*/ 7974 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 7975 { 7976 PetscErrorCode ierr; 7977 7978 PetscFunctionBegin; 7979 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7980 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 7981 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 7982 PetscFunctionReturn(0); 7983 } 7984 7985 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 7986 7987 /* 7988 Converts the input vector to a ghosted vector and then calls the standard coloring code. 7989 This has be a different function because it requires DM which is not defined in the Mat library 7990 */ 7991 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 7992 { 7993 PetscErrorCode ierr; 7994 7995 PetscFunctionBegin; 7996 if (coloring->ctype == IS_COLORING_LOCAL) { 7997 Vec x1local; 7998 DM dm; 7999 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8000 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 8001 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 8002 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8003 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8004 x1 = x1local; 8005 } 8006 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 8007 if (coloring->ctype == IS_COLORING_LOCAL) { 8008 DM dm; 8009 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8010 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 8011 } 8012 PetscFunctionReturn(0); 8013 } 8014 8015 /*@ 8016 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 8017 8018 Input Parameter: 8019 . coloring - the MatFDColoring object 8020 8021 Developer Notes: 8022 this routine exists because the PETSc Mat library does not know about the DM objects 8023 8024 Level: advanced 8025 8026 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 8027 @*/ 8028 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 8029 { 8030 PetscFunctionBegin; 8031 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 8032 PetscFunctionReturn(0); 8033 } 8034 8035 /*@ 8036 DMGetCompatibility - determine if two DMs are compatible 8037 8038 Collective 8039 8040 Input Parameters: 8041 + dm - the first DM 8042 - dm2 - the second DM 8043 8044 Output Parameters: 8045 + compatible - whether or not the two DMs are compatible 8046 - set - whether or not the compatible value was set 8047 8048 Notes: 8049 Two DMs are deemed compatible if they represent the same parallel decomposition 8050 of the same topology. This implies that the section (field data) on one 8051 "makes sense" with respect to the topology and parallel decomposition of the other. 8052 Loosely speaking, compatible DMs represent the same domain and parallel 8053 decomposition, but hold different data. 8054 8055 Typically, one would confirm compatibility if intending to simultaneously iterate 8056 over a pair of vectors obtained from different DMs. 8057 8058 For example, two DMDA objects are compatible if they have the same local 8059 and global sizes and the same stencil width. They can have different numbers 8060 of degrees of freedom per node. Thus, one could use the node numbering from 8061 either DM in bounds for a loop over vectors derived from either DM. 8062 8063 Consider the operation of summing data living on a 2-dof DMDA to data living 8064 on a 1-dof DMDA, which should be compatible, as in the following snippet. 8065 .vb 8066 ... 8067 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 8068 if (set && compatible) { 8069 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8070 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8071 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 8072 for (j=y; j<y+n; ++j) { 8073 for (i=x; i<x+m, ++i) { 8074 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 8075 } 8076 } 8077 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8078 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8079 } else { 8080 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 8081 } 8082 ... 8083 .ve 8084 8085 Checking compatibility might be expensive for a given implementation of DM, 8086 or might be impossible to unambiguously confirm or deny. For this reason, 8087 this function may decline to determine compatibility, and hence users should 8088 always check the "set" output parameter. 8089 8090 A DM is always compatible with itself. 8091 8092 In the current implementation, DMs which live on "unequal" communicators 8093 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 8094 incompatible. 8095 8096 This function is labeled "Collective," as information about all subdomains 8097 is required on each rank. However, in DM implementations which store all this 8098 information locally, this function may be merely "Logically Collective". 8099 8100 Developer Notes: 8101 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 8102 iff B is compatible with A. Thus, this function checks the implementations 8103 of both dm and dm2 (if they are of different types), attempting to determine 8104 compatibility. It is left to DM implementers to ensure that symmetry is 8105 preserved. The simplest way to do this is, when implementing type-specific 8106 logic for this function, is to check for existing logic in the implementation 8107 of other DM types and let *set = PETSC_FALSE if found. 8108 8109 Level: advanced 8110 8111 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 8112 @*/ 8113 8114 PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set) 8115 { 8116 PetscErrorCode ierr; 8117 PetscMPIInt compareResult; 8118 DMType type,type2; 8119 PetscBool sameType; 8120 8121 PetscFunctionBegin; 8122 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8123 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 8124 8125 /* Declare a DM compatible with itself */ 8126 if (dm == dm2) { 8127 *set = PETSC_TRUE; 8128 *compatible = PETSC_TRUE; 8129 PetscFunctionReturn(0); 8130 } 8131 8132 /* Declare a DM incompatible with a DM that lives on an "unequal" 8133 communicator. Note that this does not preclude compatibility with 8134 DMs living on "congruent" or "similar" communicators, but this must be 8135 determined by the implementation-specific logic */ 8136 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 8137 if (compareResult == MPI_UNEQUAL) { 8138 *set = PETSC_TRUE; 8139 *compatible = PETSC_FALSE; 8140 PetscFunctionReturn(0); 8141 } 8142 8143 /* Pass to the implementation-specific routine, if one exists. */ 8144 if (dm->ops->getcompatibility) { 8145 ierr = (*dm->ops->getcompatibility)(dm,dm2,compatible,set);CHKERRQ(ierr); 8146 if (*set) PetscFunctionReturn(0); 8147 } 8148 8149 /* If dm and dm2 are of different types, then attempt to check compatibility 8150 with an implementation of this function from dm2 */ 8151 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 8152 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 8153 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 8154 if (!sameType && dm2->ops->getcompatibility) { 8155 ierr = (*dm2->ops->getcompatibility)(dm2,dm,compatible,set);CHKERRQ(ierr); /* Note argument order */ 8156 } else { 8157 *set = PETSC_FALSE; 8158 } 8159 PetscFunctionReturn(0); 8160 } 8161 8162 /*@C 8163 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 8164 8165 Logically Collective on DM 8166 8167 Input Parameters: 8168 + DM - the DM 8169 . f - the monitor function 8170 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 8171 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 8172 8173 Options Database Keys: 8174 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 8175 does not cancel those set via the options database. 8176 8177 Notes: 8178 Several different monitoring routines may be set by calling 8179 DMMonitorSet() multiple times; all will be called in the 8180 order in which they were set. 8181 8182 Fortran Notes: 8183 Only a single monitor function can be set for each DM object 8184 8185 Level: intermediate 8186 8187 .seealso: DMMonitorCancel() 8188 @*/ 8189 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 8190 { 8191 PetscInt m; 8192 PetscErrorCode ierr; 8193 8194 PetscFunctionBegin; 8195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8196 for (m = 0; m < dm->numbermonitors; ++m) { 8197 PetscBool identical; 8198 8199 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 8200 if (identical) PetscFunctionReturn(0); 8201 } 8202 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 8203 dm->monitor[dm->numbermonitors] = f; 8204 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 8205 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 8206 PetscFunctionReturn(0); 8207 } 8208 8209 /*@ 8210 DMMonitorCancel - Clears all the monitor functions for a DM object. 8211 8212 Logically Collective on DM 8213 8214 Input Parameter: 8215 . dm - the DM 8216 8217 Options Database Key: 8218 . -dm_monitor_cancel - cancels all monitors that have been hardwired 8219 into a code by calls to DMonitorSet(), but does not cancel those 8220 set via the options database 8221 8222 Notes: 8223 There is no way to clear one specific monitor from a DM object. 8224 8225 Level: intermediate 8226 8227 .seealso: DMMonitorSet() 8228 @*/ 8229 PetscErrorCode DMMonitorCancel(DM dm) 8230 { 8231 PetscErrorCode ierr; 8232 PetscInt m; 8233 8234 PetscFunctionBegin; 8235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8236 for (m = 0; m < dm->numbermonitors; ++m) { 8237 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 8238 } 8239 dm->numbermonitors = 0; 8240 PetscFunctionReturn(0); 8241 } 8242 8243 /*@C 8244 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 8245 8246 Collective on DM 8247 8248 Input Parameters: 8249 + dm - DM object you wish to monitor 8250 . name - the monitor type one is seeking 8251 . help - message indicating what monitoring is done 8252 . manual - manual page for the monitor 8253 . monitor - the monitor function 8254 - 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 8255 8256 Output Parameter: 8257 . flg - Flag set if the monitor was created 8258 8259 Level: developer 8260 8261 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 8262 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 8263 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 8264 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 8265 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 8266 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 8267 PetscOptionsFList(), PetscOptionsEList() 8268 @*/ 8269 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 8270 { 8271 PetscViewer viewer; 8272 PetscViewerFormat format; 8273 PetscErrorCode ierr; 8274 8275 PetscFunctionBegin; 8276 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8277 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 8278 if (*flg) { 8279 PetscViewerAndFormat *vf; 8280 8281 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 8282 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 8283 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 8284 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 8285 } 8286 PetscFunctionReturn(0); 8287 } 8288 8289 /*@ 8290 DMMonitor - runs the user provided monitor routines, if they exist 8291 8292 Collective on DM 8293 8294 Input Parameters: 8295 . dm - The DM 8296 8297 Level: developer 8298 8299 .seealso: DMMonitorSet() 8300 @*/ 8301 PetscErrorCode DMMonitor(DM dm) 8302 { 8303 PetscInt m; 8304 PetscErrorCode ierr; 8305 8306 PetscFunctionBegin; 8307 if (!dm) PetscFunctionReturn(0); 8308 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8309 for (m = 0; m < dm->numbermonitors; ++m) { 8310 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 8311 } 8312 PetscFunctionReturn(0); 8313 } 8314