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: }