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