xref: /petsc/src/dm/impls/da/dacorn.c (revision c73cfb54f34510b9dcefc99e398efa3b88d5dde5)
147c6ae99SBarry Smith 
247c6ae99SBarry Smith /*
347c6ae99SBarry Smith   Code for manipulating distributed regular arrays in parallel.
447c6ae99SBarry Smith */
547c6ae99SBarry Smith 
64035e84dSBarry Smith #include <petsc-private/dmdaimpl.h>    /*I   "petscdmda.h"   I*/
747c6ae99SBarry Smith 
847c6ae99SBarry Smith #undef __FUNCT__
96636e97aSMatthew G Knepley #define __FUNCT__ "DMCreateCoordinateDM_DA"
106636e97aSMatthew G Knepley PetscErrorCode DMCreateCoordinateDM_DA(DM dm, DM *cdm)
1147c6ae99SBarry Smith {
1247c6ae99SBarry Smith   PetscErrorCode ierr;
133f2d3b52SPeter Brune   PetscFunctionBegin;
14*c73cfb54SMatthew G. Knepley   ierr = DMDAGetReducedDMDA(dm,dm->dim,cdm);CHKERRQ(ierr);
1547c6ae99SBarry Smith   PetscFunctionReturn(0);
1647c6ae99SBarry Smith }
1747c6ae99SBarry Smith 
1847c6ae99SBarry Smith #undef __FUNCT__
19aa219208SBarry Smith #define __FUNCT__ "DMDASetFieldName"
2047c6ae99SBarry Smith /*@C
21aa219208SBarry Smith    DMDASetFieldName - Sets the names of individual field components in multicomponent
22aa219208SBarry Smith    vectors associated with a DMDA.
2347c6ae99SBarry Smith 
2447c6ae99SBarry Smith    Not Collective
2547c6ae99SBarry Smith 
2647c6ae99SBarry Smith    Input Parameters:
2747c6ae99SBarry Smith +  da - the distributed array
28aa219208SBarry Smith .  nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the
29aa219208SBarry Smith         number of degrees of freedom per node within the DMDA
3047c6ae99SBarry Smith -  names - the name of the field (component)
3147c6ae99SBarry Smith 
3247c6ae99SBarry Smith   Level: intermediate
3347c6ae99SBarry Smith 
3447c6ae99SBarry Smith .keywords: distributed array, get, component name
3547c6ae99SBarry Smith 
36109c9344SBarry Smith .seealso: DMDAGetFieldName(), DMDASetCoordinateName(), DMDAGetCoordinateName()
3747c6ae99SBarry Smith @*/
387087cfbeSBarry Smith PetscErrorCode  DMDASetFieldName(DM da,PetscInt nf,const char name[])
3947c6ae99SBarry Smith {
4047c6ae99SBarry Smith   PetscErrorCode ierr;
4147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
4247c6ae99SBarry Smith 
4347c6ae99SBarry Smith   PetscFunctionBegin;
4447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
4547c6ae99SBarry Smith   if (nf < 0 || nf >= dd->w) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
46c31cb41cSBarry Smith   ierr = PetscFree(dd->fieldname[nf]);CHKERRQ(ierr);
4747c6ae99SBarry Smith   ierr = PetscStrallocpy(name,&dd->fieldname[nf]);CHKERRQ(ierr);
4847c6ae99SBarry Smith   PetscFunctionReturn(0);
4947c6ae99SBarry Smith }
5047c6ae99SBarry Smith 
5147c6ae99SBarry Smith #undef __FUNCT__
52aa219208SBarry Smith #define __FUNCT__ "DMDAGetFieldName"
5347c6ae99SBarry Smith /*@C
54aa219208SBarry Smith    DMDAGetFieldName - Gets the names of individual field components in multicomponent
55aa219208SBarry Smith    vectors associated with a DMDA.
5647c6ae99SBarry Smith 
5747c6ae99SBarry Smith    Not Collective
5847c6ae99SBarry Smith 
5947c6ae99SBarry Smith    Input Parameter:
6047c6ae99SBarry Smith +  da - the distributed array
61aa219208SBarry Smith -  nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the
62aa219208SBarry Smith         number of degrees of freedom per node within the DMDA
6347c6ae99SBarry Smith 
6447c6ae99SBarry Smith    Output Parameter:
6547c6ae99SBarry Smith .  names - the name of the field (component)
6647c6ae99SBarry Smith 
6747c6ae99SBarry Smith   Level: intermediate
6847c6ae99SBarry Smith 
6947c6ae99SBarry Smith .keywords: distributed array, get, component name
7047c6ae99SBarry Smith 
71109c9344SBarry Smith .seealso: DMDASetFieldName(), DMDASetCoordinateName(), DMDAGetCoordinateName()
7247c6ae99SBarry Smith @*/
737087cfbeSBarry Smith PetscErrorCode  DMDAGetFieldName(DM da,PetscInt nf,const char **name)
7447c6ae99SBarry Smith {
7547c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
7647c6ae99SBarry Smith 
7747c6ae99SBarry Smith   PetscFunctionBegin;
7847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
7947c6ae99SBarry Smith   PetscValidPointer(name,3);
8047c6ae99SBarry Smith   if (nf < 0 || nf >= dd->w) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
8147c6ae99SBarry Smith   *name = dd->fieldname[nf];
8247c6ae99SBarry Smith   PetscFunctionReturn(0);
8347c6ae99SBarry Smith }
8447c6ae99SBarry Smith 
8547c6ae99SBarry Smith #undef __FUNCT__
86109c9344SBarry Smith #define __FUNCT__ "DMDASetCoordinateName"
87109c9344SBarry Smith /*@C
88109c9344SBarry Smith    DMDASetCoordinateName - Sets the name of the coordinate directions associated with a DMDA, for example "x" or "y"
89109c9344SBarry Smith 
90109c9344SBarry Smith    Not Collective
91109c9344SBarry Smith 
92109c9344SBarry Smith    Input Parameters:
93*c73cfb54SMatthew G. Knepley +  dm - the DM
94109c9344SBarry Smith .  nf - coordinate number for the DMDA (0, 1, ... dim-1),
95109c9344SBarry Smith -  name - the name of the coordinate
96109c9344SBarry Smith 
97109c9344SBarry Smith   Level: intermediate
98109c9344SBarry Smith 
99109c9344SBarry Smith .keywords: distributed array, get, component name
100109c9344SBarry Smith 
101109c9344SBarry Smith .seealso: DMDAGetCoordinateName(), DMDASetFieldName(), DMDAGetFieldName()
102109c9344SBarry Smith @*/
103*c73cfb54SMatthew G. Knepley PetscErrorCode DMDASetCoordinateName(DM dm,PetscInt nf,const char name[])
104109c9344SBarry Smith {
105109c9344SBarry Smith   PetscErrorCode ierr;
106*c73cfb54SMatthew G. Knepley   DM_DA          *dd = (DM_DA*)dm->data;
107109c9344SBarry Smith 
108109c9344SBarry Smith   PetscFunctionBegin;
109*c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
110*c73cfb54SMatthew G. Knepley   if (nf < 0 || nf >= dm->dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid coordinate number: %D",nf);
111109c9344SBarry Smith   ierr = PetscFree(dd->coordinatename[nf]);CHKERRQ(ierr);
112109c9344SBarry Smith   ierr = PetscStrallocpy(name,&dd->coordinatename[nf]);CHKERRQ(ierr);
113109c9344SBarry Smith   PetscFunctionReturn(0);
114109c9344SBarry Smith }
115109c9344SBarry Smith 
116109c9344SBarry Smith #undef __FUNCT__
117109c9344SBarry Smith #define __FUNCT__ "DMDAGetCoordinateName"
118109c9344SBarry Smith /*@C
119109c9344SBarry Smith    DMDAGetCoordinateName - Gets the name of a coodinate direction associated with a DMDA.
120109c9344SBarry Smith 
121109c9344SBarry Smith    Not Collective
122109c9344SBarry Smith 
123109c9344SBarry Smith    Input Parameter:
124*c73cfb54SMatthew G. Knepley +  dm - the DM
125109c9344SBarry Smith -  nf -  number for the DMDA (0, 1, ... dim-1)
126109c9344SBarry Smith 
127109c9344SBarry Smith    Output Parameter:
128109c9344SBarry Smith .  names - the name of the coordinate direction
129109c9344SBarry Smith 
130109c9344SBarry Smith   Level: intermediate
131109c9344SBarry Smith 
132109c9344SBarry Smith .keywords: distributed array, get, component name
133109c9344SBarry Smith 
134109c9344SBarry Smith .seealso: DMDASetCoordinateName(), DMDASetFieldName(), DMDAGetFieldName()
135109c9344SBarry Smith @*/
136*c73cfb54SMatthew G. Knepley PetscErrorCode DMDAGetCoordinateName(DM dm,PetscInt nf,const char **name)
137109c9344SBarry Smith {
138*c73cfb54SMatthew G. Knepley   DM_DA *dd = (DM_DA*)dm->data;
139109c9344SBarry Smith 
140109c9344SBarry Smith   PetscFunctionBegin;
141*c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
142109c9344SBarry Smith   PetscValidPointer(name,3);
143*c73cfb54SMatthew G. Knepley   if (nf < 0 || nf >= dm->dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid coordinate number: %D",nf);
144109c9344SBarry Smith   *name = dd->coordinatename[nf];
145109c9344SBarry Smith   PetscFunctionReturn(0);
146109c9344SBarry Smith }
147109c9344SBarry Smith 
148109c9344SBarry Smith #undef __FUNCT__
149aa219208SBarry Smith #define __FUNCT__ "DMDAGetCorners"
15047c6ae99SBarry Smith /*@
151aa219208SBarry Smith    DMDAGetCorners - Returns the global (x,y,z) indices of the lower left
15247c6ae99SBarry Smith    corner of the local region, excluding ghost points.
15347c6ae99SBarry Smith 
15447c6ae99SBarry Smith    Not Collective
15547c6ae99SBarry Smith 
15647c6ae99SBarry Smith    Input Parameter:
15747c6ae99SBarry Smith .  da - the distributed array
15847c6ae99SBarry Smith 
15947c6ae99SBarry Smith    Output Parameters:
16047c6ae99SBarry Smith +  x,y,z - the corner indices (where y and z are optional; these are used
16147c6ae99SBarry Smith            for 2D and 3D problems)
16247c6ae99SBarry Smith -  m,n,p - widths in the corresponding directions (where n and p are optional;
16347c6ae99SBarry Smith            these are used for 2D and 3D problems)
16447c6ae99SBarry Smith 
16547c6ae99SBarry Smith    Note:
16647c6ae99SBarry Smith    The corner information is independent of the number of degrees of
167aa219208SBarry Smith    freedom per node set with the DMDACreateXX() routine. Thus the x, y, z, and
16847c6ae99SBarry Smith    m, n, p can be thought of as coordinates on a logical grid, where each
16947c6ae99SBarry Smith    grid point has (potentially) several degrees of freedom.
1700298fd71SBarry Smith    Any of y, z, n, and p can be passed in as NULL if not needed.
17147c6ae99SBarry Smith 
17247c6ae99SBarry Smith   Level: beginner
17347c6ae99SBarry Smith 
17447c6ae99SBarry Smith .keywords: distributed array, get, corners, nodes, local indices
17547c6ae99SBarry Smith 
176aa219208SBarry Smith .seealso: DMDAGetGhostCorners(), DMDAGetOwnershipRanges()
17747c6ae99SBarry Smith @*/
1787087cfbeSBarry Smith PetscErrorCode  DMDAGetCorners(DM da,PetscInt *x,PetscInt *y,PetscInt *z,PetscInt *m,PetscInt *n,PetscInt *p)
17947c6ae99SBarry Smith {
18047c6ae99SBarry Smith   PetscInt w;
18147c6ae99SBarry Smith   DM_DA    *dd = (DM_DA*)da->data;
18247c6ae99SBarry Smith 
18347c6ae99SBarry Smith   PetscFunctionBegin;
18447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
18547c6ae99SBarry Smith   /* since the xs, xe ... have all been multiplied by the number of degrees
18647c6ae99SBarry Smith      of freedom per cell, w = dd->w, we divide that out before returning.*/
18747c6ae99SBarry Smith   w = dd->w;
188d886c4f4SPeter Brune   if (x) *x = dd->xs/w + dd->xo; if (m) *m = (dd->xe - dd->xs)/w;
18947c6ae99SBarry Smith   /* the y and z have NOT been multiplied by w */
190d886c4f4SPeter Brune   if (y) *y = dd->ys + dd->yo; if (n) *n = (dd->ye - dd->ys);
191d886c4f4SPeter Brune   if (z) *z = dd->zs + dd->zo; if (p) *p = (dd->ze - dd->zs);
19247c6ae99SBarry Smith   PetscFunctionReturn(0);
19347c6ae99SBarry Smith }
19447c6ae99SBarry Smith 
19547c6ae99SBarry Smith #undef __FUNCT__
196aa219208SBarry Smith #define __FUNCT__ "DMDAGetLocalBoundingBox"
19747c6ae99SBarry Smith /*@
198aa219208SBarry Smith    DMDAGetLocalBoundingBox - Returns the local bounding box for the DMDA.
19947c6ae99SBarry Smith 
20047c6ae99SBarry Smith    Not Collective
20147c6ae99SBarry Smith 
20247c6ae99SBarry Smith    Input Parameter:
203*c73cfb54SMatthew G. Knepley .  dm - the DM
20447c6ae99SBarry Smith 
20547c6ae99SBarry Smith    Output Parameters:
20647c6ae99SBarry Smith +  lmin - local minimum coordinates (length dim, optional)
20747c6ae99SBarry Smith -  lmax - local maximim coordinates (length dim, optional)
20847c6ae99SBarry Smith 
20947c6ae99SBarry Smith   Level: beginner
21047c6ae99SBarry Smith 
21147c6ae99SBarry Smith .keywords: distributed array, get, coordinates
21247c6ae99SBarry Smith 
2132150357eSBarry Smith .seealso: DMDAGetCoordinateDA(), DMGetCoordinates(), DMDAGetBoundingBox()
21447c6ae99SBarry Smith @*/
215*c73cfb54SMatthew G. Knepley PetscErrorCode DMDAGetLocalBoundingBox(DM dm,PetscReal lmin[],PetscReal lmax[])
21647c6ae99SBarry Smith {
21747c6ae99SBarry Smith   PetscErrorCode    ierr;
2180298fd71SBarry Smith   Vec               coords = NULL;
21947c6ae99SBarry Smith   PetscInt          dim,i,j;
22047c6ae99SBarry Smith   const PetscScalar *local_coords;
221ea345e14SBarry Smith   PetscReal         min[3]={PETSC_MAX_REAL,PETSC_MAX_REAL,PETSC_MAX_REAL},max[3]={PETSC_MIN_REAL,PETSC_MIN_REAL,PETSC_MIN_REAL};
22247c6ae99SBarry Smith   PetscInt          N,Ni;
22347c6ae99SBarry Smith 
22447c6ae99SBarry Smith   PetscFunctionBegin;
225*c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
226*c73cfb54SMatthew G. Knepley   dim  = dm->dim;
227*c73cfb54SMatthew G. Knepley   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
2287324c66bSJed Brown   if (coords) {
22947c6ae99SBarry Smith     ierr = VecGetArrayRead(coords,&local_coords);CHKERRQ(ierr);
23047c6ae99SBarry Smith     ierr = VecGetLocalSize(coords,&N);CHKERRQ(ierr);
23147c6ae99SBarry Smith     Ni   = N/dim;
23247c6ae99SBarry Smith     for (i=0; i<Ni; i++) {
2337324c66bSJed Brown       for (j=0; j<3; j++) {
2347324c66bSJed Brown         min[j] = j < dim ? PetscMin(min[j],PetscRealPart(local_coords[i*dim+j])) : 0;
2352197688cSJed Brown         max[j] = j < dim ? PetscMax(max[j],PetscRealPart(local_coords[i*dim+j])) : 0;
23647c6ae99SBarry Smith       }
23747c6ae99SBarry Smith     }
23847c6ae99SBarry Smith     ierr = VecRestoreArrayRead(coords,&local_coords);CHKERRQ(ierr);
2397324c66bSJed Brown   } else {                      /* Just use grid indices */
2407324c66bSJed Brown     DMDALocalInfo info;
241*c73cfb54SMatthew G. Knepley     ierr   = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr);
2427324c66bSJed Brown     min[0] = info.xs;
2437324c66bSJed Brown     min[1] = info.ys;
2447324c66bSJed Brown     min[2] = info.zs;
2457324c66bSJed Brown     max[0] = info.xs + info.xm-1;
2467324c66bSJed Brown     max[1] = info.ys + info.ym-1;
2477324c66bSJed Brown     max[2] = info.zs + info.zm-1;
2487324c66bSJed Brown   }
24947c6ae99SBarry Smith   if (lmin) {ierr = PetscMemcpy(lmin,min,dim*sizeof(PetscReal));CHKERRQ(ierr);}
25047c6ae99SBarry Smith   if (lmax) {ierr = PetscMemcpy(lmax,max,dim*sizeof(PetscReal));CHKERRQ(ierr);}
25147c6ae99SBarry Smith   PetscFunctionReturn(0);
25247c6ae99SBarry Smith }
25347c6ae99SBarry Smith 
25447c6ae99SBarry Smith #undef __FUNCT__
255aa219208SBarry Smith #define __FUNCT__ "DMDAGetBoundingBox"
25647c6ae99SBarry Smith /*@
257aa219208SBarry Smith    DMDAGetBoundingBox - Returns the global bounding box for the DMDA.
25847c6ae99SBarry Smith 
259aa219208SBarry Smith    Collective on DMDA
26047c6ae99SBarry Smith 
26147c6ae99SBarry Smith    Input Parameter:
262*c73cfb54SMatthew G. Knepley .  dm - the DM
26347c6ae99SBarry Smith 
26447c6ae99SBarry Smith    Output Parameters:
26547c6ae99SBarry Smith +  gmin - global minimum coordinates (length dim, optional)
26647c6ae99SBarry Smith -  gmax - global maximim coordinates (length dim, optional)
26747c6ae99SBarry Smith 
26847c6ae99SBarry Smith   Level: beginner
26947c6ae99SBarry Smith 
27047c6ae99SBarry Smith .keywords: distributed array, get, coordinates
27147c6ae99SBarry Smith 
2722150357eSBarry Smith .seealso: DMDAGetCoordinateDA(), DMGetCoordinates(), DMDAGetLocalBoundingBox()
27347c6ae99SBarry Smith @*/
274*c73cfb54SMatthew G. Knepley PetscErrorCode DMDAGetBoundingBox(DM dm,PetscReal gmin[],PetscReal gmax[])
27547c6ae99SBarry Smith {
27647c6ae99SBarry Smith   PetscErrorCode ierr;
27747c6ae99SBarry Smith   PetscMPIInt    count;
27847c6ae99SBarry Smith   PetscReal      lmin[3],lmax[3];
27947c6ae99SBarry Smith 
28047c6ae99SBarry Smith   PetscFunctionBegin;
281*c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
282*c73cfb54SMatthew G. Knepley   ierr = PetscMPIIntCast(dm->dim,&count);CHKERRQ(ierr);
283*c73cfb54SMatthew G. Knepley   ierr = DMDAGetLocalBoundingBox(dm,lmin,lmax);CHKERRQ(ierr);
284*c73cfb54SMatthew G. Knepley   if (gmin) {ierr = MPI_Allreduce(lmin,gmin,count,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);}
285*c73cfb54SMatthew G. Knepley   if (gmax) {ierr = MPI_Allreduce(lmax,gmax,count,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);}
28647c6ae99SBarry Smith   PetscFunctionReturn(0);
28747c6ae99SBarry Smith }
288bc2bf880SBarry Smith 
289bc2bf880SBarry Smith #undef __FUNCT__
290db05f41bSBarry Smith #define __FUNCT__ "DMDAGetReducedDMDA"
291bc2bf880SBarry Smith /*@
292db05f41bSBarry Smith    DMDAGetReducedDMDA - Gets the DMDA with the same layout but with fewer or more fields
293bc2bf880SBarry Smith 
294bc2bf880SBarry Smith    Collective on DMDA
295bc2bf880SBarry Smith 
296bc2bf880SBarry Smith    Input Parameter:
297bc2bf880SBarry Smith +  da - the distributed array
298bc2bf880SBarry Smith .  nfields - number of fields in new DMDA
299bc2bf880SBarry Smith 
300bc2bf880SBarry Smith    Output Parameter:
301bc2bf880SBarry Smith .  nda - the new DMDA
302bc2bf880SBarry Smith 
303bc2bf880SBarry Smith   Level: intermediate
304bc2bf880SBarry Smith 
305bc2bf880SBarry Smith .keywords: distributed array, get, corners, nodes, local indices, coordinates
306bc2bf880SBarry Smith 
3072150357eSBarry Smith .seealso: DMDAGetGhostCorners(), DMSetCoordinates(), DMDASetUniformCoordinates(), DMGetCoordinates(), DMDAGetGhostedCoordinates()
308bc2bf880SBarry Smith @*/
309db05f41bSBarry Smith PetscErrorCode  DMDAGetReducedDMDA(DM da,PetscInt nfields,DM *nda)
310bc2bf880SBarry Smith {
311bc2bf880SBarry Smith   PetscErrorCode   ierr;
312bc2bf880SBarry Smith   DM_DA            *dd = (DM_DA*)da->data;
31395c13181SPeter Brune   PetscInt         s,m,n,p,M,N,P,dim,Mo,No,Po;
314320964c4SBlaise Bourdin   const PetscInt   *lx,*ly,*lz;
315bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx,by,bz;
316320964c4SBlaise Bourdin   DMDAStencilType  stencil_type;
31795c13181SPeter Brune   PetscInt         ox,oy,oz;
31895c13181SPeter Brune   PetscInt         cl,rl;
319320964c4SBlaise Bourdin 
320320964c4SBlaise Bourdin   PetscFunctionBegin;
321*c73cfb54SMatthew G. Knepley   dim = da->dim;
32295c13181SPeter Brune   M   = dd->M;
32395c13181SPeter Brune   N   = dd->N;
32495c13181SPeter Brune   P   = dd->P;
32595c13181SPeter Brune   m   = dd->m;
32695c13181SPeter Brune   n   = dd->n;
32795c13181SPeter Brune   p   = dd->p;
32895c13181SPeter Brune   s   = dd->s;
32995c13181SPeter Brune   bx  = dd->bx;
33095c13181SPeter Brune   by  = dd->by;
33195c13181SPeter Brune   bz  = dd->bz;
3328865f1eaSKarl Rupp 
33395c13181SPeter Brune   stencil_type = dd->stencil_type;
3348865f1eaSKarl Rupp 
335320964c4SBlaise Bourdin   ierr = DMDAGetOwnershipRanges(da,&lx,&ly,&lz);CHKERRQ(ierr);
336320964c4SBlaise Bourdin   if (dim == 1) {
337ce94432eSBarry Smith     ierr = DMDACreate1d(PetscObjectComm((PetscObject)da),bx,M,nfields,s,dd->lx,nda);CHKERRQ(ierr);
338320964c4SBlaise Bourdin   } else if (dim == 2) {
339ce94432eSBarry Smith     ierr = DMDACreate2d(PetscObjectComm((PetscObject)da),bx,by,stencil_type,M,N,m,n,nfields,s,lx,ly,nda);CHKERRQ(ierr);
340320964c4SBlaise Bourdin   } else if (dim == 3) {
341ce94432eSBarry Smith     ierr = DMDACreate3d(PetscObjectComm((PetscObject)da),bx,by,bz,stencil_type,M,N,P,m,n,p,nfields,s,lx,ly,lz,nda);CHKERRQ(ierr);
342bc2bf880SBarry Smith   }
3436636e97aSMatthew G Knepley   if (da->coordinates) {
3446636e97aSMatthew G Knepley     ierr = PetscObjectReference((PetscObject)da->coordinates);CHKERRQ(ierr);
3458865f1eaSKarl Rupp 
3466636e97aSMatthew G Knepley     (*nda)->coordinates = da->coordinates;
347bc2bf880SBarry Smith   }
34895c13181SPeter Brune 
34995c13181SPeter Brune   /* allow for getting a reduced DA corresponding to a domain decomposition */
35095c13181SPeter Brune   ierr = DMDAGetOffset(da,&ox,&oy,&oz,&Mo,&No,&Po);CHKERRQ(ierr);
35195c13181SPeter Brune   ierr = DMDASetOffset(*nda,ox,oy,oz,Mo,No,Po);CHKERRQ(ierr);
35295c13181SPeter Brune 
35395c13181SPeter Brune   /* allow for getting a reduced DA corresponding to a coarsened DA */
35495c13181SPeter Brune   ierr = DMGetCoarsenLevel(da,&cl);CHKERRQ(ierr);
35595c13181SPeter Brune   ierr = DMGetRefineLevel(da,&rl);CHKERRQ(ierr);
3568865f1eaSKarl Rupp 
35795c13181SPeter Brune   (*nda)->levelup   = rl;
35895c13181SPeter Brune   (*nda)->leveldown = cl;
359bc2bf880SBarry Smith   PetscFunctionReturn(0);
360bc2bf880SBarry Smith }
361bc2bf880SBarry Smith 
362