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