1 #include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/ 2 #include <petscsf.h> 3 #include <petscds.h> 4 5 PetscClassId DM_CLASSID; 6 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal; 7 8 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0}; 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "DMCreate" 12 /*@ 13 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 14 15 If you never call DMSetType() it will generate an 16 error when you try to use the vector. 17 18 Collective on MPI_Comm 19 20 Input Parameter: 21 . comm - The communicator for the DM object 22 23 Output Parameter: 24 . dm - The DM object 25 26 Level: beginner 27 28 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE 29 @*/ 30 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 31 { 32 DM v; 33 PetscErrorCode ierr; 34 35 PetscFunctionBegin; 36 PetscValidPointer(dm,2); 37 *dm = NULL; 38 ierr = PetscSysInitializePackage();CHKERRQ(ierr); 39 ierr = VecInitializePackage();CHKERRQ(ierr); 40 ierr = MatInitializePackage();CHKERRQ(ierr); 41 ierr = DMInitializePackage();CHKERRQ(ierr); 42 43 ierr = PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 44 ierr = PetscMemzero(v->ops, sizeof(struct _DMOps));CHKERRQ(ierr); 45 46 47 v->ltogmap = NULL; 48 v->bs = 1; 49 v->coloringtype = IS_COLORING_GLOBAL; 50 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 51 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 52 v->defaultSection = NULL; 53 v->defaultGlobalSection = NULL; 54 v->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 = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr); 63 v->dmBC = NULL; 64 v->outputSequenceNum = -1; 65 v->outputSequenceVal = 0.0; 66 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 67 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 68 *dm = v; 69 PetscFunctionReturn(0); 70 } 71 72 #undef __FUNCT__ 73 #define __FUNCT__ "DMClone" 74 /*@ 75 DMClone - Creates a DM object with the same topology as the original. 76 77 Collective on MPI_Comm 78 79 Input Parameter: 80 . dm - The original DM object 81 82 Output Parameter: 83 . newdm - The new DM object 84 85 Level: beginner 86 87 .keywords: DM, topology, create 88 @*/ 89 PetscErrorCode DMClone(DM dm, DM *newdm) 90 { 91 PetscSF sf; 92 Vec coords; 93 void *ctx; 94 PetscErrorCode ierr; 95 96 PetscFunctionBegin; 97 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 98 PetscValidPointer(newdm,2); 99 ierr = DMCreate(PetscObjectComm((PetscObject)dm), newdm);CHKERRQ(ierr); 100 if (dm->ops->clone) { 101 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 102 } 103 (*newdm)->setupcalled = PETSC_TRUE; 104 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 105 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 106 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 107 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 108 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 109 if (coords) { 110 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 111 } else { 112 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 113 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 114 } 115 if (dm->maxCell) { 116 const PetscReal *maxCell, *L; 117 ierr = DMGetPeriodicity(dm, &maxCell, &L);CHKERRQ(ierr); 118 ierr = DMSetPeriodicity(*newdm, maxCell, L);CHKERRQ(ierr); 119 } 120 PetscFunctionReturn(0); 121 } 122 123 #undef __FUNCT__ 124 #define __FUNCT__ "DMSetVecType" 125 /*@C 126 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 127 128 Logically Collective on DMDA 129 130 Input Parameter: 131 + da - initial distributed array 132 . ctype - the vector type, currently either VECSTANDARD or VECCUSP 133 134 Options Database: 135 . -dm_vec_type ctype 136 137 Level: intermediate 138 139 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType, DMGetVecType() 140 @*/ 141 PetscErrorCode DMSetVecType(DM da,VecType ctype) 142 { 143 PetscErrorCode ierr; 144 145 PetscFunctionBegin; 146 PetscValidHeaderSpecific(da,DM_CLASSID,1); 147 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 148 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 #undef __FUNCT__ 153 #define __FUNCT__ "DMGetVecType" 154 /*@C 155 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 156 157 Logically Collective on DMDA 158 159 Input Parameter: 160 . da - initial distributed array 161 162 Output Parameter: 163 . ctype - the vector type 164 165 Level: intermediate 166 167 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType 168 @*/ 169 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 170 { 171 PetscFunctionBegin; 172 PetscValidHeaderSpecific(da,DM_CLASSID,1); 173 *ctype = da->vectype; 174 PetscFunctionReturn(0); 175 } 176 177 #undef __FUNCT__ 178 #define __FUNCT__ "VecGetDM" 179 /*@ 180 VecGetDM - Gets the DM defining the data layout of the vector 181 182 Not collective 183 184 Input Parameter: 185 . v - The Vec 186 187 Output Parameter: 188 . dm - The DM 189 190 Level: intermediate 191 192 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 193 @*/ 194 PetscErrorCode VecGetDM(Vec v, DM *dm) 195 { 196 PetscErrorCode ierr; 197 198 PetscFunctionBegin; 199 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 200 PetscValidPointer(dm,2); 201 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 202 PetscFunctionReturn(0); 203 } 204 205 #undef __FUNCT__ 206 #define __FUNCT__ "VecSetDM" 207 /*@ 208 VecSetDM - Sets the DM defining the data layout of the vector 209 210 Not collective 211 212 Input Parameters: 213 + v - The Vec 214 - dm - The DM 215 216 Level: intermediate 217 218 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 219 @*/ 220 PetscErrorCode VecSetDM(Vec v, DM dm) 221 { 222 PetscErrorCode ierr; 223 224 PetscFunctionBegin; 225 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 226 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 227 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 228 PetscFunctionReturn(0); 229 } 230 231 #undef __FUNCT__ 232 #define __FUNCT__ "DMSetMatType" 233 /*@C 234 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 235 236 Logically Collective on DM 237 238 Input Parameter: 239 + dm - the DM context 240 . ctype - the matrix type 241 242 Options Database: 243 . -dm_mat_type ctype 244 245 Level: intermediate 246 247 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType() 248 @*/ 249 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 250 { 251 PetscErrorCode ierr; 252 253 PetscFunctionBegin; 254 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 255 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 256 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 257 PetscFunctionReturn(0); 258 } 259 260 #undef __FUNCT__ 261 #define __FUNCT__ "DMGetMatType" 262 /*@C 263 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 264 265 Logically Collective on DM 266 267 Input Parameter: 268 . dm - the DM context 269 270 Output Parameter: 271 . ctype - the matrix type 272 273 Options Database: 274 . -dm_mat_type ctype 275 276 Level: intermediate 277 278 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType() 279 @*/ 280 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 281 { 282 PetscFunctionBegin; 283 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 284 *ctype = dm->mattype; 285 PetscFunctionReturn(0); 286 } 287 288 #undef __FUNCT__ 289 #define __FUNCT__ "MatGetDM" 290 /*@ 291 MatGetDM - Gets the DM defining the data layout of the matrix 292 293 Not collective 294 295 Input Parameter: 296 . A - The Mat 297 298 Output Parameter: 299 . dm - The DM 300 301 Level: intermediate 302 303 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 304 @*/ 305 PetscErrorCode MatGetDM(Mat A, DM *dm) 306 { 307 PetscErrorCode ierr; 308 309 PetscFunctionBegin; 310 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 311 PetscValidPointer(dm,2); 312 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 313 PetscFunctionReturn(0); 314 } 315 316 #undef __FUNCT__ 317 #define __FUNCT__ "MatSetDM" 318 /*@ 319 MatSetDM - Sets the DM defining the data layout of the matrix 320 321 Not collective 322 323 Input Parameters: 324 + A - The Mat 325 - dm - The DM 326 327 Level: intermediate 328 329 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 330 @*/ 331 PetscErrorCode MatSetDM(Mat A, DM dm) 332 { 333 PetscErrorCode ierr; 334 335 PetscFunctionBegin; 336 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 337 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 338 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 #undef __FUNCT__ 343 #define __FUNCT__ "DMSetOptionsPrefix" 344 /*@C 345 DMSetOptionsPrefix - Sets the prefix used for searching for all 346 DMDA options in the database. 347 348 Logically Collective on DMDA 349 350 Input Parameter: 351 + da - the DMDA context 352 - prefix - the prefix to prepend to all option names 353 354 Notes: 355 A hyphen (-) must NOT be given at the beginning of the prefix name. 356 The first character of all runtime options is AUTOMATICALLY the hyphen. 357 358 Level: advanced 359 360 .keywords: DMDA, set, options, prefix, database 361 362 .seealso: DMSetFromOptions() 363 @*/ 364 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 365 { 366 PetscErrorCode ierr; 367 368 PetscFunctionBegin; 369 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 370 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 371 PetscFunctionReturn(0); 372 } 373 374 #undef __FUNCT__ 375 #define __FUNCT__ "DMDestroy" 376 /*@ 377 DMDestroy - Destroys a vector packer or DMDA. 378 379 Collective on DM 380 381 Input Parameter: 382 . dm - the DM object to destroy 383 384 Level: developer 385 386 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 387 388 @*/ 389 PetscErrorCode DMDestroy(DM *dm) 390 { 391 PetscInt i, cnt = 0, Nf = 0, f; 392 DMNamedVecLink nlink,nnext; 393 PetscErrorCode ierr; 394 395 PetscFunctionBegin; 396 if (!*dm) PetscFunctionReturn(0); 397 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 398 399 if ((*dm)->prob) { 400 PetscObject disc; 401 402 /* I think it makes sense to dump all attached things when you are destroyed, which also eliminates circular references */ 403 ierr = PetscDSGetNumFields((*dm)->prob, &Nf);CHKERRQ(ierr); 404 for (f = 0; f < Nf; ++f) { 405 ierr = PetscDSGetDiscretization((*dm)->prob, f, &disc);CHKERRQ(ierr); 406 ierr = PetscObjectCompose(disc, "pmat", NULL);CHKERRQ(ierr); 407 ierr = PetscObjectCompose(disc, "nullspace", NULL);CHKERRQ(ierr); 408 ierr = PetscObjectCompose(disc, "nearnullspace", NULL);CHKERRQ(ierr); 409 } 410 } 411 /* count all the circular references of DM and its contained Vecs */ 412 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 413 if ((*dm)->localin[i]) cnt++; 414 if ((*dm)->globalin[i]) cnt++; 415 } 416 for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++; 417 for (nlink=(*dm)->namedlocal; nlink; nlink=nlink->next) cnt++; 418 if ((*dm)->x) { 419 DM obj; 420 ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr); 421 if (obj == *dm) cnt++; 422 } 423 424 if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 425 /* 426 Need this test because the dm references the vectors that 427 reference the dm, so destroying the dm calls destroy on the 428 vectors that cause another destroy on the dm 429 */ 430 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 431 ((PetscObject) (*dm))->refct = 0; 432 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 433 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 434 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 435 } 436 nnext=(*dm)->namedglobal; 437 (*dm)->namedglobal = NULL; 438 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 439 nnext = nlink->next; 440 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 441 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 442 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 443 ierr = PetscFree(nlink);CHKERRQ(ierr); 444 } 445 nnext=(*dm)->namedlocal; 446 (*dm)->namedlocal = NULL; 447 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 448 nnext = nlink->next; 449 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 450 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 451 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 452 ierr = PetscFree(nlink);CHKERRQ(ierr); 453 } 454 455 /* Destroy the list of hooks */ 456 { 457 DMCoarsenHookLink link,next; 458 for (link=(*dm)->coarsenhook; link; link=next) { 459 next = link->next; 460 ierr = PetscFree(link);CHKERRQ(ierr); 461 } 462 (*dm)->coarsenhook = NULL; 463 } 464 { 465 DMRefineHookLink link,next; 466 for (link=(*dm)->refinehook; link; link=next) { 467 next = link->next; 468 ierr = PetscFree(link);CHKERRQ(ierr); 469 } 470 (*dm)->refinehook = NULL; 471 } 472 { 473 DMSubDomainHookLink link,next; 474 for (link=(*dm)->subdomainhook; link; link=next) { 475 next = link->next; 476 ierr = PetscFree(link);CHKERRQ(ierr); 477 } 478 (*dm)->subdomainhook = NULL; 479 } 480 { 481 DMGlobalToLocalHookLink link,next; 482 for (link=(*dm)->gtolhook; link; link=next) { 483 next = link->next; 484 ierr = PetscFree(link);CHKERRQ(ierr); 485 } 486 (*dm)->gtolhook = NULL; 487 } 488 /* Destroy the work arrays */ 489 { 490 DMWorkLink link,next; 491 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 492 for (link=(*dm)->workin; link; link=next) { 493 next = link->next; 494 ierr = PetscFree(link->mem);CHKERRQ(ierr); 495 ierr = PetscFree(link);CHKERRQ(ierr); 496 } 497 (*dm)->workin = NULL; 498 } 499 500 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 501 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 502 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 503 504 if ((*dm)->ctx && (*dm)->ctxdestroy) { 505 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 506 } 507 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 508 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 509 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 510 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 511 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 512 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 513 514 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 515 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 516 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 517 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 518 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 519 520 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 521 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 522 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 523 ierr = PetscFree((*dm)->maxCell);CHKERRQ(ierr); 524 ierr = PetscFree((*dm)->L);CHKERRQ(ierr); 525 526 ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr); 527 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 528 /* if memory was published with SAWs then destroy it */ 529 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 530 531 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 532 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 533 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 534 PetscFunctionReturn(0); 535 } 536 537 #undef __FUNCT__ 538 #define __FUNCT__ "DMSetUp" 539 /*@ 540 DMSetUp - sets up the data structures inside a DM object 541 542 Collective on DM 543 544 Input Parameter: 545 . dm - the DM object to setup 546 547 Level: developer 548 549 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 550 551 @*/ 552 PetscErrorCode DMSetUp(DM dm) 553 { 554 PetscErrorCode ierr; 555 556 PetscFunctionBegin; 557 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 558 if (dm->setupcalled) PetscFunctionReturn(0); 559 if (dm->ops->setup) { 560 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 561 } 562 dm->setupcalled = PETSC_TRUE; 563 PetscFunctionReturn(0); 564 } 565 566 #undef __FUNCT__ 567 #define __FUNCT__ "DMSetFromOptions" 568 /*@ 569 DMSetFromOptions - sets parameters in a DM from the options database 570 571 Collective on DM 572 573 Input Parameter: 574 . dm - the DM object to set options for 575 576 Options Database: 577 + -dm_preallocate_only: Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 578 . -dm_vec_type <type> type of vector to create inside DM 579 . -dm_mat_type <type> type of matrix to create inside DM 580 - -dm_coloring_type <global or ghosted> 581 582 Level: developer 583 584 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 585 586 @*/ 587 PetscErrorCode DMSetFromOptions(DM dm) 588 { 589 char typeName[256]; 590 PetscBool flg; 591 PetscErrorCode ierr; 592 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 595 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 596 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 597 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 598 if (flg) { 599 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 600 } 601 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 602 if (flg) { 603 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 604 } 605 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 606 if (dm->ops->setfromoptions) { 607 ierr = (*dm->ops->setfromoptions)(dm);CHKERRQ(ierr); 608 } 609 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 610 ierr = PetscObjectProcessOptionsHandlers((PetscObject) dm);CHKERRQ(ierr); 611 ierr = PetscOptionsEnd();CHKERRQ(ierr); 612 PetscFunctionReturn(0); 613 } 614 615 #undef __FUNCT__ 616 #define __FUNCT__ "DMView" 617 /*@C 618 DMView - Views a vector packer or DMDA. 619 620 Collective on DM 621 622 Input Parameter: 623 + dm - the DM object to view 624 - v - the viewer 625 626 Level: developer 627 628 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 629 630 @*/ 631 PetscErrorCode DMView(DM dm,PetscViewer v) 632 { 633 PetscErrorCode ierr; 634 PetscBool isbinary; 635 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 638 if (!v) { 639 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 640 } 641 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 642 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 643 if (isbinary) { 644 PetscInt classid = DM_FILE_CLASSID; 645 char type[256]; 646 647 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 648 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 649 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 650 } 651 if (dm->ops->view) { 652 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 653 } 654 PetscFunctionReturn(0); 655 } 656 657 #undef __FUNCT__ 658 #define __FUNCT__ "DMCreateGlobalVector" 659 /*@ 660 DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object 661 662 Collective on DM 663 664 Input Parameter: 665 . dm - the DM object 666 667 Output Parameter: 668 . vec - the global vector 669 670 Level: beginner 671 672 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 673 674 @*/ 675 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 676 { 677 PetscErrorCode ierr; 678 679 PetscFunctionBegin; 680 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 681 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 682 PetscFunctionReturn(0); 683 } 684 685 #undef __FUNCT__ 686 #define __FUNCT__ "DMCreateLocalVector" 687 /*@ 688 DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object 689 690 Not Collective 691 692 Input Parameter: 693 . dm - the DM object 694 695 Output Parameter: 696 . vec - the local vector 697 698 Level: beginner 699 700 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 701 702 @*/ 703 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 704 { 705 PetscErrorCode ierr; 706 707 PetscFunctionBegin; 708 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 709 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 710 PetscFunctionReturn(0); 711 } 712 713 #undef __FUNCT__ 714 #define __FUNCT__ "DMGetLocalToGlobalMapping" 715 /*@ 716 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 717 718 Collective on DM 719 720 Input Parameter: 721 . dm - the DM that provides the mapping 722 723 Output Parameter: 724 . ltog - the mapping 725 726 Level: intermediate 727 728 Notes: 729 This mapping can then be used by VecSetLocalToGlobalMapping() or 730 MatSetLocalToGlobalMapping(). 731 732 .seealso: DMCreateLocalVector() 733 @*/ 734 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 735 { 736 PetscErrorCode ierr; 737 738 PetscFunctionBegin; 739 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 740 PetscValidPointer(ltog,2); 741 if (!dm->ltogmap) { 742 PetscSection section, sectionGlobal; 743 744 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 745 if (section) { 746 PetscInt *ltog; 747 PetscInt pStart, pEnd, size, p, l; 748 749 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 750 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 751 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 752 ierr = PetscMalloc1(size, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 753 for (p = pStart, l = 0; p < pEnd; ++p) { 754 PetscInt dof, off, c; 755 756 /* Should probably use constrained dofs */ 757 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 758 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 759 for (c = 0; c < dof; ++c, ++l) { 760 ltog[l] = off+c; 761 } 762 } 763 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 764 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 765 } else { 766 if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 767 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 768 } 769 } 770 *ltog = dm->ltogmap; 771 PetscFunctionReturn(0); 772 } 773 774 #undef __FUNCT__ 775 #define __FUNCT__ "DMGetBlockSize" 776 /*@ 777 DMGetBlockSize - Gets the inherent block size associated with a DM 778 779 Not Collective 780 781 Input Parameter: 782 . dm - the DM with block structure 783 784 Output Parameter: 785 . bs - the block size, 1 implies no exploitable block structure 786 787 Level: intermediate 788 789 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 790 @*/ 791 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 792 { 793 PetscFunctionBegin; 794 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 795 PetscValidPointer(bs,2); 796 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 797 *bs = dm->bs; 798 PetscFunctionReturn(0); 799 } 800 801 #undef __FUNCT__ 802 #define __FUNCT__ "DMCreateInterpolation" 803 /*@ 804 DMCreateInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects 805 806 Collective on DM 807 808 Input Parameter: 809 + dm1 - the DM object 810 - dm2 - the second, finer DM object 811 812 Output Parameter: 813 + mat - the interpolation 814 - vec - the scaling (optional) 815 816 Level: developer 817 818 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 819 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 820 821 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 822 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 823 824 825 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen() 826 827 @*/ 828 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 829 { 830 PetscErrorCode ierr; 831 832 PetscFunctionBegin; 833 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 834 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 835 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 836 PetscFunctionReturn(0); 837 } 838 839 #undef __FUNCT__ 840 #define __FUNCT__ "DMCreateInjection" 841 /*@ 842 DMCreateInjection - Gets injection matrix between two DMDA or DMComposite objects 843 844 Collective on DM 845 846 Input Parameter: 847 + dm1 - the DM object 848 - dm2 - the second, finer DM object 849 850 Output Parameter: 851 . ctx - the injection 852 853 Level: developer 854 855 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 856 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 857 858 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 859 860 @*/ 861 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,VecScatter *ctx) 862 { 863 PetscErrorCode ierr; 864 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 867 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 868 ierr = (*dm1->ops->getinjection)(dm1,dm2,ctx);CHKERRQ(ierr); 869 PetscFunctionReturn(0); 870 } 871 872 #undef __FUNCT__ 873 #define __FUNCT__ "DMCreateColoring" 874 /*@ 875 DMCreateColoring - Gets coloring for a DM 876 877 Collective on DM 878 879 Input Parameter: 880 + dm - the DM object 881 - ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL 882 883 Output Parameter: 884 . coloring - the coloring 885 886 Level: developer 887 888 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType() 889 890 @*/ 891 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 892 { 893 PetscErrorCode ierr; 894 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 897 if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet"); 898 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 899 PetscFunctionReturn(0); 900 } 901 902 #undef __FUNCT__ 903 #define __FUNCT__ "DMCreateMatrix" 904 /*@ 905 DMCreateMatrix - Gets empty Jacobian for a DMDA or DMComposite 906 907 Collective on DM 908 909 Input Parameter: 910 . dm - the DM object 911 912 Output Parameter: 913 . mat - the empty Jacobian 914 915 Level: beginner 916 917 Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 918 do not need to do it yourself. 919 920 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 921 the nonzero pattern call DMDASetMatPreallocateOnly() 922 923 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 924 internally by PETSc. 925 926 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 927 the indices for the global numbering for DMDAs which is complicated. 928 929 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 930 931 @*/ 932 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 933 { 934 PetscErrorCode ierr; 935 936 PetscFunctionBegin; 937 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 938 ierr = MatInitializePackage();CHKERRQ(ierr); 939 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 940 PetscValidPointer(mat,3); 941 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 942 PetscFunctionReturn(0); 943 } 944 945 #undef __FUNCT__ 946 #define __FUNCT__ "DMSetMatrixPreallocateOnly" 947 /*@ 948 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 949 preallocated but the nonzero structure and zero values will not be set. 950 951 Logically Collective on DMDA 952 953 Input Parameter: 954 + dm - the DM 955 - only - PETSC_TRUE if only want preallocation 956 957 Level: developer 958 .seealso DMCreateMatrix() 959 @*/ 960 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 961 { 962 PetscFunctionBegin; 963 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 964 dm->prealloc_only = only; 965 PetscFunctionReturn(0); 966 } 967 968 #undef __FUNCT__ 969 #define __FUNCT__ "DMGetWorkArray" 970 /*@C 971 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 972 973 Not Collective 974 975 Input Parameters: 976 + dm - the DM object 977 . count - The minium size 978 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 979 980 Output Parameter: 981 . array - the work array 982 983 Level: developer 984 985 .seealso DMDestroy(), DMCreate() 986 @*/ 987 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 988 { 989 PetscErrorCode ierr; 990 DMWorkLink link; 991 size_t size; 992 993 PetscFunctionBegin; 994 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 995 PetscValidPointer(mem,4); 996 if (dm->workin) { 997 link = dm->workin; 998 dm->workin = dm->workin->next; 999 } else { 1000 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1001 } 1002 ierr = PetscDataTypeGetSize(dtype,&size);CHKERRQ(ierr); 1003 if (size*count > link->bytes) { 1004 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1005 ierr = PetscMalloc(size*count,&link->mem);CHKERRQ(ierr); 1006 link->bytes = size*count; 1007 } 1008 link->next = dm->workout; 1009 dm->workout = link; 1010 *(void**)mem = link->mem; 1011 PetscFunctionReturn(0); 1012 } 1013 1014 #undef __FUNCT__ 1015 #define __FUNCT__ "DMRestoreWorkArray" 1016 /*@C 1017 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1018 1019 Not Collective 1020 1021 Input Parameters: 1022 + dm - the DM object 1023 . count - The minium size 1024 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1025 1026 Output Parameter: 1027 . array - the work array 1028 1029 Level: developer 1030 1031 .seealso DMDestroy(), DMCreate() 1032 @*/ 1033 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1034 { 1035 DMWorkLink *p,link; 1036 1037 PetscFunctionBegin; 1038 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1039 PetscValidPointer(mem,4); 1040 for (p=&dm->workout; (link=*p); p=&link->next) { 1041 if (link->mem == *(void**)mem) { 1042 *p = link->next; 1043 link->next = dm->workin; 1044 dm->workin = link; 1045 *(void**)mem = NULL; 1046 PetscFunctionReturn(0); 1047 } 1048 } 1049 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1050 PetscFunctionReturn(0); 1051 } 1052 1053 #undef __FUNCT__ 1054 #define __FUNCT__ "DMSetNullSpaceConstructor" 1055 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1056 { 1057 PetscFunctionBegin; 1058 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1059 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1060 dm->nullspaceConstructors[field] = nullsp; 1061 PetscFunctionReturn(0); 1062 } 1063 1064 #undef __FUNCT__ 1065 #define __FUNCT__ "DMCreateFieldIS" 1066 /*@C 1067 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1068 1069 Not collective 1070 1071 Input Parameter: 1072 . dm - the DM object 1073 1074 Output Parameters: 1075 + numFields - The number of fields (or NULL if not requested) 1076 . fieldNames - The name for each field (or NULL if not requested) 1077 - fields - The global indices for each field (or NULL if not requested) 1078 1079 Level: intermediate 1080 1081 Notes: 1082 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1083 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1084 PetscFree(). 1085 1086 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1087 @*/ 1088 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1089 { 1090 PetscSection section, sectionGlobal; 1091 PetscErrorCode ierr; 1092 1093 PetscFunctionBegin; 1094 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1095 if (numFields) { 1096 PetscValidPointer(numFields,2); 1097 *numFields = 0; 1098 } 1099 if (fieldNames) { 1100 PetscValidPointer(fieldNames,3); 1101 *fieldNames = NULL; 1102 } 1103 if (fields) { 1104 PetscValidPointer(fields,4); 1105 *fields = NULL; 1106 } 1107 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1108 if (section) { 1109 PetscInt *fieldSizes, **fieldIndices; 1110 PetscInt nF, f, pStart, pEnd, p; 1111 1112 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1113 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1114 ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr); 1115 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1116 for (f = 0; f < nF; ++f) { 1117 fieldSizes[f] = 0; 1118 } 1119 for (p = pStart; p < pEnd; ++p) { 1120 PetscInt gdof; 1121 1122 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1123 if (gdof > 0) { 1124 for (f = 0; f < nF; ++f) { 1125 PetscInt fdof, fcdof; 1126 1127 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1128 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1129 fieldSizes[f] += fdof-fcdof; 1130 } 1131 } 1132 } 1133 for (f = 0; f < nF; ++f) { 1134 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1135 fieldSizes[f] = 0; 1136 } 1137 for (p = pStart; p < pEnd; ++p) { 1138 PetscInt gdof, goff; 1139 1140 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1141 if (gdof > 0) { 1142 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1143 for (f = 0; f < nF; ++f) { 1144 PetscInt fdof, fcdof, fc; 1145 1146 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1147 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1148 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1149 fieldIndices[f][fieldSizes[f]] = goff++; 1150 } 1151 } 1152 } 1153 } 1154 if (numFields) *numFields = nF; 1155 if (fieldNames) { 1156 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1157 for (f = 0; f < nF; ++f) { 1158 const char *fieldName; 1159 1160 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1161 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1162 } 1163 } 1164 if (fields) { 1165 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1166 for (f = 0; f < nF; ++f) { 1167 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1168 } 1169 } 1170 ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr); 1171 } else if (dm->ops->createfieldis) { 1172 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1173 } 1174 PetscFunctionReturn(0); 1175 } 1176 1177 1178 #undef __FUNCT__ 1179 #define __FUNCT__ "DMCreateFieldDecomposition" 1180 /*@C 1181 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1182 corresponding to different fields: each IS contains the global indices of the dofs of the 1183 corresponding field. The optional list of DMs define the DM for each subproblem. 1184 Generalizes DMCreateFieldIS(). 1185 1186 Not collective 1187 1188 Input Parameter: 1189 . dm - the DM object 1190 1191 Output Parameters: 1192 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1193 . namelist - The name for each field (or NULL if not requested) 1194 . islist - The global indices for each field (or NULL if not requested) 1195 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1196 1197 Level: intermediate 1198 1199 Notes: 1200 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1201 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1202 and all of the arrays should be freed with PetscFree(). 1203 1204 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1205 @*/ 1206 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1207 { 1208 PetscErrorCode ierr; 1209 1210 PetscFunctionBegin; 1211 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1212 if (len) { 1213 PetscValidPointer(len,2); 1214 *len = 0; 1215 } 1216 if (namelist) { 1217 PetscValidPointer(namelist,3); 1218 *namelist = 0; 1219 } 1220 if (islist) { 1221 PetscValidPointer(islist,4); 1222 *islist = 0; 1223 } 1224 if (dmlist) { 1225 PetscValidPointer(dmlist,5); 1226 *dmlist = 0; 1227 } 1228 /* 1229 Is it a good idea to apply the following check across all impls? 1230 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1231 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1232 */ 1233 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1234 if (!dm->ops->createfielddecomposition) { 1235 PetscSection section; 1236 PetscInt numFields, f; 1237 1238 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1239 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1240 if (section && numFields && dm->ops->createsubdm) { 1241 *len = numFields; 1242 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1243 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1244 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1245 for (f = 0; f < numFields; ++f) { 1246 const char *fieldName; 1247 1248 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1249 if (namelist) { 1250 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1251 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1252 } 1253 } 1254 } else { 1255 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1256 /* By default there are no DMs associated with subproblems. */ 1257 if (dmlist) *dmlist = NULL; 1258 } 1259 } else { 1260 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1261 } 1262 PetscFunctionReturn(0); 1263 } 1264 1265 #undef __FUNCT__ 1266 #define __FUNCT__ "DMCreateSubDM" 1267 /*@C 1268 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1269 The fields are defined by DMCreateFieldIS(). 1270 1271 Not collective 1272 1273 Input Parameters: 1274 + dm - the DM object 1275 . numFields - number of fields in this subproblem 1276 - len - The number of subproblems in the decomposition (or NULL if not requested) 1277 1278 Output Parameters: 1279 . is - The global indices for the subproblem 1280 - dm - The DM for the subproblem 1281 1282 Level: intermediate 1283 1284 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1285 @*/ 1286 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1287 { 1288 PetscErrorCode ierr; 1289 1290 PetscFunctionBegin; 1291 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1292 PetscValidPointer(fields,3); 1293 if (is) PetscValidPointer(is,4); 1294 if (subdm) PetscValidPointer(subdm,5); 1295 if (dm->ops->createsubdm) { 1296 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1297 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1298 PetscFunctionReturn(0); 1299 } 1300 1301 1302 #undef __FUNCT__ 1303 #define __FUNCT__ "DMCreateDomainDecomposition" 1304 /*@C 1305 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1306 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1307 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1308 define a nonoverlapping covering, while outer subdomains can overlap. 1309 The optional list of DMs define the DM for each subproblem. 1310 1311 Not collective 1312 1313 Input Parameter: 1314 . dm - the DM object 1315 1316 Output Parameters: 1317 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1318 . namelist - The name for each subdomain (or NULL if not requested) 1319 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1320 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1321 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1322 1323 Level: intermediate 1324 1325 Notes: 1326 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1327 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1328 and all of the arrays should be freed with PetscFree(). 1329 1330 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1331 @*/ 1332 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1333 { 1334 PetscErrorCode ierr; 1335 DMSubDomainHookLink link; 1336 PetscInt i,l; 1337 1338 PetscFunctionBegin; 1339 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1340 if (len) {PetscValidPointer(len,2); *len = 0;} 1341 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1342 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1343 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1344 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1345 /* 1346 Is it a good idea to apply the following check across all impls? 1347 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1348 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1349 */ 1350 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1351 if (dm->ops->createdomaindecomposition) { 1352 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1353 /* copy subdomain hooks and context over to the subdomain DMs */ 1354 if (dmlist) { 1355 for (i = 0; i < l; i++) { 1356 for (link=dm->subdomainhook; link; link=link->next) { 1357 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1358 } 1359 (*dmlist)[i]->ctx = dm->ctx; 1360 } 1361 } 1362 if (len) *len = l; 1363 } 1364 PetscFunctionReturn(0); 1365 } 1366 1367 1368 #undef __FUNCT__ 1369 #define __FUNCT__ "DMCreateDomainDecompositionScatters" 1370 /*@C 1371 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1372 1373 Not collective 1374 1375 Input Parameters: 1376 + dm - the DM object 1377 . n - the number of subdomain scatters 1378 - subdms - the local subdomains 1379 1380 Output Parameters: 1381 + n - the number of scatters returned 1382 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1383 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1384 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1385 1386 Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1387 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1388 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1389 solution and residual data. 1390 1391 Level: developer 1392 1393 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1394 @*/ 1395 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1396 { 1397 PetscErrorCode ierr; 1398 1399 PetscFunctionBegin; 1400 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1401 PetscValidPointer(subdms,3); 1402 if (dm->ops->createddscatters) { 1403 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1404 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined"); 1405 PetscFunctionReturn(0); 1406 } 1407 1408 #undef __FUNCT__ 1409 #define __FUNCT__ "DMRefine" 1410 /*@ 1411 DMRefine - Refines a DM object 1412 1413 Collective on DM 1414 1415 Input Parameter: 1416 + dm - the DM object 1417 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1418 1419 Output Parameter: 1420 . dmf - the refined DM, or NULL 1421 1422 Note: If no refinement was done, the return value is NULL 1423 1424 Level: developer 1425 1426 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1427 @*/ 1428 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1429 { 1430 PetscErrorCode ierr; 1431 DMRefineHookLink link; 1432 1433 PetscFunctionBegin; 1434 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1435 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1436 if (*dmf) { 1437 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1438 1439 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1440 1441 (*dmf)->ctx = dm->ctx; 1442 (*dmf)->leveldown = dm->leveldown; 1443 (*dmf)->levelup = dm->levelup + 1; 1444 1445 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1446 for (link=dm->refinehook; link; link=link->next) { 1447 if (link->refinehook) { 1448 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1449 } 1450 } 1451 } 1452 PetscFunctionReturn(0); 1453 } 1454 1455 #undef __FUNCT__ 1456 #define __FUNCT__ "DMRefineHookAdd" 1457 /*@C 1458 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1459 1460 Logically Collective 1461 1462 Input Arguments: 1463 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1464 . refinehook - function to run when setting up a coarser level 1465 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1466 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1467 1468 Calling sequence of refinehook: 1469 $ refinehook(DM coarse,DM fine,void *ctx); 1470 1471 + coarse - coarse level DM 1472 . fine - fine level DM to interpolate problem to 1473 - ctx - optional user-defined function context 1474 1475 Calling sequence for interphook: 1476 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1477 1478 + coarse - coarse level DM 1479 . interp - matrix interpolating a coarse-level solution to the finer grid 1480 . fine - fine level DM to update 1481 - ctx - optional user-defined function context 1482 1483 Level: advanced 1484 1485 Notes: 1486 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1487 1488 If this function is called multiple times, the hooks will be run in the order they are added. 1489 1490 This function is currently not available from Fortran. 1491 1492 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1493 @*/ 1494 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1495 { 1496 PetscErrorCode ierr; 1497 DMRefineHookLink link,*p; 1498 1499 PetscFunctionBegin; 1500 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1501 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1502 ierr = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr); 1503 link->refinehook = refinehook; 1504 link->interphook = interphook; 1505 link->ctx = ctx; 1506 link->next = NULL; 1507 *p = link; 1508 PetscFunctionReturn(0); 1509 } 1510 1511 #undef __FUNCT__ 1512 #define __FUNCT__ "DMInterpolate" 1513 /*@ 1514 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1515 1516 Collective if any hooks are 1517 1518 Input Arguments: 1519 + coarse - coarser DM to use as a base 1520 . restrct - interpolation matrix, apply using MatInterpolate() 1521 - fine - finer DM to update 1522 1523 Level: developer 1524 1525 .seealso: DMRefineHookAdd(), MatInterpolate() 1526 @*/ 1527 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1528 { 1529 PetscErrorCode ierr; 1530 DMRefineHookLink link; 1531 1532 PetscFunctionBegin; 1533 for (link=fine->refinehook; link; link=link->next) { 1534 if (link->interphook) { 1535 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1536 } 1537 } 1538 PetscFunctionReturn(0); 1539 } 1540 1541 #undef __FUNCT__ 1542 #define __FUNCT__ "DMGetRefineLevel" 1543 /*@ 1544 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1545 1546 Not Collective 1547 1548 Input Parameter: 1549 . dm - the DM object 1550 1551 Output Parameter: 1552 . level - number of refinements 1553 1554 Level: developer 1555 1556 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1557 1558 @*/ 1559 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1560 { 1561 PetscFunctionBegin; 1562 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1563 *level = dm->levelup; 1564 PetscFunctionReturn(0); 1565 } 1566 1567 #undef __FUNCT__ 1568 #define __FUNCT__ "DMGlobalToLocalHookAdd" 1569 /*@C 1570 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1571 1572 Logically Collective 1573 1574 Input Arguments: 1575 + dm - the DM 1576 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 1577 . endhook - function to run after DMGlobalToLocalEnd() has completed 1578 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1579 1580 Calling sequence for beginhook: 1581 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1582 1583 + dm - global DM 1584 . g - global vector 1585 . mode - mode 1586 . l - local vector 1587 - ctx - optional user-defined function context 1588 1589 1590 Calling sequence for endhook: 1591 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1592 1593 + global - global DM 1594 - ctx - optional user-defined function context 1595 1596 Level: advanced 1597 1598 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1599 @*/ 1600 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1601 { 1602 PetscErrorCode ierr; 1603 DMGlobalToLocalHookLink link,*p; 1604 1605 PetscFunctionBegin; 1606 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1607 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1608 ierr = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr); 1609 link->beginhook = beginhook; 1610 link->endhook = endhook; 1611 link->ctx = ctx; 1612 link->next = NULL; 1613 *p = link; 1614 PetscFunctionReturn(0); 1615 } 1616 1617 #undef __FUNCT__ 1618 #define __FUNCT__ "DMGlobalToLocalBegin" 1619 /*@ 1620 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1621 1622 Neighbor-wise Collective on DM 1623 1624 Input Parameters: 1625 + dm - the DM object 1626 . g - the global vector 1627 . mode - INSERT_VALUES or ADD_VALUES 1628 - l - the local vector 1629 1630 1631 Level: beginner 1632 1633 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1634 1635 @*/ 1636 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1637 { 1638 PetscSF sf; 1639 PetscErrorCode ierr; 1640 DMGlobalToLocalHookLink link; 1641 1642 PetscFunctionBegin; 1643 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1644 for (link=dm->gtolhook; link; link=link->next) { 1645 if (link->beginhook) { 1646 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 1647 } 1648 } 1649 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1650 if (sf) { 1651 PetscScalar *lArray, *gArray; 1652 1653 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1654 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1655 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1656 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1657 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1658 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1659 } else { 1660 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1661 } 1662 PetscFunctionReturn(0); 1663 } 1664 1665 #undef __FUNCT__ 1666 #define __FUNCT__ "DMGlobalToLocalEnd" 1667 /*@ 1668 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1669 1670 Neighbor-wise Collective on DM 1671 1672 Input Parameters: 1673 + dm - the DM object 1674 . g - the global vector 1675 . mode - INSERT_VALUES or ADD_VALUES 1676 - l - the local vector 1677 1678 1679 Level: beginner 1680 1681 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1682 1683 @*/ 1684 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 1685 { 1686 PetscSF sf; 1687 PetscErrorCode ierr; 1688 PetscScalar *lArray, *gArray; 1689 DMGlobalToLocalHookLink link; 1690 1691 PetscFunctionBegin; 1692 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1693 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1694 if (sf) { 1695 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1696 1697 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1698 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1699 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1700 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1701 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1702 } else { 1703 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1704 } 1705 for (link=dm->gtolhook; link; link=link->next) { 1706 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 1707 } 1708 PetscFunctionReturn(0); 1709 } 1710 1711 #undef __FUNCT__ 1712 #define __FUNCT__ "DMLocalToGlobalBegin" 1713 /*@ 1714 DMLocalToGlobalBegin - updates global vectors from local vectors 1715 1716 Neighbor-wise Collective on DM 1717 1718 Input Parameters: 1719 + dm - the DM object 1720 . l - the local vector 1721 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point. 1722 - g - 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 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 PetscValidPointer(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__ "DMGetDS" 3173 /*@ 3174 DMGetDS - Get the PetscDS 3175 3176 Input Parameter: 3177 . dm - The DM 3178 3179 Output Parameter: 3180 . prob - The PetscDS 3181 3182 Level: developer 3183 3184 .seealso: DMSetDS() 3185 @*/ 3186 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3187 { 3188 PetscFunctionBegin; 3189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3190 PetscValidPointer(prob, 2); 3191 *prob = dm->prob; 3192 PetscFunctionReturn(0); 3193 } 3194 3195 #undef __FUNCT__ 3196 #define __FUNCT__ "DMSetDS" 3197 /*@ 3198 DMSetDS - Set the PetscDS 3199 3200 Input Parameters: 3201 + dm - The DM 3202 - prob - The PetscDS 3203 3204 Level: developer 3205 3206 .seealso: DMGetDS() 3207 @*/ 3208 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3209 { 3210 PetscErrorCode ierr; 3211 3212 PetscFunctionBegin; 3213 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3214 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3215 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3216 dm->prob = prob; 3217 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3218 PetscFunctionReturn(0); 3219 } 3220 3221 #undef __FUNCT__ 3222 #define __FUNCT__ "DMGetNumFields" 3223 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3224 { 3225 PetscErrorCode ierr; 3226 3227 PetscFunctionBegin; 3228 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3229 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3230 PetscFunctionReturn(0); 3231 } 3232 3233 #undef __FUNCT__ 3234 #define __FUNCT__ "DMSetNumFields" 3235 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3236 { 3237 PetscInt Nf, f; 3238 PetscErrorCode ierr; 3239 3240 PetscFunctionBegin; 3241 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3242 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3243 for (f = Nf; f < numFields; ++f) { 3244 PetscContainer obj; 3245 3246 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3247 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3248 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3249 } 3250 PetscFunctionReturn(0); 3251 } 3252 3253 #undef __FUNCT__ 3254 #define __FUNCT__ "DMGetField" 3255 /*@ 3256 DMGetField - Return the discretization object for a given DM field 3257 3258 Not collective 3259 3260 Input Parameters: 3261 + dm - The DM 3262 - f - The field number 3263 3264 Output Parameter: 3265 . field - The discretization object 3266 3267 Level: developer 3268 3269 .seealso: DMSetField() 3270 @*/ 3271 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3272 { 3273 PetscErrorCode ierr; 3274 3275 PetscFunctionBegin; 3276 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3277 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3278 PetscFunctionReturn(0); 3279 } 3280 3281 #undef __FUNCT__ 3282 #define __FUNCT__ "DMSetField" 3283 /*@ 3284 DMSetField - Set the discretization object for a given DM field 3285 3286 Logically collective on DM 3287 3288 Input Parameters: 3289 + dm - The DM 3290 . f - The field number 3291 - field - The discretization object 3292 3293 Level: developer 3294 3295 .seealso: DMGetField() 3296 @*/ 3297 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3298 { 3299 PetscErrorCode ierr; 3300 3301 PetscFunctionBegin; 3302 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3303 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3304 PetscFunctionReturn(0); 3305 } 3306 3307 #undef __FUNCT__ 3308 #define __FUNCT__ "DMRestrictHook_Coordinates" 3309 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3310 { 3311 DM dm_coord,dmc_coord; 3312 PetscErrorCode ierr; 3313 Vec coords,ccoords; 3314 VecScatter scat; 3315 PetscFunctionBegin; 3316 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3317 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3318 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3319 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3320 if (coords && !ccoords) { 3321 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3322 ierr = DMCreateInjection(dmc_coord,dm_coord,&scat);CHKERRQ(ierr); 3323 ierr = VecScatterBegin(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3324 ierr = VecScatterEnd(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3325 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3326 ierr = VecScatterDestroy(&scat);CHKERRQ(ierr); 3327 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3328 } 3329 PetscFunctionReturn(0); 3330 } 3331 3332 #undef __FUNCT__ 3333 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3334 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3335 { 3336 DM dm_coord,subdm_coord; 3337 PetscErrorCode ierr; 3338 Vec coords,ccoords,clcoords; 3339 VecScatter *scat_i,*scat_g; 3340 PetscFunctionBegin; 3341 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3342 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3343 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3344 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3345 if (coords && !ccoords) { 3346 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3347 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3348 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3349 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3350 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3351 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3352 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3353 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3354 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3355 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3356 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3357 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3358 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3359 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3360 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3361 } 3362 PetscFunctionReturn(0); 3363 } 3364 3365 #undef __FUNCT__ 3366 #define __FUNCT__ "DMSetCoordinates" 3367 /*@ 3368 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3369 3370 Collective on DM 3371 3372 Input Parameters: 3373 + dm - the DM 3374 - c - coordinate vector 3375 3376 Note: 3377 The coordinates do include those for ghost points, which are in the local vector 3378 3379 Level: intermediate 3380 3381 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3382 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3383 @*/ 3384 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3385 { 3386 PetscErrorCode ierr; 3387 3388 PetscFunctionBegin; 3389 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3390 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3391 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3392 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3393 dm->coordinates = c; 3394 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3395 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3396 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3397 PetscFunctionReturn(0); 3398 } 3399 3400 #undef __FUNCT__ 3401 #define __FUNCT__ "DMSetCoordinatesLocal" 3402 /*@ 3403 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3404 3405 Collective on DM 3406 3407 Input Parameters: 3408 + dm - the DM 3409 - c - coordinate vector 3410 3411 Note: 3412 The coordinates of ghost points can be set using DMSetCoordinates() 3413 followed by DMGetCoordinatesLocal(). This is intended to enable the 3414 setting of ghost coordinates outside of the domain. 3415 3416 Level: intermediate 3417 3418 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3419 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3420 @*/ 3421 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3422 { 3423 PetscErrorCode ierr; 3424 3425 PetscFunctionBegin; 3426 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3427 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3428 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3429 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3430 3431 dm->coordinatesLocal = c; 3432 3433 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3434 PetscFunctionReturn(0); 3435 } 3436 3437 #undef __FUNCT__ 3438 #define __FUNCT__ "DMGetCoordinates" 3439 /*@ 3440 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3441 3442 Not Collective 3443 3444 Input Parameter: 3445 . dm - the DM 3446 3447 Output Parameter: 3448 . c - global coordinate vector 3449 3450 Note: 3451 This is a borrowed reference, so the user should NOT destroy this vector 3452 3453 Each process has only the local coordinates (does NOT have the ghost coordinates). 3454 3455 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3456 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3457 3458 Level: intermediate 3459 3460 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3461 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3462 @*/ 3463 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 3464 { 3465 PetscErrorCode ierr; 3466 3467 PetscFunctionBegin; 3468 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3469 PetscValidPointer(c,2); 3470 if (!dm->coordinates && dm->coordinatesLocal) { 3471 DM cdm = NULL; 3472 3473 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3474 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 3475 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 3476 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3477 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3478 } 3479 *c = dm->coordinates; 3480 PetscFunctionReturn(0); 3481 } 3482 3483 #undef __FUNCT__ 3484 #define __FUNCT__ "DMGetCoordinatesLocal" 3485 /*@ 3486 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 3487 3488 Collective on DM 3489 3490 Input Parameter: 3491 . dm - the DM 3492 3493 Output Parameter: 3494 . c - coordinate vector 3495 3496 Note: 3497 This is a borrowed reference, so the user should NOT destroy this vector 3498 3499 Each process has the local and ghost coordinates 3500 3501 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3502 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3503 3504 Level: intermediate 3505 3506 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3507 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 3508 @*/ 3509 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 3510 { 3511 PetscErrorCode ierr; 3512 3513 PetscFunctionBegin; 3514 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3515 PetscValidPointer(c,2); 3516 if (!dm->coordinatesLocal && dm->coordinates) { 3517 DM cdm = NULL; 3518 3519 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3520 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 3521 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 3522 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3523 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3524 } 3525 *c = dm->coordinatesLocal; 3526 PetscFunctionReturn(0); 3527 } 3528 3529 #undef __FUNCT__ 3530 #define __FUNCT__ "DMGetCoordinateDM" 3531 /*@ 3532 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 3533 3534 Collective on DM 3535 3536 Input Parameter: 3537 . dm - the DM 3538 3539 Output Parameter: 3540 . cdm - coordinate DM 3541 3542 Level: intermediate 3543 3544 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3545 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3546 @*/ 3547 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 3548 { 3549 PetscErrorCode ierr; 3550 3551 PetscFunctionBegin; 3552 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3553 PetscValidPointer(cdm,2); 3554 if (!dm->coordinateDM) { 3555 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 3556 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 3557 } 3558 *cdm = dm->coordinateDM; 3559 PetscFunctionReturn(0); 3560 } 3561 3562 #undef __FUNCT__ 3563 #define __FUNCT__ "DMSetCoordinateDM" 3564 /*@ 3565 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 3566 3567 Logically Collective on DM 3568 3569 Input Parameters: 3570 + dm - the DM 3571 - cdm - coordinate DM 3572 3573 Level: intermediate 3574 3575 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3576 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3577 @*/ 3578 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 3579 { 3580 PetscErrorCode ierr; 3581 3582 PetscFunctionBegin; 3583 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3584 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 3585 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 3586 dm->coordinateDM = cdm; 3587 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 3588 PetscFunctionReturn(0); 3589 } 3590 3591 #undef __FUNCT__ 3592 #define __FUNCT__ "DMGetCoordinateSection" 3593 /*@ 3594 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 3595 3596 Not Collective 3597 3598 Input Parameter: 3599 . dm - The DM object 3600 3601 Output Parameter: 3602 . section - The PetscSection object 3603 3604 Level: intermediate 3605 3606 .keywords: mesh, coordinates 3607 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 3608 @*/ 3609 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 3610 { 3611 DM cdm; 3612 PetscErrorCode ierr; 3613 3614 PetscFunctionBegin; 3615 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3616 PetscValidPointer(section, 2); 3617 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3618 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 3619 PetscFunctionReturn(0); 3620 } 3621 3622 #undef __FUNCT__ 3623 #define __FUNCT__ "DMSetCoordinateSection" 3624 /*@ 3625 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 3626 3627 Not Collective 3628 3629 Input Parameters: 3630 + dm - The DM object 3631 - section - The PetscSection object 3632 3633 Level: intermediate 3634 3635 .keywords: mesh, coordinates 3636 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 3637 @*/ 3638 PetscErrorCode DMSetCoordinateSection(DM dm, PetscSection section) 3639 { 3640 DM cdm; 3641 PetscErrorCode ierr; 3642 3643 PetscFunctionBegin; 3644 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3645 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3646 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3647 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 3648 PetscFunctionReturn(0); 3649 } 3650 3651 #undef __FUNCT__ 3652 #define __FUNCT__ "DMGetPeriodicity" 3653 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L) 3654 { 3655 PetscFunctionBegin; 3656 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3657 if (L) *L = dm->L; 3658 if (maxCell) *maxCell = dm->maxCell; 3659 PetscFunctionReturn(0); 3660 } 3661 3662 #undef __FUNCT__ 3663 #define __FUNCT__ "DMSetPeriodicity" 3664 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[]) 3665 { 3666 Vec coordinates; 3667 PetscInt dim, d; 3668 PetscErrorCode ierr; 3669 3670 PetscFunctionBegin; 3671 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3672 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3673 ierr = VecGetBlockSize(coordinates, &dim);CHKERRQ(ierr); 3674 ierr = PetscMalloc1(dim,&dm->L);CHKERRQ(ierr); 3675 ierr = PetscMalloc1(dim,&dm->maxCell);CHKERRQ(ierr); 3676 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d];} 3677 PetscFunctionReturn(0); 3678 } 3679 3680 #undef __FUNCT__ 3681 #define __FUNCT__ "DMLocatePoints" 3682 /*@ 3683 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 3684 3685 Not collective 3686 3687 Input Parameters: 3688 + dm - The DM 3689 - v - The Vec of points 3690 3691 Output Parameter: 3692 . cells - The local cell numbers for cells which contain the points 3693 3694 Level: developer 3695 3696 .keywords: point location, mesh 3697 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3698 @*/ 3699 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 3700 { 3701 PetscErrorCode ierr; 3702 3703 PetscFunctionBegin; 3704 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3705 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 3706 PetscValidPointer(cells,3); 3707 if (dm->ops->locatepoints) { 3708 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 3709 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 3710 PetscFunctionReturn(0); 3711 } 3712 3713 #undef __FUNCT__ 3714 #define __FUNCT__ "DMGetOutputDM" 3715 /*@ 3716 DMGetOutputDM - Retrieve the DM associated with the layout for output 3717 3718 Input Parameter: 3719 . dm - The original DM 3720 3721 Output Parameter: 3722 . odm - The DM which provides the layout for output 3723 3724 Level: intermediate 3725 3726 .seealso: VecView(), DMGetDefaultGlobalSection() 3727 @*/ 3728 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 3729 { 3730 PetscSection section; 3731 PetscBool hasConstraints; 3732 PetscErrorCode ierr; 3733 3734 PetscFunctionBegin; 3735 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3736 PetscValidPointer(odm,2); 3737 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3738 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 3739 if (!hasConstraints) { 3740 *odm = dm; 3741 PetscFunctionReturn(0); 3742 } 3743 if (!dm->dmBC) { 3744 PetscSection newSection, gsection; 3745 PetscSF sf; 3746 3747 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 3748 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 3749 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 3750 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 3751 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 3752 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr); 3753 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 3754 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 3755 } 3756 *odm = dm->dmBC; 3757 PetscFunctionReturn(0); 3758 } 3759 3760 #undef __FUNCT__ 3761 #define __FUNCT__ "DMGetOutputSequenceNumber" 3762 /*@ 3763 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 3764 3765 Input Parameter: 3766 . dm - The original DM 3767 3768 Output Parameters: 3769 + num - The output sequence number 3770 - val - The output sequence value 3771 3772 Level: intermediate 3773 3774 Note: This is intended for output that should appear in sequence, for instance 3775 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 3776 3777 .seealso: VecView() 3778 @*/ 3779 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 3780 { 3781 PetscFunctionBegin; 3782 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3783 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 3784 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 3785 PetscFunctionReturn(0); 3786 } 3787 3788 #undef __FUNCT__ 3789 #define __FUNCT__ "DMSetOutputSequenceNumber" 3790 /*@ 3791 DMSetOutputSequenceNumber - Set the sequence number/value for output 3792 3793 Input Parameters: 3794 + dm - The original DM 3795 . num - The output sequence number 3796 - val - The output sequence value 3797 3798 Level: intermediate 3799 3800 Note: This is intended for output that should appear in sequence, for instance 3801 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 3802 3803 .seealso: VecView() 3804 @*/ 3805 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 3806 { 3807 PetscFunctionBegin; 3808 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3809 dm->outputSequenceNum = num; 3810 dm->outputSequenceVal = val; 3811 PetscFunctionReturn(0); 3812 } 3813 3814 #undef __FUNCT__ 3815 #define __FUNCT__ "DMOutputSequenceLoad" 3816 /*@C 3817 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 3818 3819 Input Parameters: 3820 + dm - The original DM 3821 . name - The sequence name 3822 - num - The output sequence number 3823 3824 Output Parameter: 3825 . val - The output sequence value 3826 3827 Level: intermediate 3828 3829 Note: This is intended for output that should appear in sequence, for instance 3830 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 3831 3832 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 3833 @*/ 3834 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 3835 { 3836 PetscBool ishdf5; 3837 PetscErrorCode ierr; 3838 3839 PetscFunctionBegin; 3840 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3841 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3842 PetscValidPointer(val,4); 3843 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 3844 if (ishdf5) { 3845 #if defined(PETSC_HAVE_HDF5) 3846 PetscScalar value; 3847 3848 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 3849 *val = PetscRealPart(value); 3850 #endif 3851 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 3852 PetscFunctionReturn(0); 3853 } 3854