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