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