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)(PetscOptionsObject,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 . mat - 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,Mat *mat) 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,mat);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 base point. 1848 - g - the global vector 1849 1850 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 1851 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 1852 1853 Level: beginner 1854 1855 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 1856 1857 @*/ 1858 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 1859 { 1860 PetscSF sf; 1861 PetscSection s, gs; 1862 DMLocalToGlobalHookLink link; 1863 PetscScalar *lArray, *gArray; 1864 PetscBool isInsert; 1865 PetscErrorCode ierr; 1866 1867 PetscFunctionBegin; 1868 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1869 for (link=dm->ltoghook; link; link=link->next) { 1870 if (link->beginhook) { 1871 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 1872 } 1873 } 1874 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 1875 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1876 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 1877 switch (mode) { 1878 case INSERT_VALUES: 1879 case INSERT_ALL_VALUES: 1880 isInsert = PETSC_TRUE; break; 1881 case ADD_VALUES: 1882 case ADD_ALL_VALUES: 1883 isInsert = PETSC_FALSE; break; 1884 default: 1885 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1886 } 1887 if (sf && !isInsert) { 1888 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1889 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1890 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr); 1891 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1892 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1893 } else if (s && isInsert) { 1894 PetscInt gStart, pStart, pEnd, p; 1895 1896 ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); 1897 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1898 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 1899 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1900 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1901 for (p = pStart; p < pEnd; ++p) { 1902 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 1903 1904 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 1905 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 1906 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 1907 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 1908 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 1909 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 1910 /* Ignore off-process data and points with no global data */ 1911 if (!gdof || goff < 0) continue; 1912 if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 1913 /* If no constraints are enforced in the global vector */ 1914 if (!gcdof) { 1915 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 1916 /* If constraints are enforced in the global vector */ 1917 } else if (cdof == gcdof) { 1918 const PetscInt *cdofs; 1919 PetscInt cind = 0; 1920 1921 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 1922 for (d = 0, e = 0; d < dof; ++d) { 1923 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 1924 gArray[goff-gStart+e++] = lArray[off+d]; 1925 } 1926 } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 1927 } 1928 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1929 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1930 } else { 1931 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1932 } 1933 PetscFunctionReturn(0); 1934 } 1935 1936 #undef __FUNCT__ 1937 #define __FUNCT__ "DMLocalToGlobalEnd" 1938 /*@ 1939 DMLocalToGlobalEnd - updates global vectors from local vectors 1940 1941 Neighbor-wise Collective on DM 1942 1943 Input Parameters: 1944 + dm - the DM object 1945 . l - the local vector 1946 . mode - INSERT_VALUES or ADD_VALUES 1947 - g - the global vector 1948 1949 1950 Level: beginner 1951 1952 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 1953 1954 @*/ 1955 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 1956 { 1957 PetscSF sf; 1958 PetscSection s; 1959 DMLocalToGlobalHookLink link; 1960 PetscBool isInsert; 1961 PetscErrorCode ierr; 1962 1963 PetscFunctionBegin; 1964 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1965 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1966 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 1967 switch (mode) { 1968 case INSERT_VALUES: 1969 case INSERT_ALL_VALUES: 1970 isInsert = PETSC_TRUE; break; 1971 case ADD_VALUES: 1972 case ADD_ALL_VALUES: 1973 isInsert = PETSC_FALSE; break; 1974 default: 1975 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1976 } 1977 if (sf && !isInsert) { 1978 PetscScalar *lArray, *gArray; 1979 1980 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1981 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1982 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPI_SUM);CHKERRQ(ierr); 1983 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1984 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1985 } else if (s && isInsert) { 1986 } else { 1987 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1988 } 1989 for (link=dm->ltoghook; link; link=link->next) { 1990 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 1991 } 1992 PetscFunctionReturn(0); 1993 } 1994 1995 #undef __FUNCT__ 1996 #define __FUNCT__ "DMLocalToLocalBegin" 1997 /*@ 1998 DMLocalToLocalBegin - Maps from a local vector (including ghost points 1999 that contain irrelevant values) to another local vector where the ghost 2000 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2001 2002 Neighbor-wise Collective on DM and Vec 2003 2004 Input Parameters: 2005 + dm - the DM object 2006 . g - the original local vector 2007 - mode - one of INSERT_VALUES or ADD_VALUES 2008 2009 Output Parameter: 2010 . l - the local vector with correct ghost values 2011 2012 Level: intermediate 2013 2014 Notes: 2015 The local vectors used here need not be the same as those 2016 obtained from DMCreateLocalVector(), BUT they 2017 must have the same parallel data layout; they could, for example, be 2018 obtained with VecDuplicate() from the DM originating vectors. 2019 2020 .keywords: DM, local-to-local, begin 2021 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2022 2023 @*/ 2024 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2025 { 2026 PetscErrorCode ierr; 2027 2028 PetscFunctionBegin; 2029 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2030 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2031 PetscFunctionReturn(0); 2032 } 2033 2034 #undef __FUNCT__ 2035 #define __FUNCT__ "DMLocalToLocalEnd" 2036 /*@ 2037 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2038 that contain irrelevant values) to another local vector where the ghost 2039 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2040 2041 Neighbor-wise Collective on DM and Vec 2042 2043 Input Parameters: 2044 + da - the DM object 2045 . g - the original local vector 2046 - mode - one of INSERT_VALUES or ADD_VALUES 2047 2048 Output Parameter: 2049 . l - the local vector with correct ghost values 2050 2051 Level: intermediate 2052 2053 Notes: 2054 The local vectors used here need not be the same as those 2055 obtained from DMCreateLocalVector(), BUT they 2056 must have the same parallel data layout; they could, for example, be 2057 obtained with VecDuplicate() from the DM originating vectors. 2058 2059 .keywords: DM, local-to-local, end 2060 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2061 2062 @*/ 2063 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2064 { 2065 PetscErrorCode ierr; 2066 2067 PetscFunctionBegin; 2068 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2069 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2070 PetscFunctionReturn(0); 2071 } 2072 2073 2074 #undef __FUNCT__ 2075 #define __FUNCT__ "DMCoarsen" 2076 /*@ 2077 DMCoarsen - Coarsens a DM object 2078 2079 Collective on DM 2080 2081 Input Parameter: 2082 + dm - the DM object 2083 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2084 2085 Output Parameter: 2086 . dmc - the coarsened DM 2087 2088 Level: developer 2089 2090 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2091 2092 @*/ 2093 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2094 { 2095 PetscErrorCode ierr; 2096 DMCoarsenHookLink link; 2097 2098 PetscFunctionBegin; 2099 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2100 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2101 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2102 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2103 (*dmc)->ctx = dm->ctx; 2104 (*dmc)->levelup = dm->levelup; 2105 (*dmc)->leveldown = dm->leveldown + 1; 2106 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2107 for (link=dm->coarsenhook; link; link=link->next) { 2108 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2109 } 2110 PetscFunctionReturn(0); 2111 } 2112 2113 #undef __FUNCT__ 2114 #define __FUNCT__ "DMCoarsenHookAdd" 2115 /*@C 2116 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2117 2118 Logically Collective 2119 2120 Input Arguments: 2121 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2122 . coarsenhook - function to run when setting up a coarser level 2123 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2124 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2125 2126 Calling sequence of coarsenhook: 2127 $ coarsenhook(DM fine,DM coarse,void *ctx); 2128 2129 + fine - fine level DM 2130 . coarse - coarse level DM to restrict problem to 2131 - ctx - optional user-defined function context 2132 2133 Calling sequence for restricthook: 2134 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2135 2136 + fine - fine level DM 2137 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2138 . rscale - scaling vector for restriction 2139 . inject - matrix restricting by injection 2140 . coarse - coarse level DM to update 2141 - ctx - optional user-defined function context 2142 2143 Level: advanced 2144 2145 Notes: 2146 This function is only needed if auxiliary data needs to be set up on coarse grids. 2147 2148 If this function is called multiple times, the hooks will be run in the order they are added. 2149 2150 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2151 extract the finest level information from its context (instead of from the SNES). 2152 2153 This function is currently not available from Fortran. 2154 2155 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2156 @*/ 2157 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2158 { 2159 PetscErrorCode ierr; 2160 DMCoarsenHookLink link,*p; 2161 2162 PetscFunctionBegin; 2163 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2164 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2165 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 2166 link->coarsenhook = coarsenhook; 2167 link->restricthook = restricthook; 2168 link->ctx = ctx; 2169 link->next = NULL; 2170 *p = link; 2171 PetscFunctionReturn(0); 2172 } 2173 2174 #undef __FUNCT__ 2175 #define __FUNCT__ "DMRestrict" 2176 /*@ 2177 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2178 2179 Collective if any hooks are 2180 2181 Input Arguments: 2182 + fine - finer DM to use as a base 2183 . restrct - restriction matrix, apply using MatRestrict() 2184 . inject - injection matrix, also use MatRestrict() 2185 - coarse - coarer DM to update 2186 2187 Level: developer 2188 2189 .seealso: DMCoarsenHookAdd(), MatRestrict() 2190 @*/ 2191 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2192 { 2193 PetscErrorCode ierr; 2194 DMCoarsenHookLink link; 2195 2196 PetscFunctionBegin; 2197 for (link=fine->coarsenhook; link; link=link->next) { 2198 if (link->restricthook) { 2199 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2200 } 2201 } 2202 PetscFunctionReturn(0); 2203 } 2204 2205 #undef __FUNCT__ 2206 #define __FUNCT__ "DMSubDomainHookAdd" 2207 /*@C 2208 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2209 2210 Logically Collective 2211 2212 Input Arguments: 2213 + global - global DM 2214 . ddhook - function to run to pass data to the decomposition DM upon its creation 2215 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2216 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2217 2218 2219 Calling sequence for ddhook: 2220 $ ddhook(DM global,DM block,void *ctx) 2221 2222 + global - global DM 2223 . block - block DM 2224 - ctx - optional user-defined function context 2225 2226 Calling sequence for restricthook: 2227 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2228 2229 + global - global DM 2230 . out - scatter to the outer (with ghost and overlap points) block vector 2231 . in - scatter to block vector values only owned locally 2232 . block - block DM 2233 - ctx - optional user-defined function context 2234 2235 Level: advanced 2236 2237 Notes: 2238 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2239 2240 If this function is called multiple times, the hooks will be run in the order they are added. 2241 2242 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2243 extract the global information from its context (instead of from the SNES). 2244 2245 This function is currently not available from Fortran. 2246 2247 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2248 @*/ 2249 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2250 { 2251 PetscErrorCode ierr; 2252 DMSubDomainHookLink link,*p; 2253 2254 PetscFunctionBegin; 2255 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2256 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2257 ierr = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr); 2258 link->restricthook = restricthook; 2259 link->ddhook = ddhook; 2260 link->ctx = ctx; 2261 link->next = NULL; 2262 *p = link; 2263 PetscFunctionReturn(0); 2264 } 2265 2266 #undef __FUNCT__ 2267 #define __FUNCT__ "DMSubDomainRestrict" 2268 /*@ 2269 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2270 2271 Collective if any hooks are 2272 2273 Input Arguments: 2274 + fine - finer DM to use as a base 2275 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2276 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2277 - coarse - coarer DM to update 2278 2279 Level: developer 2280 2281 .seealso: DMCoarsenHookAdd(), MatRestrict() 2282 @*/ 2283 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2284 { 2285 PetscErrorCode ierr; 2286 DMSubDomainHookLink link; 2287 2288 PetscFunctionBegin; 2289 for (link=global->subdomainhook; link; link=link->next) { 2290 if (link->restricthook) { 2291 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2292 } 2293 } 2294 PetscFunctionReturn(0); 2295 } 2296 2297 #undef __FUNCT__ 2298 #define __FUNCT__ "DMGetCoarsenLevel" 2299 /*@ 2300 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2301 2302 Not Collective 2303 2304 Input Parameter: 2305 . dm - the DM object 2306 2307 Output Parameter: 2308 . level - number of coarsenings 2309 2310 Level: developer 2311 2312 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2313 2314 @*/ 2315 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2316 { 2317 PetscFunctionBegin; 2318 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2319 *level = dm->leveldown; 2320 PetscFunctionReturn(0); 2321 } 2322 2323 2324 2325 #undef __FUNCT__ 2326 #define __FUNCT__ "DMRefineHierarchy" 2327 /*@C 2328 DMRefineHierarchy - Refines 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 refinement 2335 2336 Output Parameter: 2337 . dmf - the refined DM hierarchy 2338 2339 Level: developer 2340 2341 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2342 2343 @*/ 2344 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 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 if (dm->ops->refinehierarchy) { 2353 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2354 } else if (dm->ops->refine) { 2355 PetscInt i; 2356 2357 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2358 for (i=1; i<nlevels; i++) { 2359 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2360 } 2361 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2362 PetscFunctionReturn(0); 2363 } 2364 2365 #undef __FUNCT__ 2366 #define __FUNCT__ "DMCoarsenHierarchy" 2367 /*@C 2368 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2369 2370 Collective on DM 2371 2372 Input Parameter: 2373 + dm - the DM object 2374 - nlevels - the number of levels of coarsening 2375 2376 Output Parameter: 2377 . dmc - the coarsened DM hierarchy 2378 2379 Level: developer 2380 2381 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2382 2383 @*/ 2384 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2385 { 2386 PetscErrorCode ierr; 2387 2388 PetscFunctionBegin; 2389 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2390 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2391 if (nlevels == 0) PetscFunctionReturn(0); 2392 PetscValidPointer(dmc,3); 2393 if (dm->ops->coarsenhierarchy) { 2394 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2395 } else if (dm->ops->coarsen) { 2396 PetscInt i; 2397 2398 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2399 for (i=1; i<nlevels; i++) { 2400 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2401 } 2402 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2403 PetscFunctionReturn(0); 2404 } 2405 2406 #undef __FUNCT__ 2407 #define __FUNCT__ "DMCreateAggregates" 2408 /*@ 2409 DMCreateAggregates - Gets the aggregates that map between 2410 grids associated with two DMs. 2411 2412 Collective on DM 2413 2414 Input Parameters: 2415 + dmc - the coarse grid DM 2416 - dmf - the fine grid DM 2417 2418 Output Parameters: 2419 . rest - the restriction matrix (transpose of the projection matrix) 2420 2421 Level: intermediate 2422 2423 .keywords: interpolation, restriction, multigrid 2424 2425 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2426 @*/ 2427 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2428 { 2429 PetscErrorCode ierr; 2430 2431 PetscFunctionBegin; 2432 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2433 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2434 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2435 PetscFunctionReturn(0); 2436 } 2437 2438 #undef __FUNCT__ 2439 #define __FUNCT__ "DMSetApplicationContextDestroy" 2440 /*@C 2441 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2442 2443 Not Collective 2444 2445 Input Parameters: 2446 + dm - the DM object 2447 - destroy - the destroy function 2448 2449 Level: intermediate 2450 2451 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2452 2453 @*/ 2454 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2455 { 2456 PetscFunctionBegin; 2457 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2458 dm->ctxdestroy = destroy; 2459 PetscFunctionReturn(0); 2460 } 2461 2462 #undef __FUNCT__ 2463 #define __FUNCT__ "DMSetApplicationContext" 2464 /*@ 2465 DMSetApplicationContext - Set a user context into a DM object 2466 2467 Not Collective 2468 2469 Input Parameters: 2470 + dm - the DM object 2471 - ctx - the user context 2472 2473 Level: intermediate 2474 2475 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2476 2477 @*/ 2478 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2479 { 2480 PetscFunctionBegin; 2481 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2482 dm->ctx = ctx; 2483 PetscFunctionReturn(0); 2484 } 2485 2486 #undef __FUNCT__ 2487 #define __FUNCT__ "DMGetApplicationContext" 2488 /*@ 2489 DMGetApplicationContext - Gets a user context from a DM object 2490 2491 Not Collective 2492 2493 Input Parameter: 2494 . dm - the DM object 2495 2496 Output Parameter: 2497 . ctx - the user context 2498 2499 Level: intermediate 2500 2501 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2502 2503 @*/ 2504 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2505 { 2506 PetscFunctionBegin; 2507 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2508 *(void**)ctx = dm->ctx; 2509 PetscFunctionReturn(0); 2510 } 2511 2512 #undef __FUNCT__ 2513 #define __FUNCT__ "DMSetVariableBounds" 2514 /*@C 2515 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2516 2517 Logically Collective on DM 2518 2519 Input Parameter: 2520 + dm - the DM object 2521 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2522 2523 Level: intermediate 2524 2525 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2526 DMSetJacobian() 2527 2528 @*/ 2529 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2530 { 2531 PetscFunctionBegin; 2532 dm->ops->computevariablebounds = f; 2533 PetscFunctionReturn(0); 2534 } 2535 2536 #undef __FUNCT__ 2537 #define __FUNCT__ "DMHasVariableBounds" 2538 /*@ 2539 DMHasVariableBounds - does the DM object have a variable bounds function? 2540 2541 Not Collective 2542 2543 Input Parameter: 2544 . dm - the DM object to destroy 2545 2546 Output Parameter: 2547 . flg - PETSC_TRUE if the variable bounds function exists 2548 2549 Level: developer 2550 2551 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2552 2553 @*/ 2554 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2555 { 2556 PetscFunctionBegin; 2557 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2558 PetscFunctionReturn(0); 2559 } 2560 2561 #undef __FUNCT__ 2562 #define __FUNCT__ "DMComputeVariableBounds" 2563 /*@C 2564 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2565 2566 Logically Collective on DM 2567 2568 Input Parameters: 2569 . dm - the DM object 2570 2571 Output parameters: 2572 + xl - lower bound 2573 - xu - upper bound 2574 2575 Level: advanced 2576 2577 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2578 2579 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2580 2581 @*/ 2582 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2583 { 2584 PetscErrorCode ierr; 2585 2586 PetscFunctionBegin; 2587 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2588 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2589 if (dm->ops->computevariablebounds) { 2590 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2591 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2592 PetscFunctionReturn(0); 2593 } 2594 2595 #undef __FUNCT__ 2596 #define __FUNCT__ "DMHasColoring" 2597 /*@ 2598 DMHasColoring - does the DM object have a method of providing a coloring? 2599 2600 Not Collective 2601 2602 Input Parameter: 2603 . dm - the DM object 2604 2605 Output Parameter: 2606 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2607 2608 Level: developer 2609 2610 .seealso DMHasFunction(), DMCreateColoring() 2611 2612 @*/ 2613 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2614 { 2615 PetscFunctionBegin; 2616 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2617 PetscFunctionReturn(0); 2618 } 2619 2620 #undef __FUNCT__ 2621 #define __FUNCT__ "DMSetVec" 2622 /*@C 2623 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2624 2625 Collective on DM 2626 2627 Input Parameter: 2628 + dm - the DM object 2629 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2630 2631 Level: developer 2632 2633 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2634 2635 @*/ 2636 PetscErrorCode DMSetVec(DM dm,Vec x) 2637 { 2638 PetscErrorCode ierr; 2639 2640 PetscFunctionBegin; 2641 if (x) { 2642 if (!dm->x) { 2643 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2644 } 2645 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2646 } else if (dm->x) { 2647 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2648 } 2649 PetscFunctionReturn(0); 2650 } 2651 2652 PetscFunctionList DMList = NULL; 2653 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2654 2655 #undef __FUNCT__ 2656 #define __FUNCT__ "DMSetType" 2657 /*@C 2658 DMSetType - Builds a DM, for a particular DM implementation. 2659 2660 Collective on DM 2661 2662 Input Parameters: 2663 + dm - The DM object 2664 - method - The name of the DM type 2665 2666 Options Database Key: 2667 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2668 2669 Notes: 2670 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2671 2672 Level: intermediate 2673 2674 .keywords: DM, set, type 2675 .seealso: DMGetType(), DMCreate() 2676 @*/ 2677 PetscErrorCode DMSetType(DM dm, DMType method) 2678 { 2679 PetscErrorCode (*r)(DM); 2680 PetscBool match; 2681 PetscErrorCode ierr; 2682 2683 PetscFunctionBegin; 2684 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2685 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2686 if (match) PetscFunctionReturn(0); 2687 2688 if (!DMRegisterAllCalled) {ierr = DMRegisterAll();CHKERRQ(ierr);} 2689 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 2690 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2691 2692 if (dm->ops->destroy) { 2693 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2694 dm->ops->destroy = NULL; 2695 } 2696 ierr = (*r)(dm);CHKERRQ(ierr); 2697 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2698 PetscFunctionReturn(0); 2699 } 2700 2701 #undef __FUNCT__ 2702 #define __FUNCT__ "DMGetType" 2703 /*@C 2704 DMGetType - Gets the DM type name (as a string) from the DM. 2705 2706 Not Collective 2707 2708 Input Parameter: 2709 . dm - The DM 2710 2711 Output Parameter: 2712 . type - The DM type name 2713 2714 Level: intermediate 2715 2716 .keywords: DM, get, type, name 2717 .seealso: DMSetType(), DMCreate() 2718 @*/ 2719 PetscErrorCode DMGetType(DM dm, DMType *type) 2720 { 2721 PetscErrorCode ierr; 2722 2723 PetscFunctionBegin; 2724 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2725 PetscValidPointer(type,2); 2726 if (!DMRegisterAllCalled) { 2727 ierr = DMRegisterAll();CHKERRQ(ierr); 2728 } 2729 *type = ((PetscObject)dm)->type_name; 2730 PetscFunctionReturn(0); 2731 } 2732 2733 #undef __FUNCT__ 2734 #define __FUNCT__ "DMConvert" 2735 /*@C 2736 DMConvert - Converts a DM to another DM, either of the same or different type. 2737 2738 Collective on DM 2739 2740 Input Parameters: 2741 + dm - the DM 2742 - newtype - new DM type (use "same" for the same type) 2743 2744 Output Parameter: 2745 . M - pointer to new DM 2746 2747 Notes: 2748 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 2749 the MPI communicator of the generated DM is always the same as the communicator 2750 of the input DM. 2751 2752 Level: intermediate 2753 2754 .seealso: DMCreate() 2755 @*/ 2756 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 2757 { 2758 DM B; 2759 char convname[256]; 2760 PetscBool sametype, issame; 2761 PetscErrorCode ierr; 2762 2763 PetscFunctionBegin; 2764 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2765 PetscValidType(dm,1); 2766 PetscValidPointer(M,3); 2767 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 2768 ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); 2769 { 2770 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 2771 2772 /* 2773 Order of precedence: 2774 1) See if a specialized converter is known to the current DM. 2775 2) See if a specialized converter is known to the desired DM class. 2776 3) See if a good general converter is registered for the desired class 2777 4) See if a good general converter is known for the current matrix. 2778 5) Use a really basic converter. 2779 */ 2780 2781 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2782 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2783 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2784 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2785 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2786 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2787 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 2788 if (conv) goto foundconv; 2789 2790 /* 2) See if a specialized converter is known to the desired DM class. */ 2791 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 2792 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2793 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2794 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2795 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2796 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2797 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2798 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 2799 if (conv) { 2800 ierr = DMDestroy(&B);CHKERRQ(ierr); 2801 goto foundconv; 2802 } 2803 2804 #if 0 2805 /* 3) See if a good general converter is registered for the desired class */ 2806 conv = B->ops->convertfrom; 2807 ierr = DMDestroy(&B);CHKERRQ(ierr); 2808 if (conv) goto foundconv; 2809 2810 /* 4) See if a good general converter is known for the current matrix */ 2811 if (dm->ops->convert) { 2812 conv = dm->ops->convert; 2813 } 2814 if (conv) goto foundconv; 2815 #endif 2816 2817 /* 5) Use a really basic converter. */ 2818 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 2819 2820 foundconv: 2821 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2822 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 2823 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2824 } 2825 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 2826 PetscFunctionReturn(0); 2827 } 2828 2829 /*--------------------------------------------------------------------------------------------------------------------*/ 2830 2831 #undef __FUNCT__ 2832 #define __FUNCT__ "DMRegister" 2833 /*@C 2834 DMRegister - Adds a new DM component implementation 2835 2836 Not Collective 2837 2838 Input Parameters: 2839 + name - The name of a new user-defined creation routine 2840 - create_func - The creation routine itself 2841 2842 Notes: 2843 DMRegister() may be called multiple times to add several user-defined DMs 2844 2845 2846 Sample usage: 2847 .vb 2848 DMRegister("my_da", MyDMCreate); 2849 .ve 2850 2851 Then, your DM type can be chosen with the procedural interface via 2852 .vb 2853 DMCreate(MPI_Comm, DM *); 2854 DMSetType(DM,"my_da"); 2855 .ve 2856 or at runtime via the option 2857 .vb 2858 -da_type my_da 2859 .ve 2860 2861 Level: advanced 2862 2863 .keywords: DM, register 2864 .seealso: DMRegisterAll(), DMRegisterDestroy() 2865 2866 @*/ 2867 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 2868 { 2869 PetscErrorCode ierr; 2870 2871 PetscFunctionBegin; 2872 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 2873 PetscFunctionReturn(0); 2874 } 2875 2876 #undef __FUNCT__ 2877 #define __FUNCT__ "DMLoad" 2878 /*@C 2879 DMLoad - Loads a DM that has been stored in binary with DMView(). 2880 2881 Collective on PetscViewer 2882 2883 Input Parameters: 2884 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 2885 some related function before a call to DMLoad(). 2886 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 2887 HDF5 file viewer, obtained from PetscViewerHDF5Open() 2888 2889 Level: intermediate 2890 2891 Notes: 2892 The type is determined by the data in the file, any type set into the DM before this call is ignored. 2893 2894 Notes for advanced users: 2895 Most users should not need to know the details of the binary storage 2896 format, since DMLoad() and DMView() completely hide these details. 2897 But for anyone who's interested, the standard binary matrix storage 2898 format is 2899 .vb 2900 has not yet been determined 2901 .ve 2902 2903 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 2904 @*/ 2905 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 2906 { 2907 PetscBool isbinary, ishdf5; 2908 PetscErrorCode ierr; 2909 2910 PetscFunctionBegin; 2911 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 2912 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2913 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 2914 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2915 if (isbinary) { 2916 PetscInt classid; 2917 char type[256]; 2918 2919 ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr); 2920 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 2921 ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr); 2922 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 2923 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 2924 } else if (ishdf5) { 2925 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 2926 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 2927 PetscFunctionReturn(0); 2928 } 2929 2930 /******************************** FEM Support **********************************/ 2931 2932 #undef __FUNCT__ 2933 #define __FUNCT__ "DMPrintCellVector" 2934 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 2935 { 2936 PetscInt f; 2937 PetscErrorCode ierr; 2938 2939 PetscFunctionBegin; 2940 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2941 for (f = 0; f < len; ++f) { 2942 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 2943 } 2944 PetscFunctionReturn(0); 2945 } 2946 2947 #undef __FUNCT__ 2948 #define __FUNCT__ "DMPrintCellMatrix" 2949 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 2950 { 2951 PetscInt f, g; 2952 PetscErrorCode ierr; 2953 2954 PetscFunctionBegin; 2955 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2956 for (f = 0; f < rows; ++f) { 2957 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 2958 for (g = 0; g < cols; ++g) { 2959 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 2960 } 2961 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 2962 } 2963 PetscFunctionReturn(0); 2964 } 2965 2966 #undef __FUNCT__ 2967 #define __FUNCT__ "DMPrintLocalVec" 2968 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 2969 { 2970 PetscMPIInt rank, numProcs; 2971 PetscInt p; 2972 PetscErrorCode ierr; 2973 2974 PetscFunctionBegin; 2975 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 2976 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 2977 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 2978 for (p = 0; p < numProcs; ++p) { 2979 if (p == rank) { 2980 Vec x; 2981 2982 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 2983 ierr = VecCopy(X, x);CHKERRQ(ierr); 2984 ierr = VecChop(x, tol);CHKERRQ(ierr); 2985 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 2986 ierr = VecDestroy(&x);CHKERRQ(ierr); 2987 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 2988 } 2989 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 2990 } 2991 PetscFunctionReturn(0); 2992 } 2993 2994 #undef __FUNCT__ 2995 #define __FUNCT__ "DMGetDefaultSection" 2996 /*@ 2997 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 2998 2999 Input Parameter: 3000 . dm - The DM 3001 3002 Output Parameter: 3003 . section - The PetscSection 3004 3005 Level: intermediate 3006 3007 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3008 3009 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3010 @*/ 3011 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3012 { 3013 PetscErrorCode ierr; 3014 3015 PetscFunctionBegin; 3016 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3017 PetscValidPointer(section, 2); 3018 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3019 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3020 ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, "dm_", "-petscsection_view");CHKERRQ(ierr); 3021 } 3022 *section = dm->defaultSection; 3023 PetscFunctionReturn(0); 3024 } 3025 3026 #undef __FUNCT__ 3027 #define __FUNCT__ "DMSetDefaultSection" 3028 /*@ 3029 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3030 3031 Input Parameters: 3032 + dm - The DM 3033 - section - The PetscSection 3034 3035 Level: intermediate 3036 3037 Note: Any existing Section will be destroyed 3038 3039 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3040 @*/ 3041 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3042 { 3043 PetscInt numFields; 3044 PetscInt f; 3045 PetscErrorCode ierr; 3046 3047 PetscFunctionBegin; 3048 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3049 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3050 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3051 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3052 dm->defaultSection = section; 3053 ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr); 3054 if (numFields) { 3055 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3056 for (f = 0; f < numFields; ++f) { 3057 PetscObject disc; 3058 const char *name; 3059 3060 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3061 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3062 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3063 } 3064 } 3065 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3066 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3067 PetscFunctionReturn(0); 3068 } 3069 3070 #undef __FUNCT__ 3071 #define __FUNCT__ "DMGetDefaultConstraints" 3072 /*@ 3073 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3074 3075 not collective 3076 3077 Input Parameter: 3078 . dm - The DM 3079 3080 Output Parameter: 3081 + 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. 3082 - 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. 3083 3084 Level: advanced 3085 3086 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3087 3088 .seealso: DMSetDefaultConstraints() 3089 @*/ 3090 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3091 { 3092 PetscErrorCode ierr; 3093 3094 PetscFunctionBegin; 3095 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3096 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3097 if (section) {*section = dm->defaultConstraintSection;} 3098 if (mat) {*mat = dm->defaultConstraintMat;} 3099 PetscFunctionReturn(0); 3100 } 3101 3102 #undef __FUNCT__ 3103 #define __FUNCT__ "DMSetDefaultConstraints" 3104 /*@ 3105 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3106 3107 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(). 3108 3109 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. 3110 3111 collective on dm 3112 3113 Input Parameters: 3114 + dm - The DM 3115 + 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). 3116 - 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). 3117 3118 Level: advanced 3119 3120 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3121 3122 .seealso: DMGetDefaultConstraints() 3123 @*/ 3124 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3125 { 3126 PetscMPIInt result; 3127 PetscErrorCode ierr; 3128 3129 PetscFunctionBegin; 3130 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3131 if (section) { 3132 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3133 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3134 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3135 } 3136 if (mat) { 3137 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3138 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3139 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3140 } 3141 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3142 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3143 dm->defaultConstraintSection = section; 3144 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3145 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3146 dm->defaultConstraintMat = mat; 3147 PetscFunctionReturn(0); 3148 } 3149 3150 #undef __FUNCT__ 3151 #define __FUNCT__ "DMGetDefaultGlobalSection" 3152 /*@ 3153 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3154 3155 Collective on DM 3156 3157 Input Parameter: 3158 . dm - The DM 3159 3160 Output Parameter: 3161 . section - The PetscSection 3162 3163 Level: intermediate 3164 3165 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3166 3167 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3168 @*/ 3169 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3170 { 3171 PetscErrorCode ierr; 3172 3173 PetscFunctionBegin; 3174 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3175 PetscValidPointer(section, 2); 3176 if (!dm->defaultGlobalSection) { 3177 PetscSection s; 3178 3179 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3180 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3181 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3182 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3183 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3184 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3185 } 3186 *section = dm->defaultGlobalSection; 3187 PetscFunctionReturn(0); 3188 } 3189 3190 #undef __FUNCT__ 3191 #define __FUNCT__ "DMSetDefaultGlobalSection" 3192 /*@ 3193 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3194 3195 Input Parameters: 3196 + dm - The DM 3197 - section - The PetscSection, or NULL 3198 3199 Level: intermediate 3200 3201 Note: Any existing Section will be destroyed 3202 3203 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3204 @*/ 3205 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3206 { 3207 PetscErrorCode ierr; 3208 3209 PetscFunctionBegin; 3210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3211 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3212 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3213 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3214 dm->defaultGlobalSection = section; 3215 PetscFunctionReturn(0); 3216 } 3217 3218 #undef __FUNCT__ 3219 #define __FUNCT__ "DMGetDefaultSF" 3220 /*@ 3221 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3222 it is created from the default PetscSection layouts in the DM. 3223 3224 Input Parameter: 3225 . dm - The DM 3226 3227 Output Parameter: 3228 . sf - The PetscSF 3229 3230 Level: intermediate 3231 3232 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3233 3234 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3235 @*/ 3236 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3237 { 3238 PetscInt nroots; 3239 PetscErrorCode ierr; 3240 3241 PetscFunctionBegin; 3242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3243 PetscValidPointer(sf, 2); 3244 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3245 if (nroots < 0) { 3246 PetscSection section, gSection; 3247 3248 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3249 if (section) { 3250 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3251 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3252 } else { 3253 *sf = NULL; 3254 PetscFunctionReturn(0); 3255 } 3256 } 3257 *sf = dm->defaultSF; 3258 PetscFunctionReturn(0); 3259 } 3260 3261 #undef __FUNCT__ 3262 #define __FUNCT__ "DMSetDefaultSF" 3263 /*@ 3264 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3265 3266 Input Parameters: 3267 + dm - The DM 3268 - sf - The PetscSF 3269 3270 Level: intermediate 3271 3272 Note: Any previous SF is destroyed 3273 3274 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3275 @*/ 3276 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3277 { 3278 PetscErrorCode ierr; 3279 3280 PetscFunctionBegin; 3281 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3282 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3283 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3284 dm->defaultSF = sf; 3285 PetscFunctionReturn(0); 3286 } 3287 3288 #undef __FUNCT__ 3289 #define __FUNCT__ "DMCreateDefaultSF" 3290 /*@C 3291 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3292 describing the data layout. 3293 3294 Input Parameters: 3295 + dm - The DM 3296 . localSection - PetscSection describing the local data layout 3297 - globalSection - PetscSection describing the global data layout 3298 3299 Level: intermediate 3300 3301 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3302 @*/ 3303 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3304 { 3305 MPI_Comm comm; 3306 PetscLayout layout; 3307 const PetscInt *ranges; 3308 PetscInt *local; 3309 PetscSFNode *remote; 3310 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3311 PetscMPIInt size, rank; 3312 PetscErrorCode ierr; 3313 3314 PetscFunctionBegin; 3315 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3316 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3317 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3318 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3319 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3320 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3321 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3322 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3323 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3324 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3325 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3326 for (p = pStart; p < pEnd; ++p) { 3327 PetscInt gdof, gcdof; 3328 3329 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3330 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3331 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)); 3332 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3333 } 3334 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3335 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3336 for (p = pStart, l = 0; p < pEnd; ++p) { 3337 const PetscInt *cind; 3338 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3339 3340 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3341 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3342 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3343 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3344 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3345 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3346 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3347 if (!gdof) continue; /* Censored point */ 3348 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3349 if (gsize != dof-cdof) { 3350 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); 3351 cdof = 0; /* Ignore constraints */ 3352 } 3353 for (d = 0, c = 0; d < dof; ++d) { 3354 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3355 local[l+d-c] = off+d; 3356 } 3357 if (gdof < 0) { 3358 for (d = 0; d < gsize; ++d, ++l) { 3359 PetscInt offset = -(goff+1) + d, r; 3360 3361 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3362 if (r < 0) r = -(r+2); 3363 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); 3364 remote[l].rank = r; 3365 remote[l].index = offset - ranges[r]; 3366 } 3367 } else { 3368 for (d = 0; d < gsize; ++d, ++l) { 3369 remote[l].rank = rank; 3370 remote[l].index = goff+d - ranges[rank]; 3371 } 3372 } 3373 } 3374 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3375 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3376 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3377 PetscFunctionReturn(0); 3378 } 3379 3380 #undef __FUNCT__ 3381 #define __FUNCT__ "DMGetPointSF" 3382 /*@ 3383 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3384 3385 Input Parameter: 3386 . dm - The DM 3387 3388 Output Parameter: 3389 . sf - The PetscSF 3390 3391 Level: intermediate 3392 3393 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3394 3395 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3396 @*/ 3397 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3398 { 3399 PetscFunctionBegin; 3400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3401 PetscValidPointer(sf, 2); 3402 *sf = dm->sf; 3403 PetscFunctionReturn(0); 3404 } 3405 3406 #undef __FUNCT__ 3407 #define __FUNCT__ "DMSetPointSF" 3408 /*@ 3409 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3410 3411 Input Parameters: 3412 + dm - The DM 3413 - sf - The PetscSF 3414 3415 Level: intermediate 3416 3417 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3418 @*/ 3419 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3420 { 3421 PetscErrorCode ierr; 3422 3423 PetscFunctionBegin; 3424 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3425 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3426 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3427 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3428 dm->sf = sf; 3429 PetscFunctionReturn(0); 3430 } 3431 3432 #undef __FUNCT__ 3433 #define __FUNCT__ "DMGetDS" 3434 /*@ 3435 DMGetDS - Get the PetscDS 3436 3437 Input Parameter: 3438 . dm - The DM 3439 3440 Output Parameter: 3441 . prob - The PetscDS 3442 3443 Level: developer 3444 3445 .seealso: DMSetDS() 3446 @*/ 3447 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3448 { 3449 PetscFunctionBegin; 3450 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3451 PetscValidPointer(prob, 2); 3452 *prob = dm->prob; 3453 PetscFunctionReturn(0); 3454 } 3455 3456 #undef __FUNCT__ 3457 #define __FUNCT__ "DMSetDS" 3458 /*@ 3459 DMSetDS - Set the PetscDS 3460 3461 Input Parameters: 3462 + dm - The DM 3463 - prob - The PetscDS 3464 3465 Level: developer 3466 3467 .seealso: DMGetDS() 3468 @*/ 3469 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3470 { 3471 PetscErrorCode ierr; 3472 3473 PetscFunctionBegin; 3474 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3475 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3476 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3477 dm->prob = prob; 3478 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3479 PetscFunctionReturn(0); 3480 } 3481 3482 #undef __FUNCT__ 3483 #define __FUNCT__ "DMGetNumFields" 3484 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3485 { 3486 PetscErrorCode ierr; 3487 3488 PetscFunctionBegin; 3489 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3490 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3491 PetscFunctionReturn(0); 3492 } 3493 3494 #undef __FUNCT__ 3495 #define __FUNCT__ "DMSetNumFields" 3496 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3497 { 3498 PetscInt Nf, f; 3499 PetscErrorCode ierr; 3500 3501 PetscFunctionBegin; 3502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3503 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3504 for (f = Nf; f < numFields; ++f) { 3505 PetscContainer obj; 3506 3507 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3508 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3509 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3510 } 3511 PetscFunctionReturn(0); 3512 } 3513 3514 #undef __FUNCT__ 3515 #define __FUNCT__ "DMGetField" 3516 /*@ 3517 DMGetField - Return the discretization object for a given DM field 3518 3519 Not collective 3520 3521 Input Parameters: 3522 + dm - The DM 3523 - f - The field number 3524 3525 Output Parameter: 3526 . field - The discretization object 3527 3528 Level: developer 3529 3530 .seealso: DMSetField() 3531 @*/ 3532 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3533 { 3534 PetscErrorCode ierr; 3535 3536 PetscFunctionBegin; 3537 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3538 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3539 PetscFunctionReturn(0); 3540 } 3541 3542 #undef __FUNCT__ 3543 #define __FUNCT__ "DMSetField" 3544 /*@ 3545 DMSetField - Set the discretization object for a given DM field 3546 3547 Logically collective on DM 3548 3549 Input Parameters: 3550 + dm - The DM 3551 . f - The field number 3552 - field - The discretization object 3553 3554 Level: developer 3555 3556 .seealso: DMGetField() 3557 @*/ 3558 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3559 { 3560 PetscErrorCode ierr; 3561 3562 PetscFunctionBegin; 3563 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3564 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3565 PetscFunctionReturn(0); 3566 } 3567 3568 #undef __FUNCT__ 3569 #define __FUNCT__ "DMRestrictHook_Coordinates" 3570 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3571 { 3572 DM dm_coord,dmc_coord; 3573 PetscErrorCode ierr; 3574 Vec coords,ccoords; 3575 Mat inject; 3576 PetscFunctionBegin; 3577 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3578 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3579 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3580 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3581 if (coords && !ccoords) { 3582 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3583 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3584 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3585 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3586 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3587 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3588 } 3589 PetscFunctionReturn(0); 3590 } 3591 3592 #undef __FUNCT__ 3593 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3594 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3595 { 3596 DM dm_coord,subdm_coord; 3597 PetscErrorCode ierr; 3598 Vec coords,ccoords,clcoords; 3599 VecScatter *scat_i,*scat_g; 3600 PetscFunctionBegin; 3601 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3602 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3603 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3604 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3605 if (coords && !ccoords) { 3606 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3607 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3608 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3609 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3610 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3611 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3612 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3613 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3614 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3615 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3616 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3617 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3618 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3619 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3620 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3621 } 3622 PetscFunctionReturn(0); 3623 } 3624 3625 #undef __FUNCT__ 3626 #define __FUNCT__ "DMGetDimension" 3627 /*@ 3628 DMGetDimension - Return the topological dimension of the DM 3629 3630 Not collective 3631 3632 Input Parameter: 3633 . dm - The DM 3634 3635 Output Parameter: 3636 . dim - The topological dimension 3637 3638 Level: beginner 3639 3640 .seealso: DMSetDimension(), DMCreate() 3641 @*/ 3642 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3643 { 3644 PetscFunctionBegin; 3645 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3646 PetscValidPointer(dim, 2); 3647 *dim = dm->dim; 3648 PetscFunctionReturn(0); 3649 } 3650 3651 #undef __FUNCT__ 3652 #define __FUNCT__ "DMSetDimension" 3653 /*@ 3654 DMSetDimension - Set the topological dimension of the DM 3655 3656 Collective on dm 3657 3658 Input Parameters: 3659 + dm - The DM 3660 - dim - The topological dimension 3661 3662 Level: beginner 3663 3664 .seealso: DMGetDimension(), DMCreate() 3665 @*/ 3666 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3667 { 3668 PetscFunctionBegin; 3669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3670 PetscValidLogicalCollectiveInt(dm, dim, 2); 3671 dm->dim = dim; 3672 PetscFunctionReturn(0); 3673 } 3674 3675 #undef __FUNCT__ 3676 #define __FUNCT__ "DMGetDimPoints" 3677 /*@ 3678 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3679 3680 Collective on DM 3681 3682 Input Parameters: 3683 + dm - the DM 3684 - dim - the dimension 3685 3686 Output Parameters: 3687 + pStart - The first point of the given dimension 3688 . pEnd - The first point following points of the given dimension 3689 3690 Note: 3691 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3692 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3693 then the interval is empty. 3694 3695 Level: intermediate 3696 3697 .keywords: point, Hasse Diagram, dimension 3698 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3699 @*/ 3700 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3701 { 3702 PetscInt d; 3703 PetscErrorCode ierr; 3704 3705 PetscFunctionBegin; 3706 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3707 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3708 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3709 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3710 PetscFunctionReturn(0); 3711 } 3712 3713 #undef __FUNCT__ 3714 #define __FUNCT__ "DMSetCoordinates" 3715 /*@ 3716 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3717 3718 Collective on DM 3719 3720 Input Parameters: 3721 + dm - the DM 3722 - c - coordinate vector 3723 3724 Note: 3725 The coordinates do include those for ghost points, which are in the local vector 3726 3727 Level: intermediate 3728 3729 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3730 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3731 @*/ 3732 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3733 { 3734 PetscErrorCode ierr; 3735 3736 PetscFunctionBegin; 3737 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3738 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3739 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3740 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3741 dm->coordinates = c; 3742 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3743 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3744 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3745 PetscFunctionReturn(0); 3746 } 3747 3748 #undef __FUNCT__ 3749 #define __FUNCT__ "DMSetCoordinatesLocal" 3750 /*@ 3751 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3752 3753 Collective on DM 3754 3755 Input Parameters: 3756 + dm - the DM 3757 - c - coordinate vector 3758 3759 Note: 3760 The coordinates of ghost points can be set using DMSetCoordinates() 3761 followed by DMGetCoordinatesLocal(). This is intended to enable the 3762 setting of ghost coordinates outside of the domain. 3763 3764 Level: intermediate 3765 3766 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3767 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3768 @*/ 3769 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3770 { 3771 PetscErrorCode ierr; 3772 3773 PetscFunctionBegin; 3774 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3775 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3776 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3777 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3778 3779 dm->coordinatesLocal = c; 3780 3781 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3782 PetscFunctionReturn(0); 3783 } 3784 3785 #undef __FUNCT__ 3786 #define __FUNCT__ "DMGetCoordinates" 3787 /*@ 3788 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3789 3790 Not Collective 3791 3792 Input Parameter: 3793 . dm - the DM 3794 3795 Output Parameter: 3796 . c - global coordinate vector 3797 3798 Note: 3799 This is a borrowed reference, so the user should NOT destroy this vector 3800 3801 Each process has only the local coordinates (does NOT have the ghost coordinates). 3802 3803 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3804 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3805 3806 Level: intermediate 3807 3808 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3809 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3810 @*/ 3811 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 3812 { 3813 PetscErrorCode ierr; 3814 3815 PetscFunctionBegin; 3816 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3817 PetscValidPointer(c,2); 3818 if (!dm->coordinates && dm->coordinatesLocal) { 3819 DM cdm = NULL; 3820 3821 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3822 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 3823 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 3824 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3825 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3826 } 3827 *c = dm->coordinates; 3828 PetscFunctionReturn(0); 3829 } 3830 3831 #undef __FUNCT__ 3832 #define __FUNCT__ "DMGetCoordinatesLocal" 3833 /*@ 3834 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 3835 3836 Collective on DM 3837 3838 Input Parameter: 3839 . dm - the DM 3840 3841 Output Parameter: 3842 . c - coordinate vector 3843 3844 Note: 3845 This is a borrowed reference, so the user should NOT destroy this vector 3846 3847 Each process has the local and ghost coordinates 3848 3849 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3850 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3851 3852 Level: intermediate 3853 3854 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3855 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 3856 @*/ 3857 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 3858 { 3859 PetscErrorCode ierr; 3860 3861 PetscFunctionBegin; 3862 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3863 PetscValidPointer(c,2); 3864 if (!dm->coordinatesLocal && dm->coordinates) { 3865 DM cdm = NULL; 3866 3867 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3868 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 3869 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 3870 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3871 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3872 } 3873 *c = dm->coordinatesLocal; 3874 PetscFunctionReturn(0); 3875 } 3876 3877 #undef __FUNCT__ 3878 #define __FUNCT__ "DMGetCoordinateDM" 3879 /*@ 3880 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 3881 3882 Collective on DM 3883 3884 Input Parameter: 3885 . dm - the DM 3886 3887 Output Parameter: 3888 . cdm - coordinate DM 3889 3890 Level: intermediate 3891 3892 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3893 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3894 @*/ 3895 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 3896 { 3897 PetscErrorCode ierr; 3898 3899 PetscFunctionBegin; 3900 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3901 PetscValidPointer(cdm,2); 3902 if (!dm->coordinateDM) { 3903 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 3904 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 3905 } 3906 *cdm = dm->coordinateDM; 3907 PetscFunctionReturn(0); 3908 } 3909 3910 #undef __FUNCT__ 3911 #define __FUNCT__ "DMSetCoordinateDM" 3912 /*@ 3913 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 3914 3915 Logically Collective on DM 3916 3917 Input Parameters: 3918 + dm - the DM 3919 - cdm - coordinate DM 3920 3921 Level: intermediate 3922 3923 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3924 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3925 @*/ 3926 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 3927 { 3928 PetscErrorCode ierr; 3929 3930 PetscFunctionBegin; 3931 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3932 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 3933 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 3934 dm->coordinateDM = cdm; 3935 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 3936 PetscFunctionReturn(0); 3937 } 3938 3939 #undef __FUNCT__ 3940 #define __FUNCT__ "DMGetCoordinateDim" 3941 /*@ 3942 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 3943 3944 Not Collective 3945 3946 Input Parameter: 3947 . dm - The DM object 3948 3949 Output Parameter: 3950 . dim - The embedding dimension 3951 3952 Level: intermediate 3953 3954 .keywords: mesh, coordinates 3955 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 3956 @*/ 3957 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 3958 { 3959 PetscFunctionBegin; 3960 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3961 PetscValidPointer(dim, 2); 3962 if (dm->dimEmbed == PETSC_DEFAULT) { 3963 dm->dimEmbed = dm->dim; 3964 } 3965 *dim = dm->dimEmbed; 3966 PetscFunctionReturn(0); 3967 } 3968 3969 #undef __FUNCT__ 3970 #define __FUNCT__ "DMSetCoordinateDim" 3971 /*@ 3972 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 3973 3974 Not Collective 3975 3976 Input Parameters: 3977 + dm - The DM object 3978 - dim - The embedding dimension 3979 3980 Level: intermediate 3981 3982 .keywords: mesh, coordinates 3983 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 3984 @*/ 3985 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 3986 { 3987 PetscFunctionBegin; 3988 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3989 dm->dimEmbed = dim; 3990 PetscFunctionReturn(0); 3991 } 3992 3993 #undef __FUNCT__ 3994 #define __FUNCT__ "DMGetCoordinateSection" 3995 /*@ 3996 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 3997 3998 Not Collective 3999 4000 Input Parameter: 4001 . dm - The DM object 4002 4003 Output Parameter: 4004 . section - The PetscSection object 4005 4006 Level: intermediate 4007 4008 .keywords: mesh, coordinates 4009 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4010 @*/ 4011 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4012 { 4013 DM cdm; 4014 PetscErrorCode ierr; 4015 4016 PetscFunctionBegin; 4017 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4018 PetscValidPointer(section, 2); 4019 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4020 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4021 PetscFunctionReturn(0); 4022 } 4023 4024 #undef __FUNCT__ 4025 #define __FUNCT__ "DMSetCoordinateSection" 4026 /*@ 4027 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4028 4029 Not Collective 4030 4031 Input Parameters: 4032 + dm - The DM object 4033 . dim - The embedding dimension, or PETSC_DETERMINE 4034 - section - The PetscSection object 4035 4036 Level: intermediate 4037 4038 .keywords: mesh, coordinates 4039 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4040 @*/ 4041 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4042 { 4043 DM cdm; 4044 PetscErrorCode ierr; 4045 4046 PetscFunctionBegin; 4047 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4048 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4049 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4050 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4051 if (dim == PETSC_DETERMINE) { 4052 PetscInt d = dim; 4053 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4054 4055 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4056 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4057 pStart = PetscMax(vStart, pStart); 4058 pEnd = PetscMin(vEnd, pEnd); 4059 for (v = pStart; v < pEnd; ++v) { 4060 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4061 if (dd) {d = dd; break;} 4062 } 4063 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4064 } 4065 PetscFunctionReturn(0); 4066 } 4067 4068 #undef __FUNCT__ 4069 #define __FUNCT__ "DMGetPeriodicity" 4070 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L) 4071 { 4072 PetscFunctionBegin; 4073 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4074 if (L) *L = dm->L; 4075 if (maxCell) *maxCell = dm->maxCell; 4076 PetscFunctionReturn(0); 4077 } 4078 4079 #undef __FUNCT__ 4080 #define __FUNCT__ "DMSetPeriodicity" 4081 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[]) 4082 { 4083 Vec coordinates; 4084 PetscInt dim, d; 4085 PetscErrorCode ierr; 4086 4087 PetscFunctionBegin; 4088 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4089 ierr = PetscFree(dm->L);CHKERRQ(ierr); 4090 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr); 4091 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4092 ierr = VecGetBlockSize(coordinates, &dim);CHKERRQ(ierr); 4093 ierr = PetscMalloc1(dim,&dm->L);CHKERRQ(ierr); 4094 ierr = PetscMalloc1(dim,&dm->maxCell);CHKERRQ(ierr); 4095 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d];} 4096 PetscFunctionReturn(0); 4097 } 4098 4099 #undef __FUNCT__ 4100 #define __FUNCT__ "DMLocatePoints" 4101 /*@ 4102 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4103 4104 Not collective 4105 4106 Input Parameters: 4107 + dm - The DM 4108 - v - The Vec of points 4109 4110 Output Parameter: 4111 . cells - The local cell numbers for cells which contain the points 4112 4113 Level: developer 4114 4115 .keywords: point location, mesh 4116 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4117 @*/ 4118 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4119 { 4120 PetscErrorCode ierr; 4121 4122 PetscFunctionBegin; 4123 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4124 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4125 PetscValidPointer(cells,3); 4126 if (dm->ops->locatepoints) { 4127 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4128 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4129 PetscFunctionReturn(0); 4130 } 4131 4132 #undef __FUNCT__ 4133 #define __FUNCT__ "DMGetOutputDM" 4134 /*@ 4135 DMGetOutputDM - Retrieve the DM associated with the layout for output 4136 4137 Input Parameter: 4138 . dm - The original DM 4139 4140 Output Parameter: 4141 . odm - The DM which provides the layout for output 4142 4143 Level: intermediate 4144 4145 .seealso: VecView(), DMGetDefaultGlobalSection() 4146 @*/ 4147 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4148 { 4149 PetscSection section; 4150 PetscBool hasConstraints; 4151 PetscErrorCode ierr; 4152 4153 PetscFunctionBegin; 4154 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4155 PetscValidPointer(odm,2); 4156 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4157 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4158 if (!hasConstraints) { 4159 *odm = dm; 4160 PetscFunctionReturn(0); 4161 } 4162 if (!dm->dmBC) { 4163 PetscSection newSection, gsection; 4164 PetscSF sf; 4165 4166 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4167 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4168 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4169 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4170 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4171 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr); 4172 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4173 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4174 } 4175 *odm = dm->dmBC; 4176 PetscFunctionReturn(0); 4177 } 4178 4179 #undef __FUNCT__ 4180 #define __FUNCT__ "DMGetOutputSequenceNumber" 4181 /*@ 4182 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4183 4184 Input Parameter: 4185 . dm - The original DM 4186 4187 Output Parameters: 4188 + num - The output sequence number 4189 - val - The output sequence value 4190 4191 Level: intermediate 4192 4193 Note: This is intended for output that should appear in sequence, for instance 4194 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4195 4196 .seealso: VecView() 4197 @*/ 4198 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4199 { 4200 PetscFunctionBegin; 4201 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4202 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4203 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4204 PetscFunctionReturn(0); 4205 } 4206 4207 #undef __FUNCT__ 4208 #define __FUNCT__ "DMSetOutputSequenceNumber" 4209 /*@ 4210 DMSetOutputSequenceNumber - Set the sequence number/value for output 4211 4212 Input Parameters: 4213 + dm - The original DM 4214 . num - The output sequence number 4215 - val - The output sequence value 4216 4217 Level: intermediate 4218 4219 Note: This is intended for output that should appear in sequence, for instance 4220 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4221 4222 .seealso: VecView() 4223 @*/ 4224 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4225 { 4226 PetscFunctionBegin; 4227 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4228 dm->outputSequenceNum = num; 4229 dm->outputSequenceVal = val; 4230 PetscFunctionReturn(0); 4231 } 4232 4233 #undef __FUNCT__ 4234 #define __FUNCT__ "DMOutputSequenceLoad" 4235 /*@C 4236 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4237 4238 Input Parameters: 4239 + dm - The original DM 4240 . name - The sequence name 4241 - num - The output sequence number 4242 4243 Output Parameter: 4244 . val - The output sequence value 4245 4246 Level: intermediate 4247 4248 Note: This is intended for output that should appear in sequence, for instance 4249 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4250 4251 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4252 @*/ 4253 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4254 { 4255 PetscBool ishdf5; 4256 PetscErrorCode ierr; 4257 4258 PetscFunctionBegin; 4259 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4260 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4261 PetscValidPointer(val,4); 4262 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4263 if (ishdf5) { 4264 #if defined(PETSC_HAVE_HDF5) 4265 PetscScalar value; 4266 4267 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4268 *val = PetscRealPart(value); 4269 #endif 4270 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4271 PetscFunctionReturn(0); 4272 } 4273