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