1 #define PETSCDM_DLL 2 #include "private/daimpl.h" /*I "petscdm.h" I*/ 3 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "DMDASetDim" 7 /*@ 8 DMDASetDim - Sets the dimension 9 10 Collective on DMDA 11 12 Input Parameters: 13 + da - the DMDA 14 - dim - the dimension (or PETSC_DECIDE) 15 16 Level: intermediate 17 18 .seealso: DaGetDim(), DMDASetSizes() 19 @*/ 20 PetscErrorCode DMDASetDim(DM da, PetscInt dim) 21 { 22 DM_DA *dd = (DM_DA*)da->data; 23 24 PetscFunctionBegin; 25 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 26 if (dd->dim > 0 && dim != dd->dim) SETERRQ2(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot change DMDA dim from %D after it was set to %D",dd->dim,dim); 27 dd->dim = dim; 28 PetscFunctionReturn(0); 29 } 30 31 #undef __FUNCT__ 32 #define __FUNCT__ "DMDASetSizes" 33 /*@ 34 DMDASetSizes - Sets the global sizes 35 36 Logically Collective on DMDA 37 38 Input Parameters: 39 + da - the DMDA 40 . M - the global X size (or PETSC_DECIDE) 41 . N - the global Y size (or PETSC_DECIDE) 42 - P - the global Z size (or PETSC_DECIDE) 43 44 Level: intermediate 45 46 .seealso: DMDAGetSize(), PetscSplitOwnership() 47 @*/ 48 PetscErrorCode DMDASetSizes(DM da, PetscInt M, PetscInt N, PetscInt P) 49 { 50 DM_DA *dd = (DM_DA*)da->data; 51 52 PetscFunctionBegin; 53 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 54 PetscValidLogicalCollectiveInt(da,M,2); 55 PetscValidLogicalCollectiveInt(da,N,3); 56 PetscValidLogicalCollectiveInt(da,P,4); 57 58 dd->M = M; 59 dd->N = N; 60 dd->P = P; 61 PetscFunctionReturn(0); 62 } 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "DMDASetNumProcs" 66 /*@ 67 DMDASetNumProcs - Sets the number of processes in each dimension 68 69 Logically Collective on DMDA 70 71 Input Parameters: 72 + da - the DMDA 73 . m - the number of X procs (or PETSC_DECIDE) 74 . n - the number of Y procs (or PETSC_DECIDE) 75 - p - the number of Z procs (or PETSC_DECIDE) 76 77 Level: intermediate 78 79 .seealso: DMDASetSizes(), DMDAGetSize(), PetscSplitOwnership() 80 @*/ 81 PetscErrorCode DMDASetNumProcs(DM da, PetscInt m, PetscInt n, PetscInt p) 82 { 83 DM_DA *dd = (DM_DA*)da->data; 84 85 PetscFunctionBegin; 86 PetscValidHeaderSpecific(da, DM_CLASSID, 1); 87 PetscValidLogicalCollectiveInt(da,m,2); 88 PetscValidLogicalCollectiveInt(da,n,3); 89 PetscValidLogicalCollectiveInt(da,p,4); 90 dd->m = m; 91 dd->n = n; 92 dd->p = p; 93 PetscFunctionReturn(0); 94 } 95 96 #undef __FUNCT__ 97 #define __FUNCT__ "DMDASetPeriodicity" 98 /*@ 99 DMDASetPeriodicity - Sets the type of periodicity 100 101 Not collective 102 103 Input Parameter: 104 + da - The DMDA 105 - ptype - One of DMDA_NONPERIODIC, DMDA_XPERIODIC, DMDA_YPERIODIC, DMDA_ZPERIODIC, DMDA_XYPERIODIC, DMDA_XZPERIODIC, DMDA_YZPERIODIC, or DMDA_XYZPERIODIC 106 107 Level: intermediate 108 109 .keywords: distributed array, periodicity 110 .seealso: DMDACreate(), DMDestroy(), DMDA, DMDAPeriodicType 111 @*/ 112 PetscErrorCode DMDASetPeriodicity(DM da, DMDAPeriodicType ptype) 113 { 114 DM_DA *dd = (DM_DA*)da->data; 115 116 PetscFunctionBegin; 117 PetscValidHeaderSpecific(da,DM_CLASSID,1); 118 dd->wrap = ptype; 119 PetscFunctionReturn(0); 120 } 121 122 #undef __FUNCT__ 123 #define __FUNCT__ "DMDASetDof" 124 /*@ 125 DMDASetDof - Sets the number of degrees of freedom per vertex 126 127 Not collective 128 129 Input Parameter: 130 + da - The DMDA 131 - dof - Number of degrees of freedom 132 133 Level: intermediate 134 135 .keywords: distributed array, degrees of freedom 136 .seealso: DMDACreate(), DMDestroy(), DMDA 137 @*/ 138 PetscErrorCode DMDASetDof(DM da, int dof) 139 { 140 DM_DA *dd = (DM_DA*)da->data; 141 142 PetscFunctionBegin; 143 PetscValidHeaderSpecific(da,DM_CLASSID,1); 144 dd->w = dof; 145 da->bs = dof; 146 PetscFunctionReturn(0); 147 } 148 149 #undef __FUNCT__ 150 #define __FUNCT__ "DMDASetStencilType" 151 /*@ 152 DMDASetStencilType - Sets the type of the communication stencil 153 154 Logically Collective on DMDA 155 156 Input Parameter: 157 + da - The DMDA 158 - stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR. 159 160 Level: intermediate 161 162 .keywords: distributed array, stencil 163 .seealso: DMDACreate(), DMDestroy(), DMDA 164 @*/ 165 PetscErrorCode DMDASetStencilType(DM da, DMDAStencilType stype) 166 { 167 DM_DA *dd = (DM_DA*)da->data; 168 169 PetscFunctionBegin; 170 PetscValidHeaderSpecific(da,DM_CLASSID,1); 171 PetscValidLogicalCollectiveEnum(da,stype,2); 172 dd->stencil_type = stype; 173 PetscFunctionReturn(0); 174 } 175 176 #undef __FUNCT__ 177 #define __FUNCT__ "DMDASetStencilWidth" 178 /*@ 179 DMDASetStencilWidth - Sets the width of the communication stencil 180 181 Logically Collective on DMDA 182 183 Input Parameter: 184 + da - The DMDA 185 - width - The stencil width 186 187 Level: intermediate 188 189 .keywords: distributed array, stencil 190 .seealso: DMDACreate(), DMDestroy(), DMDA 191 @*/ 192 PetscErrorCode DMDASetStencilWidth(DM da, PetscInt width) 193 { 194 DM_DA *dd = (DM_DA*)da->data; 195 196 PetscFunctionBegin; 197 PetscValidHeaderSpecific(da,DM_CLASSID,1); 198 PetscValidLogicalCollectiveInt(da,width,2); 199 dd->s = width; 200 PetscFunctionReturn(0); 201 } 202 203 #undef __FUNCT__ 204 #define __FUNCT__ "DMDACheckOwnershipRanges_Private" 205 static PetscErrorCode DMDACheckOwnershipRanges_Private(DM da,PetscInt M,PetscInt m,const PetscInt lx[]) 206 { 207 PetscInt i,sum; 208 209 PetscFunctionBegin; 210 if (M < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Global dimension not set"); 211 for (i=sum=0; i<m; i++) sum += lx[i]; 212 if (sum != M) SETERRQ2(((PetscObject)da)->comm,PETSC_ERR_ARG_INCOMP,"Ownership ranges sum to %D but global dimension is %D",sum,M); 213 PetscFunctionReturn(0); 214 } 215 216 #undef __FUNCT__ 217 #define __FUNCT__ "DMDASetOwnershipRanges" 218 /*@ 219 DMDASetOwnershipRanges - Sets the number of nodes in each direction on each process 220 221 Logically Collective on DMDA 222 223 Input Parameter: 224 + da - The DMDA 225 . lx - array containing number of nodes in the X direction on each process, or PETSC_NULL. If non-null, must be of length da->m 226 . ly - array containing number of nodes in the Y direction on each process, or PETSC_NULL. If non-null, must be of length da->n 227 - lz - array containing number of nodes in the Z direction on each process, or PETSC_NULL. If non-null, must be of length da->p. 228 229 Level: intermediate 230 231 .keywords: distributed array 232 .seealso: DMDACreate(), DMDestroy(), DMDA 233 @*/ 234 PetscErrorCode DMDASetOwnershipRanges(DM da, const PetscInt lx[], const PetscInt ly[], const PetscInt lz[]) 235 { 236 PetscErrorCode ierr; 237 DM_DA *dd = (DM_DA*)da->data; 238 239 PetscFunctionBegin; 240 PetscValidHeaderSpecific(da,DM_CLASSID,1); 241 if (lx) { 242 if (dd->m < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs"); 243 ierr = DMDACheckOwnershipRanges_Private(da,dd->M,dd->m,lx);CHKERRQ(ierr); 244 if (!dd->lx) { 245 ierr = PetscMalloc(dd->m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr); 246 } 247 ierr = PetscMemcpy(dd->lx, lx, dd->m*sizeof(PetscInt));CHKERRQ(ierr); 248 } 249 if (ly) { 250 if (dd->n < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs"); 251 ierr = DMDACheckOwnershipRanges_Private(da,dd->N,dd->n,ly);CHKERRQ(ierr); 252 if (!dd->ly) { 253 ierr = PetscMalloc(dd->n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr); 254 } 255 ierr = PetscMemcpy(dd->ly, ly, dd->n*sizeof(PetscInt));CHKERRQ(ierr); 256 } 257 if (lz) { 258 if (dd->p < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs"); 259 ierr = DMDACheckOwnershipRanges_Private(da,dd->P,dd->p,lz);CHKERRQ(ierr); 260 if (!dd->lz) { 261 ierr = PetscMalloc(dd->p*sizeof(PetscInt), &dd->lz);CHKERRQ(ierr); 262 } 263 ierr = PetscMemcpy(dd->lz, lz, dd->p*sizeof(PetscInt));CHKERRQ(ierr); 264 } 265 PetscFunctionReturn(0); 266 } 267 268 #undef __FUNCT__ 269 #define __FUNCT__ "DMDACreateOwnershipRanges" 270 /* 271 Ensure that da->lx, ly, and lz exist. Collective on DMDA. 272 */ 273 PetscErrorCode DMDACreateOwnershipRanges(DM da) 274 { 275 DM_DA *dd = (DM_DA*)da->data; 276 PetscErrorCode ierr; 277 PetscInt n; 278 MPI_Comm comm; 279 PetscMPIInt size; 280 281 PetscFunctionBegin; 282 if (!dd->lx) { 283 ierr = PetscMalloc(dd->m*sizeof(PetscInt),&dd->lx);CHKERRQ(ierr); 284 ierr = DMDAGetProcessorSubset(da,DMDA_X,dd->xs,&comm);CHKERRQ(ierr); 285 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 286 n = (dd->xe-dd->xs)/dd->w; 287 ierr = MPI_Allgather(&n,1,MPIU_INT,dd->lx,1,MPIU_INT,comm);CHKERRQ(ierr); 288 } 289 if (dd->dim > 1 && !dd->ly) { 290 ierr = PetscMalloc(dd->n*sizeof(PetscInt),&dd->ly);CHKERRQ(ierr); 291 ierr = DMDAGetProcessorSubset(da,DMDA_Y,dd->ys,&comm);CHKERRQ(ierr); 292 n = dd->ye-dd->ys; 293 ierr = MPI_Allgather(&n,1,MPIU_INT,dd->ly,1,MPIU_INT,comm);CHKERRQ(ierr); 294 } 295 if (dd->dim > 2 && !dd->lz) { 296 ierr = PetscMalloc(dd->p*sizeof(PetscInt),&dd->lz);CHKERRQ(ierr); 297 ierr = DMDAGetProcessorSubset(da,DMDA_Z,dd->zs,&comm);CHKERRQ(ierr); 298 n = dd->ze-dd->zs; 299 ierr = MPI_Allgather(&n,1,MPIU_INT,dd->lz,1,MPIU_INT,comm);CHKERRQ(ierr); 300 } 301 PetscFunctionReturn(0); 302 } 303 304 #undef __FUNCT__ 305 #define __FUNCT__ "DMDASetInterpolationType" 306 /*@ 307 DMDASetInterpolationType - Sets the type of interpolation that will be 308 returned by DMGetInterpolation() 309 310 Logically Collective on DMDA 311 312 Input Parameter: 313 + da - initial distributed array 314 . ctype - DMDA_Q1 and DMDA_Q0 are currently the only supported forms 315 316 Level: intermediate 317 318 Notes: you should call this on the coarser of the two DMDAs you pass to DMGetInterpolation() 319 320 .keywords: distributed array, interpolation 321 322 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType 323 @*/ 324 PetscErrorCode DMDASetInterpolationType(DM da,DMDAInterpolationType ctype) 325 { 326 DM_DA *dd = (DM_DA*)da->data; 327 328 PetscFunctionBegin; 329 PetscValidHeaderSpecific(da,DM_CLASSID,1); 330 PetscValidLogicalCollectiveEnum(da,ctype,2); 331 dd->interptype = ctype; 332 PetscFunctionReturn(0); 333 } 334 335 336 #undef __FUNCT__ 337 #define __FUNCT__ "DMDAGetNeighbors" 338 /*@C 339 DMDAGetNeighbors - Gets an array containing the MPI rank of all the current 340 processes neighbors. 341 342 Not Collective 343 344 Input Parameter: 345 . da - the DMDA object 346 347 Output Parameters: 348 . ranks - the neighbors ranks, stored with the x index increasing most rapidly. 349 this process itself is in the list 350 351 Notes: In 2d the array is of length 9, in 3d of length 27 352 Not supported in 1d 353 Do not free the array, it is freed when the DMDA is destroyed. 354 355 Fortran Notes: In fortran you must pass in an array of the appropriate length. 356 357 Level: intermediate 358 359 @*/ 360 PetscErrorCode DMDAGetNeighbors(DM da,const PetscMPIInt *ranks[]) 361 { 362 DM_DA *dd = (DM_DA*)da->data; 363 PetscFunctionBegin; 364 PetscValidHeaderSpecific(da,DM_CLASSID,1); 365 *ranks = dd->neighbors; 366 PetscFunctionReturn(0); 367 } 368 369 /*@C 370 DMDASetElementType - Sets the element type to be returned by DMGetElements() 371 372 Not Collective 373 374 Input Parameter: 375 . da - the DMDA object 376 377 Output Parameters: 378 . etype - the element type, currently either DMDA_ELEMENT_P1 or ELEMENT_Q1 379 380 Level: intermediate 381 382 .seealso: DMDAElementType, DMDAGetElementType(), DMGetElements(), DMRestoreElements() 383 @*/ 384 #undef __FUNCT__ 385 #define __FUNCT__ "DMDASetElementType" 386 PetscErrorCode DMDASetElementType(DM da, DMDAElementType etype) 387 { 388 DM_DA *dd = (DM_DA*)da->data; 389 PetscErrorCode ierr; 390 391 PetscFunctionBegin; 392 PetscValidHeaderSpecific(da,DM_CLASSID,1); 393 PetscValidLogicalCollectiveEnum(da,etype,2); 394 if (dd->elementtype != etype) { 395 ierr = PetscFree(dd->e);CHKERRQ(ierr); 396 dd->elementtype = etype; 397 dd->ne = 0; 398 dd->e = PETSC_NULL; 399 } 400 PetscFunctionReturn(0); 401 } 402 403 /*@C 404 DMDAGetElementType - Gets the element type to be returned by DMGetElements() 405 406 Not Collective 407 408 Input Parameter: 409 . da - the DMDA object 410 411 Output Parameters: 412 . etype - the element type, currently either DMDA_ELEMENT_P1 or ELEMENT_Q1 413 414 Level: intermediate 415 416 .seealso: DMDAElementType, DMDASetElementType(), DMGetElements(), DMRestoreElements() 417 @*/ 418 #undef __FUNCT__ 419 #define __FUNCT__ "DMDAGetElementType" 420 PetscErrorCode DMDAGetElementType(DM da, DMDAElementType *etype) 421 { 422 DM_DA *dd = (DM_DA*)da->data; 423 PetscFunctionBegin; 424 PetscValidHeaderSpecific(da,DM_CLASSID,1); 425 PetscValidPointer(etype,2); 426 *etype = dd->elementtype; 427 PetscFunctionReturn(0); 428 } 429 430 #undef __FUNCT__ 431 #define __FUNCT__ "DMGetElements" 432 /*@C 433 DMGetElements - Gets an array containing the indices (in local coordinates) 434 of all the local elements 435 436 Not Collective 437 438 Input Parameter: 439 . dm - the DM object 440 441 Output Parameters: 442 + nel - number of local elements 443 . nen - number of element nodes 444 - e - the indices of the elements vertices 445 446 Level: intermediate 447 448 .seealso: DMElementType, DMSetElementType(), DMRestoreElements() 449 @*/ 450 PetscErrorCode DMGetElements(DM dm,PetscInt *nel,PetscInt *nen,const PetscInt *e[]) 451 { 452 PetscErrorCode ierr; 453 PetscFunctionBegin; 454 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 455 PetscValidIntPointer(nel,2); 456 PetscValidIntPointer(nen,3); 457 PetscValidPointer(e,4); 458 ierr = (dm->ops->getelements)(dm,nel,nen,e);CHKERRQ(ierr); 459 PetscFunctionReturn(0); 460 } 461 462 #undef __FUNCT__ 463 #define __FUNCT__ "DMRestoreElements" 464 /*@C 465 DMRestoreElements - Returns an array containing the indices (in local coordinates) 466 of all the local elements obtained with DMGetElements() 467 468 Not Collective 469 470 Input Parameter: 471 + dm - the DM object 472 . nel - number of local elements 473 . nen - number of element nodes 474 - e - the indices of the elements vertices 475 476 Level: intermediate 477 478 .seealso: DMElementType, DMSetElementType(), DMGetElements() 479 @*/ 480 PetscErrorCode DMRestoreElements(DM dm,PetscInt *nel,PetscInt *nen,const PetscInt *e[]) 481 { 482 PetscErrorCode ierr; 483 PetscFunctionBegin; 484 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 485 PetscValidIntPointer(nel,2); 486 PetscValidIntPointer(nen,3); 487 PetscValidPointer(e,4); 488 if (dm->ops->restoreelements) { 489 ierr = (dm->ops->restoreelements)(dm,nel,nen,e);CHKERRQ(ierr); 490 } 491 PetscFunctionReturn(0); 492 } 493 494 #undef __FUNCT__ 495 #define __FUNCT__ "DMDAGetOwnershipRanges" 496 /*@C 497 DMDAGetOwnershipRanges - Gets the ranges of indices in the x, y and z direction that are owned by each process 498 499 Not Collective 500 501 Input Parameter: 502 . da - the DMDA object 503 504 Output Parameter: 505 + lx - ownership along x direction (optional) 506 . ly - ownership along y direction (optional) 507 - lz - ownership along z direction (optional) 508 509 Level: intermediate 510 511 Note: these correspond to the optional final arguments passed to DMDACreate(), DMDACreate2d(), DMDACreate3d() 512 513 In Fortran one must pass in arrays lx, ly, and lz that are long enough to hold the values; the sixth, seventh and 514 eighth arguments from DMDAGetInfo() 515 516 In C you should not free these arrays, nor change the values in them. They will only have valid values while the 517 DMDA they came from still exists (has not been destroyed). 518 519 .seealso: DMDAGetCorners(), DMDAGetGhostCorners(), DMDACreate(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), VecGetOwnershipRanges() 520 @*/ 521 PetscErrorCode DMDAGetOwnershipRanges(DM da,const PetscInt *lx[],const PetscInt *ly[],const PetscInt *lz[]) 522 { 523 DM_DA *dd = (DM_DA*)da->data; 524 525 PetscFunctionBegin; 526 PetscValidHeaderSpecific(da,DM_CLASSID,1); 527 if (lx) *lx = dd->lx; 528 if (ly) *ly = dd->ly; 529 if (lz) *lz = dd->lz; 530 PetscFunctionReturn(0); 531 } 532 533 #undef __FUNCT__ 534 #define __FUNCT__ "DMDASetRefinementFactor" 535 /*@ 536 DMDASetRefinementFactor - Set the ratios that the DMDA grid is refined 537 538 Logically Collective on DMDA 539 540 Input Parameters: 541 + da - the DMDA object 542 . refine_x - ratio of fine grid to coarse in x direction (2 by default) 543 . refine_y - ratio of fine grid to coarse in y direction (2 by default) 544 - refine_z - ratio of fine grid to coarse in z direction (2 by default) 545 546 Options Database: 547 + -da_refine_x - refinement ratio in x direction 548 . -da_refine_y - refinement ratio in y direction 549 - -da_refine_z - refinement ratio in z direction 550 551 Level: intermediate 552 553 Notes: Pass PETSC_IGNORE to leave a value unchanged 554 555 .seealso: DMRefine(), DMDAGetRefinementFactor() 556 @*/ 557 PetscErrorCode DMDASetRefinementFactor(DM da, PetscInt refine_x, PetscInt refine_y,PetscInt refine_z) 558 { 559 DM_DA *dd = (DM_DA*)da->data; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(da,DM_CLASSID,1); 563 PetscValidLogicalCollectiveInt(da,refine_x,2); 564 PetscValidLogicalCollectiveInt(da,refine_y,3); 565 PetscValidLogicalCollectiveInt(da,refine_z,4); 566 567 if (refine_x > 0) dd->refine_x = refine_x; 568 if (refine_y > 0) dd->refine_y = refine_y; 569 if (refine_z > 0) dd->refine_z = refine_z; 570 PetscFunctionReturn(0); 571 } 572 573 #undef __FUNCT__ 574 #define __FUNCT__ "DMDAGetRefinementFactor" 575 /*@C 576 DMDAGetRefinementFactor - Gets the ratios that the DMDA grid is refined 577 578 Not Collective 579 580 Input Parameter: 581 . da - the DMDA object 582 583 Output Parameters: 584 + refine_x - ratio of fine grid to coarse in x direction (2 by default) 585 . refine_y - ratio of fine grid to coarse in y direction (2 by default) 586 - refine_z - ratio of fine grid to coarse in z direction (2 by default) 587 588 Level: intermediate 589 590 Notes: Pass PETSC_NULL for values you do not need 591 592 .seealso: DMRefine(), DMDASetRefinementFactor() 593 @*/ 594 PetscErrorCode DMDAGetRefinementFactor(DM da, PetscInt *refine_x, PetscInt *refine_y,PetscInt *refine_z) 595 { 596 DM_DA *dd = (DM_DA*)da->data; 597 598 PetscFunctionBegin; 599 PetscValidHeaderSpecific(da,DM_CLASSID,1); 600 if (refine_x) *refine_x = dd->refine_x; 601 if (refine_y) *refine_y = dd->refine_y; 602 if (refine_z) *refine_z = dd->refine_z; 603 PetscFunctionReturn(0); 604 } 605 606 #undef __FUNCT__ 607 #define __FUNCT__ "DMDASetGetMatrix" 608 /*@C 609 DMDASetGetMatrix - Sets the routine used by the DMDA to allocate a matrix. 610 611 Logically Collective on DMDA 612 613 Input Parameters: 614 + da - the DMDA object 615 - f - the function that allocates the matrix for that specific DMDA 616 617 Level: developer 618 619 Notes: See DMDASetBlockFills() that provides a simple way to provide the nonzero structure for 620 the diagonal and off-diagonal blocks of the matrix 621 622 .seealso: DMGetMatrix(), DMDASetBlockFills() 623 @*/ 624 PetscErrorCode DMDASetGetMatrix(DM da,PetscErrorCode (*f)(DM, const MatType,Mat*)) 625 { 626 PetscFunctionBegin; 627 PetscValidHeaderSpecific(da,DM_CLASSID,1); 628 da->ops->getmatrix = f; 629 PetscFunctionReturn(0); 630 } 631 632 #undef __FUNCT__ 633 #define __FUNCT__ "DMDARefineOwnershipRanges" 634 /* 635 Creates "balanced" ownership ranges after refinement, constrained by the need for the 636 fine grid boundaries to fall within one stencil width of the coarse partition. 637 638 Uses a greedy algorithm to handle non-ideal layouts, could probably do something better. 639 */ 640 static PetscErrorCode DMDARefineOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lc[],PetscInt lf[]) 641 { 642 PetscInt i,totalc = 0,remaining,startc = 0,startf = 0; 643 PetscErrorCode ierr; 644 645 PetscFunctionBegin; 646 if (ratio < 1) SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_USER,"Requested refinement ratio %D must be at least 1",ratio); 647 if (ratio == 1) { 648 ierr = PetscMemcpy(lf,lc,m*sizeof(lc[0]));CHKERRQ(ierr); 649 PetscFunctionReturn(0); 650 } 651 for (i=0; i<m; i++) totalc += lc[i]; 652 remaining = (!periodic) + ratio * (totalc - (!periodic)); 653 for (i=0; i<m; i++) { 654 PetscInt want = remaining/(m-i) + !!(remaining%(m-i)); 655 if (i == m-1) lf[i] = want; 656 else { 657 const PetscInt nextc = startc + lc[i]; 658 /* Move the first fine node of the next subdomain to the right until the coarse node on its left is within one 659 * coarse stencil width of the first coarse node in the next subdomain. */ 660 while ((startf+want)/ratio < nextc - stencil_width) want++; 661 /* Move the last fine node in the current subdomain to the left until the coarse node on its right is within one 662 * coarse stencil width of the last coarse node in the current subdomain. */ 663 while ((startf+want-1+ratio-1)/ratio > nextc-1+stencil_width) want--; 664 /* Make sure all constraints are satisfied */ 665 if (want < 0 || want > remaining 666 || ((startf+want)/ratio < nextc - stencil_width) 667 || ((startf+want-1+ratio-1)/ratio > nextc-1+stencil_width)) 668 SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_SIZ,"Could not find a compatible refined ownership range"); 669 } 670 lf[i] = want; 671 startc += lc[i]; 672 startf += lf[i]; 673 remaining -= lf[i]; 674 } 675 PetscFunctionReturn(0); 676 } 677 678 #undef __FUNCT__ 679 #define __FUNCT__ "DMDACoarsenOwnershipRanges" 680 /* 681 Creates "balanced" ownership ranges after coarsening, constrained by the need for the 682 fine grid boundaries to fall within one stencil width of the coarse partition. 683 684 Uses a greedy algorithm to handle non-ideal layouts, could probably do something better. 685 */ 686 static PetscErrorCode DMDACoarsenOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lf[],PetscInt lc[]) 687 { 688 PetscInt i,totalf,remaining,startc,startf; 689 PetscErrorCode ierr; 690 691 PetscFunctionBegin; 692 if (ratio < 1) SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_USER,"Requested refinement ratio %D must be at least 1",ratio); 693 if (ratio == 1) { 694 ierr = PetscMemcpy(lc,lf,m*sizeof(lf[0]));CHKERRQ(ierr); 695 PetscFunctionReturn(0); 696 } 697 for (i=0,totalf=0; i<m; i++) totalf += lf[i]; 698 remaining = (!periodic) + (totalf - (!periodic)) / ratio; 699 for (i=0,startc=0,startf=0; i<m; i++) { 700 PetscInt want = remaining/(m-i) + !!(remaining%(m-i)); 701 if (i == m-1) lc[i] = want; 702 else { 703 const PetscInt nextf = startf+lf[i]; 704 /* Slide first coarse node of next subdomain to the left until the coarse node to the left of the first fine 705 * node is within one stencil width. */ 706 while (nextf/ratio < startc+want-stencil_width) want--; 707 /* Slide the last coarse node of the current subdomain to the right until the coarse node to the right of the last 708 * fine node is within one stencil width. */ 709 while ((nextf-1+ratio-1)/ratio > startc+want-1+stencil_width) want++; 710 if (want < 0 || want > remaining 711 || (nextf/ratio < startc+want-stencil_width) 712 || ((nextf-1+ratio-1)/ratio > startc+want-1+stencil_width)) 713 SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_SIZ,"Could not find a compatible coarsened ownership range"); 714 } 715 lc[i] = want; 716 startc += lc[i]; 717 startf += lf[i]; 718 remaining -= lc[i]; 719 } 720 PetscFunctionReturn(0); 721 } 722 723 #undef __FUNCT__ 724 #define __FUNCT__ "DMRefine_DA" 725 PetscErrorCode DMRefine_DA(DM da,MPI_Comm comm,DM *daref) 726 { 727 PetscErrorCode ierr; 728 PetscInt M,N,P; 729 DM da2; 730 DM_DA *dd = (DM_DA*)da->data,*dd2; 731 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(da,DM_CLASSID,1); 734 PetscValidPointer(daref,3); 735 736 if (DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 737 M = dd->refine_x*dd->M; 738 } else { 739 M = 1 + dd->refine_x*(dd->M - 1); 740 } 741 if (DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 742 N = dd->refine_y*dd->N; 743 } else { 744 N = 1 + dd->refine_y*(dd->N - 1); 745 } 746 if (DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 747 P = dd->refine_z*dd->P; 748 } else { 749 P = 1 + dd->refine_z*(dd->P - 1); 750 } 751 ierr = DMDACreateOwnershipRanges(da);CHKERRQ(ierr); 752 if (dd->dim == 3) { 753 PetscInt *lx,*ly,*lz; 754 ierr = PetscMalloc3(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly,dd->p,PetscInt,&lz);CHKERRQ(ierr); 755 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 756 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 757 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz);CHKERRQ(ierr); 758 ierr = DMDACreate3d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,P,dd->m,dd->n,dd->p,dd->w,dd->s,lx,ly,lz,&da2);CHKERRQ(ierr); 759 ierr = PetscFree3(lx,ly,lz);CHKERRQ(ierr); 760 } else if (dd->dim == 2) { 761 PetscInt *lx,*ly; 762 ierr = PetscMalloc2(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly);CHKERRQ(ierr); 763 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 764 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 765 ierr = DMDACreate2d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,dd->m,dd->n,dd->w,dd->s,lx,ly,&da2);CHKERRQ(ierr); 766 ierr = PetscFree2(lx,ly);CHKERRQ(ierr); 767 } else if (dd->dim == 1) { 768 PetscInt *lx; 769 ierr = PetscMalloc(dd->m*sizeof(PetscInt),&lx);CHKERRQ(ierr); 770 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 771 ierr = DMDACreate1d(((PetscObject)da)->comm,dd->wrap,M,dd->w,dd->s,lx,&da2);CHKERRQ(ierr); 772 ierr = PetscFree(lx);CHKERRQ(ierr); 773 } 774 dd2 = (DM_DA*)da2->data; 775 776 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 777 da2->ops->getmatrix = da->ops->getmatrix; 778 da2->ops->getinterpolation = da->ops->getinterpolation; 779 da2->ops->getcoloring = da->ops->getcoloring; 780 dd2->interptype = dd->interptype; 781 782 /* copy fill information if given */ 783 if (dd->dfill) { 784 ierr = PetscMalloc((dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->dfill);CHKERRQ(ierr); 785 ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 786 } 787 if (dd->ofill) { 788 ierr = PetscMalloc((dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->ofill);CHKERRQ(ierr); 789 ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 790 } 791 /* copy the refine information */ 792 dd2->refine_x = dd->refine_x; 793 dd2->refine_y = dd->refine_y; 794 dd2->refine_z = dd->refine_z; 795 796 /* copy vector type information */ 797 ierr = PetscFree(da2->vectype);CHKERRQ(ierr); 798 ierr = PetscStrallocpy(da->vectype,&da2->vectype);CHKERRQ(ierr); 799 800 /* interpolate coordinates if they are set on the coarse grid */ 801 if (dd->coordinates) { 802 DM cdaf,cdac; 803 Vec coordsc,coordsf; 804 Mat II; 805 806 ierr = DMDAGetCoordinateDA(da,&cdac);CHKERRQ(ierr); 807 ierr = DMDAGetCoordinates(da,&coordsc);CHKERRQ(ierr); 808 ierr = DMDAGetCoordinateDA(da2,&cdaf);CHKERRQ(ierr); 809 /* force creation of the coordinate vector */ 810 ierr = DMDASetUniformCoordinates(da2,0.0,1.0,0.0,1.0,0.0,1.0);CHKERRQ(ierr); 811 ierr = DMDAGetCoordinates(da2,&coordsf);CHKERRQ(ierr); 812 ierr = DMGetInterpolation(cdac,cdaf,&II,PETSC_NULL);CHKERRQ(ierr); 813 ierr = MatInterpolate(II,coordsc,coordsf);CHKERRQ(ierr); 814 ierr = MatDestroy(II);CHKERRQ(ierr); 815 } 816 *daref = da2; 817 PetscFunctionReturn(0); 818 } 819 820 #undef __FUNCT__ 821 #define __FUNCT__ "DMCoarsen_DA" 822 PetscErrorCode DMCoarsen_DA(DM da, MPI_Comm comm,DM *daref) 823 { 824 PetscErrorCode ierr; 825 PetscInt M,N,P; 826 DM da2; 827 DM_DA *dd = (DM_DA*)da->data,*dd2; 828 829 PetscFunctionBegin; 830 PetscValidHeaderSpecific(da,DM_CLASSID,1); 831 PetscValidPointer(daref,3); 832 833 if (DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 834 M = dd->M / dd->refine_x; 835 } else { 836 M = 1 + (dd->M - 1) / dd->refine_x; 837 } 838 if (DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 839 N = dd->N / dd->refine_y; 840 } else { 841 N = 1 + (dd->N - 1) / dd->refine_y; 842 } 843 if (DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 844 P = dd->P / dd->refine_z; 845 } else { 846 P = 1 + (dd->P - 1) / dd->refine_z; 847 } 848 ierr = DMDACreateOwnershipRanges(da);CHKERRQ(ierr); 849 if (dd->dim == 3) { 850 PetscInt *lx,*ly,*lz; 851 ierr = PetscMalloc3(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly,dd->p,PetscInt,&lz);CHKERRQ(ierr); 852 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 853 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 854 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz);CHKERRQ(ierr); 855 ierr = DMDACreate3d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,P,dd->m,dd->n,dd->p,dd->w,dd->s,lx,ly,lz,&da2);CHKERRQ(ierr); 856 ierr = PetscFree3(lx,ly,lz);CHKERRQ(ierr); 857 } else if (dd->dim == 2) { 858 PetscInt *lx,*ly; 859 ierr = PetscMalloc2(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly);CHKERRQ(ierr); 860 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 861 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 862 ierr = DMDACreate2d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,dd->m,dd->n,dd->w,dd->s,lx,ly,&da2);CHKERRQ(ierr); 863 ierr = PetscFree2(lx,ly);CHKERRQ(ierr); 864 } else if (dd->dim == 1) { 865 PetscInt *lx; 866 ierr = PetscMalloc(dd->m*sizeof(PetscInt),&lx);CHKERRQ(ierr); 867 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 868 ierr = DMDACreate1d(((PetscObject)da)->comm,dd->wrap,M,dd->w,dd->s,lx,&da2);CHKERRQ(ierr); 869 ierr = PetscFree(lx);CHKERRQ(ierr); 870 } 871 dd2 = (DM_DA*)da2->data; 872 873 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 874 da2->ops->getmatrix = da->ops->getmatrix; 875 da2->ops->getinterpolation = da->ops->getinterpolation; 876 da2->ops->getcoloring = da->ops->getcoloring; 877 dd2->interptype = dd->interptype; 878 879 /* copy fill information if given */ 880 if (dd->dfill) { 881 ierr = PetscMalloc((dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->dfill);CHKERRQ(ierr); 882 ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 883 } 884 if (dd->ofill) { 885 ierr = PetscMalloc((dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->ofill);CHKERRQ(ierr); 886 ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 887 } 888 /* copy the refine information */ 889 dd2->refine_x = dd->refine_x; 890 dd2->refine_y = dd->refine_y; 891 dd2->refine_z = dd->refine_z; 892 893 /* copy vector type information */ 894 ierr = PetscFree(da2->vectype);CHKERRQ(ierr); 895 ierr = PetscStrallocpy(da->vectype,&da2->vectype);CHKERRQ(ierr); 896 897 /* inject coordinates if they are set on the fine grid */ 898 if (dd->coordinates) { 899 DM cdaf,cdac; 900 Vec coordsc,coordsf; 901 VecScatter inject; 902 903 ierr = DMDAGetCoordinateDA(da,&cdaf);CHKERRQ(ierr); 904 ierr = DMDAGetCoordinates(da,&coordsf);CHKERRQ(ierr); 905 ierr = DMDAGetCoordinateDA(da2,&cdac);CHKERRQ(ierr); 906 /* force creation of the coordinate vector */ 907 ierr = DMDASetUniformCoordinates(da2,0.0,1.0,0.0,1.0,0.0,1.0);CHKERRQ(ierr); 908 ierr = DMDAGetCoordinates(da2,&coordsc);CHKERRQ(ierr); 909 910 ierr = DMGetInjection(cdac,cdaf,&inject);CHKERRQ(ierr); 911 ierr = VecScatterBegin(inject,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 912 ierr = VecScatterEnd(inject ,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 913 ierr = VecScatterDestroy(inject);CHKERRQ(ierr); 914 } 915 *daref = da2; 916 PetscFunctionReturn(0); 917 } 918 919 #undef __FUNCT__ 920 #define __FUNCT__ "DMRefineHierarchy_DA" 921 PetscErrorCode DMRefineHierarchy_DA(DM da,PetscInt nlevels,DM daf[]) 922 { 923 PetscErrorCode ierr; 924 PetscInt i,n,*refx,*refy,*refz; 925 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(da,DM_CLASSID,1); 928 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 929 if (nlevels == 0) PetscFunctionReturn(0); 930 PetscValidPointer(daf,3); 931 932 /* Get refinement factors, defaults taken from the coarse DMDA */ 933 ierr = PetscMalloc3(nlevels,PetscInt,&refx,nlevels,PetscInt,&refy,nlevels,PetscInt,&refz);CHKERRQ(ierr); 934 for (i=0; i<nlevels; i++) { 935 ierr = DMDAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]);CHKERRQ(ierr); 936 } 937 n = nlevels; 938 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,PETSC_NULL);CHKERRQ(ierr); 939 n = nlevels; 940 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,PETSC_NULL);CHKERRQ(ierr); 941 n = nlevels; 942 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,PETSC_NULL);CHKERRQ(ierr); 943 944 ierr = DMDASetRefinementFactor(da,refx[0],refy[0],refz[0]);CHKERRQ(ierr); 945 ierr = DMRefine(da,((PetscObject)da)->comm,&daf[0]);CHKERRQ(ierr); 946 for (i=1; i<nlevels; i++) { 947 ierr = DMDASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]);CHKERRQ(ierr); 948 ierr = DMRefine(daf[i-1],((PetscObject)da)->comm,&daf[i]);CHKERRQ(ierr); 949 } 950 ierr = PetscFree3(refx,refy,refz);CHKERRQ(ierr); 951 PetscFunctionReturn(0); 952 } 953 954 #undef __FUNCT__ 955 #define __FUNCT__ "DMCoarsenHierarchy_DA" 956 PetscErrorCode DMCoarsenHierarchy_DA(DM da,PetscInt nlevels,DM dac[]) 957 { 958 PetscErrorCode ierr; 959 PetscInt i; 960 961 PetscFunctionBegin; 962 PetscValidHeaderSpecific(da,DM_CLASSID,1); 963 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 964 if (nlevels == 0) PetscFunctionReturn(0); 965 PetscValidPointer(dac,3); 966 ierr = DMCoarsen(da,((PetscObject)da)->comm,&dac[0]);CHKERRQ(ierr); 967 for (i=1; i<nlevels; i++) { 968 ierr = DMCoarsen(dac[i-1],((PetscObject)da)->comm,&dac[i]);CHKERRQ(ierr); 969 } 970 PetscFunctionReturn(0); 971 } 972