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