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