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