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