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