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