xref: /petsc/src/dm/impls/da/da.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
1af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h>    /*I   "petscdmda.h"   I*/
247c6ae99SBarry Smith 
347c6ae99SBarry Smith /*@
4e43dc8daSBarry Smith   DMDASetSizes - Sets the number of grid points in the three dimensional directions
547c6ae99SBarry Smith 
6d083f849SBarry Smith   Logically Collective on da
747c6ae99SBarry Smith 
847c6ae99SBarry Smith   Input Parameters:
9aa219208SBarry Smith + da - the DMDA
10e43dc8daSBarry Smith . M - the global X size
11e43dc8daSBarry Smith . N - the global Y size
12e43dc8daSBarry Smith - P - the global Z size
1347c6ae99SBarry Smith 
1447c6ae99SBarry Smith   Level: intermediate
1547c6ae99SBarry Smith 
16628e512eSPatrick Sanan   Developer Notes:
17628e512eSPatrick Sanan   Since the dimension may not yet have been set the code cannot error check for non-positive Y and Z number of grid points
18e43dc8daSBarry Smith 
19628e512eSPatrick Sanan .seealso: PetscSplitOwnership()
2047c6ae99SBarry Smith @*/
217087cfbeSBarry Smith PetscErrorCode  DMDASetSizes(DM da, PetscInt M, PetscInt N, PetscInt P)
2247c6ae99SBarry Smith {
2347c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
2447c6ae99SBarry Smith 
2547c6ae99SBarry Smith   PetscFunctionBegin;
26a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da, DM_CLASSID, 1,DMDA);
2747c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,M,2);
2847c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,N,3);
2947c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,P,4);
307a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
317a8be351SBarry Smith   PetscCheck(M >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Number of grid points in X direction must be positive");
327a8be351SBarry Smith   PetscCheck(N >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Number of grid points in Y direction must be positive");
337a8be351SBarry Smith   PetscCheck(P >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Number of grid points in Z direction must be positive");
3447c6ae99SBarry Smith 
3547c6ae99SBarry Smith   dd->M = M;
3647c6ae99SBarry Smith   dd->N = N;
3747c6ae99SBarry Smith   dd->P = P;
3847c6ae99SBarry Smith   PetscFunctionReturn(0);
3947c6ae99SBarry Smith }
4047c6ae99SBarry Smith 
4147c6ae99SBarry Smith /*@
42aa219208SBarry Smith   DMDASetNumProcs - Sets the number of processes in each dimension
4347c6ae99SBarry Smith 
44d083f849SBarry Smith   Logically Collective on da
4547c6ae99SBarry Smith 
4647c6ae99SBarry Smith   Input Parameters:
47aa219208SBarry Smith + da - the DMDA
4847c6ae99SBarry Smith . m - the number of X procs (or PETSC_DECIDE)
4947c6ae99SBarry Smith . n - the number of Y procs (or PETSC_DECIDE)
5047c6ae99SBarry Smith - p - the number of Z procs (or PETSC_DECIDE)
5147c6ae99SBarry Smith 
5247c6ae99SBarry Smith   Level: intermediate
5347c6ae99SBarry Smith 
54628e512eSPatrick Sanan .seealso: DMDASetSizes(), PetscSplitOwnership()
5547c6ae99SBarry Smith @*/
567087cfbeSBarry Smith PetscErrorCode  DMDASetNumProcs(DM da, PetscInt m, PetscInt n, PetscInt p)
5747c6ae99SBarry Smith {
5847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
5947c6ae99SBarry Smith 
6047c6ae99SBarry Smith   PetscFunctionBegin;
61a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da, DM_CLASSID, 1,DMDA);
6247c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,m,2);
6347c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,n,3);
6447c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,p,4);
657a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
6647c6ae99SBarry Smith   dd->m = m;
6747c6ae99SBarry Smith   dd->n = n;
6847c6ae99SBarry Smith   dd->p = p;
69c73cfb54SMatthew G. Knepley   if (da->dim == 2) {
70d3be247eSBarry Smith     PetscMPIInt size;
71*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da),&size));
72e3f3e4b6SBarry Smith     if ((dd->m > 0) && (dd->n < 0)) {
73e3f3e4b6SBarry Smith       dd->n = size/dd->m;
747a8be351SBarry Smith       PetscCheck(dd->n*dd->m == size,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"%D processes in X direction not divisible into comm size %d",m,size);
75e3f3e4b6SBarry Smith     }
76e3f3e4b6SBarry Smith     if ((dd->n > 0) && (dd->m < 0)) {
77e3f3e4b6SBarry Smith       dd->m = size/dd->n;
787a8be351SBarry Smith       PetscCheck(dd->n*dd->m == size,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"%D processes in Y direction not divisible into comm size %d",n,size);
79e3f3e4b6SBarry Smith     }
80e3f3e4b6SBarry Smith   }
8147c6ae99SBarry Smith   PetscFunctionReturn(0);
8247c6ae99SBarry Smith }
8347c6ae99SBarry Smith 
8447c6ae99SBarry Smith /*@
851321219cSEthan Coon   DMDASetBoundaryType - Sets the type of ghost nodes on domain boundaries.
8647c6ae99SBarry Smith 
8747c6ae99SBarry Smith   Not collective
8847c6ae99SBarry Smith 
89d8d19677SJose E. Roman   Input Parameters:
90aa219208SBarry Smith + da    - The DMDA
91bff4a2f0SMatthew G. Knepley - bx,by,bz - One of DM_BOUNDARY_NONE, DM_BOUNDARY_GHOSTED, DM_BOUNDARY_PERIODIC
9247c6ae99SBarry Smith 
9347c6ae99SBarry Smith   Level: intermediate
9447c6ae99SBarry Smith 
95bff4a2f0SMatthew G. Knepley .seealso: DMDACreate(), DMDestroy(), DMDA, DMBoundaryType
9647c6ae99SBarry Smith @*/
97bff4a2f0SMatthew G. Knepley PetscErrorCode  DMDASetBoundaryType(DM da,DMBoundaryType bx,DMBoundaryType by,DMBoundaryType bz)
9847c6ae99SBarry Smith {
9947c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
10047c6ae99SBarry Smith 
10147c6ae99SBarry Smith   PetscFunctionBegin;
102a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
1035a43f728SLisandro Dalcin   PetscValidLogicalCollectiveEnum(da,bx,2);
1045a43f728SLisandro Dalcin   PetscValidLogicalCollectiveEnum(da,by,3);
1055a43f728SLisandro Dalcin   PetscValidLogicalCollectiveEnum(da,bz,4);
1067a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
1071321219cSEthan Coon   dd->bx = bx;
1081321219cSEthan Coon   dd->by = by;
1091321219cSEthan Coon   dd->bz = bz;
11047c6ae99SBarry Smith   PetscFunctionReturn(0);
11147c6ae99SBarry Smith }
11247c6ae99SBarry Smith 
11347c6ae99SBarry Smith /*@
114aa219208SBarry Smith   DMDASetDof - Sets the number of degrees of freedom per vertex
11547c6ae99SBarry Smith 
11647c6ae99SBarry Smith   Not collective
11747c6ae99SBarry Smith 
11859f3ab6dSMatthew G. Knepley   Input Parameters:
119aa219208SBarry Smith + da  - The DMDA
12047c6ae99SBarry Smith - dof - Number of degrees of freedom
12147c6ae99SBarry Smith 
12247c6ae99SBarry Smith   Level: intermediate
12347c6ae99SBarry Smith 
124fb6725baSMatthew G. Knepley .seealso: DMDAGetDof(), DMDACreate(), DMDestroy(), DMDA
12547c6ae99SBarry Smith @*/
12654cfb0beSLisandro Dalcin PetscErrorCode  DMDASetDof(DM da, PetscInt dof)
12747c6ae99SBarry Smith {
12847c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
12947c6ae99SBarry Smith 
13047c6ae99SBarry Smith   PetscFunctionBegin;
131a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
13254cfb0beSLisandro Dalcin   PetscValidLogicalCollectiveInt(da,dof,2);
1337a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
13447c6ae99SBarry Smith   dd->w  = dof;
1351411c6eeSJed Brown   da->bs = dof;
13647c6ae99SBarry Smith   PetscFunctionReturn(0);
13747c6ae99SBarry Smith }
13847c6ae99SBarry Smith 
139fb6725baSMatthew G. Knepley /*@
140fb6725baSMatthew G. Knepley   DMDAGetDof - Gets the number of degrees of freedom per vertex
141fb6725baSMatthew G. Knepley 
142fb6725baSMatthew G. Knepley   Not collective
143fb6725baSMatthew G. Knepley 
144fb6725baSMatthew G. Knepley   Input Parameter:
145fb6725baSMatthew G. Knepley . da  - The DMDA
146fb6725baSMatthew G. Knepley 
147fb6725baSMatthew G. Knepley   Output Parameter:
148fb6725baSMatthew G. Knepley . dof - Number of degrees of freedom
149fb6725baSMatthew G. Knepley 
150fb6725baSMatthew G. Knepley   Level: intermediate
151fb6725baSMatthew G. Knepley 
152fb6725baSMatthew G. Knepley .seealso: DMDASetDof(), DMDACreate(), DMDestroy(), DMDA
153fb6725baSMatthew G. Knepley @*/
154fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetDof(DM da, PetscInt *dof)
155fb6725baSMatthew G. Knepley {
156fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA *) da->data;
157fb6725baSMatthew G. Knepley 
158fb6725baSMatthew G. Knepley   PetscFunctionBegin;
159a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
160fb6725baSMatthew G. Knepley   PetscValidPointer(dof,2);
161fb6725baSMatthew G. Knepley   *dof = dd->w;
162fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
163fb6725baSMatthew G. Knepley }
164fb6725baSMatthew G. Knepley 
1657ddda789SPeter Brune /*@
1667ddda789SPeter Brune   DMDAGetOverlap - Gets the size of the per-processor overlap.
1677ddda789SPeter Brune 
1687ddda789SPeter Brune   Not collective
1697ddda789SPeter Brune 
170f899ff85SJose E. Roman   Input Parameter:
1717ddda789SPeter Brune . da  - The DMDA
1727ddda789SPeter Brune 
1737ddda789SPeter Brune   Output Parameters:
1747ddda789SPeter Brune + x   - Overlap in the x direction
1757ddda789SPeter Brune . y   - Overlap in the y direction
1767ddda789SPeter Brune - z   - Overlap in the z direction
1777ddda789SPeter Brune 
1787ddda789SPeter Brune   Level: intermediate
1797ddda789SPeter Brune 
1807ddda789SPeter Brune .seealso: DMDACreateDomainDecomposition(), DMDASetOverlap(), DMDA
1817ddda789SPeter Brune @*/
1827ddda789SPeter Brune PetscErrorCode  DMDAGetOverlap(DM da,PetscInt *x,PetscInt *y,PetscInt *z)
1837ddda789SPeter Brune {
1847ddda789SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
1857ddda789SPeter Brune 
1867ddda789SPeter Brune   PetscFunctionBegin;
187a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
1887ddda789SPeter Brune   if (x) *x = dd->xol;
1897ddda789SPeter Brune   if (y) *y = dd->yol;
1907ddda789SPeter Brune   if (z) *z = dd->zol;
1917ddda789SPeter Brune   PetscFunctionReturn(0);
1927ddda789SPeter Brune }
1937ddda789SPeter Brune 
19488661749SPeter Brune /*@
19588661749SPeter Brune   DMDASetOverlap - Sets the size of the per-processor overlap.
19688661749SPeter Brune 
19788661749SPeter Brune   Not collective
19888661749SPeter Brune 
1997ddda789SPeter Brune   Input Parameters:
20088661749SPeter Brune + da  - The DMDA
2017ddda789SPeter Brune . x   - Overlap in the x direction
2027ddda789SPeter Brune . y   - Overlap in the y direction
2037ddda789SPeter Brune - z   - Overlap in the z direction
20488661749SPeter Brune 
20588661749SPeter Brune   Level: intermediate
20688661749SPeter Brune 
2077ddda789SPeter Brune .seealso: DMDACreateDomainDecomposition(), DMDAGetOverlap(), DMDA
20888661749SPeter Brune @*/
2097ddda789SPeter Brune PetscErrorCode  DMDASetOverlap(DM da,PetscInt x,PetscInt y,PetscInt z)
21088661749SPeter Brune {
21188661749SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
21288661749SPeter Brune 
21388661749SPeter Brune   PetscFunctionBegin;
214a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
2157ddda789SPeter Brune   PetscValidLogicalCollectiveInt(da,x,2);
2167ddda789SPeter Brune   PetscValidLogicalCollectiveInt(da,y,3);
2177ddda789SPeter Brune   PetscValidLogicalCollectiveInt(da,z,4);
2187ddda789SPeter Brune   dd->xol = x;
2197ddda789SPeter Brune   dd->yol = y;
2207ddda789SPeter Brune   dd->zol = z;
22188661749SPeter Brune   PetscFunctionReturn(0);
22288661749SPeter Brune }
22388661749SPeter Brune 
2243e7870d2SPeter Brune /*@
2253e7870d2SPeter Brune   DMDAGetNumLocalSubDomains - Gets the number of local subdomains created upon decomposition.
2263e7870d2SPeter Brune 
2273e7870d2SPeter Brune   Not collective
2283e7870d2SPeter Brune 
2293e7870d2SPeter Brune   Input Parameters:
2303e7870d2SPeter Brune . da  - The DMDA
2313e7870d2SPeter Brune 
2323e7870d2SPeter Brune   Output Parameters:
233a2b725a8SWilliam Gropp . Nsub   - Number of local subdomains created upon decomposition
2343e7870d2SPeter Brune 
2353e7870d2SPeter Brune   Level: intermediate
2363e7870d2SPeter Brune 
2373e7870d2SPeter Brune .seealso: DMDACreateDomainDecomposition(), DMDASetNumLocalSubDomains(), DMDA
2383e7870d2SPeter Brune @*/
2393e7870d2SPeter Brune PetscErrorCode  DMDAGetNumLocalSubDomains(DM da,PetscInt *Nsub)
2403e7870d2SPeter Brune {
2413e7870d2SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
2423e7870d2SPeter Brune 
2433e7870d2SPeter Brune   PetscFunctionBegin;
244a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
2453e7870d2SPeter Brune   if (Nsub) *Nsub = dd->Nsub;
2463e7870d2SPeter Brune   PetscFunctionReturn(0);
2473e7870d2SPeter Brune }
2483e7870d2SPeter Brune 
2493e7870d2SPeter Brune /*@
2503e7870d2SPeter Brune   DMDASetNumLocalSubDomains - Sets the number of local subdomains created upon decomposition.
2513e7870d2SPeter Brune 
2523e7870d2SPeter Brune   Not collective
2533e7870d2SPeter Brune 
2543e7870d2SPeter Brune   Input Parameters:
2553e7870d2SPeter Brune + da  - The DMDA
2563e7870d2SPeter Brune - Nsub - The number of local subdomains requested
2573e7870d2SPeter Brune 
2583e7870d2SPeter Brune   Level: intermediate
2593e7870d2SPeter Brune 
2603e7870d2SPeter Brune .seealso: DMDACreateDomainDecomposition(), DMDAGetNumLocalSubDomains(), DMDA
2613e7870d2SPeter Brune @*/
2623e7870d2SPeter Brune PetscErrorCode  DMDASetNumLocalSubDomains(DM da,PetscInt Nsub)
2633e7870d2SPeter Brune {
2643e7870d2SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
2653e7870d2SPeter Brune 
2663e7870d2SPeter Brune   PetscFunctionBegin;
267a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
2683e7870d2SPeter Brune   PetscValidLogicalCollectiveInt(da,Nsub,2);
2693e7870d2SPeter Brune   dd->Nsub = Nsub;
2703e7870d2SPeter Brune   PetscFunctionReturn(0);
2713e7870d2SPeter Brune }
2723e7870d2SPeter Brune 
273d886c4f4SPeter Brune /*@
274d886c4f4SPeter Brune   DMDASetOffset - Sets the index offset of the DA.
275d886c4f4SPeter Brune 
276d886c4f4SPeter Brune   Collective on DA
277d886c4f4SPeter Brune 
278d8d19677SJose E. Roman   Input Parameters:
279d886c4f4SPeter Brune + da  - The DMDA
280d886c4f4SPeter Brune . xo  - The offset in the x direction
281d886c4f4SPeter Brune . yo  - The offset in the y direction
282d886c4f4SPeter Brune - zo  - The offset in the z direction
283d886c4f4SPeter Brune 
284d886c4f4SPeter Brune   Level: intermediate
285d886c4f4SPeter Brune 
28695452b02SPatrick Sanan   Notes:
28795452b02SPatrick Sanan     This is used primarily to overlap a computation on a local DA with that on a global DA without
288d886c4f4SPeter Brune   changing boundary conditions or subdomain features that depend upon the global offsets.
289d886c4f4SPeter Brune 
290d886c4f4SPeter Brune .seealso: DMDAGetOffset(), DMDAVecGetArray()
291d886c4f4SPeter Brune @*/
29295c13181SPeter Brune PetscErrorCode  DMDASetOffset(DM da, PetscInt xo, PetscInt yo, PetscInt zo, PetscInt Mo, PetscInt No, PetscInt Po)
293d886c4f4SPeter Brune {
294d886c4f4SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
295d886c4f4SPeter Brune 
296d886c4f4SPeter Brune   PetscFunctionBegin;
297a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
298d886c4f4SPeter Brune   PetscValidLogicalCollectiveInt(da,xo,2);
29995c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,yo,3);
30095c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,zo,4);
30195c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,Mo,5);
30295c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,No,6);
30395c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,Po,7);
304d886c4f4SPeter Brune   dd->xo = xo;
305d886c4f4SPeter Brune   dd->yo = yo;
306d886c4f4SPeter Brune   dd->zo = zo;
30795c13181SPeter Brune   dd->Mo = Mo;
30895c13181SPeter Brune   dd->No = No;
30995c13181SPeter Brune   dd->Po = Po;
31095c13181SPeter Brune 
31195c13181SPeter Brune   if (da->coordinateDM) {
312*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOffset(da->coordinateDM,xo,yo,zo,Mo,No,Po));
31395c13181SPeter Brune   }
314d886c4f4SPeter Brune   PetscFunctionReturn(0);
315d886c4f4SPeter Brune }
316d886c4f4SPeter Brune 
317d886c4f4SPeter Brune /*@
318d886c4f4SPeter Brune   DMDAGetOffset - Gets the index offset of the DA.
319d886c4f4SPeter Brune 
320d886c4f4SPeter Brune   Not collective
321d886c4f4SPeter Brune 
322d886c4f4SPeter Brune   Input Parameter:
323d886c4f4SPeter Brune . da  - The DMDA
324d886c4f4SPeter Brune 
325d886c4f4SPeter Brune   Output Parameters:
326d886c4f4SPeter Brune + xo  - The offset in the x direction
327d886c4f4SPeter Brune . yo  - The offset in the y direction
32895c13181SPeter Brune . zo  - The offset in the z direction
32995c13181SPeter Brune . Mo  - The global size in the x direction
33095c13181SPeter Brune . No  - The global size in the y direction
33195c13181SPeter Brune - Po  - The global size in the z direction
332d886c4f4SPeter Brune 
333d886c4f4SPeter Brune   Level: intermediate
334d886c4f4SPeter Brune 
335d886c4f4SPeter Brune .seealso: DMDASetOffset(), DMDAVecGetArray()
336d886c4f4SPeter Brune @*/
33795c13181SPeter Brune PetscErrorCode  DMDAGetOffset(DM da,PetscInt *xo,PetscInt *yo,PetscInt *zo,PetscInt *Mo,PetscInt *No,PetscInt *Po)
338d886c4f4SPeter Brune {
339d886c4f4SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
340d886c4f4SPeter Brune 
341d886c4f4SPeter Brune   PetscFunctionBegin;
342a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
343d886c4f4SPeter Brune   if (xo) *xo = dd->xo;
344d886c4f4SPeter Brune   if (yo) *yo = dd->yo;
345d886c4f4SPeter Brune   if (zo) *zo = dd->zo;
34695c13181SPeter Brune   if (Mo) *Mo = dd->Mo;
34795c13181SPeter Brune   if (No) *No = dd->No;
34895c13181SPeter Brune   if (Po) *Po = dd->Po;
349d886c4f4SPeter Brune   PetscFunctionReturn(0);
350d886c4f4SPeter Brune }
351d886c4f4SPeter Brune 
35240234c92SPeter Brune /*@
35340234c92SPeter Brune   DMDAGetNonOverlappingRegion - Gets the indices of the nonoverlapping region of a subdomain DM.
35440234c92SPeter Brune 
35540234c92SPeter Brune   Not collective
35640234c92SPeter Brune 
35740234c92SPeter Brune   Input Parameter:
35840234c92SPeter Brune . da  - The DMDA
35940234c92SPeter Brune 
36040234c92SPeter Brune   Output Parameters:
36140234c92SPeter Brune + xs  - The start of the region in x
36240234c92SPeter Brune . ys  - The start of the region in y
36340234c92SPeter Brune . zs  - The start of the region in z
36440234c92SPeter Brune . xs  - The size of the region in x
36540234c92SPeter Brune . ys  - The size of the region in y
366a2b725a8SWilliam Gropp - zs  - The size of the region in z
36740234c92SPeter Brune 
36840234c92SPeter Brune   Level: intermediate
36940234c92SPeter Brune 
37040234c92SPeter Brune .seealso: DMDAGetOffset(), DMDAVecGetArray()
37140234c92SPeter Brune @*/
37240234c92SPeter Brune PetscErrorCode  DMDAGetNonOverlappingRegion(DM da, PetscInt *xs, PetscInt *ys, PetscInt *zs, PetscInt *xm, PetscInt *ym, PetscInt *zm)
37340234c92SPeter Brune {
37440234c92SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
37540234c92SPeter Brune 
37640234c92SPeter Brune   PetscFunctionBegin;
377a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
37840234c92SPeter Brune   if (xs) *xs = dd->nonxs;
37940234c92SPeter Brune   if (ys) *ys = dd->nonys;
38040234c92SPeter Brune   if (zs) *zs = dd->nonzs;
38140234c92SPeter Brune   if (xm) *xm = dd->nonxm;
38240234c92SPeter Brune   if (ym) *ym = dd->nonym;
38340234c92SPeter Brune   if (zm) *zm = dd->nonzm;
38440234c92SPeter Brune   PetscFunctionReturn(0);
38540234c92SPeter Brune }
38640234c92SPeter Brune 
38740234c92SPeter Brune /*@
38840234c92SPeter Brune   DMDASetNonOverlappingRegion - Sets the indices of the nonoverlapping region of a subdomain DM.
38940234c92SPeter Brune 
39040234c92SPeter Brune   Collective on DA
39140234c92SPeter Brune 
392d8d19677SJose E. Roman   Input Parameters:
39340234c92SPeter Brune + da  - The DMDA
39440234c92SPeter Brune . xs  - The start of the region in x
39540234c92SPeter Brune . ys  - The start of the region in y
39640234c92SPeter Brune . zs  - The start of the region in z
39740234c92SPeter Brune . xs  - The size of the region in x
39840234c92SPeter Brune . ys  - The size of the region in y
399a2b725a8SWilliam Gropp - zs  - The size of the region in z
40040234c92SPeter Brune 
40140234c92SPeter Brune   Level: intermediate
40240234c92SPeter Brune 
40340234c92SPeter Brune .seealso: DMDAGetOffset(), DMDAVecGetArray()
40440234c92SPeter Brune @*/
40540234c92SPeter Brune PetscErrorCode  DMDASetNonOverlappingRegion(DM da, PetscInt xs, PetscInt ys, PetscInt zs, PetscInt xm, PetscInt ym, PetscInt zm)
40640234c92SPeter Brune {
40740234c92SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
40840234c92SPeter Brune 
40940234c92SPeter Brune   PetscFunctionBegin;
410a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
41140234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,xs,2);
41240234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,ys,3);
41340234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,zs,4);
41440234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,xm,5);
41540234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,ym,6);
41640234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,zm,7);
41740234c92SPeter Brune   dd->nonxs = xs;
41840234c92SPeter Brune   dd->nonys = ys;
41940234c92SPeter Brune   dd->nonzs = zs;
42040234c92SPeter Brune   dd->nonxm = xm;
42140234c92SPeter Brune   dd->nonym = ym;
42240234c92SPeter Brune   dd->nonzm = zm;
42340234c92SPeter Brune 
42440234c92SPeter Brune   PetscFunctionReturn(0);
42540234c92SPeter Brune }
42688661749SPeter Brune 
42747c6ae99SBarry Smith /*@
428aa219208SBarry Smith   DMDASetStencilType - Sets the type of the communication stencil
42947c6ae99SBarry Smith 
430d083f849SBarry Smith   Logically Collective on da
43147c6ae99SBarry Smith 
432d8d19677SJose E. Roman   Input Parameters:
433aa219208SBarry Smith + da    - The DMDA
434aa219208SBarry Smith - stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
43547c6ae99SBarry Smith 
43647c6ae99SBarry Smith   Level: intermediate
43747c6ae99SBarry Smith 
43896e147daSBarry Smith .seealso: DMDACreate(), DMDestroy(), DMDA
43947c6ae99SBarry Smith @*/
4407087cfbeSBarry Smith PetscErrorCode  DMDASetStencilType(DM da, DMDAStencilType stype)
44147c6ae99SBarry Smith {
44247c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
44347c6ae99SBarry Smith 
44447c6ae99SBarry Smith   PetscFunctionBegin;
445a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
44647c6ae99SBarry Smith   PetscValidLogicalCollectiveEnum(da,stype,2);
4477a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
44847c6ae99SBarry Smith   dd->stencil_type = stype;
44947c6ae99SBarry Smith   PetscFunctionReturn(0);
45047c6ae99SBarry Smith }
45147c6ae99SBarry Smith 
452fb6725baSMatthew G. Knepley /*@
453fb6725baSMatthew G. Knepley   DMDAGetStencilType - Gets the type of the communication stencil
454fb6725baSMatthew G. Knepley 
455fb6725baSMatthew G. Knepley   Not collective
456fb6725baSMatthew G. Knepley 
457fb6725baSMatthew G. Knepley   Input Parameter:
458fb6725baSMatthew G. Knepley . da    - The DMDA
459fb6725baSMatthew G. Knepley 
460fb6725baSMatthew G. Knepley   Output Parameter:
461fb6725baSMatthew G. Knepley . stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
462fb6725baSMatthew G. Knepley 
463fb6725baSMatthew G. Knepley   Level: intermediate
464fb6725baSMatthew G. Knepley 
465fb6725baSMatthew G. Knepley .seealso: DMDACreate(), DMDestroy(), DMDA
466fb6725baSMatthew G. Knepley @*/
467fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetStencilType(DM da, DMDAStencilType *stype)
468fb6725baSMatthew G. Knepley {
469fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA*)da->data;
470fb6725baSMatthew G. Knepley 
471fb6725baSMatthew G. Knepley   PetscFunctionBegin;
472a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
473fb6725baSMatthew G. Knepley   PetscValidPointer(stype,2);
474fb6725baSMatthew G. Knepley   *stype = dd->stencil_type;
475fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
476fb6725baSMatthew G. Knepley }
477fb6725baSMatthew G. Knepley 
47847c6ae99SBarry Smith /*@
479aa219208SBarry Smith   DMDASetStencilWidth - Sets the width of the communication stencil
48047c6ae99SBarry Smith 
481d083f849SBarry Smith   Logically Collective on da
48247c6ae99SBarry Smith 
483d8d19677SJose E. Roman   Input Parameters:
484aa219208SBarry Smith + da    - The DMDA
48547c6ae99SBarry Smith - width - The stencil width
48647c6ae99SBarry Smith 
48747c6ae99SBarry Smith   Level: intermediate
48847c6ae99SBarry Smith 
48996e147daSBarry Smith .seealso: DMDACreate(), DMDestroy(), DMDA
49047c6ae99SBarry Smith @*/
4917087cfbeSBarry Smith PetscErrorCode  DMDASetStencilWidth(DM da, PetscInt width)
49247c6ae99SBarry Smith {
49347c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
49447c6ae99SBarry Smith 
49547c6ae99SBarry Smith   PetscFunctionBegin;
496a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
49747c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,width,2);
4987a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
49947c6ae99SBarry Smith   dd->s = width;
50047c6ae99SBarry Smith   PetscFunctionReturn(0);
50147c6ae99SBarry Smith }
50247c6ae99SBarry Smith 
503fb6725baSMatthew G. Knepley /*@
504fb6725baSMatthew G. Knepley   DMDAGetStencilWidth - Gets the width of the communication stencil
505fb6725baSMatthew G. Knepley 
506fb6725baSMatthew G. Knepley   Not collective
507fb6725baSMatthew G. Knepley 
508fb6725baSMatthew G. Knepley   Input Parameter:
509fb6725baSMatthew G. Knepley . da    - The DMDA
510fb6725baSMatthew G. Knepley 
511fb6725baSMatthew G. Knepley   Output Parameter:
512fb6725baSMatthew G. Knepley . width - The stencil width
513fb6725baSMatthew G. Knepley 
514fb6725baSMatthew G. Knepley   Level: intermediate
515fb6725baSMatthew G. Knepley 
516fb6725baSMatthew G. Knepley .seealso: DMDACreate(), DMDestroy(), DMDA
517fb6725baSMatthew G. Knepley @*/
518fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetStencilWidth(DM da, PetscInt *width)
519fb6725baSMatthew G. Knepley {
520fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA *) da->data;
521fb6725baSMatthew G. Knepley 
522fb6725baSMatthew G. Knepley   PetscFunctionBegin;
523a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
524fb6725baSMatthew G. Knepley   PetscValidPointer(width,2);
525fb6725baSMatthew G. Knepley   *width = dd->s;
526fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
527fb6725baSMatthew G. Knepley }
528fb6725baSMatthew G. Knepley 
529aa219208SBarry Smith static PetscErrorCode DMDACheckOwnershipRanges_Private(DM da,PetscInt M,PetscInt m,const PetscInt lx[])
53047c6ae99SBarry Smith {
53147c6ae99SBarry Smith   PetscInt i,sum;
53247c6ae99SBarry Smith 
53347c6ae99SBarry Smith   PetscFunctionBegin;
5347a8be351SBarry Smith   PetscCheck(M >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Global dimension not set");
53547c6ae99SBarry Smith   for (i=sum=0; i<m; i++) sum += lx[i];
5367a8be351SBarry Smith   PetscCheck(sum == M,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"Ownership ranges sum to %D but global dimension is %D",sum,M);
53747c6ae99SBarry Smith   PetscFunctionReturn(0);
53847c6ae99SBarry Smith }
53947c6ae99SBarry Smith 
54047c6ae99SBarry Smith /*@
541aa219208SBarry Smith   DMDASetOwnershipRanges - Sets the number of nodes in each direction on each process
54247c6ae99SBarry Smith 
543d083f849SBarry Smith   Logically Collective on da
54447c6ae99SBarry Smith 
545d8d19677SJose E. Roman   Input Parameters:
546aa219208SBarry Smith + da - The DMDA
5470298fd71SBarry Smith . lx - array containing number of nodes in the X direction on each process, or NULL. If non-null, must be of length da->m
5480298fd71SBarry Smith . ly - array containing number of nodes in the Y direction on each process, or NULL. If non-null, must be of length da->n
5490298fd71SBarry Smith - lz - array containing number of nodes in the Z direction on each process, or NULL. If non-null, must be of length da->p.
55047c6ae99SBarry Smith 
55147c6ae99SBarry Smith   Level: intermediate
55247c6ae99SBarry Smith 
553e3f3e4b6SBarry Smith   Note: these numbers are NOT multiplied by the number of dof per node.
554e3f3e4b6SBarry Smith 
55596e147daSBarry Smith .seealso: DMDACreate(), DMDestroy(), DMDA
55647c6ae99SBarry Smith @*/
5577087cfbeSBarry Smith PetscErrorCode  DMDASetOwnershipRanges(DM da, const PetscInt lx[], const PetscInt ly[], const PetscInt lz[])
55847c6ae99SBarry Smith {
55947c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
56047c6ae99SBarry Smith 
56147c6ae99SBarry Smith   PetscFunctionBegin;
562a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
5637a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
56447c6ae99SBarry Smith   if (lx) {
5657a8be351SBarry Smith     PetscCheck(dd->m >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
566*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACheckOwnershipRanges_Private(da,dd->M,dd->m,lx));
56747c6ae99SBarry Smith     if (!dd->lx) {
568*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(dd->m, &dd->lx));
56947c6ae99SBarry Smith     }
570*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd->lx, lx, dd->m));
57147c6ae99SBarry Smith   }
57247c6ae99SBarry Smith   if (ly) {
5737a8be351SBarry Smith     PetscCheck(dd->n >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
574*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACheckOwnershipRanges_Private(da,dd->N,dd->n,ly));
57547c6ae99SBarry Smith     if (!dd->ly) {
576*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(dd->n, &dd->ly));
57747c6ae99SBarry Smith     }
578*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd->ly, ly, dd->n));
57947c6ae99SBarry Smith   }
58047c6ae99SBarry Smith   if (lz) {
5817a8be351SBarry Smith     PetscCheck(dd->p >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
582*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACheckOwnershipRanges_Private(da,dd->P,dd->p,lz));
58347c6ae99SBarry Smith     if (!dd->lz) {
584*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(dd->p, &dd->lz));
58547c6ae99SBarry Smith     }
586*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd->lz, lz, dd->p));
58747c6ae99SBarry Smith   }
58847c6ae99SBarry Smith   PetscFunctionReturn(0);
58947c6ae99SBarry Smith }
59047c6ae99SBarry Smith 
59147c6ae99SBarry Smith /*@
592aa219208SBarry Smith        DMDASetInterpolationType - Sets the type of interpolation that will be
593e727c939SJed Brown           returned by DMCreateInterpolation()
59447c6ae99SBarry Smith 
595d083f849SBarry Smith    Logically Collective on da
59647c6ae99SBarry Smith 
597d8d19677SJose E. Roman    Input Parameters:
59847c6ae99SBarry Smith +  da - initial distributed array
599a2b725a8SWilliam Gropp -  ctype - DMDA_Q1 and DMDA_Q0 are currently the only supported forms
60047c6ae99SBarry Smith 
60147c6ae99SBarry Smith    Level: intermediate
60247c6ae99SBarry Smith 
60395452b02SPatrick Sanan    Notes:
60495452b02SPatrick Sanan     you should call this on the coarser of the two DMDAs you pass to DMCreateInterpolation()
60547c6ae99SBarry Smith 
60696e147daSBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType
60747c6ae99SBarry Smith @*/
6087087cfbeSBarry Smith PetscErrorCode  DMDASetInterpolationType(DM da,DMDAInterpolationType ctype)
60947c6ae99SBarry Smith {
61047c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
61147c6ae99SBarry Smith 
61247c6ae99SBarry Smith   PetscFunctionBegin;
613a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
61447c6ae99SBarry Smith   PetscValidLogicalCollectiveEnum(da,ctype,2);
61547c6ae99SBarry Smith   dd->interptype = ctype;
61647c6ae99SBarry Smith   PetscFunctionReturn(0);
61747c6ae99SBarry Smith }
61847c6ae99SBarry Smith 
6192dde6fd4SLisandro Dalcin /*@
6202dde6fd4SLisandro Dalcin        DMDAGetInterpolationType - Gets the type of interpolation that will be
621e727c939SJed Brown           used by DMCreateInterpolation()
6222dde6fd4SLisandro Dalcin 
6232dde6fd4SLisandro Dalcin    Not Collective
6242dde6fd4SLisandro Dalcin 
6252dde6fd4SLisandro Dalcin    Input Parameter:
6262dde6fd4SLisandro Dalcin .  da - distributed array
6272dde6fd4SLisandro Dalcin 
6282dde6fd4SLisandro Dalcin    Output Parameter:
6292dde6fd4SLisandro Dalcin .  ctype - interpolation type (DMDA_Q1 and DMDA_Q0 are currently the only supported forms)
6302dde6fd4SLisandro Dalcin 
6312dde6fd4SLisandro Dalcin    Level: intermediate
6322dde6fd4SLisandro Dalcin 
633e727c939SJed Brown .seealso: DMDA, DMDAInterpolationType, DMDASetInterpolationType(), DMCreateInterpolation()
6342dde6fd4SLisandro Dalcin @*/
6352dde6fd4SLisandro Dalcin PetscErrorCode  DMDAGetInterpolationType(DM da,DMDAInterpolationType *ctype)
6362dde6fd4SLisandro Dalcin {
6372dde6fd4SLisandro Dalcin   DM_DA *dd = (DM_DA*)da->data;
6382dde6fd4SLisandro Dalcin 
6392dde6fd4SLisandro Dalcin   PetscFunctionBegin;
640a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
6412dde6fd4SLisandro Dalcin   PetscValidPointer(ctype,2);
6422dde6fd4SLisandro Dalcin   *ctype = dd->interptype;
6432dde6fd4SLisandro Dalcin   PetscFunctionReturn(0);
6442dde6fd4SLisandro Dalcin }
64547c6ae99SBarry Smith 
6466a119db4SBarry Smith /*@C
647aa219208SBarry Smith       DMDAGetNeighbors - Gets an array containing the MPI rank of all the current
64847c6ae99SBarry Smith         processes neighbors.
64947c6ae99SBarry Smith 
65047c6ae99SBarry Smith     Not Collective
65147c6ae99SBarry Smith 
65247c6ae99SBarry Smith    Input Parameter:
653aa219208SBarry Smith .     da - the DMDA object
65447c6ae99SBarry Smith 
65547c6ae99SBarry Smith    Output Parameters:
65647c6ae99SBarry Smith .     ranks - the neighbors ranks, stored with the x index increasing most rapidly.
65747c6ae99SBarry Smith               this process itself is in the list
65847c6ae99SBarry Smith 
65995452b02SPatrick Sanan    Notes:
66095452b02SPatrick Sanan     In 2d the array is of length 9, in 3d of length 27
66147c6ae99SBarry Smith           Not supported in 1d
662aa219208SBarry Smith           Do not free the array, it is freed when the DMDA is destroyed.
66347c6ae99SBarry Smith 
66495452b02SPatrick Sanan    Fortran Notes:
66595452b02SPatrick Sanan     In fortran you must pass in an array of the appropriate length.
66647c6ae99SBarry Smith 
66747c6ae99SBarry Smith    Level: intermediate
66847c6ae99SBarry Smith 
66947c6ae99SBarry Smith @*/
6707087cfbeSBarry Smith PetscErrorCode  DMDAGetNeighbors(DM da,const PetscMPIInt *ranks[])
67147c6ae99SBarry Smith {
67247c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
6735fd66863SKarl Rupp 
67447c6ae99SBarry Smith   PetscFunctionBegin;
675a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
67647c6ae99SBarry Smith   *ranks = dd->neighbors;
67747c6ae99SBarry Smith   PetscFunctionReturn(0);
67847c6ae99SBarry Smith }
67947c6ae99SBarry Smith 
68047c6ae99SBarry Smith /*@C
681aa219208SBarry Smith       DMDAGetOwnershipRanges - Gets the ranges of indices in the x, y and z direction that are owned by each process
68247c6ae99SBarry Smith 
68347c6ae99SBarry Smith     Not Collective
68447c6ae99SBarry Smith 
68547c6ae99SBarry Smith    Input Parameter:
686aa219208SBarry Smith .     da - the DMDA object
68747c6ae99SBarry Smith 
688d8d19677SJose E. Roman    Output Parameters:
68947c6ae99SBarry Smith +     lx - ownership along x direction (optional)
69047c6ae99SBarry Smith .     ly - ownership along y direction (optional)
69147c6ae99SBarry Smith -     lz - ownership along z direction (optional)
69247c6ae99SBarry Smith 
69347c6ae99SBarry Smith    Level: intermediate
69447c6ae99SBarry Smith 
695aa219208SBarry Smith     Note: these correspond to the optional final arguments passed to DMDACreate(), DMDACreate2d(), DMDACreate3d()
69647c6ae99SBarry Smith 
69747c6ae99SBarry Smith     In Fortran one must pass in arrays lx, ly, and lz that are long enough to hold the values; the sixth, seventh and
698aa219208SBarry Smith     eighth arguments from DMDAGetInfo()
69947c6ae99SBarry Smith 
70047c6ae99SBarry Smith      In C you should not free these arrays, nor change the values in them. They will only have valid values while the
701aa219208SBarry Smith     DMDA they came from still exists (has not been destroyed).
70247c6ae99SBarry Smith 
703e3f3e4b6SBarry Smith     These numbers are NOT multiplied by the number of dof per node.
704e3f3e4b6SBarry Smith 
705aa219208SBarry Smith .seealso: DMDAGetCorners(), DMDAGetGhostCorners(), DMDACreate(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), VecGetOwnershipRanges()
70647c6ae99SBarry Smith @*/
7077087cfbeSBarry Smith PetscErrorCode  DMDAGetOwnershipRanges(DM da,const PetscInt *lx[],const PetscInt *ly[],const PetscInt *lz[])
70847c6ae99SBarry Smith {
70947c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
71047c6ae99SBarry Smith 
71147c6ae99SBarry Smith   PetscFunctionBegin;
712a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
71347c6ae99SBarry Smith   if (lx) *lx = dd->lx;
71447c6ae99SBarry Smith   if (ly) *ly = dd->ly;
71547c6ae99SBarry Smith   if (lz) *lz = dd->lz;
71647c6ae99SBarry Smith   PetscFunctionReturn(0);
71747c6ae99SBarry Smith }
71847c6ae99SBarry Smith 
71947c6ae99SBarry Smith /*@
720aa219208SBarry Smith      DMDASetRefinementFactor - Set the ratios that the DMDA grid is refined
72147c6ae99SBarry Smith 
722d083f849SBarry Smith     Logically Collective on da
72347c6ae99SBarry Smith 
72447c6ae99SBarry Smith   Input Parameters:
725aa219208SBarry Smith +    da - the DMDA object
72647c6ae99SBarry Smith .    refine_x - ratio of fine grid to coarse in x direction (2 by default)
72747c6ae99SBarry Smith .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
72847c6ae99SBarry Smith -    refine_z - ratio of fine grid to coarse in z direction (2 by default)
72947c6ae99SBarry Smith 
73047c6ae99SBarry Smith   Options Database:
73148eeb7c8SBarry Smith +  -da_refine_x refine_x - refinement ratio in x direction
73248eeb7c8SBarry Smith .  -da_refine_y rafine_y - refinement ratio in y direction
73348eeb7c8SBarry Smith .  -da_refine_z refine_z - refinement ratio in z direction
73448eeb7c8SBarry Smith -  -da_refine <n> - refine the DMDA object n times when it is created.
73547c6ae99SBarry Smith 
73647c6ae99SBarry Smith   Level: intermediate
73747c6ae99SBarry Smith 
73895452b02SPatrick Sanan     Notes:
73995452b02SPatrick Sanan     Pass PETSC_IGNORE to leave a value unchanged
74047c6ae99SBarry Smith 
741aa219208SBarry Smith .seealso: DMRefine(), DMDAGetRefinementFactor()
74247c6ae99SBarry Smith @*/
7437087cfbeSBarry Smith PetscErrorCode  DMDASetRefinementFactor(DM da, PetscInt refine_x, PetscInt refine_y,PetscInt refine_z)
74447c6ae99SBarry Smith {
74547c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
74647c6ae99SBarry Smith 
74747c6ae99SBarry Smith   PetscFunctionBegin;
748a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
74947c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_x,2);
75047c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_y,3);
75147c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_z,4);
75247c6ae99SBarry Smith 
75347c6ae99SBarry Smith   if (refine_x > 0) dd->refine_x = refine_x;
75447c6ae99SBarry Smith   if (refine_y > 0) dd->refine_y = refine_y;
75547c6ae99SBarry Smith   if (refine_z > 0) dd->refine_z = refine_z;
75647c6ae99SBarry Smith   PetscFunctionReturn(0);
75747c6ae99SBarry Smith }
75847c6ae99SBarry Smith 
75947c6ae99SBarry Smith /*@C
760aa219208SBarry Smith      DMDAGetRefinementFactor - Gets the ratios that the DMDA grid is refined
76147c6ae99SBarry Smith 
76247c6ae99SBarry Smith     Not Collective
76347c6ae99SBarry Smith 
76447c6ae99SBarry Smith   Input Parameter:
765aa219208SBarry Smith .    da - the DMDA object
76647c6ae99SBarry Smith 
76747c6ae99SBarry Smith   Output Parameters:
76847c6ae99SBarry Smith +    refine_x - ratio of fine grid to coarse in x direction (2 by default)
76947c6ae99SBarry Smith .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
77047c6ae99SBarry Smith -    refine_z - ratio of fine grid to coarse in z direction (2 by default)
77147c6ae99SBarry Smith 
77247c6ae99SBarry Smith   Level: intermediate
77347c6ae99SBarry Smith 
77495452b02SPatrick Sanan     Notes:
77595452b02SPatrick Sanan     Pass NULL for values you do not need
77647c6ae99SBarry Smith 
777aa219208SBarry Smith .seealso: DMRefine(), DMDASetRefinementFactor()
77847c6ae99SBarry Smith @*/
7797087cfbeSBarry Smith PetscErrorCode  DMDAGetRefinementFactor(DM da, PetscInt *refine_x, PetscInt *refine_y,PetscInt *refine_z)
78047c6ae99SBarry Smith {
78147c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
78247c6ae99SBarry Smith 
78347c6ae99SBarry Smith   PetscFunctionBegin;
784a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
78547c6ae99SBarry Smith   if (refine_x) *refine_x = dd->refine_x;
78647c6ae99SBarry Smith   if (refine_y) *refine_y = dd->refine_y;
78747c6ae99SBarry Smith   if (refine_z) *refine_z = dd->refine_z;
78847c6ae99SBarry Smith   PetscFunctionReturn(0);
78947c6ae99SBarry Smith }
79047c6ae99SBarry Smith 
79147c6ae99SBarry Smith /*@C
792aa219208SBarry Smith      DMDASetGetMatrix - Sets the routine used by the DMDA to allocate a matrix.
79347c6ae99SBarry Smith 
794d083f849SBarry Smith     Logically Collective on da
79547c6ae99SBarry Smith 
79647c6ae99SBarry Smith   Input Parameters:
797aa219208SBarry Smith +    da - the DMDA object
798aa219208SBarry Smith -    f - the function that allocates the matrix for that specific DMDA
79947c6ae99SBarry Smith 
80047c6ae99SBarry Smith   Level: developer
80147c6ae99SBarry Smith 
80295452b02SPatrick Sanan    Notes:
80395452b02SPatrick Sanan     See DMDASetBlockFills() that provides a simple way to provide the nonzero structure for
80447c6ae99SBarry Smith        the diagonal and off-diagonal blocks of the matrix
80547c6ae99SBarry Smith 
8061fd49c25SBarry Smith    Not supported from Fortran
8071fd49c25SBarry Smith 
808950540a4SJed Brown .seealso: DMCreateMatrix(), DMDASetBlockFills()
80947c6ae99SBarry Smith @*/
810b412c318SBarry Smith PetscErrorCode  DMDASetGetMatrix(DM da,PetscErrorCode (*f)(DM, Mat*))
81147c6ae99SBarry Smith {
81247c6ae99SBarry Smith   PetscFunctionBegin;
813a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
81425296bd5SBarry Smith   da->ops->creatematrix = f;
81547c6ae99SBarry Smith   PetscFunctionReturn(0);
81647c6ae99SBarry Smith }
81747c6ae99SBarry Smith 
81847c6ae99SBarry Smith /*
81947c6ae99SBarry Smith   Creates "balanced" ownership ranges after refinement, constrained by the need for the
82047c6ae99SBarry Smith   fine grid boundaries to fall within one stencil width of the coarse partition.
82147c6ae99SBarry Smith 
82247c6ae99SBarry Smith   Uses a greedy algorithm to handle non-ideal layouts, could probably do something better.
82347c6ae99SBarry Smith */
82494013140SBarry Smith static PetscErrorCode DMDARefineOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lc[],PetscInt lf[])
82547c6ae99SBarry Smith {
82647c6ae99SBarry Smith   PetscInt       i,totalc = 0,remaining,startc = 0,startf = 0;
82747c6ae99SBarry Smith 
82847c6ae99SBarry Smith   PetscFunctionBegin;
8297a8be351SBarry Smith   PetscCheck(ratio >= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Requested refinement ratio %D must be at least 1",ratio);
83047c6ae99SBarry Smith   if (ratio == 1) {
831*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(lf,lc,m));
83247c6ae99SBarry Smith     PetscFunctionReturn(0);
83347c6ae99SBarry Smith   }
83447c6ae99SBarry Smith   for (i=0; i<m; i++) totalc += lc[i];
83547c6ae99SBarry Smith   remaining = (!periodic) + ratio * (totalc - (!periodic));
83647c6ae99SBarry Smith   for (i=0; i<m; i++) {
83747c6ae99SBarry Smith     PetscInt want = remaining/(m-i) + !!(remaining%(m-i));
83847c6ae99SBarry Smith     if (i == m-1) lf[i] = want;
83947c6ae99SBarry Smith     else {
8407aca7175SJed Brown       const PetscInt nextc = startc + lc[i];
8417aca7175SJed Brown       /* Move the first fine node of the next subdomain to the right until the coarse node on its left is within one
8427aca7175SJed Brown        * coarse stencil width of the first coarse node in the next subdomain. */
8437aca7175SJed Brown       while ((startf+want)/ratio < nextc - stencil_width) want++;
8447aca7175SJed Brown       /* Move the last fine node in the current subdomain to the left until the coarse node on its right is within one
8457aca7175SJed Brown        * coarse stencil width of the last coarse node in the current subdomain. */
8467aca7175SJed Brown       while ((startf+want-1+ratio-1)/ratio > nextc-1+stencil_width) want--;
8477aca7175SJed Brown       /* Make sure all constraints are satisfied */
84830729d88SBarry Smith       if (want < 0 || want > remaining || ((startf+want)/ratio < nextc - stencil_width)
849ce94432eSBarry Smith           || ((startf+want-1+ratio-1)/ratio > nextc-1+stencil_width)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Could not find a compatible refined ownership range");
85047c6ae99SBarry Smith     }
85147c6ae99SBarry Smith     lf[i]      = want;
85247c6ae99SBarry Smith     startc    += lc[i];
85347c6ae99SBarry Smith     startf    += lf[i];
85447c6ae99SBarry Smith     remaining -= lf[i];
85547c6ae99SBarry Smith   }
85647c6ae99SBarry Smith   PetscFunctionReturn(0);
85747c6ae99SBarry Smith }
85847c6ae99SBarry Smith 
8592be375d4SJed Brown /*
8602be375d4SJed Brown   Creates "balanced" ownership ranges after coarsening, constrained by the need for the
8612be375d4SJed Brown   fine grid boundaries to fall within one stencil width of the coarse partition.
8622be375d4SJed Brown 
8632be375d4SJed Brown   Uses a greedy algorithm to handle non-ideal layouts, could probably do something better.
8642be375d4SJed Brown */
8652be375d4SJed Brown static PetscErrorCode DMDACoarsenOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lf[],PetscInt lc[])
8662be375d4SJed Brown {
8672be375d4SJed Brown   PetscInt       i,totalf,remaining,startc,startf;
8682be375d4SJed Brown 
8692be375d4SJed Brown   PetscFunctionBegin;
8707a8be351SBarry Smith   PetscCheck(ratio >= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Requested refinement ratio %D must be at least 1",ratio);
8712be375d4SJed Brown   if (ratio == 1) {
872*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(lc,lf,m));
8732be375d4SJed Brown     PetscFunctionReturn(0);
8742be375d4SJed Brown   }
8752be375d4SJed Brown   for (i=0,totalf=0; i<m; i++) totalf += lf[i];
8762be375d4SJed Brown   remaining = (!periodic) + (totalf - (!periodic)) / ratio;
8772be375d4SJed Brown   for (i=0,startc=0,startf=0; i<m; i++) {
8782be375d4SJed Brown     PetscInt want = remaining/(m-i) + !!(remaining%(m-i));
8792be375d4SJed Brown     if (i == m-1) lc[i] = want;
8802be375d4SJed Brown     else {
8812be375d4SJed Brown       const PetscInt nextf = startf+lf[i];
8822be375d4SJed Brown       /* Slide first coarse node of next subdomain to the left until the coarse node to the left of the first fine
8832be375d4SJed Brown        * node is within one stencil width. */
8842be375d4SJed Brown       while (nextf/ratio < startc+want-stencil_width) want--;
8852be375d4SJed Brown       /* Slide the last coarse node of the current subdomain to the right until the coarse node to the right of the last
8862be375d4SJed Brown        * fine node is within one stencil width. */
8872be375d4SJed Brown       while ((nextf-1+ratio-1)/ratio > startc+want-1+stencil_width) want++;
8882be375d4SJed Brown       if (want < 0 || want > remaining
889ce94432eSBarry Smith           || (nextf/ratio < startc+want-stencil_width) || ((nextf-1+ratio-1)/ratio > startc+want-1+stencil_width)) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Could not find a compatible coarsened ownership range");
8902be375d4SJed Brown     }
8912be375d4SJed Brown     lc[i]      = want;
8922be375d4SJed Brown     startc    += lc[i];
8932be375d4SJed Brown     startf    += lf[i];
8942be375d4SJed Brown     remaining -= lc[i];
8952be375d4SJed Brown   }
8962be375d4SJed Brown   PetscFunctionReturn(0);
8972be375d4SJed Brown }
8982be375d4SJed Brown 
8997087cfbeSBarry Smith PetscErrorCode  DMRefine_DA(DM da,MPI_Comm comm,DM *daref)
90047c6ae99SBarry Smith {
901c73cfb54SMatthew G. Knepley   PetscInt       M,N,P,i,dim;
9029a42bb27SBarry Smith   DM             da2;
90347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data,*dd2;
90447c6ae99SBarry Smith 
90547c6ae99SBarry Smith   PetscFunctionBegin;
906a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
90747c6ae99SBarry Smith   PetscValidPointer(daref,3);
90847c6ae99SBarry Smith 
909*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(da, &dim));
910bff4a2f0SMatthew G. Knepley   if (dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
91147c6ae99SBarry Smith     M = dd->refine_x*dd->M;
91247c6ae99SBarry Smith   } else {
91347c6ae99SBarry Smith     M = 1 + dd->refine_x*(dd->M - 1);
91447c6ae99SBarry Smith   }
915bff4a2f0SMatthew G. Knepley   if (dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
916c73cfb54SMatthew G. Knepley     if (dim > 1) {
91747c6ae99SBarry Smith       N = dd->refine_y*dd->N;
91847c6ae99SBarry Smith     } else {
9191860e6e9SBarry Smith       N = 1;
9201860e6e9SBarry Smith     }
9211860e6e9SBarry Smith   } else {
92247c6ae99SBarry Smith     N = 1 + dd->refine_y*(dd->N - 1);
92347c6ae99SBarry Smith   }
924bff4a2f0SMatthew G. Knepley   if (dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
925c73cfb54SMatthew G. Knepley     if (dim > 2) {
92647c6ae99SBarry Smith       P = dd->refine_z*dd->P;
92747c6ae99SBarry Smith     } else {
9281860e6e9SBarry Smith       P = 1;
9291860e6e9SBarry Smith     }
9301860e6e9SBarry Smith   } else {
93147c6ae99SBarry Smith     P = 1 + dd->refine_z*(dd->P - 1);
93247c6ae99SBarry Smith   }
933*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDACreate(PetscObjectComm((PetscObject)da),&da2));
934*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetOptionsPrefix(da2,((PetscObject)da)->prefix));
935*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(da2,dim));
936*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetSizes(da2,M,N,P));
937*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetNumProcs(da2,dd->m,dd->n,dd->p));
938*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetBoundaryType(da2,dd->bx,dd->by,dd->bz));
939*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetDof(da2,dd->w));
940*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetStencilType(da2,dd->stencil_type));
941*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetStencilWidth(da2,dd->s));
942c73cfb54SMatthew G. Knepley   if (dim == 3) {
94347c6ae99SBarry Smith     PetscInt *lx,*ly,*lz;
944*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc3(dd->m,&lx,dd->n,&ly,dd->p,&lz));
945*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx));
946*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDARefineOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly));
947*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz));
948*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOwnershipRanges(da2,lx,ly,lz));
949*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree3(lx,ly,lz));
950c73cfb54SMatthew G. Knepley   } else if (dim == 2) {
95147c6ae99SBarry Smith     PetscInt *lx,*ly;
952*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(dd->m,&lx,dd->n,&ly));
953*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx));
954*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDARefineOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly));
955*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOwnershipRanges(da2,lx,ly,NULL));
956*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(lx,ly));
957c73cfb54SMatthew G. Knepley   } else if (dim == 1) {
95847c6ae99SBarry Smith     PetscInt *lx;
959*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd->m,&lx));
960*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx));
961*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOwnershipRanges(da2,lx,NULL,NULL));
962*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(lx));
96347c6ae99SBarry Smith   }
96447c6ae99SBarry Smith   dd2 = (DM_DA*)da2->data;
96547c6ae99SBarry Smith 
96647c6ae99SBarry Smith   /* allow overloaded (user replaced) operations to be inherited by refinement clones */
96725296bd5SBarry Smith   da2->ops->creatematrix = da->ops->creatematrix;
96825296bd5SBarry Smith   /* da2->ops->createinterpolation = da->ops->createinterpolation; this causes problem with SNESVI */
96947c6ae99SBarry Smith   da2->ops->getcoloring = da->ops->getcoloring;
97047c6ae99SBarry Smith   dd2->interptype       = dd->interptype;
97147c6ae99SBarry Smith 
97247c6ae99SBarry Smith   /* copy fill information if given */
97347c6ae99SBarry Smith   if (dd->dfill) {
974*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd->dfill[dd->w]+dd->w+1,&dd2->dfill));
975*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->dfill,dd->dfill,dd->dfill[dd->w]+dd->w+1));
97647c6ae99SBarry Smith   }
97747c6ae99SBarry Smith   if (dd->ofill) {
978*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd->ofill[dd->w]+dd->w+1,&dd2->ofill));
979*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->ofill,dd->ofill,dd->ofill[dd->w]+dd->w+1));
98047c6ae99SBarry Smith   }
98147c6ae99SBarry Smith   /* copy the refine information */
982397b6216SJed Brown   dd2->coarsen_x = dd2->refine_x = dd->refine_x;
983397b6216SJed Brown   dd2->coarsen_y = dd2->refine_y = dd->refine_y;
984397b6216SJed Brown   dd2->coarsen_z = dd2->refine_z = dd->refine_z;
98547c6ae99SBarry Smith 
986897f7067SBarry Smith   if (dd->refine_z_hier) {
987897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_z_hier_n) {
988897f7067SBarry Smith       dd2->refine_z = dd->refine_z_hier[da->levelup - da->leveldown + 1];
989897f7067SBarry Smith     }
990897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_z_hier_n) {
991897f7067SBarry Smith       dd2->coarsen_z = dd->refine_z_hier[da->levelup - da->leveldown];
992897f7067SBarry Smith     }
993897f7067SBarry Smith     dd2->refine_z_hier_n = dd->refine_z_hier_n;
994*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd2->refine_z_hier_n,&dd2->refine_z_hier));
995*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->refine_z_hier,dd->refine_z_hier,dd2->refine_z_hier_n));
996897f7067SBarry Smith   }
997897f7067SBarry Smith   if (dd->refine_y_hier) {
998897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_y_hier_n) {
999897f7067SBarry Smith       dd2->refine_y = dd->refine_y_hier[da->levelup - da->leveldown + 1];
1000897f7067SBarry Smith     }
1001897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_y_hier_n) {
1002897f7067SBarry Smith       dd2->coarsen_y = dd->refine_y_hier[da->levelup - da->leveldown];
1003897f7067SBarry Smith     }
1004897f7067SBarry Smith     dd2->refine_y_hier_n = dd->refine_y_hier_n;
1005*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd2->refine_y_hier_n,&dd2->refine_y_hier));
1006*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->refine_y_hier,dd->refine_y_hier,dd2->refine_y_hier_n));
1007897f7067SBarry Smith   }
1008897f7067SBarry Smith   if (dd->refine_x_hier) {
1009897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_x_hier_n) {
1010897f7067SBarry Smith       dd2->refine_x = dd->refine_x_hier[da->levelup - da->leveldown + 1];
1011897f7067SBarry Smith     }
1012897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_x_hier_n) {
1013897f7067SBarry Smith       dd2->coarsen_x = dd->refine_x_hier[da->levelup - da->leveldown];
1014897f7067SBarry Smith     }
1015897f7067SBarry Smith     dd2->refine_x_hier_n = dd->refine_x_hier_n;
1016*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd2->refine_x_hier_n,&dd2->refine_x_hier));
1017*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->refine_x_hier,dd->refine_x_hier,dd2->refine_x_hier_n));
1018897f7067SBarry Smith   }
1019897f7067SBarry Smith 
102047c6ae99SBarry Smith   /* copy vector type information */
1021*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetVecType(da2,da->vectype));
1022ddcf8b74SDave May 
1023efd51863SBarry Smith   dd2->lf = dd->lf;
1024efd51863SBarry Smith   dd2->lj = dd->lj;
1025efd51863SBarry Smith 
10266e87535bSJed Brown   da2->leveldown = da->leveldown;
10276e87535bSJed Brown   da2->levelup   = da->levelup + 1;
10288865f1eaSKarl Rupp 
1029*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(da2));
10306e87535bSJed Brown 
1031ddcf8b74SDave May   /* interpolate coordinates if they are set on the coarse grid */
10326636e97aSMatthew G Knepley   if (da->coordinates) {
1033ddcf8b74SDave May     DM  cdaf,cdac;
1034ddcf8b74SDave May     Vec coordsc,coordsf;
1035ddcf8b74SDave May     Mat II;
1036ddcf8b74SDave May 
1037*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(da,&cdac));
1038*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(da,&coordsc));
1039*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(da2,&cdaf));
1040b61d3410SDave May     /* force creation of the coordinate vector */
1041*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetUniformCoordinates(da2,0.0,1.0,0.0,1.0,0.0,1.0));
1042*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(da2,&coordsf));
1043*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateInterpolation(cdac,cdaf,&II,NULL));
1044*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatInterpolate(II,coordsc,coordsf));
1045*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&II));
1046ddcf8b74SDave May   }
1047397b6216SJed Brown 
1048f3141302SJed Brown   for (i=0; i<da->bs; i++) {
1049f3141302SJed Brown     const char *fieldname;
1050*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetFieldName(da,i,&fieldname));
1051*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetFieldName(da2,i,fieldname));
1052f3141302SJed Brown   }
1053397b6216SJed Brown 
105447c6ae99SBarry Smith   *daref = da2;
105547c6ae99SBarry Smith   PetscFunctionReturn(0);
105647c6ae99SBarry Smith }
105747c6ae99SBarry Smith 
1058a5bc1bf3SBarry Smith PetscErrorCode  DMCoarsen_DA(DM dmf, MPI_Comm comm,DM *dmc)
105947c6ae99SBarry Smith {
1060c73cfb54SMatthew G. Knepley   PetscInt       M,N,P,i,dim;
1061a5bc1bf3SBarry Smith   DM             dmc2;
1062a5bc1bf3SBarry Smith   DM_DA          *dd = (DM_DA*)dmf->data,*dd2;
106347c6ae99SBarry Smith 
106447c6ae99SBarry Smith   PetscFunctionBegin;
1065a5bc1bf3SBarry Smith   PetscValidHeaderSpecificType(dmf,DM_CLASSID,1,DMDA);
1066a5bc1bf3SBarry Smith   PetscValidPointer(dmc,3);
106747c6ae99SBarry Smith 
1068*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dmf, &dim));
1069bff4a2f0SMatthew G. Knepley   if (dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1070397b6216SJed Brown     M = dd->M / dd->coarsen_x;
107147c6ae99SBarry Smith   } else {
1072397b6216SJed Brown     M = 1 + (dd->M - 1) / dd->coarsen_x;
107347c6ae99SBarry Smith   }
1074bff4a2f0SMatthew G. Knepley   if (dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1075c73cfb54SMatthew G. Knepley     if (dim > 1) {
1076397b6216SJed Brown       N = dd->N / dd->coarsen_y;
107747c6ae99SBarry Smith     } else {
10781860e6e9SBarry Smith       N = 1;
10791860e6e9SBarry Smith     }
10801860e6e9SBarry Smith   } else {
1081397b6216SJed Brown     N = 1 + (dd->N - 1) / dd->coarsen_y;
108247c6ae99SBarry Smith   }
1083bff4a2f0SMatthew G. Knepley   if (dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1084c73cfb54SMatthew G. Knepley     if (dim > 2) {
1085397b6216SJed Brown       P = dd->P / dd->coarsen_z;
108647c6ae99SBarry Smith     } else {
10871860e6e9SBarry Smith       P = 1;
10881860e6e9SBarry Smith     }
10891860e6e9SBarry Smith   } else {
1090397b6216SJed Brown     P = 1 + (dd->P - 1) / dd->coarsen_z;
109147c6ae99SBarry Smith   }
1092*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDACreate(PetscObjectComm((PetscObject)dmf),&dmc2));
1093*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetOptionsPrefix(dmc2,((PetscObject)dmf)->prefix));
1094*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDimension(dmc2,dim));
1095*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetSizes(dmc2,M,N,P));
1096*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetNumProcs(dmc2,dd->m,dd->n,dd->p));
1097*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetBoundaryType(dmc2,dd->bx,dd->by,dd->bz));
1098*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetDof(dmc2,dd->w));
1099*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetStencilType(dmc2,dd->stencil_type));
1100*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetStencilWidth(dmc2,dd->s));
1101c73cfb54SMatthew G. Knepley   if (dim == 3) {
11022be375d4SJed Brown     PetscInt *lx,*ly,*lz;
1103*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc3(dd->m,&lx,dd->n,&ly,dd->p,&lz));
1104*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx));
1105*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_y,dd->n,dd->ly,ly));
1106*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_z,dd->p,dd->lz,lz));
1107*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOwnershipRanges(dmc2,lx,ly,lz));
1108*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree3(lx,ly,lz));
1109c73cfb54SMatthew G. Knepley   } else if (dim == 2) {
11102be375d4SJed Brown     PetscInt *lx,*ly;
1111*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(dd->m,&lx,dd->n,&ly));
1112*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx));
1113*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_y,dd->n,dd->ly,ly));
1114*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOwnershipRanges(dmc2,lx,ly,NULL));
1115*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(lx,ly));
1116c73cfb54SMatthew G. Knepley   } else if (dim == 1) {
11172be375d4SJed Brown     PetscInt *lx;
1118*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd->m,&lx));
1119*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx));
1120*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOwnershipRanges(dmc2,lx,NULL,NULL));
1121*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(lx));
112247c6ae99SBarry Smith   }
1123a5bc1bf3SBarry Smith   dd2 = (DM_DA*)dmc2->data;
112447c6ae99SBarry Smith 
11254dcab191SBarry Smith   /* allow overloaded (user replaced) operations to be inherited by refinement clones; why are only some inherited and not all? */
1126a5bc1bf3SBarry Smith   /* dmc2->ops->createinterpolation = dmf->ops->createinterpolation; copying this one causes trouble for DMSetVI */
1127a5bc1bf3SBarry Smith   dmc2->ops->creatematrix = dmf->ops->creatematrix;
1128a5bc1bf3SBarry Smith   dmc2->ops->getcoloring  = dmf->ops->getcoloring;
112947c6ae99SBarry Smith   dd2->interptype         = dd->interptype;
113047c6ae99SBarry Smith 
113147c6ae99SBarry Smith   /* copy fill information if given */
113247c6ae99SBarry Smith   if (dd->dfill) {
1133*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd->dfill[dd->w]+dd->w+1,&dd2->dfill));
1134*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->dfill,dd->dfill,dd->dfill[dd->w]+dd->w+1));
113547c6ae99SBarry Smith   }
113647c6ae99SBarry Smith   if (dd->ofill) {
1137*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd->ofill[dd->w]+dd->w+1,&dd2->ofill));
1138*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->ofill,dd->ofill,dd->ofill[dd->w]+dd->w+1));
113947c6ae99SBarry Smith   }
114047c6ae99SBarry Smith   /* copy the refine information */
1141397b6216SJed Brown   dd2->coarsen_x = dd2->refine_x = dd->coarsen_x;
1142397b6216SJed Brown   dd2->coarsen_y = dd2->refine_y = dd->coarsen_y;
1143397b6216SJed Brown   dd2->coarsen_z = dd2->refine_z = dd->coarsen_z;
114447c6ae99SBarry Smith 
1145897f7067SBarry Smith   if (dd->refine_z_hier) {
1146a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown -1 > -1 && dmf->levelup - dmf->leveldown - 1< dd->refine_z_hier_n) {
1147a5bc1bf3SBarry Smith       dd2->refine_z = dd->refine_z_hier[dmf->levelup - dmf->leveldown - 1];
1148897f7067SBarry Smith     }
1149a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 2 > -1 && dmf->levelup - dmf->leveldown - 2 < dd->refine_z_hier_n) {
1150a5bc1bf3SBarry Smith       dd2->coarsen_z = dd->refine_z_hier[dmf->levelup - dmf->leveldown - 2];
1151897f7067SBarry Smith     }
1152897f7067SBarry Smith     dd2->refine_z_hier_n = dd->refine_z_hier_n;
1153*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd2->refine_z_hier_n,&dd2->refine_z_hier));
1154*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->refine_z_hier,dd->refine_z_hier,dd2->refine_z_hier_n));
1155897f7067SBarry Smith   }
1156897f7067SBarry Smith   if (dd->refine_y_hier) {
1157a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 1 > -1 && dmf->levelup - dmf->leveldown - 1< dd->refine_y_hier_n) {
1158a5bc1bf3SBarry Smith       dd2->refine_y = dd->refine_y_hier[dmf->levelup - dmf->leveldown - 1];
1159897f7067SBarry Smith     }
1160a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 2 > -1 && dmf->levelup - dmf->leveldown - 2 < dd->refine_y_hier_n) {
1161a5bc1bf3SBarry Smith       dd2->coarsen_y = dd->refine_y_hier[dmf->levelup - dmf->leveldown - 2];
1162897f7067SBarry Smith     }
1163897f7067SBarry Smith     dd2->refine_y_hier_n = dd->refine_y_hier_n;
1164*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd2->refine_y_hier_n,&dd2->refine_y_hier));
1165*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->refine_y_hier,dd->refine_y_hier,dd2->refine_y_hier_n));
1166897f7067SBarry Smith   }
1167897f7067SBarry Smith   if (dd->refine_x_hier) {
1168a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 1 > -1 && dmf->levelup - dmf->leveldown - 1 < dd->refine_x_hier_n) {
1169a5bc1bf3SBarry Smith       dd2->refine_x = dd->refine_x_hier[dmf->levelup - dmf->leveldown - 1];
1170897f7067SBarry Smith     }
1171a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 2 > -1 && dmf->levelup - dmf->leveldown - 2 < dd->refine_x_hier_n) {
1172a5bc1bf3SBarry Smith       dd2->coarsen_x = dd->refine_x_hier[dmf->levelup - dmf->leveldown - 2];
1173897f7067SBarry Smith     }
1174897f7067SBarry Smith     dd2->refine_x_hier_n = dd->refine_x_hier_n;
1175*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(dd2->refine_x_hier_n,&dd2->refine_x_hier));
1176*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(dd2->refine_x_hier,dd->refine_x_hier,dd2->refine_x_hier_n));
1177897f7067SBarry Smith   }
1178897f7067SBarry Smith 
117947c6ae99SBarry Smith   /* copy vector type information */
1180*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetVecType(dmc2,dmf->vectype));
118147c6ae99SBarry Smith 
1182644e2e5bSBarry Smith   dd2->lf = dd->lf;
1183644e2e5bSBarry Smith   dd2->lj = dd->lj;
1184644e2e5bSBarry Smith 
1185a5bc1bf3SBarry Smith   dmc2->leveldown = dmf->leveldown + 1;
1186a5bc1bf3SBarry Smith   dmc2->levelup   = dmf->levelup;
11878865f1eaSKarl Rupp 
1188*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(dmc2));
11896e87535bSJed Brown 
1190ddcf8b74SDave May   /* inject coordinates if they are set on the fine grid */
1191a5bc1bf3SBarry Smith   if (dmf->coordinates) {
1192ddcf8b74SDave May     DM         cdaf,cdac;
1193ddcf8b74SDave May     Vec        coordsc,coordsf;
11946dbf9973SLawrence Mitchell     Mat        inject;
11956dbf9973SLawrence Mitchell     VecScatter vscat;
1196ddcf8b74SDave May 
1197*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dmf,&cdaf));
1198*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(dmf,&coordsf));
1199*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dmc2,&cdac));
1200b61d3410SDave May     /* force creation of the coordinate vector */
1201*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetUniformCoordinates(dmc2,0.0,1.0,0.0,1.0,0.0,1.0));
1202*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(dmc2,&coordsc));
1203ddcf8b74SDave May 
1204*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateInjection(cdac,cdaf,&inject));
1205*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatScatterGetVecScatter(inject,&vscat));
1206*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(vscat,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD));
1207*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(vscat,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD));
1208*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&inject));
1209ddcf8b74SDave May   }
1210f98405f7SJed Brown 
1211a5bc1bf3SBarry Smith   for (i=0; i<dmf->bs; i++) {
1212f98405f7SJed Brown     const char *fieldname;
1213*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetFieldName(dmf,i,&fieldname));
1214*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetFieldName(dmc2,i,fieldname));
1215f98405f7SJed Brown   }
1216f98405f7SJed Brown 
1217a5bc1bf3SBarry Smith   *dmc = dmc2;
121847c6ae99SBarry Smith   PetscFunctionReturn(0);
121947c6ae99SBarry Smith }
122047c6ae99SBarry Smith 
12217087cfbeSBarry Smith PetscErrorCode  DMRefineHierarchy_DA(DM da,PetscInt nlevels,DM daf[])
122247c6ae99SBarry Smith {
122347c6ae99SBarry Smith   PetscInt       i,n,*refx,*refy,*refz;
122447c6ae99SBarry Smith 
122547c6ae99SBarry Smith   PetscFunctionBegin;
122647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
12277a8be351SBarry Smith   PetscCheck(nlevels >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
122847c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
122947c6ae99SBarry Smith   PetscValidPointer(daf,3);
123047c6ae99SBarry Smith 
1231aa219208SBarry Smith   /* Get refinement factors, defaults taken from the coarse DMDA */
1232*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc3(nlevels,&refx,nlevels,&refy,nlevels,&refz));
123347c6ae99SBarry Smith   for (i=0; i<nlevels; i++) {
1234*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]));
123547c6ae99SBarry Smith   }
123647c6ae99SBarry Smith   n    = nlevels;
1237*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,NULL));
123847c6ae99SBarry Smith   n    = nlevels;
1239*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,NULL));
124047c6ae99SBarry Smith   n    = nlevels;
1241*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,NULL));
124247c6ae99SBarry Smith 
1243*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetRefinementFactor(da,refx[0],refy[0],refz[0]));
1244*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRefine(da,PetscObjectComm((PetscObject)da),&daf[0]));
124547c6ae99SBarry Smith   for (i=1; i<nlevels; i++) {
1246*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]));
1247*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRefine(daf[i-1],PetscObjectComm((PetscObject)da),&daf[i]));
124847c6ae99SBarry Smith   }
1249*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree3(refx,refy,refz));
125047c6ae99SBarry Smith   PetscFunctionReturn(0);
125147c6ae99SBarry Smith }
125247c6ae99SBarry Smith 
12537087cfbeSBarry Smith PetscErrorCode  DMCoarsenHierarchy_DA(DM da,PetscInt nlevels,DM dac[])
125447c6ae99SBarry Smith {
125547c6ae99SBarry Smith   PetscInt       i;
125647c6ae99SBarry Smith 
125747c6ae99SBarry Smith   PetscFunctionBegin;
125847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
12597a8be351SBarry Smith   PetscCheck(nlevels >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
126047c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
126147c6ae99SBarry Smith   PetscValidPointer(dac,3);
1262*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCoarsen(da,PetscObjectComm((PetscObject)da),&dac[0]));
126347c6ae99SBarry Smith   for (i=1; i<nlevels; i++) {
1264*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCoarsen(dac[i-1],PetscObjectComm((PetscObject)da),&dac[i]));
126547c6ae99SBarry Smith   }
126647c6ae99SBarry Smith   PetscFunctionReturn(0);
126747c6ae99SBarry Smith }
126862197512SBarry Smith 
12698272889dSSatish Balay PetscErrorCode DMDASetGLLCoordinates_1d(DM dm,PetscInt n,PetscReal *nodes)
127062197512SBarry Smith {
12718272889dSSatish Balay   PetscInt       i,j,xs,xn,q;
127262197512SBarry Smith   PetscScalar    *xx;
127362197512SBarry Smith   PetscReal      h;
127462197512SBarry Smith   Vec            x;
127562197512SBarry Smith   DM_DA          *da = (DM_DA*)dm->data;
127662197512SBarry Smith 
127762197512SBarry Smith   PetscFunctionBegin;
127862197512SBarry Smith   if (da->bx != DM_BOUNDARY_PERIODIC) {
1279*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetInfo(dm,NULL,&q,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
128062197512SBarry Smith     q    = (q-1)/(n-1);  /* number of spectral elements */
128162197512SBarry Smith     h    = 2.0/q;
1282*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetCorners(dm,&xs,NULL,NULL,&xn,NULL,NULL));
128362197512SBarry Smith     xs   = xs/(n-1);
128462197512SBarry Smith     xn   = xn/(n-1);
1285*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetUniformCoordinates(dm,-1.,1.,0.,0.,0.,0.));
1286*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(dm,&x));
1287*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAVecGetArray(dm,x,&xx));
128862197512SBarry Smith 
128962197512SBarry Smith     /* loop over local spectral elements */
129062197512SBarry Smith     for (j=xs; j<xs+xn; j++) {
129162197512SBarry Smith       /*
129262197512SBarry Smith        Except for the first process, each process starts on the second GLL point of the first element on that process
129362197512SBarry Smith        */
129462197512SBarry Smith       for (i= (j == xs && xs > 0)? 1 : 0; i<n; i++) {
12958272889dSSatish Balay         xx[j*(n-1) + i] = -1.0 + h*j + h*(nodes[i]+1.0)/2.;
129662197512SBarry Smith       }
129762197512SBarry Smith     }
1298*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAVecRestoreArray(dm,x,&xx));
129962197512SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not yet implemented for periodic");
130062197512SBarry Smith   PetscFunctionReturn(0);
130162197512SBarry Smith }
130262197512SBarry Smith 
13031fd49c25SBarry Smith /*@
130462197512SBarry Smith 
130562197512SBarry Smith      DMDASetGLLCoordinates - Sets the global coordinates from -1 to 1 to the GLL points of as many GLL elements that fit the number of grid points
130662197512SBarry Smith 
1307d083f849SBarry Smith    Collective on da
130862197512SBarry Smith 
130962197512SBarry Smith    Input Parameters:
131062197512SBarry Smith +   da - the DMDA object
13118272889dSSatish Balay -   n - the number of GLL nodes
13128272889dSSatish Balay -   nodes - the GLL nodes
131362197512SBarry Smith 
131495452b02SPatrick Sanan    Notes:
131595452b02SPatrick Sanan     the parallel decomposition of grid points must correspond to the degree of the GLL. That is, the number of grid points
131662197512SBarry Smith           on each process much be divisible by the number of GLL elements needed per process. This depends on whether the DM is
131762197512SBarry Smith           periodic or not.
131862197512SBarry Smith 
1319edc382c3SSatish Balay    Level: advanced
1320edc382c3SSatish Balay 
13218272889dSSatish Balay .seealso:   DMDACreate(), PetscDTGaussLobattoLegendreQuadrature(), DMGetCoordinates()
132262197512SBarry Smith @*/
13238272889dSSatish Balay PetscErrorCode DMDASetGLLCoordinates(DM da,PetscInt n,PetscReal *nodes)
132462197512SBarry Smith {
132562197512SBarry Smith   PetscFunctionBegin;
132662197512SBarry Smith   if (da->dim == 1) {
1327*5f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetGLLCoordinates_1d(da,n,nodes));
132862197512SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not yet implemented for 2 or 3d");
132962197512SBarry Smith   PetscFunctionReturn(0);
133062197512SBarry Smith }
13317c3cd84eSPatrick Sanan 
13327c3cd84eSPatrick Sanan PETSC_INTERN PetscErrorCode DMGetCompatibility_DA(DM da1,DM dm2,PetscBool *compatible,PetscBool *set)
13337c3cd84eSPatrick Sanan {
13347c3cd84eSPatrick Sanan   DM_DA          *dd1 = (DM_DA*)da1->data,*dd2;
13357c3cd84eSPatrick Sanan   DM             da2;
13367c3cd84eSPatrick Sanan   DMType         dmtype2;
13377c3cd84eSPatrick Sanan   PetscBool      isda,compatibleLocal;
13387c3cd84eSPatrick Sanan   PetscInt       i;
13397c3cd84eSPatrick Sanan 
13407c3cd84eSPatrick Sanan   PetscFunctionBegin;
13417a8be351SBarry Smith   PetscCheck(da1->setupcalled,PetscObjectComm((PetscObject)da1),PETSC_ERR_ARG_WRONGSTATE,"DMSetUp() must be called on first DM before DMGetCompatibility()");
1342*5f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetType(dm2,&dmtype2));
1343*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(dmtype2,DMDA,&isda));
13447c3cd84eSPatrick Sanan   if (isda) {
13457c3cd84eSPatrick Sanan     da2 = dm2;
13467c3cd84eSPatrick Sanan     dd2 = (DM_DA*)da2->data;
13477a8be351SBarry Smith     PetscCheck(da2->setupcalled,PetscObjectComm((PetscObject)da2),PETSC_ERR_ARG_WRONGSTATE,"DMSetUp() must be called on second DM before DMGetCompatibility()");
1348110623a0SKarl Rupp     compatibleLocal = (PetscBool)(da1->dim == da2->dim);
1349c790a739SKarl Rupp     if (compatibleLocal) compatibleLocal = (PetscBool)(compatibleLocal && (dd1->s == dd2->s)); /* Stencil width */
1350110623a0SKarl Rupp     /*                                                                           Global size              ranks               Boundary type */
1351c790a739SKarl Rupp     if (compatibleLocal)                 compatibleLocal = (PetscBool)(compatibleLocal && (dd1->M == dd2->M) && (dd1->m == dd2->m) && (dd1->bx == dd2->bx));
1352c790a739SKarl Rupp     if (compatibleLocal && da1->dim > 1) compatibleLocal = (PetscBool)(compatibleLocal && (dd1->N == dd2->N) && (dd1->n == dd2->n) && (dd1->by == dd2->by));
1353c790a739SKarl Rupp     if (compatibleLocal && da1->dim > 2) compatibleLocal = (PetscBool)(compatibleLocal && (dd1->P == dd2->P) && (dd1->p == dd2->p) && (dd1->bz == dd2->bz));
13547c3cd84eSPatrick Sanan     if (compatibleLocal) {
13557c3cd84eSPatrick Sanan       for (i=0; i<dd1->m; ++i) {
1356c790a739SKarl Rupp         compatibleLocal = (PetscBool)(compatibleLocal && (dd1->lx[i] == dd2->lx[i]));           /* Local size     */
13577c3cd84eSPatrick Sanan       }
13587c3cd84eSPatrick Sanan     }
13597c3cd84eSPatrick Sanan     if (compatibleLocal && da1->dim > 1) {
13607c3cd84eSPatrick Sanan       for (i=0; i<dd1->n; ++i) {
1361c790a739SKarl Rupp         compatibleLocal = (PetscBool)(compatibleLocal && (dd1->ly[i] == dd2->ly[i]));
13627c3cd84eSPatrick Sanan       }
13637c3cd84eSPatrick Sanan     }
13647c3cd84eSPatrick Sanan     if (compatibleLocal && da1->dim > 2) {
13657c3cd84eSPatrick Sanan       for (i=0; i<dd1->p; ++i) {
1366c790a739SKarl Rupp         compatibleLocal = (PetscBool)(compatibleLocal && (dd1->lz[i] == dd2->lz[i]));
13677c3cd84eSPatrick Sanan       }
13687c3cd84eSPatrick Sanan     }
13697c3cd84eSPatrick Sanan     *compatible = compatibleLocal;
13707c3cd84eSPatrick Sanan     *set = PETSC_TRUE;
13717c3cd84eSPatrick Sanan   } else {
13727c3cd84eSPatrick Sanan     /* Decline to determine compatibility with other DM types */
13737c3cd84eSPatrick Sanan     *set = PETSC_FALSE;
13747c3cd84eSPatrick Sanan   }
13757c3cd84eSPatrick Sanan   PetscFunctionReturn(0);
13767c3cd84eSPatrick Sanan }
1377