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