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