xref: /petsc/src/dm/impls/da/dacorn.c (revision c31cb41c0ee9b115779dca6896353b82fd361af9)
147c6ae99SBarry Smith #define PETSCDM_DLL
247c6ae99SBarry Smith 
347c6ae99SBarry Smith /*
447c6ae99SBarry Smith   Code for manipulating distributed regular arrays in parallel.
547c6ae99SBarry Smith */
647c6ae99SBarry Smith 
7e1589f56SBarry Smith #include "private/daimpl.h"    /*I   "petscdm.h"   I*/
847c6ae99SBarry Smith 
947c6ae99SBarry Smith #undef __FUNCT__
10aa219208SBarry Smith #define __FUNCT__ "DMDASetCoordinates"
1147c6ae99SBarry Smith /*@
12aa219208SBarry Smith    DMDASetCoordinates - Sets into the DMDA a vector that indicates the
1347c6ae99SBarry Smith       coordinates of the local nodes (NOT including ghost nodes).
1447c6ae99SBarry Smith 
15aa219208SBarry Smith    Collective on DMDA
1647c6ae99SBarry Smith 
1747c6ae99SBarry Smith    Input Parameter:
1847c6ae99SBarry Smith +  da - the distributed array
1947c6ae99SBarry Smith -  c - coordinate vector
2047c6ae99SBarry Smith 
2147c6ae99SBarry Smith    Note:
2247c6ae99SBarry Smith     The coordinates should NOT include those for all ghost points
2347c6ae99SBarry Smith 
2447c6ae99SBarry Smith   Level: intermediate
2547c6ae99SBarry Smith 
2647c6ae99SBarry Smith .keywords: distributed array, get, corners, nodes, local indices, coordinates
2747c6ae99SBarry Smith 
28aa219208SBarry Smith .seealso: DMDAGetGhostCorners(), DMDAGetCoordinates(), DMDASetUniformCoordinates(). DMDAGetGhostedCoordinates(), DMDAGetCoordinateDA()
2947c6ae99SBarry Smith @*/
307087cfbeSBarry Smith PetscErrorCode  DMDASetCoordinates(DM da,Vec c)
3147c6ae99SBarry Smith {
3247c6ae99SBarry Smith   PetscErrorCode ierr;
3347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
3447c6ae99SBarry Smith 
3547c6ae99SBarry Smith   PetscFunctionBegin;
3647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
3747c6ae99SBarry Smith   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3847c6ae99SBarry Smith   ierr = PetscObjectReference((PetscObject)c);CHKERRQ(ierr);
3947c6ae99SBarry Smith   if (dd->coordinates) {ierr = VecDestroy(dd->coordinates);CHKERRQ(ierr);}
4047c6ae99SBarry Smith   dd->coordinates = c;
4147c6ae99SBarry Smith   ierr = VecSetBlockSize(c,dd->dim);CHKERRQ(ierr);
4247c6ae99SBarry Smith   if (dd->ghosted_coordinates) { /* The ghosted coordinates are no longer valid */
4347c6ae99SBarry Smith     ierr = VecDestroy(dd->ghosted_coordinates);CHKERRQ(ierr);
4447c6ae99SBarry Smith     dd->ghosted_coordinates = PETSC_NULL;
4547c6ae99SBarry Smith   }
4647c6ae99SBarry Smith   PetscFunctionReturn(0);
4747c6ae99SBarry Smith }
4847c6ae99SBarry Smith 
4947c6ae99SBarry Smith #undef __FUNCT__
50aa219208SBarry Smith #define __FUNCT__ "DMDAGetCoordinates"
5147c6ae99SBarry Smith /*@
52aa219208SBarry Smith    DMDAGetCoordinates - Gets the node coordinates associated with a DMDA.
5347c6ae99SBarry Smith 
5447c6ae99SBarry Smith    Not Collective
5547c6ae99SBarry Smith 
5647c6ae99SBarry Smith    Input Parameter:
5747c6ae99SBarry Smith .  da - the distributed array
5847c6ae99SBarry Smith 
5947c6ae99SBarry Smith    Output Parameter:
6047c6ae99SBarry Smith .  c - coordinate vector
6147c6ae99SBarry Smith 
6247c6ae99SBarry Smith    Note:
6347c6ae99SBarry Smith     Each process has only the coordinates for its local nodes (does NOT have the
6447c6ae99SBarry Smith   coordinates for the ghost nodes).
6547c6ae99SBarry Smith 
6647c6ae99SBarry Smith     For two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
6747c6ae99SBarry Smith     and (x_0,y_0,z_0,x_1,y_1,z_1...)
6847c6ae99SBarry Smith 
6947c6ae99SBarry Smith   Level: intermediate
7047c6ae99SBarry Smith 
7147c6ae99SBarry Smith .keywords: distributed array, get, corners, nodes, local indices, coordinates
7247c6ae99SBarry Smith 
73aa219208SBarry Smith .seealso: DMDAGetGhostCorners(), DMDASetCoordinates(), DMDASetUniformCoordinates(), DMDAGetGhostedCoordinates(), DMDAGetCoordinateDA()
7447c6ae99SBarry Smith @*/
757087cfbeSBarry Smith PetscErrorCode  DMDAGetCoordinates(DM da,Vec *c)
7647c6ae99SBarry Smith {
7747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
7847c6ae99SBarry Smith   PetscFunctionBegin;
7947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
8047c6ae99SBarry Smith   PetscValidPointer(c,2);
8147c6ae99SBarry Smith   *c = dd->coordinates;
8247c6ae99SBarry Smith   PetscFunctionReturn(0);
8347c6ae99SBarry Smith }
8447c6ae99SBarry Smith 
8547c6ae99SBarry Smith #undef __FUNCT__
86aa219208SBarry Smith #define __FUNCT__ "DMDAGetCoordinateDA"
8747c6ae99SBarry Smith /*@
88aa219208SBarry Smith    DMDAGetCoordinateDA - Gets the DMDA that scatters between global and local DMDA coordinates
8947c6ae99SBarry Smith 
90aa219208SBarry Smith    Collective on DMDA
9147c6ae99SBarry Smith 
9247c6ae99SBarry Smith    Input Parameter:
9347c6ae99SBarry Smith .  da - the distributed array
9447c6ae99SBarry Smith 
9547c6ae99SBarry Smith    Output Parameter:
96aa219208SBarry Smith .  dac - coordinate DMDA
9747c6ae99SBarry Smith 
9847c6ae99SBarry Smith   Level: intermediate
9947c6ae99SBarry Smith 
10047c6ae99SBarry Smith .keywords: distributed array, get, corners, nodes, local indices, coordinates
10147c6ae99SBarry Smith 
102aa219208SBarry Smith .seealso: DMDAGetGhostCorners(), DMDASetCoordinates(), DMDASetUniformCoordinates(), DMDAGetCoordinates(), DMDAGetGhostedCoordinates()
10347c6ae99SBarry Smith @*/
1047087cfbeSBarry Smith PetscErrorCode  DMDAGetCoordinateDA(DM da,DM *cda)
10547c6ae99SBarry Smith {
10647c6ae99SBarry Smith   PetscMPIInt    size;
10747c6ae99SBarry Smith   PetscErrorCode ierr;
10847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
10947c6ae99SBarry Smith 
11047c6ae99SBarry Smith   PetscFunctionBegin;
11147c6ae99SBarry Smith   if (!dd->da_coordinates) {
11247c6ae99SBarry Smith     ierr = MPI_Comm_size(((PetscObject)da)->comm,&size);CHKERRQ(ierr);
11347c6ae99SBarry Smith     if (dd->dim == 1) {
11447c6ae99SBarry Smith       PetscInt            s,m,*lc,l;
115aa219208SBarry Smith       DMDAPeriodicType pt;
116aa219208SBarry Smith       ierr = DMDAGetInfo(da,0,&m,0,0,0,0,0,0,&s,&pt,0);CHKERRQ(ierr);
117aa219208SBarry Smith       ierr = DMDAGetCorners(da,0,0,0,&l,0,0);CHKERRQ(ierr);
11847c6ae99SBarry Smith       ierr = PetscMalloc(size*sizeof(PetscInt),&lc);CHKERRQ(ierr);
11947c6ae99SBarry Smith       ierr = MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr);
120aa219208SBarry Smith       ierr = DMDACreate1d(((PetscObject)da)->comm,pt,m,1,s,lc,&dd->da_coordinates);CHKERRQ(ierr);
12147c6ae99SBarry Smith       ierr = PetscFree(lc);CHKERRQ(ierr);
12247c6ae99SBarry Smith     } else if (dd->dim == 2) {
12347c6ae99SBarry Smith       PetscInt            i,s,m,*lc,*ld,l,k,n,M,N;
124aa219208SBarry Smith       DMDAPeriodicType pt;
125aa219208SBarry Smith       ierr = DMDAGetInfo(da,0,&m,&n,0,&M,&N,0,0,&s,&pt,0);CHKERRQ(ierr);
126aa219208SBarry Smith       ierr = DMDAGetCorners(da,0,0,0,&l,&k,0);CHKERRQ(ierr);
12747c6ae99SBarry Smith       ierr = PetscMalloc2(size,PetscInt,&lc,size,PetscInt,&ld);CHKERRQ(ierr);
12847c6ae99SBarry Smith       /* only first M values in lc matter */
12947c6ae99SBarry Smith       ierr = MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr);
13047c6ae99SBarry Smith       /* every Mth value in ld matters */
13147c6ae99SBarry Smith       ierr = MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr);
13247c6ae99SBarry Smith       for ( i=0; i<N; i++) {
13347c6ae99SBarry Smith         ld[i] = ld[M*i];
13447c6ae99SBarry Smith       }
135aa219208SBarry Smith       ierr = DMDACreate2d(((PetscObject)da)->comm,pt,DMDA_STENCIL_BOX,m,n,M,N,2,s,lc,ld,&dd->da_coordinates);CHKERRQ(ierr);
13647c6ae99SBarry Smith       ierr = PetscFree2(lc,ld);CHKERRQ(ierr);
13747c6ae99SBarry Smith     } else if (dd->dim == 3) {
13847c6ae99SBarry Smith       PetscInt            i,s,m,*lc,*ld,*le,l,k,q,n,M,N,P,p;
139aa219208SBarry Smith       DMDAPeriodicType pt;
140aa219208SBarry Smith       ierr = DMDAGetInfo(da,0,&m,&n,&p,&M,&N,&P,0,&s,&pt,0);CHKERRQ(ierr);
141aa219208SBarry Smith       ierr = DMDAGetCorners(da,0,0,0,&l,&k,&q);CHKERRQ(ierr);
14247c6ae99SBarry Smith       ierr = PetscMalloc3(size,PetscInt,&lc,size,PetscInt,&ld,size,PetscInt,&le);CHKERRQ(ierr);
14347c6ae99SBarry Smith       /* only first M values in lc matter */
14447c6ae99SBarry Smith       ierr = MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr);
14547c6ae99SBarry Smith       /* every Mth value in ld matters */
14647c6ae99SBarry Smith       ierr = MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr);
14747c6ae99SBarry Smith       for ( i=0; i<N; i++) {
14847c6ae99SBarry Smith         ld[i] = ld[M*i];
14947c6ae99SBarry Smith       }
15047c6ae99SBarry Smith       ierr = MPI_Allgather(&q,1,MPIU_INT,le,1,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr);
15147c6ae99SBarry Smith       for ( i=0; i<P; i++) {
15247c6ae99SBarry Smith         le[i] = le[M*N*i];
15347c6ae99SBarry Smith       }
154aa219208SBarry Smith       ierr = DMDACreate3d(((PetscObject)da)->comm,pt,DMDA_STENCIL_BOX,m,n,p,M,N,P,3,s,lc,ld,le,&dd->da_coordinates);CHKERRQ(ierr);
15547c6ae99SBarry Smith       ierr = PetscFree3(lc,ld,le);CHKERRQ(ierr);
15647c6ae99SBarry Smith     }
15747c6ae99SBarry Smith   }
15847c6ae99SBarry Smith   *cda = dd->da_coordinates;
15947c6ae99SBarry Smith   PetscFunctionReturn(0);
16047c6ae99SBarry Smith }
16147c6ae99SBarry Smith 
16247c6ae99SBarry Smith 
16347c6ae99SBarry Smith #undef __FUNCT__
164aa219208SBarry Smith #define __FUNCT__ "DMDAGetGhostedCoordinates"
16547c6ae99SBarry Smith /*@
166aa219208SBarry Smith    DMDAGetGhostedCoordinates - Gets the node coordinates associated with a DMDA.
16747c6ae99SBarry Smith 
168aa219208SBarry Smith    Collective on DMDA
16947c6ae99SBarry Smith 
17047c6ae99SBarry Smith    Input Parameter:
17147c6ae99SBarry Smith .  da - the distributed array
17247c6ae99SBarry Smith 
17347c6ae99SBarry Smith    Output Parameter:
17447c6ae99SBarry Smith .  c - coordinate vector
17547c6ae99SBarry Smith 
17647c6ae99SBarry Smith    Note:
17747c6ae99SBarry Smith     Each process has only the coordinates for its local AND ghost nodes
17847c6ae99SBarry Smith 
17947c6ae99SBarry Smith     For two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
18047c6ae99SBarry Smith     and (x_0,y_0,z_0,x_1,y_1,z_1...)
18147c6ae99SBarry Smith 
18247c6ae99SBarry Smith   Level: intermediate
18347c6ae99SBarry Smith 
18447c6ae99SBarry Smith .keywords: distributed array, get, corners, nodes, local indices, coordinates
18547c6ae99SBarry Smith 
186aa219208SBarry Smith .seealso: DMDAGetGhostCorners(), DMDASetCoordinates(), DMDASetUniformCoordinates(), DMDAGetCoordinates(), DMDAGetCoordinateDA()
18747c6ae99SBarry Smith @*/
1887087cfbeSBarry Smith PetscErrorCode  DMDAGetGhostedCoordinates(DM da,Vec *c)
18947c6ae99SBarry Smith {
19047c6ae99SBarry Smith   PetscErrorCode ierr;
19147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
19247c6ae99SBarry Smith 
19347c6ae99SBarry Smith   PetscFunctionBegin;
19447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
19547c6ae99SBarry Smith   PetscValidPointer(c,2);
196aa219208SBarry Smith   if (!dd->coordinates) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"You must call DMDASetCoordinates() before this call");
19747c6ae99SBarry Smith   if (!dd->ghosted_coordinates) {
1989a42bb27SBarry Smith     DM dac;
199aa219208SBarry Smith     ierr = DMDAGetCoordinateDA(da,&dac);CHKERRQ(ierr);
200564755cdSBarry Smith     ierr = DMCreateLocalVector(dac,&dd->ghosted_coordinates);CHKERRQ(ierr);
2019a42bb27SBarry Smith     ierr = DMGlobalToLocalBegin(dac,dd->coordinates,INSERT_VALUES,dd->ghosted_coordinates);CHKERRQ(ierr);
2029a42bb27SBarry Smith     ierr = DMGlobalToLocalEnd(dac,dd->coordinates,INSERT_VALUES,dd->ghosted_coordinates);CHKERRQ(ierr);
20347c6ae99SBarry Smith   }
20447c6ae99SBarry Smith   *c = dd->ghosted_coordinates;
20547c6ae99SBarry Smith   PetscFunctionReturn(0);
20647c6ae99SBarry Smith }
20747c6ae99SBarry Smith 
20847c6ae99SBarry Smith #undef __FUNCT__
209aa219208SBarry Smith #define __FUNCT__ "DMDASetFieldName"
21047c6ae99SBarry Smith /*@C
211aa219208SBarry Smith    DMDASetFieldName - Sets the names of individual field components in multicomponent
212aa219208SBarry Smith    vectors associated with a DMDA.
21347c6ae99SBarry Smith 
21447c6ae99SBarry Smith    Not Collective
21547c6ae99SBarry Smith 
21647c6ae99SBarry Smith    Input Parameters:
21747c6ae99SBarry Smith +  da - the distributed array
218aa219208SBarry Smith .  nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the
219aa219208SBarry Smith         number of degrees of freedom per node within the DMDA
22047c6ae99SBarry Smith -  names - the name of the field (component)
22147c6ae99SBarry Smith 
22247c6ae99SBarry Smith   Level: intermediate
22347c6ae99SBarry Smith 
22447c6ae99SBarry Smith .keywords: distributed array, get, component name
22547c6ae99SBarry Smith 
226aa219208SBarry Smith .seealso: DMDAGetFieldName()
22747c6ae99SBarry Smith @*/
2287087cfbeSBarry Smith PetscErrorCode  DMDASetFieldName(DM da,PetscInt nf,const char name[])
22947c6ae99SBarry Smith {
23047c6ae99SBarry Smith   PetscErrorCode ierr;
23147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
23247c6ae99SBarry Smith 
23347c6ae99SBarry Smith   PetscFunctionBegin;
23447c6ae99SBarry Smith    PetscValidHeaderSpecific(da,DM_CLASSID,1);
23547c6ae99SBarry Smith   if (nf < 0 || nf >= dd->w) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
236*c31cb41cSBarry Smith   ierr = PetscFree(dd->fieldname[nf]);CHKERRQ(ierr);
23747c6ae99SBarry Smith   ierr = PetscStrallocpy(name,&dd->fieldname[nf]);CHKERRQ(ierr);
23847c6ae99SBarry Smith   PetscFunctionReturn(0);
23947c6ae99SBarry Smith }
24047c6ae99SBarry Smith 
24147c6ae99SBarry Smith #undef __FUNCT__
242aa219208SBarry Smith #define __FUNCT__ "DMDAGetFieldName"
24347c6ae99SBarry Smith /*@C
244aa219208SBarry Smith    DMDAGetFieldName - Gets the names of individual field components in multicomponent
245aa219208SBarry Smith    vectors associated with a DMDA.
24647c6ae99SBarry Smith 
24747c6ae99SBarry Smith    Not Collective
24847c6ae99SBarry Smith 
24947c6ae99SBarry Smith    Input Parameter:
25047c6ae99SBarry Smith +  da - the distributed array
251aa219208SBarry Smith -  nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the
252aa219208SBarry Smith         number of degrees of freedom per node within the DMDA
25347c6ae99SBarry Smith 
25447c6ae99SBarry Smith    Output Parameter:
25547c6ae99SBarry Smith .  names - the name of the field (component)
25647c6ae99SBarry Smith 
25747c6ae99SBarry Smith   Level: intermediate
25847c6ae99SBarry Smith 
25947c6ae99SBarry Smith .keywords: distributed array, get, component name
26047c6ae99SBarry Smith 
261aa219208SBarry Smith .seealso: DMDASetFieldName()
26247c6ae99SBarry Smith @*/
2637087cfbeSBarry Smith PetscErrorCode  DMDAGetFieldName(DM da,PetscInt nf,const char **name)
26447c6ae99SBarry Smith {
26547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
26647c6ae99SBarry Smith 
26747c6ae99SBarry Smith   PetscFunctionBegin;
26847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
26947c6ae99SBarry Smith   PetscValidPointer(name,3);
27047c6ae99SBarry Smith   if (nf < 0 || nf >= dd->w) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
27147c6ae99SBarry Smith   *name = dd->fieldname[nf];
27247c6ae99SBarry Smith   PetscFunctionReturn(0);
27347c6ae99SBarry Smith }
27447c6ae99SBarry Smith 
27547c6ae99SBarry Smith #undef __FUNCT__
276aa219208SBarry Smith #define __FUNCT__ "DMDAGetCorners"
27747c6ae99SBarry Smith /*@
278aa219208SBarry Smith    DMDAGetCorners - Returns the global (x,y,z) indices of the lower left
27947c6ae99SBarry Smith    corner of the local region, excluding ghost points.
28047c6ae99SBarry Smith 
28147c6ae99SBarry Smith    Not Collective
28247c6ae99SBarry Smith 
28347c6ae99SBarry Smith    Input Parameter:
28447c6ae99SBarry Smith .  da - the distributed array
28547c6ae99SBarry Smith 
28647c6ae99SBarry Smith    Output Parameters:
28747c6ae99SBarry Smith +  x,y,z - the corner indices (where y and z are optional; these are used
28847c6ae99SBarry Smith            for 2D and 3D problems)
28947c6ae99SBarry Smith -  m,n,p - widths in the corresponding directions (where n and p are optional;
29047c6ae99SBarry Smith            these are used for 2D and 3D problems)
29147c6ae99SBarry Smith 
29247c6ae99SBarry Smith    Note:
29347c6ae99SBarry Smith    The corner information is independent of the number of degrees of
294aa219208SBarry Smith    freedom per node set with the DMDACreateXX() routine. Thus the x, y, z, and
29547c6ae99SBarry Smith    m, n, p can be thought of as coordinates on a logical grid, where each
29647c6ae99SBarry Smith    grid point has (potentially) several degrees of freedom.
29747c6ae99SBarry Smith    Any of y, z, n, and p can be passed in as PETSC_NULL if not needed.
29847c6ae99SBarry Smith 
29947c6ae99SBarry Smith   Level: beginner
30047c6ae99SBarry Smith 
30147c6ae99SBarry Smith .keywords: distributed array, get, corners, nodes, local indices
30247c6ae99SBarry Smith 
303aa219208SBarry Smith .seealso: DMDAGetGhostCorners(), DMDAGetOwnershipRanges()
30447c6ae99SBarry Smith @*/
3057087cfbeSBarry Smith PetscErrorCode  DMDAGetCorners(DM da,PetscInt *x,PetscInt *y,PetscInt *z,PetscInt *m,PetscInt *n,PetscInt *p)
30647c6ae99SBarry Smith {
30747c6ae99SBarry Smith   PetscInt w;
30847c6ae99SBarry Smith   DM_DA    *dd = (DM_DA*)da->data;
30947c6ae99SBarry Smith 
31047c6ae99SBarry Smith   PetscFunctionBegin;
31147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
31247c6ae99SBarry Smith   /* since the xs, xe ... have all been multiplied by the number of degrees
31347c6ae99SBarry Smith      of freedom per cell, w = dd->w, we divide that out before returning.*/
31447c6ae99SBarry Smith   w = dd->w;
31547c6ae99SBarry Smith   if (x) *x = dd->xs/w; if(m) *m = (dd->xe - dd->xs)/w;
31647c6ae99SBarry Smith   /* the y and z have NOT been multiplied by w */
31747c6ae99SBarry Smith   if (y) *y = dd->ys;   if (n) *n = (dd->ye - dd->ys);
31847c6ae99SBarry Smith   if (z) *z = dd->zs;   if (p) *p = (dd->ze - dd->zs);
31947c6ae99SBarry Smith   PetscFunctionReturn(0);
32047c6ae99SBarry Smith }
32147c6ae99SBarry Smith 
32247c6ae99SBarry Smith #undef __FUNCT__
323aa219208SBarry Smith #define __FUNCT__ "DMDAGetLocalBoundingBox"
32447c6ae99SBarry Smith /*@
325aa219208SBarry Smith    DMDAGetLocalBoundingBox - Returns the local bounding box for the DMDA.
32647c6ae99SBarry Smith 
32747c6ae99SBarry Smith    Not Collective
32847c6ae99SBarry Smith 
32947c6ae99SBarry Smith    Input Parameter:
33047c6ae99SBarry Smith .  da - the distributed array
33147c6ae99SBarry Smith 
33247c6ae99SBarry Smith    Output Parameters:
33347c6ae99SBarry Smith +  lmin - local minimum coordinates (length dim, optional)
33447c6ae99SBarry Smith -  lmax - local maximim coordinates (length dim, optional)
33547c6ae99SBarry Smith 
33647c6ae99SBarry Smith   Level: beginner
33747c6ae99SBarry Smith 
33847c6ae99SBarry Smith .keywords: distributed array, get, coordinates
33947c6ae99SBarry Smith 
340aa219208SBarry Smith .seealso: DMDAGetCoordinateDA(), DMDAGetCoordinates(), DMDAGetBoundingBox()
34147c6ae99SBarry Smith @*/
3427087cfbeSBarry Smith PetscErrorCode  DMDAGetLocalBoundingBox(DM da,PetscReal lmin[],PetscReal lmax[])
34347c6ae99SBarry Smith {
34447c6ae99SBarry Smith   PetscErrorCode    ierr;
34547c6ae99SBarry Smith   Vec               coords  = PETSC_NULL;
34647c6ae99SBarry Smith   PetscInt          dim,i,j;
34747c6ae99SBarry Smith   const PetscScalar *local_coords;
34847c6ae99SBarry Smith   PetscReal         min[3]={PETSC_MAX,PETSC_MAX,PETSC_MAX},max[3]={PETSC_MIN,PETSC_MIN,PETSC_MIN};
34947c6ae99SBarry Smith   PetscInt          N,Ni;
35047c6ae99SBarry Smith   DM_DA             *dd = (DM_DA*)da->data;
35147c6ae99SBarry Smith 
35247c6ae99SBarry Smith   PetscFunctionBegin;
35347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
35447c6ae99SBarry Smith   dim = dd->dim;
355aa219208SBarry Smith   ierr = DMDAGetCoordinates(da,&coords);CHKERRQ(ierr);
35647c6ae99SBarry Smith   ierr = VecGetArrayRead(coords,&local_coords);CHKERRQ(ierr);
35747c6ae99SBarry Smith   ierr = VecGetLocalSize(coords,&N);CHKERRQ(ierr);
35847c6ae99SBarry Smith   Ni = N/dim;
35947c6ae99SBarry Smith   for (i=0; i<Ni; i++) {
36047c6ae99SBarry Smith     for (j=0; j<dim; j++) {
36147c6ae99SBarry Smith       min[j] = PetscMin(min[j],PetscRealPart(local_coords[i*dim+j]));CHKERRQ(ierr);
36247c6ae99SBarry Smith       max[j] = PetscMax(min[j],PetscRealPart(local_coords[i*dim+j]));CHKERRQ(ierr);
36347c6ae99SBarry Smith     }
36447c6ae99SBarry Smith   }
36547c6ae99SBarry Smith   ierr = VecRestoreArrayRead(coords,&local_coords);CHKERRQ(ierr);
36647c6ae99SBarry Smith   if (lmin) {ierr = PetscMemcpy(lmin,min,dim*sizeof(PetscReal));CHKERRQ(ierr);}
36747c6ae99SBarry Smith   if (lmax) {ierr = PetscMemcpy(lmax,max,dim*sizeof(PetscReal));CHKERRQ(ierr);}
36847c6ae99SBarry Smith   PetscFunctionReturn(0);
36947c6ae99SBarry Smith }
37047c6ae99SBarry Smith 
37147c6ae99SBarry Smith #undef __FUNCT__
372aa219208SBarry Smith #define __FUNCT__ "DMDAGetBoundingBox"
37347c6ae99SBarry Smith /*@
374aa219208SBarry Smith    DMDAGetBoundingBox - Returns the global bounding box for the DMDA.
37547c6ae99SBarry Smith 
376aa219208SBarry Smith    Collective on DMDA
37747c6ae99SBarry Smith 
37847c6ae99SBarry Smith    Input Parameter:
37947c6ae99SBarry Smith .  da - the distributed array
38047c6ae99SBarry Smith 
38147c6ae99SBarry Smith    Output Parameters:
38247c6ae99SBarry Smith +  gmin - global minimum coordinates (length dim, optional)
38347c6ae99SBarry Smith -  gmax - global maximim coordinates (length dim, optional)
38447c6ae99SBarry Smith 
38547c6ae99SBarry Smith   Level: beginner
38647c6ae99SBarry Smith 
38747c6ae99SBarry Smith .keywords: distributed array, get, coordinates
38847c6ae99SBarry Smith 
389aa219208SBarry Smith .seealso: DMDAGetCoordinateDA(), DMDAGetCoordinates(), DMDAGetLocalBoundingBox()
39047c6ae99SBarry Smith @*/
3917087cfbeSBarry Smith PetscErrorCode  DMDAGetBoundingBox(DM da,PetscReal gmin[],PetscReal gmax[])
39247c6ae99SBarry Smith {
39347c6ae99SBarry Smith   PetscErrorCode ierr;
39447c6ae99SBarry Smith   PetscMPIInt    count;
39547c6ae99SBarry Smith   PetscReal      lmin[3],lmax[3];
39647c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
39747c6ae99SBarry Smith 
39847c6ae99SBarry Smith   PetscFunctionBegin;
39947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
40047c6ae99SBarry Smith   count = PetscMPIIntCast(dd->dim);
401aa219208SBarry Smith   ierr = DMDAGetLocalBoundingBox(da,lmin,lmax);CHKERRQ(ierr);
40247c6ae99SBarry Smith   if (gmin) {ierr = MPI_Allreduce(lmin,gmin,count,MPIU_REAL,MPI_MIN,((PetscObject)da)->comm);CHKERRQ(ierr);}
40347c6ae99SBarry Smith   if (gmax) {ierr = MPI_Allreduce(lmax,gmax,count,MPIU_REAL,MPI_MAX,((PetscObject)da)->comm);CHKERRQ(ierr);}
40447c6ae99SBarry Smith   PetscFunctionReturn(0);
40547c6ae99SBarry Smith }
406