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