Actual source code: da.c

  1: #define PETSCDM_DLL
 2:  #include private/daimpl.h

  6: /*@C
  7:    DASetOptionsPrefix - Sets the prefix used for searching for all 
  8:    DA options in the database.

 10:    Collective on DA

 12:    Input Parameter:
 13: +  da - the DA context
 14: -  prefix - the prefix to prepend to all option names

 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.

 20:    Level: advanced

 22: .keywords: DA, set, options, prefix, database

 24: .seealso: DASetFromOptions()
 25: @*/
 26: PetscErrorCode  DASetOptionsPrefix(DA da,const char prefix[])
 27: {

 32:   PetscObjectSetOptionsPrefix((PetscObject)da,prefix);
 33:   return(0);
 34: }

 38: /*@
 39:   DASetDim - Sets the dimension

 41:   Collective on DA

 43:   Input Parameters:
 44: + da - the DA
 45: - dim - the dimension (or PETSC_DECIDE)

 47:   Level: intermediate

 49: .seealso: DaGetDim(), DASetSizes()
 50: @*/
 51: PetscErrorCode  DASetDim(DA da, PetscInt dim)
 52: {
 55:   if (da->dim > 0 && dim != da->dim) SETERRQ2(PETSC_ERR_ARG_WRONGSTATE,"Cannot change DA dim from %D after it was set to %D",da->dim,dim);
 56:   da->dim = dim;
 57:   return(0);
 58: }

 62: /*@
 63:   DASetSizes - Sets the global sizes

 65:   Collective on DA

 67:   Input Parameters:
 68: + da - the DA
 69: . M - the global X size (or PETSC_DECIDE)
 70: . N - the global Y size (or PETSC_DECIDE)
 71: - P - the global Z size (or PETSC_DECIDE)

 73:   Level: intermediate

 75: .seealso: DAGetSize(), PetscSplitOwnership()
 76: @*/
 77: PetscErrorCode  DASetSizes(DA da, PetscInt M, PetscInt N, PetscInt P)
 78: {
 81:   da->M = M;
 82:   da->N = N;
 83:   da->P = P;
 84:   return(0);
 85: }

 89: /*@
 90:   DASetNumProcs - Sets the number of processes in each dimension

 92:   Collective on DA

 94:   Input Parameters:
 95: + da - the DA
 96: . m - the number of X procs (or PETSC_DECIDE)
 97: . n - the number of Y procs (or PETSC_DECIDE)
 98: - p - the number of Z procs (or PETSC_DECIDE)

100:   Level: intermediate

102: .seealso: DASetSizes(), DAGetSize(), PetscSplitOwnership()
103: @*/
104: PetscErrorCode  DASetNumProcs(DA da, PetscInt m, PetscInt n, PetscInt p)
105: {
108:   da->m = m;
109:   da->n = n;
110:   da->p = p;
111:   return(0);
112: }

116: /*@
117:   DASetPeriodicity - Sets the type of periodicity

119:   Not collective

121:   Input Parameter:
122: + da    - The DA
123: - ptype - One of DA_NONPERIODIC, DA_XPERIODIC, DA_YPERIODIC, DA_ZPERIODIC, DA_XYPERIODIC, DA_XZPERIODIC, DA_YZPERIODIC, or DA_XYZPERIODIC

125:   Level: intermediate

127: .keywords:  distributed array, periodicity
128: .seealso: DACreate(), DADestroy(), DA, DAPeriodicType
129: @*/
130: PetscErrorCode  DASetPeriodicity(DA da, DAPeriodicType ptype)
131: {
134:   da->wrap = ptype;
135:   return(0);
136: }

140: /*@
141:   DASetDof - Sets the number of degrees of freedom per vertex

143:   Not collective

145:   Input Parameter:
146: + da  - The DA
147: - dof - Number of degrees of freedom

149:   Level: intermediate

151: .keywords:  distributed array, degrees of freedom
152: .seealso: DACreate(), DADestroy(), DA
153: @*/
154: PetscErrorCode  DASetDof(DA da, int dof)
155: {
158:   da->w = dof;
159:   return(0);
160: }

164: /*@
165:   DASetStencilType - Sets the type of the communication stencil

167:   Not collective

169:   Input Parameter:
170: + da    - The DA
171: - stype - The stencil type, use either DA_STENCIL_BOX or DA_STENCIL_STAR.

173:   Level: intermediate

175: .keywords:  distributed array, stencil
176: .seealso: DACreate(), DADestroy(), DA
177: @*/
178: PetscErrorCode  DASetStencilType(DA da, DAStencilType stype)
179: {
182:   da->stencil_type = stype;
183:   return(0);
184: }

188: /*@
189:   DASetStencilWidth - Sets the width of the communication stencil

191:   Not collective

193:   Input Parameter:
194: + da    - The DA
195: - width - The stencil width

197:   Level: intermediate

199: .keywords:  distributed array, stencil
200: .seealso: DACreate(), DADestroy(), DA
201: @*/
202: PetscErrorCode  DASetStencilWidth(DA da, int width)
203: {
206:   da->s = width;
207:   return(0);
208: }

212: /*@
213:   DASetVertexDivision - Sets the number of nodes in each direction on each process

215:   Not collective

217:   Input Parameter:
218: + da - The DA
219: . 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
220: . 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
221: - 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.

223:   Level: intermediate

225: .keywords:  distributed array
226: .seealso: DACreate(), DADestroy(), DA
227: @*/
228: PetscErrorCode  DASetVertexDivision(DA da, const PetscInt lx[], const PetscInt ly[], const PetscInt lz[])
229: {
231: 
234:   if (lx) {
235:     if (da->m < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Cannot set vertex division before setting number of procs");
236:     if (!da->lx) {
237:       PetscMalloc(da->m*sizeof(PetscInt), &da->lx);
238:     }
239:     PetscMemcpy(da->lx, lx, da->m*sizeof(PetscInt));
240:   }
241:   if (ly) {
242:     if (da->n < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Cannot set vertex division before setting number of procs");
243:     if (!da->ly) {
244:       PetscMalloc(da->n*sizeof(PetscInt), &da->ly);
245:     }
246:     PetscMemcpy(da->ly, ly, da->n*sizeof(PetscInt));
247:   }
248:   if (lz) {
249:     if (da->p < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Cannot set vertex division before setting number of procs");
250:     if (!da->lz) {
251:       PetscMalloc(da->p*sizeof(PetscInt), &da->lz);
252:     }
253:     PetscMemcpy(da->lz, lz, da->p*sizeof(PetscInt));
254:   }
255:   return(0);
256: }

260: /*@
261:        DASetInterpolationType - Sets the type of interpolation that will be 
262:           returned by DAGetInterpolation()

264:    Collective on DA

266:    Input Parameter:
267: +  da - initial distributed array
268: .  ctype - DA_Q1 and DA_Q0 are currently the only supported forms

270:    Level: intermediate

272:    Notes: you should call this on the coarser of the two DAs you pass to DAGetInterpolation()

274: .keywords:  distributed array, interpolation

276: .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DADestroy(), DA, DAInterpolationType
277: @*/
278: PetscErrorCode  DASetInterpolationType(DA da,DAInterpolationType ctype)
279: {
282:   da->interptype = ctype;
283:   return(0);
284: }

288: /*@C
289:       DAGetNeighbors - Gets an array containing the MPI rank of all the current
290:         processes neighbors.

292:     Not Collective

294:    Input Parameter:
295: .     da - the DA object

297:    Output Parameters:
298: .     ranks - the neighbors ranks, stored with the x index increasing most rapidly.
299:               this process itself is in the list

301:    Notes: In 2d the array is of length 9, in 3d of length 27
302:           Not supported in 1d
303:           Do not free the array, it is freed when the DA is destroyed.

305:    Fortran Notes: In fortran you must pass in an array of the appropriate length.

307:    Level: intermediate

309: @*/
310: PetscErrorCode  DAGetNeighbors(DA da,const PetscMPIInt *ranks[])
311: {
314:   *ranks = da->neighbors;
315:   return(0);
316: }

320: /*@C
321:       DMGetElements - Gets an array containing the indices (in local coordinates) 
322:                  of all the local elements

324:     Not Collective

326:    Input Parameter:
327: .     dm - the DM object

329:    Output Parameters:
330: +     n - number of local elements
331: -     e - the indices of the elements vertices

333:    Level: intermediate

335: .seealso: DMElementType, DMSetElementType(), DMRestoreElements()
336: @*/
337: PetscErrorCode  DMGetElements(DM dm,PetscInt *n,const PetscInt *e[])
338: {
342:   (dm->ops->getelements)(dm,n,e);
343:   return(0);
344: }

348: /*@C
349:       DMRestoreElements - Returns an array containing the indices (in local coordinates) 
350:                  of all the local elements obtained with DMGetElements()

352:     Not Collective

354:    Input Parameter:
355: +     dm - the DM object
356: .     n - number of local elements
357: -     e - the indices of the elements vertices

359:    Level: intermediate

361: .seealso: DMElementType, DMSetElementType(), DMGetElements()
362: @*/
363: PetscErrorCode  DMRestoreElements(DM dm,PetscInt *n,const PetscInt *e[])
364: {
368:   if (dm->ops->restoreelements) {
369:     (dm->ops->restoreelements)(dm,n,e);
370:   }
371:   return(0);
372: }

376: /*@C
377:       DAGetOwnershipRanges - Gets the ranges of indices in the x, y and z direction that are owned by each process

379:     Not Collective

381:    Input Parameter:
382: .     da - the DA object

384:    Output Parameter:
385: +     lx - ownership along x direction (optional)
386: .     ly - ownership along y direction (optional)
387: -     lz - ownership along z direction (optional)

389:    Level: intermediate

391:     Note: these correspond to the optional final arguments passed to DACreate(), DACreate2d(), DACreate3d()

393:     In Fortran one must pass in arrays lx, ly, and lz that are long enough to hold the values; the sixth, seventh and
394:     eighth arguments from DAGetInfo()

396:      In C you should not free these arrays, nor change the values in them. They will only have valid values while the
397:     DA they came from still exists (has not been destroyed).

399: .seealso: DAGetCorners(), DAGetGhostCorners(), DACreate(), DACreate1d(), DACreate2d(), DACreate3d(), VecGetOwnershipRanges()
400: @*/
401: PetscErrorCode  DAGetOwnershipRanges(DA da,const PetscInt *lx[],const PetscInt *ly[],const PetscInt *lz[])
402: {
405:   if (lx) *lx = da->lx;
406:   if (ly) *ly = da->ly;
407:   if (lz) *lz = da->lz;
408:   return(0);
409: }

411: /*@
412:      DASetRefinementFactor - Set the ratios that the DA grid is refined

414:     Collective on DA

416:   Input Parameters:
417: +    da - the DA object
418: .    refine_x - ratio of fine grid to coarse in x direction (2 by default)
419: .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
420: -    refine_z - ratio of fine grid to coarse in z direction (2 by default)

422:   Options Database:
423: +  -da_refine_x - refinement ratio in x direction
424: .  -da_refine_y - refinement ratio in y direction
425: -  -da_refine_z - refinement ratio in z direction

427:   Level: intermediate

429:     Notes: Pass PETSC_IGNORE to leave a value unchanged

431: .seealso: DARefine(), DAGetRefinementFactor()
432: @*/
433: PetscErrorCode  DASetRefinementFactor(DA da, PetscInt refine_x, PetscInt refine_y,PetscInt refine_z)
434: {
436:   if (refine_x > 0) da->refine_x = refine_x;
437:   if (refine_y > 0) da->refine_y = refine_y;
438:   if (refine_z > 0) da->refine_z = refine_z;
439:   return(0);
440: }

442: /*@C
443:      DAGetRefinementFactor - Gets the ratios that the DA grid is refined

445:     Not Collective

447:   Input Parameter:
448: .    da - the DA object

450:   Output Parameters:
451: +    refine_x - ratio of fine grid to coarse in x direction (2 by default)
452: .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
453: -    refine_z - ratio of fine grid to coarse in z direction (2 by default)

455:   Level: intermediate

457:     Notes: Pass PETSC_NULL for values you do not need

459: .seealso: DARefine(), DASetRefinementFactor()
460: @*/
461: PetscErrorCode  DAGetRefinementFactor(DA da, PetscInt *refine_x, PetscInt *refine_y,PetscInt *refine_z)
462: {
464:   if (refine_x) *refine_x = da->refine_x;
465:   if (refine_y) *refine_y = da->refine_y;
466:   if (refine_z) *refine_z = da->refine_z;
467:   return(0);
468: }

470: /*@C
471:      DASetGetMatrix - Sets the routine used by the DA to allocate a matrix.

473:     Collective on DA

475:   Input Parameters:
476: +    da - the DA object
477: -    f - the function that allocates the matrix for that specific DA

479:   Level: developer

481:    Notes: See DASetBlockFills() that provides a simple way to provide the nonzero structure for 
482:        the diagonal and off-diagonal blocks of the matrix

484: .seealso: DAGetMatrix(), DASetBlockFills()
485: @*/
486: PetscErrorCode  DASetGetMatrix(DA da,PetscErrorCode (*f)(DA, const MatType,Mat*))
487: {
489:   da->ops->getmatrix = f;
490:   return(0);
491: }

495: /*@
496:    DARefine - Creates a new distributed array that is a refinement of a given
497:    distributed array.

499:    Collective on DA

501:    Input Parameter:
502: +  da - initial distributed array
503: -  comm - communicator to contain refined DA, must be either same as the da communicator or include the 
504:           da communicator and be 2, 4, or 8 times larger. Currently ignored

506:    Output Parameter:
507: .  daref - refined distributed array

509:    Level: advanced

511:    Note:
512:    Currently, refinement consists of just doubling the number of grid spaces
513:    in each dimension of the DA.

515: .keywords:  distributed array, refine

517: .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DADestroy(), DAGetOwnershipRanges()
518: @*/
519: PetscErrorCode  DARefine(DA da,MPI_Comm comm,DA *daref)
520: {
522:   PetscInt       M,N,P;
523:   DA             da2;


529:   if (DAXPeriodic(da->wrap) || da->interptype == DA_Q0){
530:     M = da->refine_x*da->M;
531:   } else {
532:     M = 1 + da->refine_x*(da->M - 1);
533:   }
534:   if (DAYPeriodic(da->wrap) || da->interptype == DA_Q0){
535:     N = da->refine_y*da->N;
536:   } else {
537:     N = 1 + da->refine_y*(da->N - 1);
538:   }
539:   if (DAZPeriodic(da->wrap) || da->interptype == DA_Q0){
540:     P = da->refine_z*da->P;
541:   } else {
542:     P = 1 + da->refine_z*(da->P - 1);
543:   }
544:   if (da->dim == 3) {
545:     DACreate3d(((PetscObject)da)->comm,da->wrap,da->stencil_type,M,N,P,da->m,da->n,da->p,da->w,da->s,0,0,0,&da2);
546:   } else if (da->dim == 2) {
547:     DACreate2d(((PetscObject)da)->comm,da->wrap,da->stencil_type,M,N,da->m,da->n,da->w,da->s,0,0,&da2);
548:   } else if (da->dim == 1) {
549:     DACreate1d(((PetscObject)da)->comm,da->wrap,M,da->w,da->s,0,&da2);
550:   }

552:   /* allow overloaded (user replaced) operations to be inherited by refinement clones */
553:   da2->ops->getmatrix        = da->ops->getmatrix;
554:   da2->ops->getinterpolation = da->ops->getinterpolation;
555:   da2->ops->getcoloring      = da->ops->getcoloring;
556:   da2->interptype            = da->interptype;
557: 
558:   /* copy fill information if given */
559:   if (da->dfill) {
560:     PetscMalloc((da->dfill[da->w]+da->w+1)*sizeof(PetscInt),&da2->dfill);
561:     PetscMemcpy(da2->dfill,da->dfill,(da->dfill[da->w]+da->w+1)*sizeof(PetscInt));
562:   }
563:   if (da->ofill) {
564:     PetscMalloc((da->ofill[da->w]+da->w+1)*sizeof(PetscInt),&da2->ofill);
565:     PetscMemcpy(da2->ofill,da->ofill,(da->ofill[da->w]+da->w+1)*sizeof(PetscInt));
566:   }
567:   /* copy the refine information */
568:   da2->refine_x = da->refine_x;
569:   da2->refine_y = da->refine_y;
570:   da2->refine_z = da->refine_z;
571:   *daref = da2;
572:   return(0);
573: }

577: /*@
578:    DACoarsen - Creates a new distributed array that is a coarsenment of a given
579:    distributed array.

581:    Collective on DA

583:    Input Parameter:
584: +  da - initial distributed array
585: -  comm - communicator to contain coarsend DA. Currently ignored

587:    Output Parameter:
588: .  daref - coarsend distributed array

590:    Level: advanced

592:    Note:
593:    Currently, coarsenment consists of just dividing the number of grid spaces
594:    in each dimension of the DA by refinex_x, refinex_y, ....

596: .keywords:  distributed array, coarsen

598: .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DADestroy(), DAGetOwnershipRanges()
599: @*/
600: PetscErrorCode  DACoarsen(DA da, MPI_Comm comm,DA *daref)
601: {
603:   PetscInt       M,N,P;
604:   DA             da2;


610:   if (DAXPeriodic(da->wrap) || da->interptype == DA_Q0){
611:     if(da->refine_x)
612:       M = da->M / da->refine_x;
613:     else
614:       M = da->M;
615:   } else {
616:     if(da->refine_x)
617:       M = 1 + (da->M - 1) / da->refine_x;
618:     else
619:       M = da->M;
620:   }
621:   if (DAYPeriodic(da->wrap) || da->interptype == DA_Q0){
622:     if(da->refine_y)
623:       N = da->N / da->refine_y;
624:     else
625:       N = da->N;
626:   } else {
627:     if(da->refine_y)
628:       N = 1 + (da->N - 1) / da->refine_y;
629:     else
630:       N = da->M;
631:   }
632:   if (DAZPeriodic(da->wrap) || da->interptype == DA_Q0){
633:     if(da->refine_z)
634:       P = da->P / da->refine_z;
635:     else
636:       P = da->P;
637:   } else {
638:     if(da->refine_z)
639:       P = 1 + (da->P - 1) / da->refine_z;
640:     else
641:       P = da->P;
642:   }
643:   if (da->dim == 3) {
644:     DACreate3d(((PetscObject)da)->comm,da->wrap,da->stencil_type,M,N,P,da->m,da->n,da->p,da->w,da->s,0,0,0,&da2);
645:   } else if (da->dim == 2) {
646:     DACreate2d(((PetscObject)da)->comm,da->wrap,da->stencil_type,M,N,da->m,da->n,da->w,da->s,0,0,&da2);
647:   } else if (da->dim == 1) {
648:     DACreate1d(((PetscObject)da)->comm,da->wrap,M,da->w,da->s,0,&da2);
649:   }

651:   /* allow overloaded (user replaced) operations to be inherited by refinement clones */
652:   da2->ops->getmatrix        = da->ops->getmatrix;
653:   da2->ops->getinterpolation = da->ops->getinterpolation;
654:   da2->ops->getcoloring      = da->ops->getcoloring;
655:   da2->interptype            = da->interptype;
656: 
657:   /* copy fill information if given */
658:   if (da->dfill) {
659:     PetscMalloc((da->dfill[da->w]+da->w+1)*sizeof(PetscInt),&da2->dfill);
660:     PetscMemcpy(da2->dfill,da->dfill,(da->dfill[da->w]+da->w+1)*sizeof(PetscInt));
661:   }
662:   if (da->ofill) {
663:     PetscMalloc((da->ofill[da->w]+da->w+1)*sizeof(PetscInt),&da2->ofill);
664:     PetscMemcpy(da2->ofill,da->ofill,(da->ofill[da->w]+da->w+1)*sizeof(PetscInt));
665:   }
666:   /* copy the refine information */
667:   da2->refine_x = da->refine_x;
668:   da2->refine_y = da->refine_y;
669:   da2->refine_z = da->refine_z;
670:   *daref = da2;
671:   return(0);
672: }

676: /*@
677:    DARefineHierarchy - Perform multiple levels of refinement.

679:    Collective on DA

681:    Input Parameter:
682: +  da - initial distributed array
683: -  nlevels - number of levels of refinement to perform

685:    Output Parameter:
686: .  daf - array of refined DAs

688:    Options Database:
689: +  -da_refine_hierarchy_x - list of refinement ratios in x direction
690: .  -da_refine_hierarchy_y - list of refinement ratios in y direction
691: -  -da_refine_hierarchy_z - list of refinement ratios in z direction

693:    Level: advanced

695: .keywords: distributed array, refine

697: .seealso: DARefine(), DACoarsenHierarchy()
698: @*/
699: PetscErrorCode  DARefineHierarchy(DA da,PetscInt nlevels,DA daf[])
700: {
702:   PetscInt i,n,*refx,*refy,*refz;

706:   if (nlevels < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
707:   if (nlevels == 0) return(0);

710:   /* Get refinement factors, defaults taken from the coarse DA */
711:   PetscMalloc3(nlevels,PetscInt,&refx,nlevels,PetscInt,&refy,nlevels,PetscInt,&refz);
712:   for (i=0; i<nlevels; i++) {
713:     DAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]);
714:   }
715:   n = nlevels;
716:   PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,PETSC_NULL);
717:   n = nlevels;
718:   PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,PETSC_NULL);
719:   n = nlevels;
720:   PetscOptionsGetIntArray(((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,PETSC_NULL);

722:   DASetRefinementFactor(da,refx[0],refy[0],refz[0]);
723:   DARefine(da,((PetscObject)da)->comm,&daf[0]);
724:   for (i=1; i<nlevels; i++) {
725:     DASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]);
726:     DARefine(daf[i-1],((PetscObject)da)->comm,&daf[i]);
727:   }
728:   PetscFree3(refx,refy,refz);
729:   return(0);
730: }

734: /*@
735:    DACoarsenHierarchy - Perform multiple levels of coarsening

737:    Collective on DA

739:    Input Parameter:
740: +  da - initial distributed array
741: -  nlevels - number of levels of coarsening to perform

743:    Output Parameter:
744: .  dac - array of coarsened DAs

746:    Level: advanced

748: .keywords: distributed array, coarsen

750: .seealso: DACoarsen(), DARefineHierarchy()
751: @*/
752: PetscErrorCode  DACoarsenHierarchy(DA da,PetscInt nlevels,DA dac[])
753: {
755:   PetscInt i;

759:   if (nlevels < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
760:   if (nlevels == 0) return(0);
762:   DACoarsen(da,((PetscObject)da)->comm,&dac[0]);
763:   for (i=1; i<nlevels; i++) {
764:     DACoarsen(dac[i-1],((PetscObject)da)->comm,&dac[i]);
765:   }
766:   return(0);
767: }