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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 PETSCDM_DLLEXPORT 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 = DMDAGetCoordinateDA(da2,&cdaf);CHKERRQ(ierr); 808 ierr = DMDAGetCoordinates(da,&coordsc);CHKERRQ(ierr); 809 ierr = DMDAGetCoordinates(da2,&coordsf);CHKERRQ(ierr); 810 ierr = DMGetInterpolation(cdac,cdaf,&II,PETSC_NULL);CHKERRQ(ierr); 811 ierr = MatInterpolate(II,coordsc,coordsf);CHKERRQ(ierr); 812 ierr = MatDestroy(II);CHKERRQ(ierr); 813 } 814 *daref = da2; 815 PetscFunctionReturn(0); 816 } 817 818 #undef __FUNCT__ 819 #define __FUNCT__ "DMCoarsen_DA" 820 PetscErrorCode PETSCDM_DLLEXPORT DMCoarsen_DA(DM da, MPI_Comm comm,DM *daref) 821 { 822 PetscErrorCode ierr; 823 PetscInt M,N,P; 824 DM da2; 825 DM_DA *dd = (DM_DA*)da->data,*dd2; 826 827 PetscFunctionBegin; 828 PetscValidHeaderSpecific(da,DM_CLASSID,1); 829 PetscValidPointer(daref,3); 830 831 if (DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 832 M = dd->M / dd->refine_x; 833 } else { 834 M = 1 + (dd->M - 1) / dd->refine_x; 835 } 836 if (DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 837 N = dd->N / dd->refine_y; 838 } else { 839 N = 1 + (dd->N - 1) / dd->refine_y; 840 } 841 if (DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 842 P = dd->P / dd->refine_z; 843 } else { 844 P = 1 + (dd->P - 1) / dd->refine_z; 845 } 846 ierr = DMDACreateOwnershipRanges(da);CHKERRQ(ierr); 847 if (dd->dim == 3) { 848 PetscInt *lx,*ly,*lz; 849 ierr = PetscMalloc3(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly,dd->p,PetscInt,&lz);CHKERRQ(ierr); 850 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 851 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 852 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz);CHKERRQ(ierr); 853 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); 854 ierr = PetscFree3(lx,ly,lz);CHKERRQ(ierr); 855 } else if (dd->dim == 2) { 856 PetscInt *lx,*ly; 857 ierr = PetscMalloc2(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly);CHKERRQ(ierr); 858 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 859 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 860 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); 861 ierr = PetscFree2(lx,ly);CHKERRQ(ierr); 862 } else if (dd->dim == 1) { 863 PetscInt *lx; 864 ierr = PetscMalloc(dd->m*sizeof(PetscInt),&lx);CHKERRQ(ierr); 865 ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 866 ierr = DMDACreate1d(((PetscObject)da)->comm,dd->wrap,M,dd->w,dd->s,lx,&da2);CHKERRQ(ierr); 867 ierr = PetscFree(lx);CHKERRQ(ierr); 868 } 869 dd2 = (DM_DA*)da2->data; 870 871 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 872 da2->ops->getmatrix = da->ops->getmatrix; 873 da2->ops->getinterpolation = da->ops->getinterpolation; 874 da2->ops->getcoloring = da->ops->getcoloring; 875 dd2->interptype = dd->interptype; 876 877 /* copy fill information if given */ 878 if (dd->dfill) { 879 ierr = PetscMalloc((dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->dfill);CHKERRQ(ierr); 880 ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 881 } 882 if (dd->ofill) { 883 ierr = PetscMalloc((dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->ofill);CHKERRQ(ierr); 884 ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 885 } 886 /* copy the refine information */ 887 dd2->refine_x = dd->refine_x; 888 dd2->refine_y = dd->refine_y; 889 dd2->refine_z = dd->refine_z; 890 891 /* copy vector type information */ 892 ierr = PetscFree(da2->vectype);CHKERRQ(ierr); 893 ierr = PetscStrallocpy(da->vectype,&da2->vectype);CHKERRQ(ierr); 894 895 /* inject coordinates if they are set on the fine grid */ 896 if (dd->coordinates) { 897 DM cdaf,cdac; 898 Vec coordsc,coordsf; 899 VecScatter inject; 900 901 ierr = DMDAGetCoordinateDA(da,&cdaf);CHKERRQ(ierr); 902 ierr = DMDAGetCoordinateDA(da2,&cdac);CHKERRQ(ierr); 903 ierr = DMDAGetCoordinates(da,&coordsf);CHKERRQ(ierr); 904 ierr = DMDAGetCoordinates(da2,&coordsc);CHKERRQ(ierr); 905 906 ierr = DMGetInjection(cdac,cdaf,&inject);CHKERRQ(ierr); 907 ierr = VecScatterBegin(inject,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 908 ierr = VecScatterEnd(inject ,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 909 ierr = VecScatterDestroy(inject);CHKERRQ(ierr); 910 } 911 *daref = da2; 912 PetscFunctionReturn(0); 913 } 914 915 #undef __FUNCT__ 916 #define __FUNCT__ "DMRefineHierarchy_DA" 917 PetscErrorCode PETSCDM_DLLEXPORT DMRefineHierarchy_DA(DM da,PetscInt nlevels,DM daf[]) 918 { 919 PetscErrorCode ierr; 920 PetscInt i,n,*refx,*refy,*refz; 921 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(da,DM_CLASSID,1); 924 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 925 if (nlevels == 0) PetscFunctionReturn(0); 926 PetscValidPointer(daf,3); 927 928 /* Get refinement factors, defaults taken from the coarse DMDA */ 929 ierr = PetscMalloc3(nlevels,PetscInt,&refx,nlevels,PetscInt,&refy,nlevels,PetscInt,&refz);CHKERRQ(ierr); 930 for (i=0; i<nlevels; i++) { 931 ierr = DMDAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]);CHKERRQ(ierr); 932 } 933 n = nlevels; 934 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,PETSC_NULL);CHKERRQ(ierr); 935 n = nlevels; 936 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,PETSC_NULL);CHKERRQ(ierr); 937 n = nlevels; 938 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,PETSC_NULL);CHKERRQ(ierr); 939 940 ierr = DMDASetRefinementFactor(da,refx[0],refy[0],refz[0]);CHKERRQ(ierr); 941 ierr = DMRefine(da,((PetscObject)da)->comm,&daf[0]);CHKERRQ(ierr); 942 for (i=1; i<nlevels; i++) { 943 ierr = DMDASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]);CHKERRQ(ierr); 944 ierr = DMRefine(daf[i-1],((PetscObject)da)->comm,&daf[i]);CHKERRQ(ierr); 945 } 946 ierr = PetscFree3(refx,refy,refz);CHKERRQ(ierr); 947 PetscFunctionReturn(0); 948 } 949 950 #undef __FUNCT__ 951 #define __FUNCT__ "DMCoarsenHierarchy_DA" 952 PetscErrorCode PETSCDM_DLLEXPORT DMCoarsenHierarchy_DA(DM da,PetscInt nlevels,DM dac[]) 953 { 954 PetscErrorCode ierr; 955 PetscInt i; 956 957 PetscFunctionBegin; 958 PetscValidHeaderSpecific(da,DM_CLASSID,1); 959 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 960 if (nlevels == 0) PetscFunctionReturn(0); 961 PetscValidPointer(dac,3); 962 ierr = DMCoarsen(da,((PetscObject)da)->comm,&dac[0]);CHKERRQ(ierr); 963 for (i=1; i<nlevels; i++) { 964 ierr = DMCoarsen(dac[i-1],((PetscObject)da)->comm,&dac[i]);CHKERRQ(ierr); 965 } 966 PetscFunctionReturn(0); 967 } 968