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