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