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 PetscFunctionReturn(0); 146 } 147 148 #undef __FUNCT__ 149 #define __FUNCT__ "DMDASetStencilType" 150 /*@ 151 DMDASetStencilType - Sets the type of the communication stencil 152 153 Logically Collective on DMDA 154 155 Input Parameter: 156 + da - The DMDA 157 - stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR. 158 159 Level: intermediate 160 161 .keywords: distributed array, stencil 162 .seealso: DMDACreate(), DMDestroy(), DMDA 163 @*/ 164 PetscErrorCode PETSCDM_DLLEXPORT DMDASetStencilType(DM da, DMDAStencilType stype) 165 { 166 DM_DA *dd = (DM_DA*)da->data; 167 168 PetscFunctionBegin; 169 PetscValidHeaderSpecific(da,DM_CLASSID,1); 170 PetscValidLogicalCollectiveEnum(da,stype,2); 171 dd->stencil_type = stype; 172 PetscFunctionReturn(0); 173 } 174 175 #undef __FUNCT__ 176 #define __FUNCT__ "DMDASetStencilWidth" 177 /*@ 178 DMDASetStencilWidth - Sets the width of the communication stencil 179 180 Logically Collective on DMDA 181 182 Input Parameter: 183 + da - The DMDA 184 - width - The stencil width 185 186 Level: intermediate 187 188 .keywords: distributed array, stencil 189 .seealso: DMDACreate(), DMDestroy(), DMDA 190 @*/ 191 PetscErrorCode PETSCDM_DLLEXPORT DMDASetStencilWidth(DM da, PetscInt width) 192 { 193 DM_DA *dd = (DM_DA*)da->data; 194 195 PetscFunctionBegin; 196 PetscValidHeaderSpecific(da,DM_CLASSID,1); 197 PetscValidLogicalCollectiveInt(da,width,2); 198 dd->s = width; 199 PetscFunctionReturn(0); 200 } 201 202 #undef __FUNCT__ 203 #define __FUNCT__ "DMDACheckOwnershipRanges_Private" 204 static PetscErrorCode DMDACheckOwnershipRanges_Private(DM da,PetscInt M,PetscInt m,const PetscInt lx[]) 205 { 206 PetscInt i,sum; 207 208 PetscFunctionBegin; 209 if (M < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Global dimension not set"); 210 for (i=sum=0; i<m; i++) sum += lx[i]; 211 if (sum != M) SETERRQ2(((PetscObject)da)->comm,PETSC_ERR_ARG_INCOMP,"Ownership ranges sum to %D but global dimension is %D",sum,M); 212 PetscFunctionReturn(0); 213 } 214 215 #undef __FUNCT__ 216 #define __FUNCT__ "DMDASetOwnershipRanges" 217 /*@ 218 DMDASetOwnershipRanges - Sets the number of nodes in each direction on each process 219 220 Logically Collective on DMDA 221 222 Input Parameter: 223 + da - The DMDA 224 . 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 225 . 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 226 - 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. 227 228 Level: intermediate 229 230 .keywords: distributed array 231 .seealso: DMDACreate(), DMDestroy(), DMDA 232 @*/ 233 PetscErrorCode PETSCDM_DLLEXPORT DMDASetOwnershipRanges(DM da, const PetscInt lx[], const PetscInt ly[], const PetscInt lz[]) 234 { 235 PetscErrorCode ierr; 236 DM_DA *dd = (DM_DA*)da->data; 237 238 PetscFunctionBegin; 239 PetscValidHeaderSpecific(da,DM_CLASSID,1); 240 if (lx) { 241 if (dd->m < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs"); 242 ierr = DMDACheckOwnershipRanges_Private(da,dd->M,dd->m,lx);CHKERRQ(ierr); 243 if (!dd->lx) { 244 ierr = PetscMalloc(dd->m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr); 245 } 246 ierr = PetscMemcpy(dd->lx, lx, dd->m*sizeof(PetscInt));CHKERRQ(ierr); 247 } 248 if (ly) { 249 if (dd->n < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs"); 250 ierr = DMDACheckOwnershipRanges_Private(da,dd->N,dd->n,ly);CHKERRQ(ierr); 251 if (!dd->ly) { 252 ierr = PetscMalloc(dd->n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr); 253 } 254 ierr = PetscMemcpy(dd->ly, ly, dd->n*sizeof(PetscInt));CHKERRQ(ierr); 255 } 256 if (lz) { 257 if (dd->p < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs"); 258 ierr = DMDACheckOwnershipRanges_Private(da,dd->P,dd->p,lz);CHKERRQ(ierr); 259 if (!dd->lz) { 260 ierr = PetscMalloc(dd->p*sizeof(PetscInt), &dd->lz);CHKERRQ(ierr); 261 } 262 ierr = PetscMemcpy(dd->lz, lz, dd->p*sizeof(PetscInt));CHKERRQ(ierr); 263 } 264 PetscFunctionReturn(0); 265 } 266 267 #undef __FUNCT__ 268 #define __FUNCT__ "DMDACreateOwnershipRanges" 269 /* 270 Ensure that da->lx, ly, and lz exist. Collective on DMDA. 271 */ 272 PetscErrorCode PETSCDM_DLLEXPORT DMDACreateOwnershipRanges(DM da) 273 { 274 DM_DA *dd = (DM_DA*)da->data; 275 PetscErrorCode ierr; 276 PetscInt n; 277 MPI_Comm comm; 278 PetscMPIInt size; 279 280 PetscFunctionBegin; 281 if (!dd->lx) { 282 ierr = PetscMalloc(dd->m*sizeof(PetscInt),&dd->lx);CHKERRQ(ierr); 283 ierr = DMDAGetProcessorSubset(da,DMDA_X,dd->xs,&comm);CHKERRQ(ierr); 284 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 285 n = (dd->xe-dd->xs)/dd->w; 286 ierr = MPI_Allgather(&n,1,MPIU_INT,dd->lx,1,MPIU_INT,comm);CHKERRQ(ierr); 287 } 288 if (dd->dim > 1 && !dd->ly) { 289 ierr = PetscMalloc(dd->n*sizeof(PetscInt),&dd->ly);CHKERRQ(ierr); 290 ierr = DMDAGetProcessorSubset(da,DMDA_Y,dd->ys,&comm);CHKERRQ(ierr); 291 n = dd->ye-dd->ys; 292 ierr = MPI_Allgather(&n,1,MPIU_INT,dd->ly,1,MPIU_INT,comm);CHKERRQ(ierr); 293 } 294 if (dd->dim > 2 && !dd->lz) { 295 ierr = PetscMalloc(dd->p*sizeof(PetscInt),&dd->lz);CHKERRQ(ierr); 296 ierr = DMDAGetProcessorSubset(da,DMDA_Z,dd->zs,&comm);CHKERRQ(ierr); 297 n = dd->ze-dd->zs; 298 ierr = MPI_Allgather(&n,1,MPIU_INT,dd->lz,1,MPIU_INT,comm);CHKERRQ(ierr); 299 } 300 PetscFunctionReturn(0); 301 } 302 303 #undef __FUNCT__ 304 #define __FUNCT__ "DMDASetInterpolationType" 305 /*@ 306 DMDASetInterpolationType - Sets the type of interpolation that will be 307 returned by DMGetInterpolation() 308 309 Logically Collective on DMDA 310 311 Input Parameter: 312 + da - initial distributed array 313 . ctype - DMDA_Q1 and DMDA_Q0 are currently the only supported forms 314 315 Level: intermediate 316 317 Notes: you should call this on the coarser of the two DMDAs you pass to DMGetInterpolation() 318 319 .keywords: distributed array, interpolation 320 321 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType 322 @*/ 323 PetscErrorCode PETSCDM_DLLEXPORT DMDASetInterpolationType(DM da,DMDAInterpolationType ctype) 324 { 325 DM_DA *dd = (DM_DA*)da->data; 326 327 PetscFunctionBegin; 328 PetscValidHeaderSpecific(da,DM_CLASSID,1); 329 PetscValidLogicalCollectiveEnum(da,ctype,2); 330 dd->interptype = ctype; 331 PetscFunctionReturn(0); 332 } 333 334 335 #undef __FUNCT__ 336 #define __FUNCT__ "DMDAGetNeighbors" 337 /*@C 338 DMDAGetNeighbors - Gets an array containing the MPI rank of all the current 339 processes neighbors. 340 341 Not Collective 342 343 Input Parameter: 344 . da - the DMDA object 345 346 Output Parameters: 347 . ranks - the neighbors ranks, stored with the x index increasing most rapidly. 348 this process itself is in the list 349 350 Notes: In 2d the array is of length 9, in 3d of length 27 351 Not supported in 1d 352 Do not free the array, it is freed when the DMDA is destroyed. 353 354 Fortran Notes: In fortran you must pass in an array of the appropriate length. 355 356 Level: intermediate 357 358 @*/ 359 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetNeighbors(DM da,const PetscMPIInt *ranks[]) 360 { 361 DM_DA *dd = (DM_DA*)da->data; 362 PetscFunctionBegin; 363 PetscValidHeaderSpecific(da,DM_CLASSID,1); 364 *ranks = dd->neighbors; 365 PetscFunctionReturn(0); 366 } 367 368 /*@C 369 DMDASetElementType - Sets the element type to be returned by DMGetElements() 370 371 Not Collective 372 373 Input Parameter: 374 . da - the DMDA object 375 376 Output Parameters: 377 . etype - the element type, currently either DMDA_ELEMENT_P1 or ELEMENT_Q1 378 379 Level: intermediate 380 381 .seealso: DMDAElementType, DMDAGetElementType(), DMGetElements(), DMRestoreElements() 382 @*/ 383 #undef __FUNCT__ 384 #define __FUNCT__ "DMDASetElementType" 385 PetscErrorCode PETSCDM_DLLEXPORT DMDASetElementType(DM da, DMDAElementType etype) 386 { 387 DM_DA *dd = (DM_DA*)da->data; 388 PetscErrorCode ierr; 389 390 PetscFunctionBegin; 391 PetscValidHeaderSpecific(da,DM_CLASSID,1); 392 PetscValidLogicalCollectiveEnum(da,etype,2); 393 if (dd->elementtype != etype) { 394 ierr = PetscFree(dd->e);CHKERRQ(ierr); 395 dd->elementtype = etype; 396 dd->ne = 0; 397 dd->e = PETSC_NULL; 398 } 399 PetscFunctionReturn(0); 400 } 401 402 /*@C 403 DMDAGetElementType - Gets the element type to be returned by DMGetElements() 404 405 Not Collective 406 407 Input Parameter: 408 . da - the DMDA object 409 410 Output Parameters: 411 . etype - the element type, currently either DMDA_ELEMENT_P1 or ELEMENT_Q1 412 413 Level: intermediate 414 415 .seealso: DMDAElementType, DMDASetElementType(), DMGetElements(), DMRestoreElements() 416 @*/ 417 #undef __FUNCT__ 418 #define __FUNCT__ "DMDAGetElementType" 419 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetElementType(DM da, DMDAElementType *etype) 420 { 421 DM_DA *dd = (DM_DA*)da->data; 422 PetscFunctionBegin; 423 PetscValidHeaderSpecific(da,DM_CLASSID,1); 424 PetscValidPointer(etype,2); 425 *etype = dd->elementtype; 426 PetscFunctionReturn(0); 427 } 428 429 #undef __FUNCT__ 430 #define __FUNCT__ "DMGetElements" 431 /*@C 432 DMGetElements - Gets an array containing the indices (in local coordinates) 433 of all the local elements 434 435 Not Collective 436 437 Input Parameter: 438 . dm - the DM object 439 440 Output Parameters: 441 + n - number of local elements 442 - e - the indices of the elements vertices 443 444 Level: intermediate 445 446 .seealso: DMElementType, DMSetElementType(), DMRestoreElements() 447 @*/ 448 PetscErrorCode PETSCDM_DLLEXPORT DMGetElements(DM dm,PetscInt *n,const PetscInt *e[]) 449 { 450 PetscErrorCode ierr; 451 PetscFunctionBegin; 452 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 453 ierr = (dm->ops->getelements)(dm,n,e);CHKERRQ(ierr); 454 PetscFunctionReturn(0); 455 } 456 457 #undef __FUNCT__ 458 #define __FUNCT__ "DMRestoreElements" 459 /*@C 460 DMRestoreElements - Returns an array containing the indices (in local coordinates) 461 of all the local elements obtained with DMGetElements() 462 463 Not Collective 464 465 Input Parameter: 466 + dm - the DM object 467 . n - number of local elements 468 - e - the indices of the elements vertices 469 470 Level: intermediate 471 472 .seealso: DMElementType, DMSetElementType(), DMGetElements() 473 @*/ 474 PetscErrorCode PETSCDM_DLLEXPORT DMRestoreElements(DM dm,PetscInt *n,const PetscInt *e[]) 475 { 476 PetscErrorCode ierr; 477 PetscFunctionBegin; 478 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 479 if (dm->ops->restoreelements) { 480 ierr = (dm->ops->restoreelements)(dm,n,e);CHKERRQ(ierr); 481 } 482 PetscFunctionReturn(0); 483 } 484 485 #undef __FUNCT__ 486 #define __FUNCT__ "DMDAGetOwnershipRanges" 487 /*@C 488 DMDAGetOwnershipRanges - Gets the ranges of indices in the x, y and z direction that are owned by each process 489 490 Not Collective 491 492 Input Parameter: 493 . da - the DMDA object 494 495 Output Parameter: 496 + lx - ownership along x direction (optional) 497 . ly - ownership along y direction (optional) 498 - lz - ownership along z direction (optional) 499 500 Level: intermediate 501 502 Note: these correspond to the optional final arguments passed to DMDACreate(), DMDACreate2d(), DMDACreate3d() 503 504 In Fortran one must pass in arrays lx, ly, and lz that are long enough to hold the values; the sixth, seventh and 505 eighth arguments from DMDAGetInfo() 506 507 In C you should not free these arrays, nor change the values in them. They will only have valid values while the 508 DMDA they came from still exists (has not been destroyed). 509 510 .seealso: DMDAGetCorners(), DMDAGetGhostCorners(), DMDACreate(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), VecGetOwnershipRanges() 511 @*/ 512 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetOwnershipRanges(DM da,const PetscInt *lx[],const PetscInt *ly[],const PetscInt *lz[]) 513 { 514 DM_DA *dd = (DM_DA*)da->data; 515 516 PetscFunctionBegin; 517 PetscValidHeaderSpecific(da,DM_CLASSID,1); 518 if (lx) *lx = dd->lx; 519 if (ly) *ly = dd->ly; 520 if (lz) *lz = dd->lz; 521 PetscFunctionReturn(0); 522 } 523 524 #undef __FUNCT__ 525 #define __FUNCT__ "DMDASetRefinementFactor" 526 /*@ 527 DMDASetRefinementFactor - Set the ratios that the DMDA grid is refined 528 529 Logically Collective on DMDA 530 531 Input Parameters: 532 + da - the DMDA object 533 . refine_x - ratio of fine grid to coarse in x direction (2 by default) 534 . refine_y - ratio of fine grid to coarse in y direction (2 by default) 535 - refine_z - ratio of fine grid to coarse in z direction (2 by default) 536 537 Options Database: 538 + -da_refine_x - refinement ratio in x direction 539 . -da_refine_y - refinement ratio in y direction 540 - -da_refine_z - refinement ratio in z direction 541 542 Level: intermediate 543 544 Notes: Pass PETSC_IGNORE to leave a value unchanged 545 546 .seealso: DMRefine(), DMDAGetRefinementFactor() 547 @*/ 548 PetscErrorCode PETSCDM_DLLEXPORT DMDASetRefinementFactor(DM da, PetscInt refine_x, PetscInt refine_y,PetscInt refine_z) 549 { 550 DM_DA *dd = (DM_DA*)da->data; 551 552 PetscFunctionBegin; 553 PetscValidHeaderSpecific(da,DM_CLASSID,1); 554 PetscValidLogicalCollectiveInt(da,refine_x,2); 555 PetscValidLogicalCollectiveInt(da,refine_y,3); 556 PetscValidLogicalCollectiveInt(da,refine_z,4); 557 558 if (refine_x > 0) dd->refine_x = refine_x; 559 if (refine_y > 0) dd->refine_y = refine_y; 560 if (refine_z > 0) dd->refine_z = refine_z; 561 PetscFunctionReturn(0); 562 } 563 564 #undef __FUNCT__ 565 #define __FUNCT__ "DMDAGetRefinementFactor" 566 /*@C 567 DMDAGetRefinementFactor - Gets the ratios that the DMDA grid is refined 568 569 Not Collective 570 571 Input Parameter: 572 . da - the DMDA object 573 574 Output Parameters: 575 + refine_x - ratio of fine grid to coarse in x direction (2 by default) 576 . refine_y - ratio of fine grid to coarse in y direction (2 by default) 577 - refine_z - ratio of fine grid to coarse in z direction (2 by default) 578 579 Level: intermediate 580 581 Notes: Pass PETSC_NULL for values you do not need 582 583 .seealso: DMRefine(), DMDASetRefinementFactor() 584 @*/ 585 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetRefinementFactor(DM da, PetscInt *refine_x, PetscInt *refine_y,PetscInt *refine_z) 586 { 587 DM_DA *dd = (DM_DA*)da->data; 588 589 PetscFunctionBegin; 590 PetscValidHeaderSpecific(da,DM_CLASSID,1); 591 if (refine_x) *refine_x = dd->refine_x; 592 if (refine_y) *refine_y = dd->refine_y; 593 if (refine_z) *refine_z = dd->refine_z; 594 PetscFunctionReturn(0); 595 } 596 597 #undef __FUNCT__ 598 #define __FUNCT__ "DMDASetGetMatrix" 599 /*@C 600 DMDASetGetMatrix - Sets the routine used by the DMDA to allocate a matrix. 601 602 Logically Collective on DMDA 603 604 Input Parameters: 605 + da - the DMDA object 606 - f - the function that allocates the matrix for that specific DMDA 607 608 Level: developer 609 610 Notes: See DMDASetBlockFills() that provides a simple way to provide the nonzero structure for 611 the diagonal and off-diagonal blocks of the matrix 612 613 .seealso: DMGetMatrix(), DMDASetBlockFills() 614 @*/ 615 PetscErrorCode PETSCDM_DLLEXPORT DMDASetGetMatrix(DM da,PetscErrorCode (*f)(DM, const MatType,Mat*)) 616 { 617 PetscFunctionBegin; 618 PetscValidHeaderSpecific(da,DM_CLASSID,1); 619 da->ops->getmatrix = f; 620 PetscFunctionReturn(0); 621 } 622 623 #undef __FUNCT__ 624 #define __FUNCT__ "DMDARefineOwnershipRanges" 625 /* 626 Creates "balanced" ownership ranges after refinement, constrained by the need for the 627 fine grid boundaries to fall within one stencil width of the coarse partition. 628 629 Uses a greedy algorithm to handle non-ideal layouts, could probably do something better. 630 */ 631 static PetscErrorCode DMDARefineOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lc[],PetscInt lf[]) 632 { 633 PetscInt i,totalc = 0,remaining,startc = 0,startf = 0; 634 PetscErrorCode ierr; 635 636 PetscFunctionBegin; 637 if (ratio < 1) SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_USER,"Requested refinement ratio %D must be at least 1",ratio); 638 if (ratio == 1) { 639 ierr = PetscMemcpy(lf,lc,m*sizeof(lc[0]));CHKERRQ(ierr); 640 PetscFunctionReturn(0); 641 } 642 for (i=0; i<m; i++) totalc += lc[i]; 643 remaining = (!periodic) + ratio * (totalc - (!periodic)); 644 for (i=0; i<m; i++) { 645 PetscInt want = remaining/(m-i) + !!(remaining%(m-i)); 646 if (i == m-1) lf[i] = want; 647 else { 648 PetscInt diffc = (startf+want)/ratio - (startc + lc[i]); 649 while (PetscAbs(diffc) > stencil_width) { 650 want += (diffc < 0); 651 diffc = (startf+want)/ratio - (startc + lc[i]); 652 } 653 } 654 lf[i] = want; 655 startc += lc[i]; 656 startf += lf[i]; 657 remaining -= lf[i]; 658 } 659 PetscFunctionReturn(0); 660 } 661 662 #undef __FUNCT__ 663 #define __FUNCT__ "DMRefine_DA" 664 PetscErrorCode PETSCDM_DLLEXPORT DMRefine_DA(DM da,MPI_Comm comm,DM *daref) 665 { 666 PetscErrorCode ierr; 667 PetscInt M,N,P; 668 DM da2; 669 DM_DA *dd = (DM_DA*)da->data,*dd2; 670 671 PetscFunctionBegin; 672 PetscValidHeaderSpecific(da,DM_CLASSID,1); 673 PetscValidPointer(daref,3); 674 675 if (DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 676 M = dd->refine_x*dd->M; 677 } else { 678 M = 1 + dd->refine_x*(dd->M - 1); 679 } 680 if (DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 681 N = dd->refine_y*dd->N; 682 } else { 683 N = 1 + dd->refine_y*(dd->N - 1); 684 } 685 if (DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 686 P = dd->refine_z*dd->P; 687 } else { 688 P = 1 + dd->refine_z*(dd->P - 1); 689 } 690 ierr = DMDACreateOwnershipRanges(da);CHKERRQ(ierr); 691 if (dd->dim == 3) { 692 PetscInt *lx,*ly,*lz; 693 ierr = PetscMalloc3(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly,dd->p,PetscInt,&lz);CHKERRQ(ierr); 694 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 695 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 696 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz);CHKERRQ(ierr); 697 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); 698 ierr = PetscFree3(lx,ly,lz);CHKERRQ(ierr); 699 } else if (dd->dim == 2) { 700 PetscInt *lx,*ly; 701 ierr = PetscMalloc2(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly);CHKERRQ(ierr); 702 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 703 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 704 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); 705 ierr = PetscFree2(lx,ly);CHKERRQ(ierr); 706 } else if (dd->dim == 1) { 707 PetscInt *lx; 708 ierr = PetscMalloc(dd->m*sizeof(PetscInt),&lx);CHKERRQ(ierr); 709 ierr = DMDARefineOwnershipRanges(da,(PetscBool)(DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 710 ierr = DMDACreate1d(((PetscObject)da)->comm,dd->wrap,M,dd->w,dd->s,lx,&da2);CHKERRQ(ierr); 711 ierr = PetscFree(lx);CHKERRQ(ierr); 712 } 713 dd2 = (DM_DA*)da2->data; 714 715 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 716 da2->ops->getmatrix = da->ops->getmatrix; 717 da2->ops->getinterpolation = da->ops->getinterpolation; 718 da2->ops->getcoloring = da->ops->getcoloring; 719 dd2->interptype = dd->interptype; 720 721 /* copy fill information if given */ 722 if (dd->dfill) { 723 ierr = PetscMalloc((dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->dfill);CHKERRQ(ierr); 724 ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 725 } 726 if (dd->ofill) { 727 ierr = PetscMalloc((dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->ofill);CHKERRQ(ierr); 728 ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 729 } 730 /* copy the refine information */ 731 dd2->refine_x = dd->refine_x; 732 dd2->refine_y = dd->refine_y; 733 dd2->refine_z = dd->refine_z; 734 735 /* copy vector type information */ 736 ierr = PetscFree(da2->vectype);CHKERRQ(ierr); 737 ierr = PetscStrallocpy(da->vectype,&da2->vectype);CHKERRQ(ierr); 738 *daref = da2; 739 PetscFunctionReturn(0); 740 } 741 742 #undef __FUNCT__ 743 #define __FUNCT__ "DMCoarsen_DA" 744 PetscErrorCode PETSCDM_DLLEXPORT DMCoarsen_DA(DM da, MPI_Comm comm,DM *daref) 745 { 746 PetscErrorCode ierr; 747 PetscInt M,N,P; 748 DM da2; 749 DM_DA *dd = (DM_DA*)da->data,*dd2; 750 751 PetscFunctionBegin; 752 PetscValidHeaderSpecific(da,DM_CLASSID,1); 753 PetscValidPointer(daref,3); 754 755 if (DMDAXPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 756 if(dd->refine_x) 757 M = dd->M / dd->refine_x; 758 else 759 M = dd->M; 760 } else { 761 if(dd->refine_x) 762 M = 1 + (dd->M - 1) / dd->refine_x; 763 else 764 M = dd->M; 765 } 766 if (DMDAYPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 767 if(dd->refine_y) 768 N = dd->N / dd->refine_y; 769 else 770 N = dd->N; 771 } else { 772 if(dd->refine_y) 773 N = 1 + (dd->N - 1) / dd->refine_y; 774 else 775 N = dd->M; 776 } 777 if (DMDAZPeriodic(dd->wrap) || dd->interptype == DMDA_Q0){ 778 if(dd->refine_z) 779 P = dd->P / dd->refine_z; 780 else 781 P = dd->P; 782 } else { 783 if(dd->refine_z) 784 P = 1 + (dd->P - 1) / dd->refine_z; 785 else 786 P = dd->P; 787 } 788 if (dd->dim == 3) { 789 ierr = DMDACreate3d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,P,dd->m,dd->n,dd->p,dd->w,dd->s,0,0,0,&da2);CHKERRQ(ierr); 790 } else if (dd->dim == 2) { 791 ierr = DMDACreate2d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,dd->m,dd->n,dd->w,dd->s,0,0,&da2);CHKERRQ(ierr); 792 } else if (dd->dim == 1) { 793 ierr = DMDACreate1d(((PetscObject)da)->comm,dd->wrap,M,dd->w,dd->s,0,&da2);CHKERRQ(ierr); 794 } 795 dd2 = (DM_DA*)da2->data; 796 797 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 798 da2->ops->getmatrix = da->ops->getmatrix; 799 da2->ops->getinterpolation = da->ops->getinterpolation; 800 da2->ops->getcoloring = da->ops->getcoloring; 801 dd2->interptype = dd->interptype; 802 803 /* copy fill information if given */ 804 if (dd->dfill) { 805 ierr = PetscMalloc((dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->dfill);CHKERRQ(ierr); 806 ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 807 } 808 if (dd->ofill) { 809 ierr = PetscMalloc((dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->ofill);CHKERRQ(ierr); 810 ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 811 } 812 /* copy the refine information */ 813 dd2->refine_x = dd->refine_x; 814 dd2->refine_y = dd->refine_y; 815 dd2->refine_z = dd->refine_z; 816 817 /* copy vector type information */ 818 ierr = PetscFree(da2->vectype);CHKERRQ(ierr); 819 ierr = PetscStrallocpy(da->vectype,&da2->vectype);CHKERRQ(ierr); 820 821 *daref = da2; 822 PetscFunctionReturn(0); 823 } 824 825 #undef __FUNCT__ 826 #define __FUNCT__ "DMRefineHierarchy_DA" 827 PetscErrorCode PETSCDM_DLLEXPORT DMRefineHierarchy_DA(DM da,PetscInt nlevels,DM daf[]) 828 { 829 PetscErrorCode ierr; 830 PetscInt i,n,*refx,*refy,*refz; 831 832 PetscFunctionBegin; 833 PetscValidHeaderSpecific(da,DM_CLASSID,1); 834 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 835 if (nlevels == 0) PetscFunctionReturn(0); 836 PetscValidPointer(daf,3); 837 838 /* Get refinement factors, defaults taken from the coarse DMDA */ 839 ierr = PetscMalloc3(nlevels,PetscInt,&refx,nlevels,PetscInt,&refy,nlevels,PetscInt,&refz);CHKERRQ(ierr); 840 for (i=0; i<nlevels; i++) { 841 ierr = DMDAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]);CHKERRQ(ierr); 842 } 843 n = nlevels; 844 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,PETSC_NULL);CHKERRQ(ierr); 845 n = nlevels; 846 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,PETSC_NULL);CHKERRQ(ierr); 847 n = nlevels; 848 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,PETSC_NULL);CHKERRQ(ierr); 849 850 ierr = DMDASetRefinementFactor(da,refx[0],refy[0],refz[0]);CHKERRQ(ierr); 851 ierr = DMRefine(da,((PetscObject)da)->comm,&daf[0]);CHKERRQ(ierr); 852 for (i=1; i<nlevels; i++) { 853 ierr = DMDASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]);CHKERRQ(ierr); 854 ierr = DMRefine(daf[i-1],((PetscObject)da)->comm,&daf[i]);CHKERRQ(ierr); 855 } 856 ierr = PetscFree3(refx,refy,refz);CHKERRQ(ierr); 857 PetscFunctionReturn(0); 858 } 859 860 #undef __FUNCT__ 861 #define __FUNCT__ "DMCoarsenHierarchy_DA" 862 PetscErrorCode PETSCDM_DLLEXPORT DMCoarsenHierarchy_DA(DM da,PetscInt nlevels,DM dac[]) 863 { 864 PetscErrorCode ierr; 865 PetscInt i; 866 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(da,DM_CLASSID,1); 869 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 870 if (nlevels == 0) PetscFunctionReturn(0); 871 PetscValidPointer(dac,3); 872 ierr = DMCoarsen(da,((PetscObject)da)->comm,&dac[0]);CHKERRQ(ierr); 873 for (i=1; i<nlevels; i++) { 874 ierr = DMCoarsen(dac[i-1],((PetscObject)da)->comm,&dac[i]);CHKERRQ(ierr); 875 } 876 PetscFunctionReturn(0); 877 } 878