1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 2 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 3 #include <petscsf.h> 4 #include <petscds.h> 5 6 PetscClassId DM_CLASSID; 7 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_CreateInterpolation; 8 9 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0}; 10 11 #undef __FUNCT__ 12 #define __FUNCT__ "DMCreate" 13 /*@ 14 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 15 16 If you never call DMSetType() it will generate an 17 error when you try to use the vector. 18 19 Collective on MPI_Comm 20 21 Input Parameter: 22 . comm - The communicator for the DM object 23 24 Output Parameter: 25 . dm - The DM object 26 27 Level: beginner 28 29 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK 30 @*/ 31 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 32 { 33 DM v; 34 PetscErrorCode ierr; 35 36 PetscFunctionBegin; 37 PetscValidPointer(dm,2); 38 *dm = NULL; 39 ierr = PetscSysInitializePackage();CHKERRQ(ierr); 40 ierr = VecInitializePackage();CHKERRQ(ierr); 41 ierr = MatInitializePackage();CHKERRQ(ierr); 42 ierr = DMInitializePackage();CHKERRQ(ierr); 43 44 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 45 46 v->ltogmap = NULL; 47 v->bs = 1; 48 v->coloringtype = IS_COLORING_GLOBAL; 49 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 50 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 51 v->labels = NULL; 52 v->depthLabel = NULL; 53 v->defaultSection = NULL; 54 v->defaultGlobalSection = NULL; 55 v->defaultConstraintSection = NULL; 56 v->defaultConstraintMat = NULL; 57 v->L = NULL; 58 v->maxCell = NULL; 59 v->bdtype = NULL; 60 v->dimEmbed = PETSC_DEFAULT; 61 { 62 PetscInt i; 63 for (i = 0; i < 10; ++i) { 64 v->nullspaceConstructors[i] = NULL; 65 } 66 } 67 ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr); 68 v->dmBC = NULL; 69 v->outputSequenceNum = -1; 70 v->outputSequenceVal = 0.0; 71 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 72 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 73 ierr = PetscCalloc1(1,&(v->labels));CHKERRQ(ierr); 74 v->labels->refct = 1; 75 *dm = v; 76 PetscFunctionReturn(0); 77 } 78 79 #undef __FUNCT__ 80 #define __FUNCT__ "DMClone" 81 /*@ 82 DMClone - Creates a DM object with the same topology as the original. 83 84 Collective on MPI_Comm 85 86 Input Parameter: 87 . dm - The original DM object 88 89 Output Parameter: 90 . newdm - The new DM object 91 92 Level: beginner 93 94 .keywords: DM, topology, create 95 @*/ 96 PetscErrorCode DMClone(DM dm, DM *newdm) 97 { 98 PetscSF sf; 99 Vec coords; 100 void *ctx; 101 PetscInt dim; 102 PetscErrorCode ierr; 103 104 PetscFunctionBegin; 105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 106 PetscValidPointer(newdm,2); 107 ierr = DMCreate(PetscObjectComm((PetscObject)dm), newdm);CHKERRQ(ierr); 108 ierr = PetscFree((*newdm)->labels);CHKERRQ(ierr); 109 dm->labels->refct++; 110 (*newdm)->labels = dm->labels; 111 (*newdm)->depthLabel = dm->depthLabel; 112 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 113 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr); 114 if (dm->ops->clone) { 115 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 116 } 117 (*newdm)->setupcalled = PETSC_TRUE; 118 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 119 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 120 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 121 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 122 if (dm->coordinateDM) { 123 DM ncdm; 124 PetscSection cs; 125 PetscInt pEnd = -1; 126 127 ierr = DMGetDefaultSection(dm->coordinateDM, &cs);CHKERRQ(ierr); 128 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);} 129 if (pEnd >= 0) { 130 ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr); 131 ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr); 132 ierr = DMSetDefaultSection(ncdm, cs);CHKERRQ(ierr); 133 ierr = DMDestroy(&ncdm);CHKERRQ(ierr); 134 } 135 } 136 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 137 if (coords) { 138 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 139 } else { 140 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 141 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 142 } 143 if (dm->maxCell) { 144 const PetscReal *maxCell, *L; 145 const DMBoundaryType *bd; 146 ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr); 147 ierr = DMSetPeriodicity(*newdm, maxCell, L, bd);CHKERRQ(ierr); 148 } 149 PetscFunctionReturn(0); 150 } 151 152 #undef __FUNCT__ 153 #define __FUNCT__ "DMSetVecType" 154 /*@C 155 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 156 157 Logically Collective on DM 158 159 Input Parameter: 160 + da - initial distributed array 161 . ctype - the vector type, currently either VECSTANDARD or VECCUSP 162 163 Options Database: 164 . -dm_vec_type ctype 165 166 Level: intermediate 167 168 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType() 169 @*/ 170 PetscErrorCode DMSetVecType(DM da,VecType ctype) 171 { 172 PetscErrorCode ierr; 173 174 PetscFunctionBegin; 175 PetscValidHeaderSpecific(da,DM_CLASSID,1); 176 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 177 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 178 PetscFunctionReturn(0); 179 } 180 181 #undef __FUNCT__ 182 #define __FUNCT__ "DMGetVecType" 183 /*@C 184 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 185 186 Logically Collective on DM 187 188 Input Parameter: 189 . da - initial distributed array 190 191 Output Parameter: 192 . ctype - the vector type 193 194 Level: intermediate 195 196 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType 197 @*/ 198 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 199 { 200 PetscFunctionBegin; 201 PetscValidHeaderSpecific(da,DM_CLASSID,1); 202 *ctype = da->vectype; 203 PetscFunctionReturn(0); 204 } 205 206 #undef __FUNCT__ 207 #define __FUNCT__ "VecGetDM" 208 /*@ 209 VecGetDM - Gets the DM defining the data layout of the vector 210 211 Not collective 212 213 Input Parameter: 214 . v - The Vec 215 216 Output Parameter: 217 . dm - The DM 218 219 Level: intermediate 220 221 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 222 @*/ 223 PetscErrorCode VecGetDM(Vec v, DM *dm) 224 { 225 PetscErrorCode ierr; 226 227 PetscFunctionBegin; 228 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 229 PetscValidPointer(dm,2); 230 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 231 PetscFunctionReturn(0); 232 } 233 234 #undef __FUNCT__ 235 #define __FUNCT__ "VecSetDM" 236 /*@ 237 VecSetDM - Sets the DM defining the data layout of the vector. 238 239 Not collective 240 241 Input Parameters: 242 + v - The Vec 243 - dm - The DM 244 245 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. 246 247 Level: intermediate 248 249 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 250 @*/ 251 PetscErrorCode VecSetDM(Vec v, DM dm) 252 { 253 PetscErrorCode ierr; 254 255 PetscFunctionBegin; 256 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 257 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 258 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 259 PetscFunctionReturn(0); 260 } 261 262 #undef __FUNCT__ 263 #define __FUNCT__ "DMSetMatType" 264 /*@C 265 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 266 267 Logically Collective on DM 268 269 Input Parameter: 270 + dm - the DM context 271 . ctype - the matrix type 272 273 Options Database: 274 . -dm_mat_type ctype 275 276 Level: intermediate 277 278 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType() 279 @*/ 280 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 281 { 282 PetscErrorCode ierr; 283 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 286 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 287 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 288 PetscFunctionReturn(0); 289 } 290 291 #undef __FUNCT__ 292 #define __FUNCT__ "DMGetMatType" 293 /*@C 294 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 295 296 Logically Collective on DM 297 298 Input Parameter: 299 . dm - the DM context 300 301 Output Parameter: 302 . ctype - the matrix type 303 304 Options Database: 305 . -dm_mat_type ctype 306 307 Level: intermediate 308 309 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType() 310 @*/ 311 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 312 { 313 PetscFunctionBegin; 314 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 315 *ctype = dm->mattype; 316 PetscFunctionReturn(0); 317 } 318 319 #undef __FUNCT__ 320 #define __FUNCT__ "MatGetDM" 321 /*@ 322 MatGetDM - Gets the DM defining the data layout of the matrix 323 324 Not collective 325 326 Input Parameter: 327 . A - The Mat 328 329 Output Parameter: 330 . dm - The DM 331 332 Level: intermediate 333 334 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 335 @*/ 336 PetscErrorCode MatGetDM(Mat A, DM *dm) 337 { 338 PetscErrorCode ierr; 339 340 PetscFunctionBegin; 341 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 342 PetscValidPointer(dm,2); 343 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 344 PetscFunctionReturn(0); 345 } 346 347 #undef __FUNCT__ 348 #define __FUNCT__ "MatSetDM" 349 /*@ 350 MatSetDM - Sets the DM defining the data layout of the matrix 351 352 Not collective 353 354 Input Parameters: 355 + A - The Mat 356 - dm - The DM 357 358 Level: intermediate 359 360 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 361 @*/ 362 PetscErrorCode MatSetDM(Mat A, DM dm) 363 { 364 PetscErrorCode ierr; 365 366 PetscFunctionBegin; 367 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 368 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 369 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 370 PetscFunctionReturn(0); 371 } 372 373 #undef __FUNCT__ 374 #define __FUNCT__ "DMSetOptionsPrefix" 375 /*@C 376 DMSetOptionsPrefix - Sets the prefix used for searching for all 377 DM options in the database. 378 379 Logically Collective on DM 380 381 Input Parameter: 382 + da - the DM context 383 - prefix - the prefix to prepend to all option names 384 385 Notes: 386 A hyphen (-) must NOT be given at the beginning of the prefix name. 387 The first character of all runtime options is AUTOMATICALLY the hyphen. 388 389 Level: advanced 390 391 .keywords: DM, set, options, prefix, database 392 393 .seealso: DMSetFromOptions() 394 @*/ 395 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 396 { 397 PetscErrorCode ierr; 398 399 PetscFunctionBegin; 400 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 401 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 402 if (dm->sf) { 403 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr); 404 } 405 if (dm->defaultSF) { 406 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);CHKERRQ(ierr); 407 } 408 PetscFunctionReturn(0); 409 } 410 411 #undef __FUNCT__ 412 #define __FUNCT__ "DMAppendOptionsPrefix" 413 /*@C 414 DMAppendOptionsPrefix - Appends to the prefix used for searching for all 415 DM options in the database. 416 417 Logically Collective on DM 418 419 Input Parameters: 420 + dm - the DM context 421 - prefix - the prefix string to prepend to all DM option requests 422 423 Notes: 424 A hyphen (-) must NOT be given at the beginning of the prefix name. 425 The first character of all runtime options is AUTOMATICALLY the hyphen. 426 427 Level: advanced 428 429 .keywords: DM, append, options, prefix, database 430 431 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix() 432 @*/ 433 PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[]) 434 { 435 PetscErrorCode ierr; 436 437 PetscFunctionBegin; 438 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 439 ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 440 PetscFunctionReturn(0); 441 } 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "DMGetOptionsPrefix" 445 /*@C 446 DMGetOptionsPrefix - Gets the prefix used for searching for all 447 DM options in the database. 448 449 Not Collective 450 451 Input Parameters: 452 . dm - the DM context 453 454 Output Parameters: 455 . prefix - pointer to the prefix string used is returned 456 457 Notes: On the fortran side, the user should pass in a string 'prefix' of 458 sufficient length to hold the prefix. 459 460 Level: advanced 461 462 .keywords: DM, set, options, prefix, database 463 464 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix() 465 @*/ 466 PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[]) 467 { 468 PetscErrorCode ierr; 469 470 PetscFunctionBegin; 471 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 472 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 473 PetscFunctionReturn(0); 474 } 475 476 #undef __FUNCT__ 477 #define __FUNCT__ "DMDestroy" 478 /*@ 479 DMDestroy - Destroys a vector packer or DM. 480 481 Collective on DM 482 483 Input Parameter: 484 . dm - the DM object to destroy 485 486 Level: developer 487 488 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 489 490 @*/ 491 PetscErrorCode DMDestroy(DM *dm) 492 { 493 PetscInt i, cnt = 0; 494 DMNamedVecLink nlink,nnext; 495 PetscErrorCode ierr; 496 497 PetscFunctionBegin; 498 if (!*dm) PetscFunctionReturn(0); 499 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 500 501 /* count all the circular references of DM and its contained Vecs */ 502 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 503 if ((*dm)->localin[i]) cnt++; 504 if ((*dm)->globalin[i]) cnt++; 505 } 506 for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++; 507 for (nlink=(*dm)->namedlocal; nlink; nlink=nlink->next) cnt++; 508 if ((*dm)->x) { 509 DM obj; 510 ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr); 511 if (obj == *dm) cnt++; 512 } 513 514 if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 515 /* 516 Need this test because the dm references the vectors that 517 reference the dm, so destroying the dm calls destroy on the 518 vectors that cause another destroy on the dm 519 */ 520 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 521 ((PetscObject) (*dm))->refct = 0; 522 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 523 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 524 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 525 } 526 nnext=(*dm)->namedglobal; 527 (*dm)->namedglobal = NULL; 528 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 529 nnext = nlink->next; 530 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 531 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 532 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 533 ierr = PetscFree(nlink);CHKERRQ(ierr); 534 } 535 nnext=(*dm)->namedlocal; 536 (*dm)->namedlocal = NULL; 537 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 538 nnext = nlink->next; 539 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 540 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 541 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 542 ierr = PetscFree(nlink);CHKERRQ(ierr); 543 } 544 545 /* Destroy the list of hooks */ 546 { 547 DMCoarsenHookLink link,next; 548 for (link=(*dm)->coarsenhook; link; link=next) { 549 next = link->next; 550 ierr = PetscFree(link);CHKERRQ(ierr); 551 } 552 (*dm)->coarsenhook = NULL; 553 } 554 { 555 DMRefineHookLink link,next; 556 for (link=(*dm)->refinehook; link; link=next) { 557 next = link->next; 558 ierr = PetscFree(link);CHKERRQ(ierr); 559 } 560 (*dm)->refinehook = NULL; 561 } 562 { 563 DMSubDomainHookLink link,next; 564 for (link=(*dm)->subdomainhook; link; link=next) { 565 next = link->next; 566 ierr = PetscFree(link);CHKERRQ(ierr); 567 } 568 (*dm)->subdomainhook = NULL; 569 } 570 { 571 DMGlobalToLocalHookLink link,next; 572 for (link=(*dm)->gtolhook; link; link=next) { 573 next = link->next; 574 ierr = PetscFree(link);CHKERRQ(ierr); 575 } 576 (*dm)->gtolhook = NULL; 577 } 578 { 579 DMLocalToGlobalHookLink link,next; 580 for (link=(*dm)->ltoghook; link; link=next) { 581 next = link->next; 582 ierr = PetscFree(link);CHKERRQ(ierr); 583 } 584 (*dm)->ltoghook = NULL; 585 } 586 /* Destroy the work arrays */ 587 { 588 DMWorkLink link,next; 589 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 590 for (link=(*dm)->workin; link; link=next) { 591 next = link->next; 592 ierr = PetscFree(link->mem);CHKERRQ(ierr); 593 ierr = PetscFree(link);CHKERRQ(ierr); 594 } 595 (*dm)->workin = NULL; 596 } 597 if (!--((*dm)->labels->refct)) { 598 DMLabelLink next = (*dm)->labels->next; 599 600 /* destroy the labels */ 601 while (next) { 602 DMLabelLink tmp = next->next; 603 604 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 605 ierr = PetscFree(next);CHKERRQ(ierr); 606 next = tmp; 607 } 608 ierr = PetscFree((*dm)->labels);CHKERRQ(ierr); 609 } 610 611 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 612 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 613 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 614 615 if ((*dm)->ctx && (*dm)->ctxdestroy) { 616 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 617 } 618 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 619 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 620 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 621 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 622 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 623 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 624 625 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 626 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 627 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 628 ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr); 629 ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr); 630 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 631 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 632 ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr); 633 634 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 635 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 636 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 637 ierr = PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);CHKERRQ(ierr); 638 639 ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr); 640 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 641 /* if memory was published with SAWs then destroy it */ 642 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 643 644 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 645 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 646 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 647 PetscFunctionReturn(0); 648 } 649 650 #undef __FUNCT__ 651 #define __FUNCT__ "DMSetUp" 652 /*@ 653 DMSetUp - sets up the data structures inside a DM object 654 655 Collective on DM 656 657 Input Parameter: 658 . dm - the DM object to setup 659 660 Level: developer 661 662 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 663 664 @*/ 665 PetscErrorCode DMSetUp(DM dm) 666 { 667 PetscErrorCode ierr; 668 669 PetscFunctionBegin; 670 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 671 if (dm->setupcalled) PetscFunctionReturn(0); 672 if (dm->ops->setup) { 673 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 674 } 675 dm->setupcalled = PETSC_TRUE; 676 PetscFunctionReturn(0); 677 } 678 679 #undef __FUNCT__ 680 #define __FUNCT__ "DMSetFromOptions" 681 /*@ 682 DMSetFromOptions - sets parameters in a DM from the options database 683 684 Collective on DM 685 686 Input Parameter: 687 . dm - the DM object to set options for 688 689 Options Database: 690 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 691 . -dm_vec_type <type> - type of vector to create inside DM 692 . -dm_mat_type <type> - type of matrix to create inside DM 693 - -dm_coloring_type - <global or ghosted> 694 695 Level: developer 696 697 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 698 699 @*/ 700 PetscErrorCode DMSetFromOptions(DM dm) 701 { 702 char typeName[256]; 703 PetscBool flg; 704 PetscErrorCode ierr; 705 706 PetscFunctionBegin; 707 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 708 if (dm->sf) { 709 ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr); 710 } 711 if (dm->defaultSF) { 712 ierr = PetscSFSetFromOptions(dm->defaultSF);CHKERRQ(ierr); 713 } 714 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 715 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 716 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 717 if (flg) { 718 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 719 } 720 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 721 if (flg) { 722 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 723 } 724 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 725 if (dm->ops->setfromoptions) { 726 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr); 727 } 728 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 729 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr); 730 ierr = PetscOptionsEnd();CHKERRQ(ierr); 731 PetscFunctionReturn(0); 732 } 733 734 #undef __FUNCT__ 735 #define __FUNCT__ "DMView" 736 /*@C 737 DMView - Views a DM 738 739 Collective on DM 740 741 Input Parameter: 742 + dm - the DM object to view 743 - v - the viewer 744 745 Level: beginner 746 747 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 748 749 @*/ 750 PetscErrorCode DMView(DM dm,PetscViewer v) 751 { 752 PetscErrorCode ierr; 753 PetscBool isbinary; 754 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 757 if (!v) { 758 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 759 } 760 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 761 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 762 if (isbinary) { 763 PetscInt classid = DM_FILE_CLASSID; 764 char type[256]; 765 766 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 767 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 768 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 769 } 770 if (dm->ops->view) { 771 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 772 } 773 PetscFunctionReturn(0); 774 } 775 776 #undef __FUNCT__ 777 #define __FUNCT__ "DMCreateGlobalVector" 778 /*@ 779 DMCreateGlobalVector - Creates a global vector from a DM object 780 781 Collective on DM 782 783 Input Parameter: 784 . dm - the DM object 785 786 Output Parameter: 787 . vec - the global vector 788 789 Level: beginner 790 791 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 792 793 @*/ 794 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 795 { 796 PetscErrorCode ierr; 797 798 PetscFunctionBegin; 799 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 800 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 801 PetscFunctionReturn(0); 802 } 803 804 #undef __FUNCT__ 805 #define __FUNCT__ "DMCreateLocalVector" 806 /*@ 807 DMCreateLocalVector - Creates a local vector from a DM object 808 809 Not Collective 810 811 Input Parameter: 812 . dm - the DM object 813 814 Output Parameter: 815 . vec - the local vector 816 817 Level: beginner 818 819 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 820 821 @*/ 822 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 823 { 824 PetscErrorCode ierr; 825 826 PetscFunctionBegin; 827 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 828 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 829 PetscFunctionReturn(0); 830 } 831 832 #undef __FUNCT__ 833 #define __FUNCT__ "DMGetLocalToGlobalMapping" 834 /*@ 835 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 836 837 Collective on DM 838 839 Input Parameter: 840 . dm - the DM that provides the mapping 841 842 Output Parameter: 843 . ltog - the mapping 844 845 Level: intermediate 846 847 Notes: 848 This mapping can then be used by VecSetLocalToGlobalMapping() or 849 MatSetLocalToGlobalMapping(). 850 851 .seealso: DMCreateLocalVector() 852 @*/ 853 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 854 { 855 PetscErrorCode ierr; 856 857 PetscFunctionBegin; 858 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 859 PetscValidPointer(ltog,2); 860 if (!dm->ltogmap) { 861 PetscSection section, sectionGlobal; 862 863 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 864 if (section) { 865 PetscInt *ltog; 866 PetscInt pStart, pEnd, size, p, l; 867 868 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 869 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 870 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 871 ierr = PetscMalloc1(size, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 872 for (p = pStart, l = 0; p < pEnd; ++p) { 873 PetscInt dof, off, c; 874 875 /* Should probably use constrained dofs */ 876 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 877 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 878 for (c = 0; c < dof; ++c, ++l) { 879 ltog[l] = off+c; 880 } 881 } 882 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 883 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 884 } else { 885 if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 886 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 887 } 888 } 889 *ltog = dm->ltogmap; 890 PetscFunctionReturn(0); 891 } 892 893 #undef __FUNCT__ 894 #define __FUNCT__ "DMGetBlockSize" 895 /*@ 896 DMGetBlockSize - Gets the inherent block size associated with a DM 897 898 Not Collective 899 900 Input Parameter: 901 . dm - the DM with block structure 902 903 Output Parameter: 904 . bs - the block size, 1 implies no exploitable block structure 905 906 Level: intermediate 907 908 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 909 @*/ 910 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 911 { 912 PetscFunctionBegin; 913 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 914 PetscValidPointer(bs,2); 915 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 916 *bs = dm->bs; 917 PetscFunctionReturn(0); 918 } 919 920 #undef __FUNCT__ 921 #define __FUNCT__ "DMCreateInterpolation" 922 /*@ 923 DMCreateInterpolation - Gets interpolation matrix between two DM objects 924 925 Collective on DM 926 927 Input Parameter: 928 + dm1 - the DM object 929 - dm2 - the second, finer DM object 930 931 Output Parameter: 932 + mat - the interpolation 933 - vec - the scaling (optional) 934 935 Level: developer 936 937 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 938 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 939 940 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 941 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 942 943 944 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen() 945 946 @*/ 947 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 948 { 949 PetscErrorCode ierr; 950 951 PetscFunctionBegin; 952 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 953 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 954 ierr = PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr); 955 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 956 ierr = PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr); 957 PetscFunctionReturn(0); 958 } 959 960 #undef __FUNCT__ 961 #define __FUNCT__ "DMCreateInjection" 962 /*@ 963 DMCreateInjection - Gets injection matrix between two DM objects 964 965 Collective on DM 966 967 Input Parameter: 968 + dm1 - the DM object 969 - dm2 - the second, finer DM object 970 971 Output Parameter: 972 . mat - the injection 973 974 Level: developer 975 976 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 977 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 978 979 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 980 981 @*/ 982 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat) 983 { 984 PetscErrorCode ierr; 985 986 PetscFunctionBegin; 987 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 988 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 989 ierr = (*dm1->ops->getinjection)(dm1,dm2,mat);CHKERRQ(ierr); 990 PetscFunctionReturn(0); 991 } 992 993 #undef __FUNCT__ 994 #define __FUNCT__ "DMCreateColoring" 995 /*@ 996 DMCreateColoring - Gets coloring for a DM 997 998 Collective on DM 999 1000 Input Parameter: 1001 + dm - the DM object 1002 - ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL 1003 1004 Output Parameter: 1005 . coloring - the coloring 1006 1007 Level: developer 1008 1009 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType() 1010 1011 @*/ 1012 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 1013 { 1014 PetscErrorCode ierr; 1015 1016 PetscFunctionBegin; 1017 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1018 if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet"); 1019 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 1020 PetscFunctionReturn(0); 1021 } 1022 1023 #undef __FUNCT__ 1024 #define __FUNCT__ "DMCreateMatrix" 1025 /*@ 1026 DMCreateMatrix - Gets empty Jacobian for a DM 1027 1028 Collective on DM 1029 1030 Input Parameter: 1031 . dm - the DM object 1032 1033 Output Parameter: 1034 . mat - the empty Jacobian 1035 1036 Level: beginner 1037 1038 Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 1039 do not need to do it yourself. 1040 1041 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 1042 the nonzero pattern call DMDASetMatPreallocateOnly() 1043 1044 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 1045 internally by PETSc. 1046 1047 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 1048 the indices for the global numbering for DMDAs which is complicated. 1049 1050 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 1051 1052 @*/ 1053 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 1054 { 1055 PetscErrorCode ierr; 1056 1057 PetscFunctionBegin; 1058 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1059 ierr = MatInitializePackage();CHKERRQ(ierr); 1060 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1061 PetscValidPointer(mat,3); 1062 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 1063 PetscFunctionReturn(0); 1064 } 1065 1066 #undef __FUNCT__ 1067 #define __FUNCT__ "DMSetMatrixPreallocateOnly" 1068 /*@ 1069 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 1070 preallocated but the nonzero structure and zero values will not be set. 1071 1072 Logically Collective on DM 1073 1074 Input Parameter: 1075 + dm - the DM 1076 - only - PETSC_TRUE if only want preallocation 1077 1078 Level: developer 1079 .seealso DMCreateMatrix() 1080 @*/ 1081 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 1082 { 1083 PetscFunctionBegin; 1084 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1085 dm->prealloc_only = only; 1086 PetscFunctionReturn(0); 1087 } 1088 1089 #undef __FUNCT__ 1090 #define __FUNCT__ "DMGetWorkArray" 1091 /*@C 1092 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1093 1094 Not Collective 1095 1096 Input Parameters: 1097 + dm - the DM object 1098 . count - The minium size 1099 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1100 1101 Output Parameter: 1102 . array - the work array 1103 1104 Level: developer 1105 1106 .seealso DMDestroy(), DMCreate() 1107 @*/ 1108 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1109 { 1110 PetscErrorCode ierr; 1111 DMWorkLink link; 1112 size_t dsize; 1113 1114 PetscFunctionBegin; 1115 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1116 PetscValidPointer(mem,4); 1117 if (dm->workin) { 1118 link = dm->workin; 1119 dm->workin = dm->workin->next; 1120 } else { 1121 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1122 } 1123 ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr); 1124 if (dsize*count > link->bytes) { 1125 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1126 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr); 1127 link->bytes = dsize*count; 1128 } 1129 link->next = dm->workout; 1130 dm->workout = link; 1131 *(void**)mem = link->mem; 1132 PetscFunctionReturn(0); 1133 } 1134 1135 #undef __FUNCT__ 1136 #define __FUNCT__ "DMRestoreWorkArray" 1137 /*@C 1138 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1139 1140 Not Collective 1141 1142 Input Parameters: 1143 + dm - the DM object 1144 . count - The minium size 1145 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1146 1147 Output Parameter: 1148 . array - the work array 1149 1150 Level: developer 1151 1152 .seealso DMDestroy(), DMCreate() 1153 @*/ 1154 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1155 { 1156 DMWorkLink *p,link; 1157 1158 PetscFunctionBegin; 1159 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1160 PetscValidPointer(mem,4); 1161 for (p=&dm->workout; (link=*p); p=&link->next) { 1162 if (link->mem == *(void**)mem) { 1163 *p = link->next; 1164 link->next = dm->workin; 1165 dm->workin = link; 1166 *(void**)mem = NULL; 1167 PetscFunctionReturn(0); 1168 } 1169 } 1170 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1171 } 1172 1173 #undef __FUNCT__ 1174 #define __FUNCT__ "DMSetNullSpaceConstructor" 1175 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1176 { 1177 PetscFunctionBegin; 1178 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1179 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1180 dm->nullspaceConstructors[field] = nullsp; 1181 PetscFunctionReturn(0); 1182 } 1183 1184 #undef __FUNCT__ 1185 #define __FUNCT__ "DMCreateFieldIS" 1186 /*@C 1187 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1188 1189 Not collective 1190 1191 Input Parameter: 1192 . dm - the DM object 1193 1194 Output Parameters: 1195 + numFields - The number of fields (or NULL if not requested) 1196 . fieldNames - The name for each field (or NULL if not requested) 1197 - fields - The global indices for each field (or NULL if not requested) 1198 1199 Level: intermediate 1200 1201 Notes: 1202 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1203 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1204 PetscFree(). 1205 1206 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1207 @*/ 1208 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1209 { 1210 PetscSection section, sectionGlobal; 1211 PetscErrorCode ierr; 1212 1213 PetscFunctionBegin; 1214 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1215 if (numFields) { 1216 PetscValidPointer(numFields,2); 1217 *numFields = 0; 1218 } 1219 if (fieldNames) { 1220 PetscValidPointer(fieldNames,3); 1221 *fieldNames = NULL; 1222 } 1223 if (fields) { 1224 PetscValidPointer(fields,4); 1225 *fields = NULL; 1226 } 1227 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1228 if (section) { 1229 PetscInt *fieldSizes, **fieldIndices; 1230 PetscInt nF, f, pStart, pEnd, p; 1231 1232 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1233 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1234 ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr); 1235 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1236 for (f = 0; f < nF; ++f) { 1237 fieldSizes[f] = 0; 1238 } 1239 for (p = pStart; p < pEnd; ++p) { 1240 PetscInt gdof; 1241 1242 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1243 if (gdof > 0) { 1244 for (f = 0; f < nF; ++f) { 1245 PetscInt fdof, fcdof; 1246 1247 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1248 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1249 fieldSizes[f] += fdof-fcdof; 1250 } 1251 } 1252 } 1253 for (f = 0; f < nF; ++f) { 1254 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1255 fieldSizes[f] = 0; 1256 } 1257 for (p = pStart; p < pEnd; ++p) { 1258 PetscInt gdof, goff; 1259 1260 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1261 if (gdof > 0) { 1262 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1263 for (f = 0; f < nF; ++f) { 1264 PetscInt fdof, fcdof, fc; 1265 1266 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1267 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1268 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1269 fieldIndices[f][fieldSizes[f]] = goff++; 1270 } 1271 } 1272 } 1273 } 1274 if (numFields) *numFields = nF; 1275 if (fieldNames) { 1276 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1277 for (f = 0; f < nF; ++f) { 1278 const char *fieldName; 1279 1280 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1281 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1282 } 1283 } 1284 if (fields) { 1285 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1286 for (f = 0; f < nF; ++f) { 1287 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1288 } 1289 } 1290 ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr); 1291 } else if (dm->ops->createfieldis) { 1292 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1293 } 1294 PetscFunctionReturn(0); 1295 } 1296 1297 1298 #undef __FUNCT__ 1299 #define __FUNCT__ "DMCreateFieldDecomposition" 1300 /*@C 1301 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1302 corresponding to different fields: each IS contains the global indices of the dofs of the 1303 corresponding field. The optional list of DMs define the DM for each subproblem. 1304 Generalizes DMCreateFieldIS(). 1305 1306 Not collective 1307 1308 Input Parameter: 1309 . dm - the DM object 1310 1311 Output Parameters: 1312 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1313 . namelist - The name for each field (or NULL if not requested) 1314 . islist - The global indices for each field (or NULL if not requested) 1315 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1316 1317 Level: intermediate 1318 1319 Notes: 1320 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1321 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1322 and all of the arrays should be freed with PetscFree(). 1323 1324 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1325 @*/ 1326 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1327 { 1328 PetscErrorCode ierr; 1329 1330 PetscFunctionBegin; 1331 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1332 if (len) { 1333 PetscValidPointer(len,2); 1334 *len = 0; 1335 } 1336 if (namelist) { 1337 PetscValidPointer(namelist,3); 1338 *namelist = 0; 1339 } 1340 if (islist) { 1341 PetscValidPointer(islist,4); 1342 *islist = 0; 1343 } 1344 if (dmlist) { 1345 PetscValidPointer(dmlist,5); 1346 *dmlist = 0; 1347 } 1348 /* 1349 Is it a good idea to apply the following check across all impls? 1350 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1351 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1352 */ 1353 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1354 if (!dm->ops->createfielddecomposition) { 1355 PetscSection section; 1356 PetscInt numFields, f; 1357 1358 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1359 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1360 if (section && numFields && dm->ops->createsubdm) { 1361 *len = numFields; 1362 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1363 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1364 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1365 for (f = 0; f < numFields; ++f) { 1366 const char *fieldName; 1367 1368 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1369 if (namelist) { 1370 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1371 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1372 } 1373 } 1374 } else { 1375 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1376 /* By default there are no DMs associated with subproblems. */ 1377 if (dmlist) *dmlist = NULL; 1378 } 1379 } else { 1380 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1381 } 1382 PetscFunctionReturn(0); 1383 } 1384 1385 #undef __FUNCT__ 1386 #define __FUNCT__ "DMCreateSubDM" 1387 /*@ 1388 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1389 The fields are defined by DMCreateFieldIS(). 1390 1391 Not collective 1392 1393 Input Parameters: 1394 + dm - the DM object 1395 . numFields - number of fields in this subproblem 1396 - len - The number of subproblems in the decomposition (or NULL if not requested) 1397 1398 Output Parameters: 1399 . is - The global indices for the subproblem 1400 - dm - The DM for the subproblem 1401 1402 Level: intermediate 1403 1404 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1405 @*/ 1406 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1407 { 1408 PetscErrorCode ierr; 1409 1410 PetscFunctionBegin; 1411 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1412 PetscValidPointer(fields,3); 1413 if (is) PetscValidPointer(is,4); 1414 if (subdm) PetscValidPointer(subdm,5); 1415 if (dm->ops->createsubdm) { 1416 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1417 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1418 PetscFunctionReturn(0); 1419 } 1420 1421 1422 #undef __FUNCT__ 1423 #define __FUNCT__ "DMCreateDomainDecomposition" 1424 /*@C 1425 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1426 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1427 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1428 define a nonoverlapping covering, while outer subdomains can overlap. 1429 The optional list of DMs define the DM for each subproblem. 1430 1431 Not collective 1432 1433 Input Parameter: 1434 . dm - the DM object 1435 1436 Output Parameters: 1437 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1438 . namelist - The name for each subdomain (or NULL if not requested) 1439 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1440 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1441 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1442 1443 Level: intermediate 1444 1445 Notes: 1446 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1447 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1448 and all of the arrays should be freed with PetscFree(). 1449 1450 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1451 @*/ 1452 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1453 { 1454 PetscErrorCode ierr; 1455 DMSubDomainHookLink link; 1456 PetscInt i,l; 1457 1458 PetscFunctionBegin; 1459 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1460 if (len) {PetscValidPointer(len,2); *len = 0;} 1461 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1462 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1463 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1464 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1465 /* 1466 Is it a good idea to apply the following check across all impls? 1467 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1468 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1469 */ 1470 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1471 if (dm->ops->createdomaindecomposition) { 1472 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1473 /* copy subdomain hooks and context over to the subdomain DMs */ 1474 if (dmlist) { 1475 for (i = 0; i < l; i++) { 1476 for (link=dm->subdomainhook; link; link=link->next) { 1477 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1478 } 1479 (*dmlist)[i]->ctx = dm->ctx; 1480 } 1481 } 1482 if (len) *len = l; 1483 } 1484 PetscFunctionReturn(0); 1485 } 1486 1487 1488 #undef __FUNCT__ 1489 #define __FUNCT__ "DMCreateDomainDecompositionScatters" 1490 /*@C 1491 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1492 1493 Not collective 1494 1495 Input Parameters: 1496 + dm - the DM object 1497 . n - the number of subdomain scatters 1498 - subdms - the local subdomains 1499 1500 Output Parameters: 1501 + n - the number of scatters returned 1502 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1503 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1504 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1505 1506 Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1507 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1508 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1509 solution and residual data. 1510 1511 Level: developer 1512 1513 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1514 @*/ 1515 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1516 { 1517 PetscErrorCode ierr; 1518 1519 PetscFunctionBegin; 1520 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1521 PetscValidPointer(subdms,3); 1522 if (dm->ops->createddscatters) { 1523 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1524 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined"); 1525 PetscFunctionReturn(0); 1526 } 1527 1528 #undef __FUNCT__ 1529 #define __FUNCT__ "DMRefine" 1530 /*@ 1531 DMRefine - Refines a DM object 1532 1533 Collective on DM 1534 1535 Input Parameter: 1536 + dm - the DM object 1537 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1538 1539 Output Parameter: 1540 . dmf - the refined DM, or NULL 1541 1542 Note: If no refinement was done, the return value is NULL 1543 1544 Level: developer 1545 1546 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1547 @*/ 1548 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1549 { 1550 PetscErrorCode ierr; 1551 DMRefineHookLink link; 1552 1553 PetscFunctionBegin; 1554 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1555 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1556 if (*dmf) { 1557 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1558 1559 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1560 1561 (*dmf)->ctx = dm->ctx; 1562 (*dmf)->leveldown = dm->leveldown; 1563 (*dmf)->levelup = dm->levelup + 1; 1564 1565 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1566 for (link=dm->refinehook; link; link=link->next) { 1567 if (link->refinehook) { 1568 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1569 } 1570 } 1571 } 1572 PetscFunctionReturn(0); 1573 } 1574 1575 #undef __FUNCT__ 1576 #define __FUNCT__ "DMRefineHookAdd" 1577 /*@C 1578 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1579 1580 Logically Collective 1581 1582 Input Arguments: 1583 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1584 . refinehook - function to run when setting up a coarser level 1585 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1586 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1587 1588 Calling sequence of refinehook: 1589 $ refinehook(DM coarse,DM fine,void *ctx); 1590 1591 + coarse - coarse level DM 1592 . fine - fine level DM to interpolate problem to 1593 - ctx - optional user-defined function context 1594 1595 Calling sequence for interphook: 1596 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1597 1598 + coarse - coarse level DM 1599 . interp - matrix interpolating a coarse-level solution to the finer grid 1600 . fine - fine level DM to update 1601 - ctx - optional user-defined function context 1602 1603 Level: advanced 1604 1605 Notes: 1606 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1607 1608 If this function is called multiple times, the hooks will be run in the order they are added. 1609 1610 This function is currently not available from Fortran. 1611 1612 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1613 @*/ 1614 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1615 { 1616 PetscErrorCode ierr; 1617 DMRefineHookLink link,*p; 1618 1619 PetscFunctionBegin; 1620 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1621 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1622 ierr = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr); 1623 link->refinehook = refinehook; 1624 link->interphook = interphook; 1625 link->ctx = ctx; 1626 link->next = NULL; 1627 *p = link; 1628 PetscFunctionReturn(0); 1629 } 1630 1631 #undef __FUNCT__ 1632 #define __FUNCT__ "DMInterpolate" 1633 /*@ 1634 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1635 1636 Collective if any hooks are 1637 1638 Input Arguments: 1639 + coarse - coarser DM to use as a base 1640 . restrct - interpolation matrix, apply using MatInterpolate() 1641 - fine - finer DM to update 1642 1643 Level: developer 1644 1645 .seealso: DMRefineHookAdd(), MatInterpolate() 1646 @*/ 1647 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1648 { 1649 PetscErrorCode ierr; 1650 DMRefineHookLink link; 1651 1652 PetscFunctionBegin; 1653 for (link=fine->refinehook; link; link=link->next) { 1654 if (link->interphook) { 1655 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1656 } 1657 } 1658 PetscFunctionReturn(0); 1659 } 1660 1661 #undef __FUNCT__ 1662 #define __FUNCT__ "DMGetRefineLevel" 1663 /*@ 1664 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1665 1666 Not Collective 1667 1668 Input Parameter: 1669 . dm - the DM object 1670 1671 Output Parameter: 1672 . level - number of refinements 1673 1674 Level: developer 1675 1676 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1677 1678 @*/ 1679 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1680 { 1681 PetscFunctionBegin; 1682 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1683 *level = dm->levelup; 1684 PetscFunctionReturn(0); 1685 } 1686 1687 #undef __FUNCT__ 1688 #define __FUNCT__ "DMGlobalToLocalHookAdd" 1689 /*@C 1690 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1691 1692 Logically Collective 1693 1694 Input Arguments: 1695 + dm - the DM 1696 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 1697 . endhook - function to run after DMGlobalToLocalEnd() has completed 1698 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1699 1700 Calling sequence for beginhook: 1701 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1702 1703 + dm - global DM 1704 . g - global vector 1705 . mode - mode 1706 . l - local vector 1707 - ctx - optional user-defined function context 1708 1709 1710 Calling sequence for endhook: 1711 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1712 1713 + global - global DM 1714 - ctx - optional user-defined function context 1715 1716 Level: advanced 1717 1718 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1719 @*/ 1720 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1721 { 1722 PetscErrorCode ierr; 1723 DMGlobalToLocalHookLink link,*p; 1724 1725 PetscFunctionBegin; 1726 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1727 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1728 ierr = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr); 1729 link->beginhook = beginhook; 1730 link->endhook = endhook; 1731 link->ctx = ctx; 1732 link->next = NULL; 1733 *p = link; 1734 PetscFunctionReturn(0); 1735 } 1736 1737 #undef __FUNCT__ 1738 #define __FUNCT__ "DMGlobalToLocalHook_Constraints" 1739 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 1740 { 1741 Mat cMat; 1742 Vec cVec; 1743 PetscSection section, cSec; 1744 PetscInt pStart, pEnd, p, dof; 1745 PetscErrorCode ierr; 1746 1747 PetscFunctionBegin; 1748 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1749 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1750 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 1751 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1752 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1753 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 1754 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1755 for (p = pStart; p < pEnd; p++) { 1756 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1757 if (dof) { 1758 PetscScalar *vals; 1759 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 1760 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 1761 } 1762 } 1763 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1764 } 1765 PetscFunctionReturn(0); 1766 } 1767 1768 #undef __FUNCT__ 1769 #define __FUNCT__ "DMGlobalToLocalBegin" 1770 /*@ 1771 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1772 1773 Neighbor-wise Collective on DM 1774 1775 Input Parameters: 1776 + dm - the DM object 1777 . g - the global vector 1778 . mode - INSERT_VALUES or ADD_VALUES 1779 - l - the local vector 1780 1781 1782 Level: beginner 1783 1784 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1785 1786 @*/ 1787 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1788 { 1789 PetscSF sf; 1790 PetscErrorCode ierr; 1791 DMGlobalToLocalHookLink link; 1792 1793 PetscFunctionBegin; 1794 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1795 for (link=dm->gtolhook; link; link=link->next) { 1796 if (link->beginhook) { 1797 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 1798 } 1799 } 1800 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1801 if (sf) { 1802 const PetscScalar *gArray; 1803 PetscScalar *lArray; 1804 1805 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1806 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1807 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1808 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1809 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1810 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1811 } else { 1812 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1813 } 1814 PetscFunctionReturn(0); 1815 } 1816 1817 #undef __FUNCT__ 1818 #define __FUNCT__ "DMGlobalToLocalEnd" 1819 /*@ 1820 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1821 1822 Neighbor-wise Collective on DM 1823 1824 Input Parameters: 1825 + dm - the DM object 1826 . g - the global vector 1827 . mode - INSERT_VALUES or ADD_VALUES 1828 - l - the local vector 1829 1830 1831 Level: beginner 1832 1833 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1834 1835 @*/ 1836 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 1837 { 1838 PetscSF sf; 1839 PetscErrorCode ierr; 1840 const PetscScalar *gArray; 1841 PetscScalar *lArray; 1842 DMGlobalToLocalHookLink link; 1843 1844 PetscFunctionBegin; 1845 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1846 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1847 if (sf) { 1848 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1849 1850 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1851 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1852 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1853 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1854 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1855 } else { 1856 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1857 } 1858 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 1859 for (link=dm->gtolhook; link; link=link->next) { 1860 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 1861 } 1862 PetscFunctionReturn(0); 1863 } 1864 1865 #undef __FUNCT__ 1866 #define __FUNCT__ "DMLocalToGlobalHookAdd" 1867 /*@C 1868 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 1869 1870 Logically Collective 1871 1872 Input Arguments: 1873 + dm - the DM 1874 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 1875 . endhook - function to run after DMLocalToGlobalEnd() has completed 1876 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1877 1878 Calling sequence for beginhook: 1879 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 1880 1881 + dm - global DM 1882 . l - local vector 1883 . mode - mode 1884 . g - global vector 1885 - ctx - optional user-defined function context 1886 1887 1888 Calling sequence for endhook: 1889 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 1890 1891 + global - global DM 1892 . l - local vector 1893 . mode - mode 1894 . g - global vector 1895 - ctx - optional user-defined function context 1896 1897 Level: advanced 1898 1899 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1900 @*/ 1901 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1902 { 1903 PetscErrorCode ierr; 1904 DMLocalToGlobalHookLink link,*p; 1905 1906 PetscFunctionBegin; 1907 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1908 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1909 ierr = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&link);CHKERRQ(ierr); 1910 link->beginhook = beginhook; 1911 link->endhook = endhook; 1912 link->ctx = ctx; 1913 link->next = NULL; 1914 *p = link; 1915 PetscFunctionReturn(0); 1916 } 1917 1918 #undef __FUNCT__ 1919 #define __FUNCT__ "DMLocalToGlobalHook_Constraints" 1920 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 1921 { 1922 Mat cMat; 1923 Vec cVec; 1924 PetscSection section, cSec; 1925 PetscInt pStart, pEnd, p, dof; 1926 PetscErrorCode ierr; 1927 1928 PetscFunctionBegin; 1929 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1930 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1931 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 1932 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1933 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1934 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1935 for (p = pStart; p < pEnd; p++) { 1936 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1937 if (dof) { 1938 PetscInt d; 1939 PetscScalar *vals; 1940 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 1941 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 1942 /* for this to be the true transpose, we have to zero the values that 1943 * we just extracted */ 1944 for (d = 0; d < dof; d++) { 1945 vals[d] = 0.; 1946 } 1947 } 1948 } 1949 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 1950 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1951 } 1952 PetscFunctionReturn(0); 1953 } 1954 1955 #undef __FUNCT__ 1956 #define __FUNCT__ "DMLocalToGlobalBegin" 1957 /*@ 1958 DMLocalToGlobalBegin - updates global vectors from local vectors 1959 1960 Neighbor-wise Collective on DM 1961 1962 Input Parameters: 1963 + dm - the DM object 1964 . l - the local vector 1965 . 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. 1966 - g - the global vector 1967 1968 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 1969 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 1970 1971 Level: beginner 1972 1973 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 1974 1975 @*/ 1976 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 1977 { 1978 PetscSF sf; 1979 PetscSection s, gs; 1980 DMLocalToGlobalHookLink link; 1981 const PetscScalar *lArray; 1982 PetscScalar *gArray; 1983 PetscBool isInsert; 1984 PetscErrorCode ierr; 1985 1986 PetscFunctionBegin; 1987 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1988 for (link=dm->ltoghook; link; link=link->next) { 1989 if (link->beginhook) { 1990 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 1991 } 1992 } 1993 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 1994 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1995 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 1996 switch (mode) { 1997 case INSERT_VALUES: 1998 case INSERT_ALL_VALUES: 1999 isInsert = PETSC_TRUE; break; 2000 case ADD_VALUES: 2001 case ADD_ALL_VALUES: 2002 isInsert = PETSC_FALSE; break; 2003 default: 2004 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2005 } 2006 if (sf && !isInsert) { 2007 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2008 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2009 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2010 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2011 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2012 } else if (s && isInsert) { 2013 PetscInt gStart, pStart, pEnd, p; 2014 2015 ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); 2016 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2017 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2018 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2019 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2020 for (p = pStart; p < pEnd; ++p) { 2021 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2022 2023 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2024 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2025 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2026 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2027 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2028 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2029 /* Ignore off-process data and points with no global data */ 2030 if (!gdof || goff < 0) continue; 2031 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); 2032 /* If no constraints are enforced in the global vector */ 2033 if (!gcdof) { 2034 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2035 /* If constraints are enforced in the global vector */ 2036 } else if (cdof == gcdof) { 2037 const PetscInt *cdofs; 2038 PetscInt cind = 0; 2039 2040 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2041 for (d = 0, e = 0; d < dof; ++d) { 2042 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2043 gArray[goff-gStart+e++] = lArray[off+d]; 2044 } 2045 } 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); 2046 } 2047 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2048 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2049 } else { 2050 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2051 } 2052 PetscFunctionReturn(0); 2053 } 2054 2055 #undef __FUNCT__ 2056 #define __FUNCT__ "DMLocalToGlobalEnd" 2057 /*@ 2058 DMLocalToGlobalEnd - updates global vectors from local vectors 2059 2060 Neighbor-wise Collective on DM 2061 2062 Input Parameters: 2063 + dm - the DM object 2064 . l - the local vector 2065 . mode - INSERT_VALUES or ADD_VALUES 2066 - g - the global vector 2067 2068 2069 Level: beginner 2070 2071 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2072 2073 @*/ 2074 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2075 { 2076 PetscSF sf; 2077 PetscSection s; 2078 DMLocalToGlobalHookLink link; 2079 PetscBool isInsert; 2080 PetscErrorCode ierr; 2081 2082 PetscFunctionBegin; 2083 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2084 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2085 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2086 switch (mode) { 2087 case INSERT_VALUES: 2088 case INSERT_ALL_VALUES: 2089 isInsert = PETSC_TRUE; break; 2090 case ADD_VALUES: 2091 case ADD_ALL_VALUES: 2092 isInsert = PETSC_FALSE; break; 2093 default: 2094 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2095 } 2096 if (sf && !isInsert) { 2097 const PetscScalar *lArray; 2098 PetscScalar *gArray; 2099 2100 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2101 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2102 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2103 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2104 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2105 } else if (s && isInsert) { 2106 } else { 2107 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2108 } 2109 for (link=dm->ltoghook; link; link=link->next) { 2110 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2111 } 2112 PetscFunctionReturn(0); 2113 } 2114 2115 #undef __FUNCT__ 2116 #define __FUNCT__ "DMLocalToLocalBegin" 2117 /*@ 2118 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2119 that contain irrelevant values) to another local vector where the ghost 2120 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2121 2122 Neighbor-wise Collective on DM and Vec 2123 2124 Input Parameters: 2125 + dm - the DM object 2126 . g - the original local vector 2127 - mode - one of INSERT_VALUES or ADD_VALUES 2128 2129 Output Parameter: 2130 . l - the local vector with correct ghost values 2131 2132 Level: intermediate 2133 2134 Notes: 2135 The local vectors used here need not be the same as those 2136 obtained from DMCreateLocalVector(), BUT they 2137 must have the same parallel data layout; they could, for example, be 2138 obtained with VecDuplicate() from the DM originating vectors. 2139 2140 .keywords: DM, local-to-local, begin 2141 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2142 2143 @*/ 2144 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2145 { 2146 PetscErrorCode ierr; 2147 2148 PetscFunctionBegin; 2149 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2150 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2151 PetscFunctionReturn(0); 2152 } 2153 2154 #undef __FUNCT__ 2155 #define __FUNCT__ "DMLocalToLocalEnd" 2156 /*@ 2157 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2158 that contain irrelevant values) to another local vector where the ghost 2159 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2160 2161 Neighbor-wise Collective on DM and Vec 2162 2163 Input Parameters: 2164 + da - the DM object 2165 . g - the original local vector 2166 - mode - one of INSERT_VALUES or ADD_VALUES 2167 2168 Output Parameter: 2169 . l - the local vector with correct ghost values 2170 2171 Level: intermediate 2172 2173 Notes: 2174 The local vectors used here need not be the same as those 2175 obtained from DMCreateLocalVector(), BUT they 2176 must have the same parallel data layout; they could, for example, be 2177 obtained with VecDuplicate() from the DM originating vectors. 2178 2179 .keywords: DM, local-to-local, end 2180 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2181 2182 @*/ 2183 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2184 { 2185 PetscErrorCode ierr; 2186 2187 PetscFunctionBegin; 2188 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2189 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2190 PetscFunctionReturn(0); 2191 } 2192 2193 2194 #undef __FUNCT__ 2195 #define __FUNCT__ "DMCoarsen" 2196 /*@ 2197 DMCoarsen - Coarsens a DM object 2198 2199 Collective on DM 2200 2201 Input Parameter: 2202 + dm - the DM object 2203 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2204 2205 Output Parameter: 2206 . dmc - the coarsened DM 2207 2208 Level: developer 2209 2210 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2211 2212 @*/ 2213 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2214 { 2215 PetscErrorCode ierr; 2216 DMCoarsenHookLink link; 2217 2218 PetscFunctionBegin; 2219 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2220 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2221 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2222 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2223 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2224 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2225 (*dmc)->ctx = dm->ctx; 2226 (*dmc)->levelup = dm->levelup; 2227 (*dmc)->leveldown = dm->leveldown + 1; 2228 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2229 for (link=dm->coarsenhook; link; link=link->next) { 2230 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2231 } 2232 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2233 PetscFunctionReturn(0); 2234 } 2235 2236 #undef __FUNCT__ 2237 #define __FUNCT__ "DMCoarsenHookAdd" 2238 /*@C 2239 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2240 2241 Logically Collective 2242 2243 Input Arguments: 2244 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2245 . coarsenhook - function to run when setting up a coarser level 2246 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2247 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2248 2249 Calling sequence of coarsenhook: 2250 $ coarsenhook(DM fine,DM coarse,void *ctx); 2251 2252 + fine - fine level DM 2253 . coarse - coarse level DM to restrict problem to 2254 - ctx - optional user-defined function context 2255 2256 Calling sequence for restricthook: 2257 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2258 2259 + fine - fine level DM 2260 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2261 . rscale - scaling vector for restriction 2262 . inject - matrix restricting by injection 2263 . coarse - coarse level DM to update 2264 - ctx - optional user-defined function context 2265 2266 Level: advanced 2267 2268 Notes: 2269 This function is only needed if auxiliary data needs to be set up on coarse grids. 2270 2271 If this function is called multiple times, the hooks will be run in the order they are added. 2272 2273 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2274 extract the finest level information from its context (instead of from the SNES). 2275 2276 This function is currently not available from Fortran. 2277 2278 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2279 @*/ 2280 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2281 { 2282 PetscErrorCode ierr; 2283 DMCoarsenHookLink link,*p; 2284 2285 PetscFunctionBegin; 2286 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2287 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2288 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 2289 link->coarsenhook = coarsenhook; 2290 link->restricthook = restricthook; 2291 link->ctx = ctx; 2292 link->next = NULL; 2293 *p = link; 2294 PetscFunctionReturn(0); 2295 } 2296 2297 #undef __FUNCT__ 2298 #define __FUNCT__ "DMRestrict" 2299 /*@ 2300 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2301 2302 Collective if any hooks are 2303 2304 Input Arguments: 2305 + fine - finer DM to use as a base 2306 . restrct - restriction matrix, apply using MatRestrict() 2307 . inject - injection matrix, also use MatRestrict() 2308 - coarse - coarer DM to update 2309 2310 Level: developer 2311 2312 .seealso: DMCoarsenHookAdd(), MatRestrict() 2313 @*/ 2314 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2315 { 2316 PetscErrorCode ierr; 2317 DMCoarsenHookLink link; 2318 2319 PetscFunctionBegin; 2320 for (link=fine->coarsenhook; link; link=link->next) { 2321 if (link->restricthook) { 2322 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2323 } 2324 } 2325 PetscFunctionReturn(0); 2326 } 2327 2328 #undef __FUNCT__ 2329 #define __FUNCT__ "DMSubDomainHookAdd" 2330 /*@C 2331 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2332 2333 Logically Collective 2334 2335 Input Arguments: 2336 + global - global DM 2337 . ddhook - function to run to pass data to the decomposition DM upon its creation 2338 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2339 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2340 2341 2342 Calling sequence for ddhook: 2343 $ ddhook(DM global,DM block,void *ctx) 2344 2345 + global - global DM 2346 . block - block DM 2347 - ctx - optional user-defined function context 2348 2349 Calling sequence for restricthook: 2350 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2351 2352 + global - global DM 2353 . out - scatter to the outer (with ghost and overlap points) block vector 2354 . in - scatter to block vector values only owned locally 2355 . block - block DM 2356 - ctx - optional user-defined function context 2357 2358 Level: advanced 2359 2360 Notes: 2361 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2362 2363 If this function is called multiple times, the hooks will be run in the order they are added. 2364 2365 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2366 extract the global information from its context (instead of from the SNES). 2367 2368 This function is currently not available from Fortran. 2369 2370 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2371 @*/ 2372 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2373 { 2374 PetscErrorCode ierr; 2375 DMSubDomainHookLink link,*p; 2376 2377 PetscFunctionBegin; 2378 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2379 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2380 ierr = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr); 2381 link->restricthook = restricthook; 2382 link->ddhook = ddhook; 2383 link->ctx = ctx; 2384 link->next = NULL; 2385 *p = link; 2386 PetscFunctionReturn(0); 2387 } 2388 2389 #undef __FUNCT__ 2390 #define __FUNCT__ "DMSubDomainRestrict" 2391 /*@ 2392 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2393 2394 Collective if any hooks are 2395 2396 Input Arguments: 2397 + fine - finer DM to use as a base 2398 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2399 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2400 - coarse - coarer DM to update 2401 2402 Level: developer 2403 2404 .seealso: DMCoarsenHookAdd(), MatRestrict() 2405 @*/ 2406 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2407 { 2408 PetscErrorCode ierr; 2409 DMSubDomainHookLink link; 2410 2411 PetscFunctionBegin; 2412 for (link=global->subdomainhook; link; link=link->next) { 2413 if (link->restricthook) { 2414 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2415 } 2416 } 2417 PetscFunctionReturn(0); 2418 } 2419 2420 #undef __FUNCT__ 2421 #define __FUNCT__ "DMGetCoarsenLevel" 2422 /*@ 2423 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2424 2425 Not Collective 2426 2427 Input Parameter: 2428 . dm - the DM object 2429 2430 Output Parameter: 2431 . level - number of coarsenings 2432 2433 Level: developer 2434 2435 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2436 2437 @*/ 2438 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2439 { 2440 PetscFunctionBegin; 2441 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2442 *level = dm->leveldown; 2443 PetscFunctionReturn(0); 2444 } 2445 2446 2447 2448 #undef __FUNCT__ 2449 #define __FUNCT__ "DMRefineHierarchy" 2450 /*@C 2451 DMRefineHierarchy - Refines a DM object, all levels at once 2452 2453 Collective on DM 2454 2455 Input Parameter: 2456 + dm - the DM object 2457 - nlevels - the number of levels of refinement 2458 2459 Output Parameter: 2460 . dmf - the refined DM hierarchy 2461 2462 Level: developer 2463 2464 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2465 2466 @*/ 2467 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2468 { 2469 PetscErrorCode ierr; 2470 2471 PetscFunctionBegin; 2472 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2473 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2474 if (nlevels == 0) PetscFunctionReturn(0); 2475 if (dm->ops->refinehierarchy) { 2476 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2477 } else if (dm->ops->refine) { 2478 PetscInt i; 2479 2480 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2481 for (i=1; i<nlevels; i++) { 2482 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2483 } 2484 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2485 PetscFunctionReturn(0); 2486 } 2487 2488 #undef __FUNCT__ 2489 #define __FUNCT__ "DMCoarsenHierarchy" 2490 /*@C 2491 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2492 2493 Collective on DM 2494 2495 Input Parameter: 2496 + dm - the DM object 2497 - nlevels - the number of levels of coarsening 2498 2499 Output Parameter: 2500 . dmc - the coarsened DM hierarchy 2501 2502 Level: developer 2503 2504 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2505 2506 @*/ 2507 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2508 { 2509 PetscErrorCode ierr; 2510 2511 PetscFunctionBegin; 2512 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2513 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2514 if (nlevels == 0) PetscFunctionReturn(0); 2515 PetscValidPointer(dmc,3); 2516 if (dm->ops->coarsenhierarchy) { 2517 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2518 } else if (dm->ops->coarsen) { 2519 PetscInt i; 2520 2521 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2522 for (i=1; i<nlevels; i++) { 2523 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2524 } 2525 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2526 PetscFunctionReturn(0); 2527 } 2528 2529 #undef __FUNCT__ 2530 #define __FUNCT__ "DMCreateAggregates" 2531 /*@ 2532 DMCreateAggregates - Gets the aggregates that map between 2533 grids associated with two DMs. 2534 2535 Collective on DM 2536 2537 Input Parameters: 2538 + dmc - the coarse grid DM 2539 - dmf - the fine grid DM 2540 2541 Output Parameters: 2542 . rest - the restriction matrix (transpose of the projection matrix) 2543 2544 Level: intermediate 2545 2546 .keywords: interpolation, restriction, multigrid 2547 2548 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2549 @*/ 2550 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2551 { 2552 PetscErrorCode ierr; 2553 2554 PetscFunctionBegin; 2555 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2556 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2557 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2558 PetscFunctionReturn(0); 2559 } 2560 2561 #undef __FUNCT__ 2562 #define __FUNCT__ "DMSetApplicationContextDestroy" 2563 /*@C 2564 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2565 2566 Not Collective 2567 2568 Input Parameters: 2569 + dm - the DM object 2570 - destroy - the destroy function 2571 2572 Level: intermediate 2573 2574 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2575 2576 @*/ 2577 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2578 { 2579 PetscFunctionBegin; 2580 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2581 dm->ctxdestroy = destroy; 2582 PetscFunctionReturn(0); 2583 } 2584 2585 #undef __FUNCT__ 2586 #define __FUNCT__ "DMSetApplicationContext" 2587 /*@ 2588 DMSetApplicationContext - Set a user context into a DM object 2589 2590 Not Collective 2591 2592 Input Parameters: 2593 + dm - the DM object 2594 - ctx - the user context 2595 2596 Level: intermediate 2597 2598 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2599 2600 @*/ 2601 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2602 { 2603 PetscFunctionBegin; 2604 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2605 dm->ctx = ctx; 2606 PetscFunctionReturn(0); 2607 } 2608 2609 #undef __FUNCT__ 2610 #define __FUNCT__ "DMGetApplicationContext" 2611 /*@ 2612 DMGetApplicationContext - Gets a user context from a DM object 2613 2614 Not Collective 2615 2616 Input Parameter: 2617 . dm - the DM object 2618 2619 Output Parameter: 2620 . ctx - the user context 2621 2622 Level: intermediate 2623 2624 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2625 2626 @*/ 2627 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2628 { 2629 PetscFunctionBegin; 2630 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2631 *(void**)ctx = dm->ctx; 2632 PetscFunctionReturn(0); 2633 } 2634 2635 #undef __FUNCT__ 2636 #define __FUNCT__ "DMSetVariableBounds" 2637 /*@C 2638 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2639 2640 Logically Collective on DM 2641 2642 Input Parameter: 2643 + dm - the DM object 2644 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2645 2646 Level: intermediate 2647 2648 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2649 DMSetJacobian() 2650 2651 @*/ 2652 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2653 { 2654 PetscFunctionBegin; 2655 dm->ops->computevariablebounds = f; 2656 PetscFunctionReturn(0); 2657 } 2658 2659 #undef __FUNCT__ 2660 #define __FUNCT__ "DMHasVariableBounds" 2661 /*@ 2662 DMHasVariableBounds - does the DM object have a variable bounds function? 2663 2664 Not Collective 2665 2666 Input Parameter: 2667 . dm - the DM object to destroy 2668 2669 Output Parameter: 2670 . flg - PETSC_TRUE if the variable bounds function exists 2671 2672 Level: developer 2673 2674 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2675 2676 @*/ 2677 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2678 { 2679 PetscFunctionBegin; 2680 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2681 PetscFunctionReturn(0); 2682 } 2683 2684 #undef __FUNCT__ 2685 #define __FUNCT__ "DMComputeVariableBounds" 2686 /*@C 2687 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2688 2689 Logically Collective on DM 2690 2691 Input Parameters: 2692 . dm - the DM object 2693 2694 Output parameters: 2695 + xl - lower bound 2696 - xu - upper bound 2697 2698 Level: advanced 2699 2700 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2701 2702 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2703 2704 @*/ 2705 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2706 { 2707 PetscErrorCode ierr; 2708 2709 PetscFunctionBegin; 2710 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2711 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2712 if (dm->ops->computevariablebounds) { 2713 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2714 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2715 PetscFunctionReturn(0); 2716 } 2717 2718 #undef __FUNCT__ 2719 #define __FUNCT__ "DMHasColoring" 2720 /*@ 2721 DMHasColoring - does the DM object have a method of providing a coloring? 2722 2723 Not Collective 2724 2725 Input Parameter: 2726 . dm - the DM object 2727 2728 Output Parameter: 2729 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2730 2731 Level: developer 2732 2733 .seealso DMHasFunction(), DMCreateColoring() 2734 2735 @*/ 2736 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2737 { 2738 PetscFunctionBegin; 2739 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2740 PetscFunctionReturn(0); 2741 } 2742 2743 #undef __FUNCT__ 2744 #define __FUNCT__ "DMSetVec" 2745 /*@C 2746 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2747 2748 Collective on DM 2749 2750 Input Parameter: 2751 + dm - the DM object 2752 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2753 2754 Level: developer 2755 2756 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2757 2758 @*/ 2759 PetscErrorCode DMSetVec(DM dm,Vec x) 2760 { 2761 PetscErrorCode ierr; 2762 2763 PetscFunctionBegin; 2764 if (x) { 2765 if (!dm->x) { 2766 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2767 } 2768 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2769 } else if (dm->x) { 2770 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2771 } 2772 PetscFunctionReturn(0); 2773 } 2774 2775 PetscFunctionList DMList = NULL; 2776 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2777 2778 #undef __FUNCT__ 2779 #define __FUNCT__ "DMSetType" 2780 /*@C 2781 DMSetType - Builds a DM, for a particular DM implementation. 2782 2783 Collective on DM 2784 2785 Input Parameters: 2786 + dm - The DM object 2787 - method - The name of the DM type 2788 2789 Options Database Key: 2790 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2791 2792 Notes: 2793 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2794 2795 Level: intermediate 2796 2797 .keywords: DM, set, type 2798 .seealso: DMGetType(), DMCreate() 2799 @*/ 2800 PetscErrorCode DMSetType(DM dm, DMType method) 2801 { 2802 PetscErrorCode (*r)(DM); 2803 PetscBool match; 2804 PetscErrorCode ierr; 2805 2806 PetscFunctionBegin; 2807 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2808 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2809 if (match) PetscFunctionReturn(0); 2810 2811 ierr = DMRegisterAll();CHKERRQ(ierr); 2812 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 2813 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2814 2815 if (dm->ops->destroy) { 2816 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2817 dm->ops->destroy = NULL; 2818 } 2819 ierr = (*r)(dm);CHKERRQ(ierr); 2820 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2821 PetscFunctionReturn(0); 2822 } 2823 2824 #undef __FUNCT__ 2825 #define __FUNCT__ "DMGetType" 2826 /*@C 2827 DMGetType - Gets the DM type name (as a string) from the DM. 2828 2829 Not Collective 2830 2831 Input Parameter: 2832 . dm - The DM 2833 2834 Output Parameter: 2835 . type - The DM type name 2836 2837 Level: intermediate 2838 2839 .keywords: DM, get, type, name 2840 .seealso: DMSetType(), DMCreate() 2841 @*/ 2842 PetscErrorCode DMGetType(DM dm, DMType *type) 2843 { 2844 PetscErrorCode ierr; 2845 2846 PetscFunctionBegin; 2847 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2848 PetscValidPointer(type,2); 2849 ierr = DMRegisterAll();CHKERRQ(ierr); 2850 *type = ((PetscObject)dm)->type_name; 2851 PetscFunctionReturn(0); 2852 } 2853 2854 #undef __FUNCT__ 2855 #define __FUNCT__ "DMConvert" 2856 /*@C 2857 DMConvert - Converts a DM to another DM, either of the same or different type. 2858 2859 Collective on DM 2860 2861 Input Parameters: 2862 + dm - the DM 2863 - newtype - new DM type (use "same" for the same type) 2864 2865 Output Parameter: 2866 . M - pointer to new DM 2867 2868 Notes: 2869 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 2870 the MPI communicator of the generated DM is always the same as the communicator 2871 of the input DM. 2872 2873 Level: intermediate 2874 2875 .seealso: DMCreate() 2876 @*/ 2877 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 2878 { 2879 DM B; 2880 char convname[256]; 2881 PetscBool sametype, issame; 2882 PetscErrorCode ierr; 2883 2884 PetscFunctionBegin; 2885 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2886 PetscValidType(dm,1); 2887 PetscValidPointer(M,3); 2888 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 2889 ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); 2890 { 2891 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 2892 2893 /* 2894 Order of precedence: 2895 1) See if a specialized converter is known to the current DM. 2896 2) See if a specialized converter is known to the desired DM class. 2897 3) See if a good general converter is registered for the desired class 2898 4) See if a good general converter is known for the current matrix. 2899 5) Use a really basic converter. 2900 */ 2901 2902 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2903 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2904 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2905 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2906 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2907 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2908 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 2909 if (conv) goto foundconv; 2910 2911 /* 2) See if a specialized converter is known to the desired DM class. */ 2912 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 2913 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2914 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2915 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2916 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2917 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2918 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2919 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 2920 if (conv) { 2921 ierr = DMDestroy(&B);CHKERRQ(ierr); 2922 goto foundconv; 2923 } 2924 2925 #if 0 2926 /* 3) See if a good general converter is registered for the desired class */ 2927 conv = B->ops->convertfrom; 2928 ierr = DMDestroy(&B);CHKERRQ(ierr); 2929 if (conv) goto foundconv; 2930 2931 /* 4) See if a good general converter is known for the current matrix */ 2932 if (dm->ops->convert) { 2933 conv = dm->ops->convert; 2934 } 2935 if (conv) goto foundconv; 2936 #endif 2937 2938 /* 5) Use a really basic converter. */ 2939 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 2940 2941 foundconv: 2942 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2943 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 2944 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2945 } 2946 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 2947 PetscFunctionReturn(0); 2948 } 2949 2950 /*--------------------------------------------------------------------------------------------------------------------*/ 2951 2952 #undef __FUNCT__ 2953 #define __FUNCT__ "DMRegister" 2954 /*@C 2955 DMRegister - Adds a new DM component implementation 2956 2957 Not Collective 2958 2959 Input Parameters: 2960 + name - The name of a new user-defined creation routine 2961 - create_func - The creation routine itself 2962 2963 Notes: 2964 DMRegister() may be called multiple times to add several user-defined DMs 2965 2966 2967 Sample usage: 2968 .vb 2969 DMRegister("my_da", MyDMCreate); 2970 .ve 2971 2972 Then, your DM type can be chosen with the procedural interface via 2973 .vb 2974 DMCreate(MPI_Comm, DM *); 2975 DMSetType(DM,"my_da"); 2976 .ve 2977 or at runtime via the option 2978 .vb 2979 -da_type my_da 2980 .ve 2981 2982 Level: advanced 2983 2984 .keywords: DM, register 2985 .seealso: DMRegisterAll(), DMRegisterDestroy() 2986 2987 @*/ 2988 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 2989 { 2990 PetscErrorCode ierr; 2991 2992 PetscFunctionBegin; 2993 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 2994 PetscFunctionReturn(0); 2995 } 2996 2997 #undef __FUNCT__ 2998 #define __FUNCT__ "DMLoad" 2999 /*@C 3000 DMLoad - Loads a DM that has been stored in binary with DMView(). 3001 3002 Collective on PetscViewer 3003 3004 Input Parameters: 3005 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3006 some related function before a call to DMLoad(). 3007 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3008 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3009 3010 Level: intermediate 3011 3012 Notes: 3013 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3014 3015 Notes for advanced users: 3016 Most users should not need to know the details of the binary storage 3017 format, since DMLoad() and DMView() completely hide these details. 3018 But for anyone who's interested, the standard binary matrix storage 3019 format is 3020 .vb 3021 has not yet been determined 3022 .ve 3023 3024 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3025 @*/ 3026 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3027 { 3028 PetscBool isbinary, ishdf5; 3029 PetscErrorCode ierr; 3030 3031 PetscFunctionBegin; 3032 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3033 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3034 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3035 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3036 if (isbinary) { 3037 PetscInt classid; 3038 char type[256]; 3039 3040 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3041 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3042 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3043 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3044 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3045 } else if (ishdf5) { 3046 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3047 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3048 PetscFunctionReturn(0); 3049 } 3050 3051 /******************************** FEM Support **********************************/ 3052 3053 #undef __FUNCT__ 3054 #define __FUNCT__ "DMPrintCellVector" 3055 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3056 { 3057 PetscInt f; 3058 PetscErrorCode ierr; 3059 3060 PetscFunctionBegin; 3061 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3062 for (f = 0; f < len; ++f) { 3063 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3064 } 3065 PetscFunctionReturn(0); 3066 } 3067 3068 #undef __FUNCT__ 3069 #define __FUNCT__ "DMPrintCellMatrix" 3070 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3071 { 3072 PetscInt f, g; 3073 PetscErrorCode ierr; 3074 3075 PetscFunctionBegin; 3076 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3077 for (f = 0; f < rows; ++f) { 3078 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3079 for (g = 0; g < cols; ++g) { 3080 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3081 } 3082 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3083 } 3084 PetscFunctionReturn(0); 3085 } 3086 3087 #undef __FUNCT__ 3088 #define __FUNCT__ "DMPrintLocalVec" 3089 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3090 { 3091 PetscMPIInt rank, numProcs; 3092 PetscInt p; 3093 PetscErrorCode ierr; 3094 3095 PetscFunctionBegin; 3096 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 3097 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 3098 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 3099 for (p = 0; p < numProcs; ++p) { 3100 if (p == rank) { 3101 Vec x; 3102 3103 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3104 ierr = VecCopy(X, x);CHKERRQ(ierr); 3105 ierr = VecChop(x, tol);CHKERRQ(ierr); 3106 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3107 ierr = VecDestroy(&x);CHKERRQ(ierr); 3108 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3109 } 3110 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 3111 } 3112 PetscFunctionReturn(0); 3113 } 3114 3115 #undef __FUNCT__ 3116 #define __FUNCT__ "DMGetDefaultSection" 3117 /*@ 3118 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3119 3120 Input Parameter: 3121 . dm - The DM 3122 3123 Output Parameter: 3124 . section - The PetscSection 3125 3126 Level: intermediate 3127 3128 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3129 3130 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3131 @*/ 3132 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3133 { 3134 PetscErrorCode ierr; 3135 3136 PetscFunctionBegin; 3137 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3138 PetscValidPointer(section, 2); 3139 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3140 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3141 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3142 } 3143 *section = dm->defaultSection; 3144 PetscFunctionReturn(0); 3145 } 3146 3147 #undef __FUNCT__ 3148 #define __FUNCT__ "DMSetDefaultSection" 3149 /*@ 3150 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3151 3152 Input Parameters: 3153 + dm - The DM 3154 - section - The PetscSection 3155 3156 Level: intermediate 3157 3158 Note: Any existing Section will be destroyed 3159 3160 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3161 @*/ 3162 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3163 { 3164 PetscInt numFields = 0; 3165 PetscInt f; 3166 PetscErrorCode ierr; 3167 3168 PetscFunctionBegin; 3169 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3170 if (section) { 3171 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3172 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3173 } 3174 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3175 dm->defaultSection = section; 3176 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3177 if (numFields) { 3178 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3179 for (f = 0; f < numFields; ++f) { 3180 PetscObject disc; 3181 const char *name; 3182 3183 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3184 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3185 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3186 } 3187 } 3188 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3189 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3190 PetscFunctionReturn(0); 3191 } 3192 3193 #undef __FUNCT__ 3194 #define __FUNCT__ "DMGetDefaultConstraints" 3195 /*@ 3196 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3197 3198 not collective 3199 3200 Input Parameter: 3201 . dm - The DM 3202 3203 Output Parameter: 3204 + 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. 3205 - 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. 3206 3207 Level: advanced 3208 3209 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3210 3211 .seealso: DMSetDefaultConstraints() 3212 @*/ 3213 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3214 { 3215 PetscErrorCode ierr; 3216 3217 PetscFunctionBegin; 3218 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3219 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3220 if (section) {*section = dm->defaultConstraintSection;} 3221 if (mat) {*mat = dm->defaultConstraintMat;} 3222 PetscFunctionReturn(0); 3223 } 3224 3225 #undef __FUNCT__ 3226 #define __FUNCT__ "DMSetDefaultConstraints" 3227 /*@ 3228 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3229 3230 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(). 3231 3232 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. 3233 3234 collective on dm 3235 3236 Input Parameters: 3237 + dm - The DM 3238 + 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). 3239 - 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). 3240 3241 Level: advanced 3242 3243 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3244 3245 .seealso: DMGetDefaultConstraints() 3246 @*/ 3247 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3248 { 3249 PetscMPIInt result; 3250 PetscErrorCode ierr; 3251 3252 PetscFunctionBegin; 3253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3254 if (section) { 3255 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3256 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3257 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3258 } 3259 if (mat) { 3260 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3261 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3262 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3263 } 3264 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3265 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3266 dm->defaultConstraintSection = section; 3267 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3268 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3269 dm->defaultConstraintMat = mat; 3270 PetscFunctionReturn(0); 3271 } 3272 3273 #ifdef PETSC_USE_DEBUG 3274 #undef __FUNCT__ 3275 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal" 3276 /* 3277 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3278 3279 Input Parameters: 3280 + dm - The DM 3281 . localSection - PetscSection describing the local data layout 3282 - globalSection - PetscSection describing the global data layout 3283 3284 Level: intermediate 3285 3286 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3287 */ 3288 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3289 { 3290 MPI_Comm comm; 3291 PetscLayout layout; 3292 const PetscInt *ranges; 3293 PetscInt pStart, pEnd, p, nroots; 3294 PetscMPIInt size, rank; 3295 PetscBool valid = PETSC_TRUE, gvalid; 3296 PetscErrorCode ierr; 3297 3298 PetscFunctionBegin; 3299 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3301 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3302 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3303 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3304 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3305 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3306 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3307 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3308 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3309 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3310 for (p = pStart; p < pEnd; ++p) { 3311 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3312 3313 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3314 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3315 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3316 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3317 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3318 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3319 if (!gdof) continue; /* Censored point */ 3320 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;} 3321 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;} 3322 if (gdof < 0) { 3323 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3324 for (d = 0; d < gsize; ++d) { 3325 PetscInt offset = -(goff+1) + d, r; 3326 3327 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3328 if (r < 0) r = -(r+2); 3329 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;} 3330 } 3331 } 3332 } 3333 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3334 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3335 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3336 if (!gvalid) { 3337 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3338 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3339 } 3340 PetscFunctionReturn(0); 3341 } 3342 #endif 3343 3344 #undef __FUNCT__ 3345 #define __FUNCT__ "DMGetDefaultGlobalSection" 3346 /*@ 3347 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3348 3349 Collective on DM 3350 3351 Input Parameter: 3352 . dm - The DM 3353 3354 Output Parameter: 3355 . section - The PetscSection 3356 3357 Level: intermediate 3358 3359 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3360 3361 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3362 @*/ 3363 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3364 { 3365 PetscErrorCode ierr; 3366 3367 PetscFunctionBegin; 3368 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3369 PetscValidPointer(section, 2); 3370 if (!dm->defaultGlobalSection) { 3371 PetscSection s; 3372 3373 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3374 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3375 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3376 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3377 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3378 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3379 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3380 } 3381 *section = dm->defaultGlobalSection; 3382 PetscFunctionReturn(0); 3383 } 3384 3385 #undef __FUNCT__ 3386 #define __FUNCT__ "DMSetDefaultGlobalSection" 3387 /*@ 3388 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3389 3390 Input Parameters: 3391 + dm - The DM 3392 - section - The PetscSection, or NULL 3393 3394 Level: intermediate 3395 3396 Note: Any existing Section will be destroyed 3397 3398 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3399 @*/ 3400 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3401 { 3402 PetscErrorCode ierr; 3403 3404 PetscFunctionBegin; 3405 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3406 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3407 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3408 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3409 dm->defaultGlobalSection = section; 3410 #ifdef PETSC_USE_DEBUG 3411 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3412 #endif 3413 PetscFunctionReturn(0); 3414 } 3415 3416 #undef __FUNCT__ 3417 #define __FUNCT__ "DMGetDefaultSF" 3418 /*@ 3419 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3420 it is created from the default PetscSection layouts in the DM. 3421 3422 Input Parameter: 3423 . dm - The DM 3424 3425 Output Parameter: 3426 . sf - The PetscSF 3427 3428 Level: intermediate 3429 3430 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3431 3432 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3433 @*/ 3434 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3435 { 3436 PetscInt nroots; 3437 PetscErrorCode ierr; 3438 3439 PetscFunctionBegin; 3440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3441 PetscValidPointer(sf, 2); 3442 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3443 if (nroots < 0) { 3444 PetscSection section, gSection; 3445 3446 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3447 if (section) { 3448 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3449 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3450 } else { 3451 *sf = NULL; 3452 PetscFunctionReturn(0); 3453 } 3454 } 3455 *sf = dm->defaultSF; 3456 PetscFunctionReturn(0); 3457 } 3458 3459 #undef __FUNCT__ 3460 #define __FUNCT__ "DMSetDefaultSF" 3461 /*@ 3462 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3463 3464 Input Parameters: 3465 + dm - The DM 3466 - sf - The PetscSF 3467 3468 Level: intermediate 3469 3470 Note: Any previous SF is destroyed 3471 3472 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3473 @*/ 3474 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3475 { 3476 PetscErrorCode ierr; 3477 3478 PetscFunctionBegin; 3479 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3480 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3481 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3482 dm->defaultSF = sf; 3483 PetscFunctionReturn(0); 3484 } 3485 3486 #undef __FUNCT__ 3487 #define __FUNCT__ "DMCreateDefaultSF" 3488 /*@C 3489 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3490 describing the data layout. 3491 3492 Input Parameters: 3493 + dm - The DM 3494 . localSection - PetscSection describing the local data layout 3495 - globalSection - PetscSection describing the global data layout 3496 3497 Level: intermediate 3498 3499 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3500 @*/ 3501 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3502 { 3503 MPI_Comm comm; 3504 PetscLayout layout; 3505 const PetscInt *ranges; 3506 PetscInt *local; 3507 PetscSFNode *remote; 3508 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3509 PetscMPIInt size, rank; 3510 PetscErrorCode ierr; 3511 3512 PetscFunctionBegin; 3513 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3514 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3515 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3516 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3517 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3518 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3519 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3520 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3521 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3522 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3523 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3524 for (p = pStart; p < pEnd; ++p) { 3525 PetscInt gdof, gcdof; 3526 3527 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3528 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3529 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)); 3530 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3531 } 3532 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3533 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3534 for (p = pStart, l = 0; p < pEnd; ++p) { 3535 const PetscInt *cind; 3536 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3537 3538 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3539 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3540 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3541 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3542 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3543 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3544 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3545 if (!gdof) continue; /* Censored point */ 3546 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3547 if (gsize != dof-cdof) { 3548 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); 3549 cdof = 0; /* Ignore constraints */ 3550 } 3551 for (d = 0, c = 0; d < dof; ++d) { 3552 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3553 local[l+d-c] = off+d; 3554 } 3555 if (gdof < 0) { 3556 for (d = 0; d < gsize; ++d, ++l) { 3557 PetscInt offset = -(goff+1) + d, r; 3558 3559 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3560 if (r < 0) r = -(r+2); 3561 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); 3562 remote[l].rank = r; 3563 remote[l].index = offset - ranges[r]; 3564 } 3565 } else { 3566 for (d = 0; d < gsize; ++d, ++l) { 3567 remote[l].rank = rank; 3568 remote[l].index = goff+d - ranges[rank]; 3569 } 3570 } 3571 } 3572 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3573 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3574 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3575 PetscFunctionReturn(0); 3576 } 3577 3578 #undef __FUNCT__ 3579 #define __FUNCT__ "DMGetPointSF" 3580 /*@ 3581 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3582 3583 Input Parameter: 3584 . dm - The DM 3585 3586 Output Parameter: 3587 . sf - The PetscSF 3588 3589 Level: intermediate 3590 3591 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3592 3593 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3594 @*/ 3595 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3596 { 3597 PetscFunctionBegin; 3598 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3599 PetscValidPointer(sf, 2); 3600 *sf = dm->sf; 3601 PetscFunctionReturn(0); 3602 } 3603 3604 #undef __FUNCT__ 3605 #define __FUNCT__ "DMSetPointSF" 3606 /*@ 3607 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3608 3609 Input Parameters: 3610 + dm - The DM 3611 - sf - The PetscSF 3612 3613 Level: intermediate 3614 3615 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3616 @*/ 3617 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3618 { 3619 PetscErrorCode ierr; 3620 3621 PetscFunctionBegin; 3622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3623 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3624 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3625 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3626 dm->sf = sf; 3627 PetscFunctionReturn(0); 3628 } 3629 3630 #undef __FUNCT__ 3631 #define __FUNCT__ "DMGetDS" 3632 /*@ 3633 DMGetDS - Get the PetscDS 3634 3635 Input Parameter: 3636 . dm - The DM 3637 3638 Output Parameter: 3639 . prob - The PetscDS 3640 3641 Level: developer 3642 3643 .seealso: DMSetDS() 3644 @*/ 3645 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3646 { 3647 PetscFunctionBegin; 3648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3649 PetscValidPointer(prob, 2); 3650 *prob = dm->prob; 3651 PetscFunctionReturn(0); 3652 } 3653 3654 #undef __FUNCT__ 3655 #define __FUNCT__ "DMSetDS" 3656 /*@ 3657 DMSetDS - Set the PetscDS 3658 3659 Input Parameters: 3660 + dm - The DM 3661 - prob - The PetscDS 3662 3663 Level: developer 3664 3665 .seealso: DMGetDS() 3666 @*/ 3667 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3668 { 3669 PetscErrorCode ierr; 3670 3671 PetscFunctionBegin; 3672 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3673 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3674 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3675 dm->prob = prob; 3676 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3677 PetscFunctionReturn(0); 3678 } 3679 3680 #undef __FUNCT__ 3681 #define __FUNCT__ "DMGetNumFields" 3682 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3683 { 3684 PetscErrorCode ierr; 3685 3686 PetscFunctionBegin; 3687 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3688 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3689 PetscFunctionReturn(0); 3690 } 3691 3692 #undef __FUNCT__ 3693 #define __FUNCT__ "DMSetNumFields" 3694 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3695 { 3696 PetscInt Nf, f; 3697 PetscErrorCode ierr; 3698 3699 PetscFunctionBegin; 3700 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3701 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3702 for (f = Nf; f < numFields; ++f) { 3703 PetscContainer obj; 3704 3705 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3706 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3707 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3708 } 3709 PetscFunctionReturn(0); 3710 } 3711 3712 #undef __FUNCT__ 3713 #define __FUNCT__ "DMGetField" 3714 /*@ 3715 DMGetField - Return the discretization object for a given DM field 3716 3717 Not collective 3718 3719 Input Parameters: 3720 + dm - The DM 3721 - f - The field number 3722 3723 Output Parameter: 3724 . field - The discretization object 3725 3726 Level: developer 3727 3728 .seealso: DMSetField() 3729 @*/ 3730 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3731 { 3732 PetscErrorCode ierr; 3733 3734 PetscFunctionBegin; 3735 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3736 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3737 PetscFunctionReturn(0); 3738 } 3739 3740 #undef __FUNCT__ 3741 #define __FUNCT__ "DMSetField" 3742 /*@ 3743 DMSetField - Set the discretization object for a given DM field 3744 3745 Logically collective on DM 3746 3747 Input Parameters: 3748 + dm - The DM 3749 . f - The field number 3750 - field - The discretization object 3751 3752 Level: developer 3753 3754 .seealso: DMGetField() 3755 @*/ 3756 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3757 { 3758 PetscErrorCode ierr; 3759 3760 PetscFunctionBegin; 3761 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3762 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3763 PetscFunctionReturn(0); 3764 } 3765 3766 #undef __FUNCT__ 3767 #define __FUNCT__ "DMRestrictHook_Coordinates" 3768 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3769 { 3770 DM dm_coord,dmc_coord; 3771 PetscErrorCode ierr; 3772 Vec coords,ccoords; 3773 Mat inject; 3774 PetscFunctionBegin; 3775 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3776 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3777 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3778 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3779 if (coords && !ccoords) { 3780 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3781 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3782 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3783 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3784 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3785 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3786 } 3787 PetscFunctionReturn(0); 3788 } 3789 3790 #undef __FUNCT__ 3791 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3792 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3793 { 3794 DM dm_coord,subdm_coord; 3795 PetscErrorCode ierr; 3796 Vec coords,ccoords,clcoords; 3797 VecScatter *scat_i,*scat_g; 3798 PetscFunctionBegin; 3799 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3800 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3801 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3802 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3803 if (coords && !ccoords) { 3804 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3805 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3806 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 3807 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3808 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3809 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3810 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3811 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3812 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3813 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3814 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3815 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3816 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3817 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3818 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3819 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3820 } 3821 PetscFunctionReturn(0); 3822 } 3823 3824 #undef __FUNCT__ 3825 #define __FUNCT__ "DMGetDimension" 3826 /*@ 3827 DMGetDimension - Return the topological dimension of the DM 3828 3829 Not collective 3830 3831 Input Parameter: 3832 . dm - The DM 3833 3834 Output Parameter: 3835 . dim - The topological dimension 3836 3837 Level: beginner 3838 3839 .seealso: DMSetDimension(), DMCreate() 3840 @*/ 3841 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3842 { 3843 PetscFunctionBegin; 3844 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3845 PetscValidPointer(dim, 2); 3846 *dim = dm->dim; 3847 PetscFunctionReturn(0); 3848 } 3849 3850 #undef __FUNCT__ 3851 #define __FUNCT__ "DMSetDimension" 3852 /*@ 3853 DMSetDimension - Set the topological dimension of the DM 3854 3855 Collective on dm 3856 3857 Input Parameters: 3858 + dm - The DM 3859 - dim - The topological dimension 3860 3861 Level: beginner 3862 3863 .seealso: DMGetDimension(), DMCreate() 3864 @*/ 3865 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3866 { 3867 PetscFunctionBegin; 3868 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3869 PetscValidLogicalCollectiveInt(dm, dim, 2); 3870 dm->dim = dim; 3871 PetscFunctionReturn(0); 3872 } 3873 3874 #undef __FUNCT__ 3875 #define __FUNCT__ "DMGetDimPoints" 3876 /*@ 3877 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3878 3879 Collective on DM 3880 3881 Input Parameters: 3882 + dm - the DM 3883 - dim - the dimension 3884 3885 Output Parameters: 3886 + pStart - The first point of the given dimension 3887 . pEnd - The first point following points of the given dimension 3888 3889 Note: 3890 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3891 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3892 then the interval is empty. 3893 3894 Level: intermediate 3895 3896 .keywords: point, Hasse Diagram, dimension 3897 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3898 @*/ 3899 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3900 { 3901 PetscInt d; 3902 PetscErrorCode ierr; 3903 3904 PetscFunctionBegin; 3905 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3906 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3907 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3908 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3909 PetscFunctionReturn(0); 3910 } 3911 3912 #undef __FUNCT__ 3913 #define __FUNCT__ "DMSetCoordinates" 3914 /*@ 3915 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3916 3917 Collective on DM 3918 3919 Input Parameters: 3920 + dm - the DM 3921 - c - coordinate vector 3922 3923 Note: 3924 The coordinates do include those for ghost points, which are in the local vector 3925 3926 Level: intermediate 3927 3928 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3929 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3930 @*/ 3931 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3932 { 3933 PetscErrorCode ierr; 3934 3935 PetscFunctionBegin; 3936 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3937 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3938 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3939 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3940 dm->coordinates = c; 3941 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3942 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3943 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3944 PetscFunctionReturn(0); 3945 } 3946 3947 #undef __FUNCT__ 3948 #define __FUNCT__ "DMSetCoordinatesLocal" 3949 /*@ 3950 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3951 3952 Collective on DM 3953 3954 Input Parameters: 3955 + dm - the DM 3956 - c - coordinate vector 3957 3958 Note: 3959 The coordinates of ghost points can be set using DMSetCoordinates() 3960 followed by DMGetCoordinatesLocal(). This is intended to enable the 3961 setting of ghost coordinates outside of the domain. 3962 3963 Level: intermediate 3964 3965 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3966 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3967 @*/ 3968 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3969 { 3970 PetscErrorCode ierr; 3971 3972 PetscFunctionBegin; 3973 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3974 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3975 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3976 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3977 3978 dm->coordinatesLocal = c; 3979 3980 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3981 PetscFunctionReturn(0); 3982 } 3983 3984 #undef __FUNCT__ 3985 #define __FUNCT__ "DMGetCoordinates" 3986 /*@ 3987 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3988 3989 Not Collective 3990 3991 Input Parameter: 3992 . dm - the DM 3993 3994 Output Parameter: 3995 . c - global coordinate vector 3996 3997 Note: 3998 This is a borrowed reference, so the user should NOT destroy this vector 3999 4000 Each process has only the local coordinates (does NOT have the ghost coordinates). 4001 4002 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4003 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4004 4005 Level: intermediate 4006 4007 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4008 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4009 @*/ 4010 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4011 { 4012 PetscErrorCode ierr; 4013 4014 PetscFunctionBegin; 4015 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4016 PetscValidPointer(c,2); 4017 if (!dm->coordinates && dm->coordinatesLocal) { 4018 DM cdm = NULL; 4019 4020 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4021 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4022 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4023 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4024 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4025 } 4026 *c = dm->coordinates; 4027 PetscFunctionReturn(0); 4028 } 4029 4030 #undef __FUNCT__ 4031 #define __FUNCT__ "DMGetCoordinatesLocal" 4032 /*@ 4033 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4034 4035 Collective on DM 4036 4037 Input Parameter: 4038 . dm - the DM 4039 4040 Output Parameter: 4041 . c - coordinate vector 4042 4043 Note: 4044 This is a borrowed reference, so the user should NOT destroy this vector 4045 4046 Each process has the local and ghost coordinates 4047 4048 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4049 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4050 4051 Level: intermediate 4052 4053 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4054 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4055 @*/ 4056 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4057 { 4058 PetscErrorCode ierr; 4059 4060 PetscFunctionBegin; 4061 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4062 PetscValidPointer(c,2); 4063 if (!dm->coordinatesLocal && dm->coordinates) { 4064 DM cdm = NULL; 4065 4066 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4067 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4068 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4069 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4070 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4071 } 4072 *c = dm->coordinatesLocal; 4073 PetscFunctionReturn(0); 4074 } 4075 4076 #undef __FUNCT__ 4077 #define __FUNCT__ "DMGetCoordinateDM" 4078 /*@ 4079 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4080 4081 Collective on DM 4082 4083 Input Parameter: 4084 . dm - the DM 4085 4086 Output Parameter: 4087 . cdm - coordinate DM 4088 4089 Level: intermediate 4090 4091 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4092 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4093 @*/ 4094 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4095 { 4096 PetscErrorCode ierr; 4097 4098 PetscFunctionBegin; 4099 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4100 PetscValidPointer(cdm,2); 4101 if (!dm->coordinateDM) { 4102 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4103 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4104 } 4105 *cdm = dm->coordinateDM; 4106 PetscFunctionReturn(0); 4107 } 4108 4109 #undef __FUNCT__ 4110 #define __FUNCT__ "DMSetCoordinateDM" 4111 /*@ 4112 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4113 4114 Logically Collective on DM 4115 4116 Input Parameters: 4117 + dm - the DM 4118 - cdm - coordinate DM 4119 4120 Level: intermediate 4121 4122 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4123 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4124 @*/ 4125 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4126 { 4127 PetscErrorCode ierr; 4128 4129 PetscFunctionBegin; 4130 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4131 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4132 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4133 dm->coordinateDM = cdm; 4134 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 4135 PetscFunctionReturn(0); 4136 } 4137 4138 #undef __FUNCT__ 4139 #define __FUNCT__ "DMGetCoordinateDim" 4140 /*@ 4141 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4142 4143 Not Collective 4144 4145 Input Parameter: 4146 . dm - The DM object 4147 4148 Output Parameter: 4149 . dim - The embedding dimension 4150 4151 Level: intermediate 4152 4153 .keywords: mesh, coordinates 4154 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4155 @*/ 4156 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4157 { 4158 PetscFunctionBegin; 4159 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4160 PetscValidPointer(dim, 2); 4161 if (dm->dimEmbed == PETSC_DEFAULT) { 4162 dm->dimEmbed = dm->dim; 4163 } 4164 *dim = dm->dimEmbed; 4165 PetscFunctionReturn(0); 4166 } 4167 4168 #undef __FUNCT__ 4169 #define __FUNCT__ "DMSetCoordinateDim" 4170 /*@ 4171 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4172 4173 Not Collective 4174 4175 Input Parameters: 4176 + dm - The DM object 4177 - dim - The embedding dimension 4178 4179 Level: intermediate 4180 4181 .keywords: mesh, coordinates 4182 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4183 @*/ 4184 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4185 { 4186 PetscFunctionBegin; 4187 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4188 dm->dimEmbed = dim; 4189 PetscFunctionReturn(0); 4190 } 4191 4192 #undef __FUNCT__ 4193 #define __FUNCT__ "DMGetCoordinateSection" 4194 /*@ 4195 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4196 4197 Not Collective 4198 4199 Input Parameter: 4200 . dm - The DM object 4201 4202 Output Parameter: 4203 . section - The PetscSection object 4204 4205 Level: intermediate 4206 4207 .keywords: mesh, coordinates 4208 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4209 @*/ 4210 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4211 { 4212 DM cdm; 4213 PetscErrorCode ierr; 4214 4215 PetscFunctionBegin; 4216 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4217 PetscValidPointer(section, 2); 4218 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4219 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4220 PetscFunctionReturn(0); 4221 } 4222 4223 #undef __FUNCT__ 4224 #define __FUNCT__ "DMSetCoordinateSection" 4225 /*@ 4226 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4227 4228 Not Collective 4229 4230 Input Parameters: 4231 + dm - The DM object 4232 . dim - The embedding dimension, or PETSC_DETERMINE 4233 - section - The PetscSection object 4234 4235 Level: intermediate 4236 4237 .keywords: mesh, coordinates 4238 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4239 @*/ 4240 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4241 { 4242 DM cdm; 4243 PetscErrorCode ierr; 4244 4245 PetscFunctionBegin; 4246 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4247 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4248 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4249 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4250 if (dim == PETSC_DETERMINE) { 4251 PetscInt d = dim; 4252 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4253 4254 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4255 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4256 pStart = PetscMax(vStart, pStart); 4257 pEnd = PetscMin(vEnd, pEnd); 4258 for (v = pStart; v < pEnd; ++v) { 4259 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4260 if (dd) {d = dd; break;} 4261 } 4262 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4263 } 4264 PetscFunctionReturn(0); 4265 } 4266 4267 #undef __FUNCT__ 4268 #define __FUNCT__ "DMGetPeriodicity" 4269 /*@C 4270 DMSetPeriodicity - Set the description of mesh periodicity 4271 4272 Input Parameters: 4273 + dm - The DM object 4274 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4275 . L - If we assume the mesh is a torus, this is the length of each coordinate 4276 - bd - This describes the type of periodicity in each topological dimension 4277 4278 Level: developer 4279 4280 .seealso: DMGetPeriodicity() 4281 @*/ 4282 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4283 { 4284 PetscFunctionBegin; 4285 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4286 if (L) *L = dm->L; 4287 if (maxCell) *maxCell = dm->maxCell; 4288 if (bd) *bd = dm->bdtype; 4289 PetscFunctionReturn(0); 4290 } 4291 4292 #undef __FUNCT__ 4293 #define __FUNCT__ "DMSetPeriodicity" 4294 /*@C 4295 DMSetPeriodicity - Set the description of mesh periodicity 4296 4297 Input Parameters: 4298 + dm - The DM object 4299 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4300 . L - If we assume the mesh is a torus, this is the length of each coordinate 4301 - bd - This describes the type of periodicity in each topological dimension 4302 4303 Level: developer 4304 4305 .seealso: DMGetPeriodicity() 4306 @*/ 4307 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4308 { 4309 PetscInt dim, d; 4310 PetscErrorCode ierr; 4311 4312 PetscFunctionBegin; 4313 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4314 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4315 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4316 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4317 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4318 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4319 PetscFunctionReturn(0); 4320 } 4321 4322 #undef __FUNCT__ 4323 #define __FUNCT__ "DMLocatePoints" 4324 /*@ 4325 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4326 4327 Not collective 4328 4329 Input Parameters: 4330 + dm - The DM 4331 - v - The Vec of points 4332 4333 Output Parameter: 4334 . cells - The local cell numbers for cells which contain the points 4335 4336 Level: developer 4337 4338 .keywords: point location, mesh 4339 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4340 @*/ 4341 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4342 { 4343 PetscErrorCode ierr; 4344 4345 PetscFunctionBegin; 4346 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4347 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4348 PetscValidPointer(cells,3); 4349 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4350 if (dm->ops->locatepoints) { 4351 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4352 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4353 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4354 PetscFunctionReturn(0); 4355 } 4356 4357 #undef __FUNCT__ 4358 #define __FUNCT__ "DMGetOutputDM" 4359 /*@ 4360 DMGetOutputDM - Retrieve the DM associated with the layout for output 4361 4362 Input Parameter: 4363 . dm - The original DM 4364 4365 Output Parameter: 4366 . odm - The DM which provides the layout for output 4367 4368 Level: intermediate 4369 4370 .seealso: VecView(), DMGetDefaultGlobalSection() 4371 @*/ 4372 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4373 { 4374 PetscSection section; 4375 PetscBool hasConstraints; 4376 PetscErrorCode ierr; 4377 4378 PetscFunctionBegin; 4379 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4380 PetscValidPointer(odm,2); 4381 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4382 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4383 if (!hasConstraints) { 4384 *odm = dm; 4385 PetscFunctionReturn(0); 4386 } 4387 if (!dm->dmBC) { 4388 PetscSection newSection, gsection; 4389 PetscSF sf; 4390 4391 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4392 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4393 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4394 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4395 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4396 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4397 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4398 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4399 } 4400 *odm = dm->dmBC; 4401 PetscFunctionReturn(0); 4402 } 4403 4404 #undef __FUNCT__ 4405 #define __FUNCT__ "DMGetOutputSequenceNumber" 4406 /*@ 4407 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4408 4409 Input Parameter: 4410 . dm - The original DM 4411 4412 Output Parameters: 4413 + num - The output sequence number 4414 - val - The output sequence value 4415 4416 Level: intermediate 4417 4418 Note: This is intended for output that should appear in sequence, for instance 4419 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4420 4421 .seealso: VecView() 4422 @*/ 4423 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4424 { 4425 PetscFunctionBegin; 4426 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4427 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4428 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4429 PetscFunctionReturn(0); 4430 } 4431 4432 #undef __FUNCT__ 4433 #define __FUNCT__ "DMSetOutputSequenceNumber" 4434 /*@ 4435 DMSetOutputSequenceNumber - Set the sequence number/value for output 4436 4437 Input Parameters: 4438 + dm - The original DM 4439 . num - The output sequence number 4440 - val - The output sequence value 4441 4442 Level: intermediate 4443 4444 Note: This is intended for output that should appear in sequence, for instance 4445 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4446 4447 .seealso: VecView() 4448 @*/ 4449 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4450 { 4451 PetscFunctionBegin; 4452 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4453 dm->outputSequenceNum = num; 4454 dm->outputSequenceVal = val; 4455 PetscFunctionReturn(0); 4456 } 4457 4458 #undef __FUNCT__ 4459 #define __FUNCT__ "DMOutputSequenceLoad" 4460 /*@C 4461 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4462 4463 Input Parameters: 4464 + dm - The original DM 4465 . name - The sequence name 4466 - num - The output sequence number 4467 4468 Output Parameter: 4469 . val - The output sequence value 4470 4471 Level: intermediate 4472 4473 Note: This is intended for output that should appear in sequence, for instance 4474 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4475 4476 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4477 @*/ 4478 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4479 { 4480 PetscBool ishdf5; 4481 PetscErrorCode ierr; 4482 4483 PetscFunctionBegin; 4484 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4485 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4486 PetscValidPointer(val,4); 4487 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4488 if (ishdf5) { 4489 #if defined(PETSC_HAVE_HDF5) 4490 PetscScalar value; 4491 4492 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4493 *val = PetscRealPart(value); 4494 #endif 4495 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4496 PetscFunctionReturn(0); 4497 } 4498 4499 #undef __FUNCT__ 4500 #define __FUNCT__ "DMGetUseNatural" 4501 /*@ 4502 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 4503 4504 Not collective 4505 4506 Input Parameter: 4507 . dm - The DM 4508 4509 Output Parameter: 4510 . useNatural - The flag to build the mapping to a natural order during distribution 4511 4512 Level: beginner 4513 4514 .seealso: DMSetUseNatural(), DMCreate() 4515 @*/ 4516 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 4517 { 4518 PetscFunctionBegin; 4519 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4520 PetscValidPointer(useNatural, 2); 4521 *useNatural = dm->useNatural; 4522 PetscFunctionReturn(0); 4523 } 4524 4525 #undef __FUNCT__ 4526 #define __FUNCT__ "DMSetUseNatural" 4527 /*@ 4528 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 4529 4530 Collective on dm 4531 4532 Input Parameters: 4533 + dm - The DM 4534 - useNatural - The flag to build the mapping to a natural order during distribution 4535 4536 Level: beginner 4537 4538 .seealso: DMGetUseNatural(), DMCreate() 4539 @*/ 4540 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 4541 { 4542 PetscFunctionBegin; 4543 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4544 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 4545 dm->useNatural = useNatural; 4546 PetscFunctionReturn(0); 4547 } 4548 4549 #undef __FUNCT__ 4550 #define __FUNCT__ 4551 4552 #undef __FUNCT__ 4553 #define __FUNCT__ "DMCreateLabel" 4554 /*@C 4555 DMCreateLabel - Create a label of the given name if it does not already exist 4556 4557 Not Collective 4558 4559 Input Parameters: 4560 + dm - The DM object 4561 - name - The label name 4562 4563 Level: intermediate 4564 4565 .keywords: mesh 4566 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4567 @*/ 4568 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 4569 { 4570 DMLabelLink next = dm->labels->next; 4571 PetscBool flg = PETSC_FALSE; 4572 PetscErrorCode ierr; 4573 4574 PetscFunctionBegin; 4575 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4576 PetscValidCharPointer(name, 2); 4577 while (next) { 4578 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 4579 if (flg) break; 4580 next = next->next; 4581 } 4582 if (!flg) { 4583 DMLabelLink tmpLabel; 4584 4585 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 4586 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 4587 tmpLabel->output = PETSC_TRUE; 4588 tmpLabel->next = dm->labels->next; 4589 dm->labels->next = tmpLabel; 4590 } 4591 PetscFunctionReturn(0); 4592 } 4593 4594 #undef __FUNCT__ 4595 #define __FUNCT__ "DMGetLabelValue" 4596 /*@C 4597 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 4598 4599 Not Collective 4600 4601 Input Parameters: 4602 + dm - The DM object 4603 . name - The label name 4604 - point - The mesh point 4605 4606 Output Parameter: 4607 . value - The label value for this point, or -1 if the point is not in the label 4608 4609 Level: beginner 4610 4611 .keywords: mesh 4612 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 4613 @*/ 4614 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 4615 { 4616 DMLabel label; 4617 PetscErrorCode ierr; 4618 4619 PetscFunctionBegin; 4620 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4621 PetscValidCharPointer(name, 2); 4622 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4623 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); 4624 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 4625 PetscFunctionReturn(0); 4626 } 4627 4628 #undef __FUNCT__ 4629 #define __FUNCT__ "DMSetLabelValue" 4630 /*@C 4631 DMSetLabelValue - Add a point to a Sieve Label with given value 4632 4633 Not Collective 4634 4635 Input Parameters: 4636 + dm - The DM object 4637 . name - The label name 4638 . point - The mesh point 4639 - value - The label value for this point 4640 4641 Output Parameter: 4642 4643 Level: beginner 4644 4645 .keywords: mesh 4646 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 4647 @*/ 4648 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 4649 { 4650 DMLabel label; 4651 PetscErrorCode ierr; 4652 4653 PetscFunctionBegin; 4654 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4655 PetscValidCharPointer(name, 2); 4656 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4657 if (!label) { 4658 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 4659 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4660 } 4661 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 4662 PetscFunctionReturn(0); 4663 } 4664 4665 #undef __FUNCT__ 4666 #define __FUNCT__ "DMClearLabelValue" 4667 /*@C 4668 DMClearLabelValue - Remove a point from a Sieve Label with given value 4669 4670 Not Collective 4671 4672 Input Parameters: 4673 + dm - The DM object 4674 . name - The label name 4675 . point - The mesh point 4676 - value - The label value for this point 4677 4678 Output Parameter: 4679 4680 Level: beginner 4681 4682 .keywords: mesh 4683 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 4684 @*/ 4685 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 4686 { 4687 DMLabel label; 4688 PetscErrorCode ierr; 4689 4690 PetscFunctionBegin; 4691 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4692 PetscValidCharPointer(name, 2); 4693 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4694 if (!label) PetscFunctionReturn(0); 4695 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 4696 PetscFunctionReturn(0); 4697 } 4698 4699 #undef __FUNCT__ 4700 #define __FUNCT__ "DMGetLabelSize" 4701 /*@C 4702 DMGetLabelSize - Get the number of different integer ids in a Label 4703 4704 Not Collective 4705 4706 Input Parameters: 4707 + dm - The DM object 4708 - name - The label name 4709 4710 Output Parameter: 4711 . size - The number of different integer ids, or 0 if the label does not exist 4712 4713 Level: beginner 4714 4715 .keywords: mesh 4716 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 4717 @*/ 4718 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 4719 { 4720 DMLabel label; 4721 PetscErrorCode ierr; 4722 4723 PetscFunctionBegin; 4724 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4725 PetscValidCharPointer(name, 2); 4726 PetscValidPointer(size, 3); 4727 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4728 *size = 0; 4729 if (!label) PetscFunctionReturn(0); 4730 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 4731 PetscFunctionReturn(0); 4732 } 4733 4734 #undef __FUNCT__ 4735 #define __FUNCT__ "DMGetLabelIdIS" 4736 /*@C 4737 DMGetLabelIdIS - Get the integer ids in a label 4738 4739 Not Collective 4740 4741 Input Parameters: 4742 + mesh - The DM object 4743 - name - The label name 4744 4745 Output Parameter: 4746 . ids - The integer ids, or NULL if the label does not exist 4747 4748 Level: beginner 4749 4750 .keywords: mesh 4751 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 4752 @*/ 4753 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 4754 { 4755 DMLabel label; 4756 PetscErrorCode ierr; 4757 4758 PetscFunctionBegin; 4759 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4760 PetscValidCharPointer(name, 2); 4761 PetscValidPointer(ids, 3); 4762 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4763 *ids = NULL; 4764 if (!label) PetscFunctionReturn(0); 4765 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 4766 PetscFunctionReturn(0); 4767 } 4768 4769 #undef __FUNCT__ 4770 #define __FUNCT__ "DMGetStratumSize" 4771 /*@C 4772 DMGetStratumSize - Get the number of points in a label stratum 4773 4774 Not Collective 4775 4776 Input Parameters: 4777 + dm - The DM object 4778 . name - The label name 4779 - value - The stratum value 4780 4781 Output Parameter: 4782 . size - The stratum size 4783 4784 Level: beginner 4785 4786 .keywords: mesh 4787 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 4788 @*/ 4789 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 4790 { 4791 DMLabel label; 4792 PetscErrorCode ierr; 4793 4794 PetscFunctionBegin; 4795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4796 PetscValidCharPointer(name, 2); 4797 PetscValidPointer(size, 4); 4798 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4799 *size = 0; 4800 if (!label) PetscFunctionReturn(0); 4801 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 4802 PetscFunctionReturn(0); 4803 } 4804 4805 #undef __FUNCT__ 4806 #define __FUNCT__ "DMGetStratumIS" 4807 /*@C 4808 DMGetStratumIS - Get the points in a label stratum 4809 4810 Not Collective 4811 4812 Input Parameters: 4813 + dm - The DM object 4814 . name - The label name 4815 - value - The stratum value 4816 4817 Output Parameter: 4818 . points - The stratum points, or NULL if the label does not exist or does not have that value 4819 4820 Level: beginner 4821 4822 .keywords: mesh 4823 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 4824 @*/ 4825 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 4826 { 4827 DMLabel label; 4828 PetscErrorCode ierr; 4829 4830 PetscFunctionBegin; 4831 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4832 PetscValidCharPointer(name, 2); 4833 PetscValidPointer(points, 4); 4834 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4835 *points = NULL; 4836 if (!label) PetscFunctionReturn(0); 4837 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 4838 PetscFunctionReturn(0); 4839 } 4840 4841 #undef __FUNCT__ 4842 #define __FUNCT__ "DMClearLabelStratum" 4843 /*@C 4844 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 4845 4846 Not Collective 4847 4848 Input Parameters: 4849 + dm - The DM object 4850 . name - The label name 4851 - value - The label value for this point 4852 4853 Output Parameter: 4854 4855 Level: beginner 4856 4857 .keywords: mesh 4858 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 4859 @*/ 4860 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 4861 { 4862 DMLabel label; 4863 PetscErrorCode ierr; 4864 4865 PetscFunctionBegin; 4866 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4867 PetscValidCharPointer(name, 2); 4868 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4869 if (!label) PetscFunctionReturn(0); 4870 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 4871 PetscFunctionReturn(0); 4872 } 4873 4874 #undef __FUNCT__ 4875 #define __FUNCT__ "DMGetNumLabels" 4876 /*@ 4877 DMGetNumLabels - Return the number of labels defined by the mesh 4878 4879 Not Collective 4880 4881 Input Parameter: 4882 . dm - The DM object 4883 4884 Output Parameter: 4885 . numLabels - the number of Labels 4886 4887 Level: intermediate 4888 4889 .keywords: mesh 4890 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4891 @*/ 4892 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 4893 { 4894 DMLabelLink next = dm->labels->next; 4895 PetscInt n = 0; 4896 4897 PetscFunctionBegin; 4898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4899 PetscValidPointer(numLabels, 2); 4900 while (next) {++n; next = next->next;} 4901 *numLabels = n; 4902 PetscFunctionReturn(0); 4903 } 4904 4905 #undef __FUNCT__ 4906 #define __FUNCT__ "DMGetLabelName" 4907 /*@C 4908 DMGetLabelName - Return the name of nth label 4909 4910 Not Collective 4911 4912 Input Parameters: 4913 + dm - The DM object 4914 - n - the label number 4915 4916 Output Parameter: 4917 . name - the label name 4918 4919 Level: intermediate 4920 4921 .keywords: mesh 4922 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4923 @*/ 4924 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 4925 { 4926 DMLabelLink next = dm->labels->next; 4927 PetscInt l = 0; 4928 4929 PetscFunctionBegin; 4930 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4931 PetscValidPointer(name, 3); 4932 while (next) { 4933 if (l == n) { 4934 *name = next->label->name; 4935 PetscFunctionReturn(0); 4936 } 4937 ++l; 4938 next = next->next; 4939 } 4940 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 4941 } 4942 4943 #undef __FUNCT__ 4944 #define __FUNCT__ "DMHasLabel" 4945 /*@C 4946 DMHasLabel - Determine whether the mesh has a label of a given name 4947 4948 Not Collective 4949 4950 Input Parameters: 4951 + dm - The DM object 4952 - name - The label name 4953 4954 Output Parameter: 4955 . hasLabel - PETSC_TRUE if the label is present 4956 4957 Level: intermediate 4958 4959 .keywords: mesh 4960 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4961 @*/ 4962 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 4963 { 4964 DMLabelLink next = dm->labels->next; 4965 PetscErrorCode ierr; 4966 4967 PetscFunctionBegin; 4968 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4969 PetscValidCharPointer(name, 2); 4970 PetscValidPointer(hasLabel, 3); 4971 *hasLabel = PETSC_FALSE; 4972 while (next) { 4973 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 4974 if (*hasLabel) break; 4975 next = next->next; 4976 } 4977 PetscFunctionReturn(0); 4978 } 4979 4980 #undef __FUNCT__ 4981 #define __FUNCT__ "DMGetLabel" 4982 /*@C 4983 DMGetLabel - Return the label of a given name, or NULL 4984 4985 Not Collective 4986 4987 Input Parameters: 4988 + dm - The DM object 4989 - name - The label name 4990 4991 Output Parameter: 4992 . label - The DMLabel, or NULL if the label is absent 4993 4994 Level: intermediate 4995 4996 .keywords: mesh 4997 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4998 @*/ 4999 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5000 { 5001 DMLabelLink next = dm->labels->next; 5002 PetscBool hasLabel; 5003 PetscErrorCode ierr; 5004 5005 PetscFunctionBegin; 5006 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5007 PetscValidCharPointer(name, 2); 5008 PetscValidPointer(label, 3); 5009 *label = NULL; 5010 while (next) { 5011 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5012 if (hasLabel) { 5013 *label = next->label; 5014 break; 5015 } 5016 next = next->next; 5017 } 5018 PetscFunctionReturn(0); 5019 } 5020 5021 #undef __FUNCT__ 5022 #define __FUNCT__ "DMGetLabelByNum" 5023 /*@C 5024 DMGetLabelByNum - Return the nth label 5025 5026 Not Collective 5027 5028 Input Parameters: 5029 + dm - The DM object 5030 - n - the label number 5031 5032 Output Parameter: 5033 . label - the label 5034 5035 Level: intermediate 5036 5037 .keywords: mesh 5038 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5039 @*/ 5040 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5041 { 5042 DMLabelLink next = dm->labels->next; 5043 PetscInt l = 0; 5044 5045 PetscFunctionBegin; 5046 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5047 PetscValidPointer(label, 3); 5048 while (next) { 5049 if (l == n) { 5050 *label = next->label; 5051 PetscFunctionReturn(0); 5052 } 5053 ++l; 5054 next = next->next; 5055 } 5056 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5057 } 5058 5059 #undef __FUNCT__ 5060 #define __FUNCT__ "DMAddLabel" 5061 /*@C 5062 DMAddLabel - Add the label to this mesh 5063 5064 Not Collective 5065 5066 Input Parameters: 5067 + dm - The DM object 5068 - label - The DMLabel 5069 5070 Level: developer 5071 5072 .keywords: mesh 5073 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5074 @*/ 5075 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5076 { 5077 DMLabelLink tmpLabel; 5078 PetscBool hasLabel; 5079 PetscErrorCode ierr; 5080 5081 PetscFunctionBegin; 5082 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5083 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5084 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5085 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5086 tmpLabel->label = label; 5087 tmpLabel->output = PETSC_TRUE; 5088 tmpLabel->next = dm->labels->next; 5089 dm->labels->next = tmpLabel; 5090 PetscFunctionReturn(0); 5091 } 5092 5093 #undef __FUNCT__ 5094 #define __FUNCT__ "DMRemoveLabel" 5095 /*@C 5096 DMRemoveLabel - Remove the label from this mesh 5097 5098 Not Collective 5099 5100 Input Parameters: 5101 + dm - The DM object 5102 - name - The label name 5103 5104 Output Parameter: 5105 . label - The DMLabel, or NULL if the label is absent 5106 5107 Level: developer 5108 5109 .keywords: mesh 5110 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5111 @*/ 5112 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5113 { 5114 DMLabelLink next = dm->labels->next; 5115 DMLabelLink last = NULL; 5116 PetscBool hasLabel; 5117 PetscErrorCode ierr; 5118 5119 PetscFunctionBegin; 5120 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5121 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5122 *label = NULL; 5123 if (!hasLabel) PetscFunctionReturn(0); 5124 while (next) { 5125 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5126 if (hasLabel) { 5127 if (last) last->next = next->next; 5128 else dm->labels->next = next->next; 5129 next->next = NULL; 5130 *label = next->label; 5131 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5132 if (hasLabel) { 5133 dm->depthLabel = NULL; 5134 } 5135 ierr = PetscFree(next);CHKERRQ(ierr); 5136 break; 5137 } 5138 last = next; 5139 next = next->next; 5140 } 5141 PetscFunctionReturn(0); 5142 } 5143 5144 #undef __FUNCT__ 5145 #define __FUNCT__ "DMGetLabelOutput" 5146 /*@C 5147 DMGetLabelOutput - Get the output flag for a given label 5148 5149 Not Collective 5150 5151 Input Parameters: 5152 + dm - The DM object 5153 - name - The label name 5154 5155 Output Parameter: 5156 . output - The flag for output 5157 5158 Level: developer 5159 5160 .keywords: mesh 5161 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5162 @*/ 5163 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5164 { 5165 DMLabelLink next = dm->labels->next; 5166 PetscErrorCode ierr; 5167 5168 PetscFunctionBegin; 5169 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5170 PetscValidPointer(name, 2); 5171 PetscValidPointer(output, 3); 5172 while (next) { 5173 PetscBool flg; 5174 5175 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5176 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5177 next = next->next; 5178 } 5179 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5180 } 5181 5182 #undef __FUNCT__ 5183 #define __FUNCT__ "DMSetLabelOutput" 5184 /*@C 5185 DMSetLabelOutput - Set the output flag for a given label 5186 5187 Not Collective 5188 5189 Input Parameters: 5190 + dm - The DM object 5191 . name - The label name 5192 - output - The flag for output 5193 5194 Level: developer 5195 5196 .keywords: mesh 5197 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5198 @*/ 5199 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5200 { 5201 DMLabelLink next = dm->labels->next; 5202 PetscErrorCode ierr; 5203 5204 PetscFunctionBegin; 5205 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5206 PetscValidPointer(name, 2); 5207 while (next) { 5208 PetscBool flg; 5209 5210 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5211 if (flg) {next->output = output; PetscFunctionReturn(0);} 5212 next = next->next; 5213 } 5214 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5215 } 5216 5217 5218 #undef __FUNCT__ 5219 #define __FUNCT__ "DMCopyLabels" 5220 /*@ 5221 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5222 5223 Collective on DM 5224 5225 Input Parameter: 5226 . dmA - The DMPlex object with initial labels 5227 5228 Output Parameter: 5229 . dmB - The DMPlex object with copied labels 5230 5231 Level: intermediate 5232 5233 Note: This is typically used when interpolating or otherwise adding to a mesh 5234 5235 .keywords: mesh 5236 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5237 @*/ 5238 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5239 { 5240 PetscInt numLabels, l; 5241 PetscErrorCode ierr; 5242 5243 PetscFunctionBegin; 5244 if (dmA == dmB) PetscFunctionReturn(0); 5245 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5246 for (l = 0; l < numLabels; ++l) { 5247 DMLabel label, labelNew; 5248 const char *name; 5249 PetscBool flg; 5250 5251 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5252 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5253 if (flg) continue; 5254 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5255 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5256 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5257 } 5258 PetscFunctionReturn(0); 5259 } 5260