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