1 #define PETSCDM_DLL 2 #include "private/daimpl.h" /*I "petscda.h" I*/ 3 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "DASetDim" 7 /*@ 8 DASetDim - Sets the dimension 9 10 Collective on DA 11 12 Input Parameters: 13 + da - the DA 14 - dim - the dimension (or PETSC_DECIDE) 15 16 Level: intermediate 17 18 .seealso: DaGetDim(), DASetSizes() 19 @*/ 20 PetscErrorCode PETSCDM_DLLEXPORT DASetDim(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 DA 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__ "DASetSizes" 33 /*@ 34 DASetSizes - Sets the global sizes 35 36 Logically Collective on DA 37 38 Input Parameters: 39 + da - the DA 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: DAGetSize(), PetscSplitOwnership() 47 @*/ 48 PetscErrorCode PETSCDM_DLLEXPORT DASetSizes(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__ "DASetNumProcs" 66 /*@ 67 DASetNumProcs - Sets the number of processes in each dimension 68 69 Logically Collective on DA 70 71 Input Parameters: 72 + da - the DA 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: DASetSizes(), DAGetSize(), PetscSplitOwnership() 80 @*/ 81 PetscErrorCode PETSCDM_DLLEXPORT DASetNumProcs(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__ "DASetPeriodicity" 98 /*@ 99 DASetPeriodicity - Sets the type of periodicity 100 101 Not collective 102 103 Input Parameter: 104 + da - The DA 105 - ptype - One of DA_NONPERIODIC, DA_XPERIODIC, DA_YPERIODIC, DA_ZPERIODIC, DA_XYPERIODIC, DA_XZPERIODIC, DA_YZPERIODIC, or DA_XYZPERIODIC 106 107 Level: intermediate 108 109 .keywords: distributed array, periodicity 110 .seealso: DACreate(), DMDestroy(), DA, DAPeriodicType 111 @*/ 112 PetscErrorCode PETSCDM_DLLEXPORT DASetPeriodicity(DM da, DAPeriodicType 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__ "DASetDof" 124 /*@ 125 DASetDof - Sets the number of degrees of freedom per vertex 126 127 Not collective 128 129 Input Parameter: 130 + da - The DA 131 - dof - Number of degrees of freedom 132 133 Level: intermediate 134 135 .keywords: distributed array, degrees of freedom 136 .seealso: DACreate(), DMDestroy(), DA 137 @*/ 138 PetscErrorCode PETSCDM_DLLEXPORT DASetDof(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__ "DASetStencilType" 150 /*@ 151 DASetStencilType - Sets the type of the communication stencil 152 153 Logically Collective on DA 154 155 Input Parameter: 156 + da - The DA 157 - stype - The stencil type, use either DA_STENCIL_BOX or DA_STENCIL_STAR. 158 159 Level: intermediate 160 161 .keywords: distributed array, stencil 162 .seealso: DACreate(), DMDestroy(), DA 163 @*/ 164 PetscErrorCode PETSCDM_DLLEXPORT DASetStencilType(DM da, DAStencilType 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__ "DASetStencilWidth" 177 /*@ 178 DASetStencilWidth - Sets the width of the communication stencil 179 180 Logically Collective on DA 181 182 Input Parameter: 183 + da - The DA 184 - width - The stencil width 185 186 Level: intermediate 187 188 .keywords: distributed array, stencil 189 .seealso: DACreate(), DMDestroy(), DA 190 @*/ 191 PetscErrorCode PETSCDM_DLLEXPORT DASetStencilWidth(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__ "DACheckOwnershipRanges_Private" 204 static PetscErrorCode DACheckOwnershipRanges_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__ "DASetOwnershipRanges" 217 /*@ 218 DASetOwnershipRanges - Sets the number of nodes in each direction on each process 219 220 Logically Collective on DA 221 222 Input Parameter: 223 + da - The DA 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: DACreate(), DMDestroy(), DA 232 @*/ 233 PetscErrorCode PETSCDM_DLLEXPORT DASetOwnershipRanges(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 = DACheckOwnershipRanges_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 = DACheckOwnershipRanges_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 = DACheckOwnershipRanges_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__ "DACreateOwnershipRanges" 269 /* 270 Ensure that da->lx, ly, and lz exist. Collective on DA. 271 */ 272 PetscErrorCode PETSCDM_DLLEXPORT DACreateOwnershipRanges(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 = DAGetProcessorSubset(da,DA_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 = DAGetProcessorSubset(da,DA_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 = DAGetProcessorSubset(da,DA_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__ "DASetInterpolationType" 305 /*@ 306 DASetInterpolationType - Sets the type of interpolation that will be 307 returned by DAGetInterpolation() 308 309 Logically Collective on DA 310 311 Input Parameter: 312 + da - initial distributed array 313 . ctype - DA_Q1 and DA_Q0 are currently the only supported forms 314 315 Level: intermediate 316 317 Notes: you should call this on the coarser of the two DAs you pass to DAGetInterpolation() 318 319 .keywords: distributed array, interpolation 320 321 .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DA, DAInterpolationType 322 @*/ 323 PetscErrorCode PETSCDM_DLLEXPORT DASetInterpolationType(DM da,DAInterpolationType 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__ "DAGetNeighbors" 337 /*@C 338 DAGetNeighbors - 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 DA 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 DA 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 DAGetNeighbors(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 DASetElementType - Sets the element type to be returned by DMGetElements() 370 371 Not Collective 372 373 Input Parameter: 374 . da - the DA object 375 376 Output Parameters: 377 . etype - the element type, currently either DA_ELEMENT_P1 or ELEMENT_Q1 378 379 Level: intermediate 380 381 .seealso: DAElementType, DAGetElementType(), DMGetElements(), DMRestoreElements() 382 @*/ 383 #undef __FUNCT__ 384 #define __FUNCT__ "DASetElementType" 385 PetscErrorCode PETSCDM_DLLEXPORT DASetElementType(DM da, DAElementType 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 DAGetElementType - Gets the element type to be returned by DMGetElements() 404 405 Not Collective 406 407 Input Parameter: 408 . da - the DA object 409 410 Output Parameters: 411 . etype - the element type, currently either DA_ELEMENT_P1 or ELEMENT_Q1 412 413 Level: intermediate 414 415 .seealso: DAElementType, DASetElementType(), DMGetElements(), DMRestoreElements() 416 @*/ 417 #undef __FUNCT__ 418 #define __FUNCT__ "DAGetElementType" 419 PetscErrorCode PETSCDM_DLLEXPORT DAGetElementType(DM da, DAElementType *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__ "DAGetOwnershipRanges" 487 /*@C 488 DAGetOwnershipRanges - 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 DA 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 DACreate(), DACreate2d(), DACreate3d() 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 DAGetInfo() 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 DA they came from still exists (has not been destroyed). 509 510 .seealso: DAGetCorners(), DAGetGhostCorners(), DACreate(), DACreate1d(), DACreate2d(), DACreate3d(), VecGetOwnershipRanges() 511 @*/ 512 PetscErrorCode PETSCDM_DLLEXPORT DAGetOwnershipRanges(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__ "DASetRefinementFactor" 526 /*@ 527 DASetRefinementFactor - Set the ratios that the DA grid is refined 528 529 Logically Collective on DA 530 531 Input Parameters: 532 + da - the DA 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: DARefine(), DAGetRefinementFactor() 547 @*/ 548 PetscErrorCode PETSCDM_DLLEXPORT DASetRefinementFactor(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__ "DAGetRefinementFactor" 566 /*@C 567 DAGetRefinementFactor - Gets the ratios that the DA grid is refined 568 569 Not Collective 570 571 Input Parameter: 572 . da - the DA 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: DARefine(), DASetRefinementFactor() 584 @*/ 585 PetscErrorCode PETSCDM_DLLEXPORT DAGetRefinementFactor(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__ "DASetGetMatrix" 599 /*@C 600 DASetGetMatrix - Sets the routine used by the DA to allocate a matrix. 601 602 Logically Collective on DA 603 604 Input Parameters: 605 + da - the DA object 606 - f - the function that allocates the matrix for that specific DA 607 608 Level: developer 609 610 Notes: See DASetBlockFills() that provides a simple way to provide the nonzero structure for 611 the diagonal and off-diagonal blocks of the matrix 612 613 .seealso: DAGetMatrix(), DASetBlockFills() 614 @*/ 615 PetscErrorCode PETSCDM_DLLEXPORT DASetGetMatrix(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__ "DARefineOwnershipRanges" 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 DARefineOwnershipRanges(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__ "DARefine" 664 /*@ 665 DARefine - Creates a new distributed array that is a refinement of a given 666 distributed array. 667 668 Collective on DA 669 670 Input Parameter: 671 + da - initial distributed array 672 - comm - communicator to contain refined DA, must be either same as the da communicator or include the 673 da communicator and be 2, 4, or 8 times larger. Currently ignored 674 675 Output Parameter: 676 . daref - refined distributed array 677 678 Level: advanced 679 680 Note: 681 Currently, refinement consists of just doubling the number of grid spaces 682 in each dimension of the DA. 683 684 .keywords: distributed array, refine 685 686 .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetOwnershipRanges() 687 @*/ 688 PetscErrorCode PETSCDM_DLLEXPORT DARefine(DM da,MPI_Comm comm,DM *daref) 689 { 690 PetscErrorCode ierr; 691 PetscInt M,N,P; 692 DM da2; 693 DM_DA *dd = (DM_DA*)da->data,*dd2; 694 695 PetscFunctionBegin; 696 PetscValidHeaderSpecific(da,DM_CLASSID,1); 697 PetscValidPointer(daref,3); 698 699 if (DAXPeriodic(dd->wrap) || dd->interptype == DA_Q0){ 700 M = dd->refine_x*dd->M; 701 } else { 702 M = 1 + dd->refine_x*(dd->M - 1); 703 } 704 if (DAYPeriodic(dd->wrap) || dd->interptype == DA_Q0){ 705 N = dd->refine_y*dd->N; 706 } else { 707 N = 1 + dd->refine_y*(dd->N - 1); 708 } 709 if (DAZPeriodic(dd->wrap) || dd->interptype == DA_Q0){ 710 P = dd->refine_z*dd->P; 711 } else { 712 P = 1 + dd->refine_z*(dd->P - 1); 713 } 714 ierr = DACreateOwnershipRanges(da);CHKERRQ(ierr); 715 if (dd->dim == 3) { 716 PetscInt *lx,*ly,*lz; 717 ierr = PetscMalloc3(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly,dd->p,PetscInt,&lz);CHKERRQ(ierr); 718 ierr = DARefineOwnershipRanges(da,(PetscBool)(DAXPeriodic(dd->wrap) || dd->interptype == DA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 719 ierr = DARefineOwnershipRanges(da,(PetscBool)(DAYPeriodic(dd->wrap) || dd->interptype == DA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 720 ierr = DARefineOwnershipRanges(da,(PetscBool)(DAZPeriodic(dd->wrap) || dd->interptype == DA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz);CHKERRQ(ierr); 721 ierr = DACreate3d(((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); 722 ierr = PetscFree3(lx,ly,lz);CHKERRQ(ierr); 723 } else if (dd->dim == 2) { 724 PetscInt *lx,*ly; 725 ierr = PetscMalloc2(dd->m,PetscInt,&lx,dd->n,PetscInt,&ly);CHKERRQ(ierr); 726 ierr = DARefineOwnershipRanges(da,(PetscBool)(DAXPeriodic(dd->wrap) || dd->interptype == DA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 727 ierr = DARefineOwnershipRanges(da,(PetscBool)(DAYPeriodic(dd->wrap) || dd->interptype == DA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr); 728 ierr = DACreate2d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,dd->m,dd->n,dd->w,dd->s,lx,ly,&da2);CHKERRQ(ierr); 729 ierr = PetscFree2(lx,ly);CHKERRQ(ierr); 730 } else if (dd->dim == 1) { 731 PetscInt *lx; 732 ierr = PetscMalloc(dd->m*sizeof(PetscInt),&lx);CHKERRQ(ierr); 733 ierr = DARefineOwnershipRanges(da,(PetscBool)(DAXPeriodic(dd->wrap) || dd->interptype == DA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr); 734 ierr = DACreate1d(((PetscObject)da)->comm,dd->wrap,M,dd->w,dd->s,lx,&da2);CHKERRQ(ierr); 735 ierr = PetscFree(lx);CHKERRQ(ierr); 736 } 737 dd2 = (DM_DA*)da2->data; 738 739 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 740 da2->ops->getmatrix = da->ops->getmatrix; 741 da2->ops->getinterpolation = da->ops->getinterpolation; 742 da2->ops->getcoloring = da->ops->getcoloring; 743 dd2->interptype = dd->interptype; 744 745 /* copy fill information if given */ 746 if (dd->dfill) { 747 ierr = PetscMalloc((dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->dfill);CHKERRQ(ierr); 748 ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 749 } 750 if (dd->ofill) { 751 ierr = PetscMalloc((dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->ofill);CHKERRQ(ierr); 752 ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 753 } 754 /* copy the refine information */ 755 dd2->refine_x = dd->refine_x; 756 dd2->refine_y = dd->refine_y; 757 dd2->refine_z = dd->refine_z; 758 759 /* copy vector type information */ 760 ierr = PetscFree(da2->vectype);CHKERRQ(ierr); 761 ierr = PetscStrallocpy(da->vectype,&da2->vectype);CHKERRQ(ierr); 762 *daref = da2; 763 PetscFunctionReturn(0); 764 } 765 766 #undef __FUNCT__ 767 #define __FUNCT__ "DACoarsen" 768 /*@ 769 DACoarsen - Creates a new distributed array that is a coarsenment of a given 770 distributed array. 771 772 Collective on DA 773 774 Input Parameter: 775 + da - initial distributed array 776 - comm - communicator to contain coarsend DA. Currently ignored 777 778 Output Parameter: 779 . daref - coarsend distributed array 780 781 Level: advanced 782 783 Note: 784 Currently, coarsenment consists of just dividing the number of grid spaces 785 in each dimension of the DA by refinex_x, refinex_y, .... 786 787 .keywords: distributed array, coarsen 788 789 .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetOwnershipRanges() 790 @*/ 791 PetscErrorCode PETSCDM_DLLEXPORT DACoarsen(DM da, MPI_Comm comm,DM *daref) 792 { 793 PetscErrorCode ierr; 794 PetscInt M,N,P; 795 DM da2; 796 DM_DA *dd = (DM_DA*)da->data,*dd2; 797 798 PetscFunctionBegin; 799 PetscValidHeaderSpecific(da,DM_CLASSID,1); 800 PetscValidPointer(daref,3); 801 802 if (DAXPeriodic(dd->wrap) || dd->interptype == DA_Q0){ 803 if(dd->refine_x) 804 M = dd->M / dd->refine_x; 805 else 806 M = dd->M; 807 } else { 808 if(dd->refine_x) 809 M = 1 + (dd->M - 1) / dd->refine_x; 810 else 811 M = dd->M; 812 } 813 if (DAYPeriodic(dd->wrap) || dd->interptype == DA_Q0){ 814 if(dd->refine_y) 815 N = dd->N / dd->refine_y; 816 else 817 N = dd->N; 818 } else { 819 if(dd->refine_y) 820 N = 1 + (dd->N - 1) / dd->refine_y; 821 else 822 N = dd->M; 823 } 824 if (DAZPeriodic(dd->wrap) || dd->interptype == DA_Q0){ 825 if(dd->refine_z) 826 P = dd->P / dd->refine_z; 827 else 828 P = dd->P; 829 } else { 830 if(dd->refine_z) 831 P = 1 + (dd->P - 1) / dd->refine_z; 832 else 833 P = dd->P; 834 } 835 if (dd->dim == 3) { 836 ierr = DACreate3d(((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); 837 } else if (dd->dim == 2) { 838 ierr = DACreate2d(((PetscObject)da)->comm,dd->wrap,dd->stencil_type,M,N,dd->m,dd->n,dd->w,dd->s,0,0,&da2);CHKERRQ(ierr); 839 } else if (dd->dim == 1) { 840 ierr = DACreate1d(((PetscObject)da)->comm,dd->wrap,M,dd->w,dd->s,0,&da2);CHKERRQ(ierr); 841 } 842 dd2 = (DM_DA*)da2->data; 843 844 /* allow overloaded (user replaced) operations to be inherited by refinement clones */ 845 da2->ops->getmatrix = da->ops->getmatrix; 846 da2->ops->getinterpolation = da->ops->getinterpolation; 847 da2->ops->getcoloring = da->ops->getcoloring; 848 dd2->interptype = dd->interptype; 849 850 /* copy fill information if given */ 851 if (dd->dfill) { 852 ierr = PetscMalloc((dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->dfill);CHKERRQ(ierr); 853 ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 854 } 855 if (dd->ofill) { 856 ierr = PetscMalloc((dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt),&dd2->ofill);CHKERRQ(ierr); 857 ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr); 858 } 859 /* copy the refine information */ 860 dd2->refine_x = dd->refine_x; 861 dd2->refine_y = dd->refine_y; 862 dd2->refine_z = dd->refine_z; 863 864 /* copy vector type information */ 865 ierr = PetscFree(da2->vectype);CHKERRQ(ierr); 866 ierr = PetscStrallocpy(da->vectype,&da2->vectype);CHKERRQ(ierr); 867 868 *daref = da2; 869 PetscFunctionReturn(0); 870 } 871 872 #undef __FUNCT__ 873 #define __FUNCT__ "DARefineHierarchy" 874 /*@ 875 DARefineHierarchy - Perform multiple levels of refinement. 876 877 Collective on DA 878 879 Input Parameter: 880 + da - initial distributed array 881 - nlevels - number of levels of refinement to perform 882 883 Output Parameter: 884 . daf - array of refined DAs 885 886 Options Database: 887 + -da_refine_hierarchy_x - list of refinement ratios in x direction 888 . -da_refine_hierarchy_y - list of refinement ratios in y direction 889 - -da_refine_hierarchy_z - list of refinement ratios in z direction 890 891 Level: advanced 892 893 .keywords: distributed array, refine 894 895 .seealso: DARefine(), DACoarsenHierarchy() 896 @*/ 897 PetscErrorCode PETSCDM_DLLEXPORT DARefineHierarchy(DM da,PetscInt nlevels,DM daf[]) 898 { 899 PetscErrorCode ierr; 900 PetscInt i,n,*refx,*refy,*refz; 901 902 PetscFunctionBegin; 903 PetscValidHeaderSpecific(da,DM_CLASSID,1); 904 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 905 if (nlevels == 0) PetscFunctionReturn(0); 906 PetscValidPointer(daf,3); 907 908 /* Get refinement factors, defaults taken from the coarse DA */ 909 ierr = PetscMalloc3(nlevels,PetscInt,&refx,nlevels,PetscInt,&refy,nlevels,PetscInt,&refz);CHKERRQ(ierr); 910 for (i=0; i<nlevels; i++) { 911 ierr = DAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]);CHKERRQ(ierr); 912 } 913 n = nlevels; 914 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,PETSC_NULL);CHKERRQ(ierr); 915 n = nlevels; 916 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,PETSC_NULL);CHKERRQ(ierr); 917 n = nlevels; 918 ierr = PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,PETSC_NULL);CHKERRQ(ierr); 919 920 ierr = DASetRefinementFactor(da,refx[0],refy[0],refz[0]);CHKERRQ(ierr); 921 ierr = DARefine(da,((PetscObject)da)->comm,&daf[0]);CHKERRQ(ierr); 922 for (i=1; i<nlevels; i++) { 923 ierr = DASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]);CHKERRQ(ierr); 924 ierr = DARefine(daf[i-1],((PetscObject)da)->comm,&daf[i]);CHKERRQ(ierr); 925 } 926 ierr = PetscFree3(refx,refy,refz);CHKERRQ(ierr); 927 PetscFunctionReturn(0); 928 } 929 930 #undef __FUNCT__ 931 #define __FUNCT__ "DACoarsenHierarchy" 932 /*@ 933 DACoarsenHierarchy - Perform multiple levels of coarsening 934 935 Collective on DA 936 937 Input Parameter: 938 + da - initial distributed array 939 - nlevels - number of levels of coarsening to perform 940 941 Output Parameter: 942 . dac - array of coarsened DAs 943 944 Level: advanced 945 946 .keywords: distributed array, coarsen 947 948 .seealso: DACoarsen(), DARefineHierarchy() 949 @*/ 950 PetscErrorCode PETSCDM_DLLEXPORT DACoarsenHierarchy(DM da,PetscInt nlevels,DM dac[]) 951 { 952 PetscErrorCode ierr; 953 PetscInt i; 954 955 PetscFunctionBegin; 956 PetscValidHeaderSpecific(da,DM_CLASSID,1); 957 if (nlevels < 0) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 958 if (nlevels == 0) PetscFunctionReturn(0); 959 PetscValidPointer(dac,3); 960 ierr = DACoarsen(da,((PetscObject)da)->comm,&dac[0]);CHKERRQ(ierr); 961 for (i=1; i<nlevels; i++) { 962 ierr = DACoarsen(dac[i-1],((PetscObject)da)->comm,&dac[i]);CHKERRQ(ierr); 963 } 964 PetscFunctionReturn(0); 965 } 966