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