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