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