xref: /petsc/src/dm/impls/da/da.c (revision 95452b02e12c0ee11232c7ff2b24b568a8e07e43)
1af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h>    /*I   "petscdmda.h"   I*/
247c6ae99SBarry Smith 
347c6ae99SBarry Smith /*@
4aa219208SBarry Smith   DMDASetSizes - Sets the global sizes
547c6ae99SBarry Smith 
6aa219208SBarry Smith   Logically Collective on DMDA
747c6ae99SBarry Smith 
847c6ae99SBarry Smith   Input Parameters:
9aa219208SBarry Smith + da - the DMDA
1047c6ae99SBarry Smith . M - the global X size (or PETSC_DECIDE)
1147c6ae99SBarry Smith . N - the global Y size (or PETSC_DECIDE)
1247c6ae99SBarry Smith - P - the global Z size (or PETSC_DECIDE)
1347c6ae99SBarry Smith 
1447c6ae99SBarry Smith   Level: intermediate
1547c6ae99SBarry Smith 
16aa219208SBarry Smith .seealso: DMDAGetSize(), PetscSplitOwnership()
1747c6ae99SBarry Smith @*/
187087cfbeSBarry Smith PetscErrorCode  DMDASetSizes(DM da, PetscInt M, PetscInt N, PetscInt P)
1947c6ae99SBarry Smith {
2047c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
2147c6ae99SBarry Smith 
2247c6ae99SBarry Smith   PetscFunctionBegin;
2347c6ae99SBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
2447c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,M,2);
2547c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,N,3);
2647c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,P,4);
27ce94432eSBarry Smith   if (da->setupcalled) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
2847c6ae99SBarry Smith 
2947c6ae99SBarry Smith   dd->M = M;
3047c6ae99SBarry Smith   dd->N = N;
3147c6ae99SBarry Smith   dd->P = P;
3247c6ae99SBarry Smith   PetscFunctionReturn(0);
3347c6ae99SBarry Smith }
3447c6ae99SBarry Smith 
3547c6ae99SBarry Smith /*@
36aa219208SBarry Smith   DMDASetNumProcs - Sets the number of processes in each dimension
3747c6ae99SBarry Smith 
38aa219208SBarry Smith   Logically Collective on DMDA
3947c6ae99SBarry Smith 
4047c6ae99SBarry Smith   Input Parameters:
41aa219208SBarry Smith + da - the DMDA
4247c6ae99SBarry Smith . m - the number of X procs (or PETSC_DECIDE)
4347c6ae99SBarry Smith . n - the number of Y procs (or PETSC_DECIDE)
4447c6ae99SBarry Smith - p - the number of Z procs (or PETSC_DECIDE)
4547c6ae99SBarry Smith 
4647c6ae99SBarry Smith   Level: intermediate
4747c6ae99SBarry Smith 
48aa219208SBarry Smith .seealso: DMDASetSizes(), DMDAGetSize(), PetscSplitOwnership()
4947c6ae99SBarry Smith @*/
507087cfbeSBarry Smith PetscErrorCode  DMDASetNumProcs(DM da, PetscInt m, PetscInt n, PetscInt p)
5147c6ae99SBarry Smith {
5247c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
53e3f3e4b6SBarry Smith   PetscErrorCode ierr;
5447c6ae99SBarry Smith 
5547c6ae99SBarry Smith   PetscFunctionBegin;
5647c6ae99SBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
5747c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,m,2);
5847c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,n,3);
5947c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,p,4);
60ce94432eSBarry Smith   if (da->setupcalled) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
6147c6ae99SBarry Smith   dd->m = m;
6247c6ae99SBarry Smith   dd->n = n;
6347c6ae99SBarry Smith   dd->p = p;
64c73cfb54SMatthew G. Knepley   if (da->dim == 2) {
65d3be247eSBarry Smith     PetscMPIInt size;
66d3be247eSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)da),&size);CHKERRQ(ierr);
67e3f3e4b6SBarry Smith     if ((dd->m > 0) && (dd->n < 0)) {
68e3f3e4b6SBarry Smith       dd->n = size/dd->m;
69ce94432eSBarry Smith       if (dd->n*dd->m != size) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"%D processes in X direction not divisible into comm size %d",m,size);
70e3f3e4b6SBarry Smith     }
71e3f3e4b6SBarry Smith     if ((dd->n > 0) && (dd->m < 0)) {
72e3f3e4b6SBarry Smith       dd->m = size/dd->n;
73ce94432eSBarry Smith       if (dd->n*dd->m != size) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"%D processes in Y direction not divisible into comm size %d",n,size);
74e3f3e4b6SBarry Smith     }
75e3f3e4b6SBarry Smith   }
7647c6ae99SBarry Smith   PetscFunctionReturn(0);
7747c6ae99SBarry Smith }
7847c6ae99SBarry Smith 
7947c6ae99SBarry Smith /*@
801321219cSEthan Coon   DMDASetBoundaryType - Sets the type of ghost nodes on domain boundaries.
8147c6ae99SBarry Smith 
8247c6ae99SBarry Smith   Not collective
8347c6ae99SBarry Smith 
8447c6ae99SBarry Smith   Input Parameter:
85aa219208SBarry Smith + da    - The DMDA
86bff4a2f0SMatthew G. Knepley - bx,by,bz - One of DM_BOUNDARY_NONE, DM_BOUNDARY_GHOSTED, DM_BOUNDARY_PERIODIC
8747c6ae99SBarry Smith 
8847c6ae99SBarry Smith   Level: intermediate
8947c6ae99SBarry Smith 
9047c6ae99SBarry Smith .keywords:  distributed array, periodicity
91bff4a2f0SMatthew G. Knepley .seealso: DMDACreate(), DMDestroy(), DMDA, DMBoundaryType
9247c6ae99SBarry Smith @*/
93bff4a2f0SMatthew G. Knepley PetscErrorCode  DMDASetBoundaryType(DM da,DMBoundaryType bx,DMBoundaryType by,DMBoundaryType bz)
9447c6ae99SBarry Smith {
9547c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
9647c6ae99SBarry Smith 
9747c6ae99SBarry Smith   PetscFunctionBegin;
9847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
995a43f728SLisandro Dalcin   PetscValidLogicalCollectiveEnum(da,bx,2);
1005a43f728SLisandro Dalcin   PetscValidLogicalCollectiveEnum(da,by,3);
1015a43f728SLisandro Dalcin   PetscValidLogicalCollectiveEnum(da,bz,4);
102ce94432eSBarry Smith   if (da->setupcalled) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
1031321219cSEthan Coon   dd->bx = bx;
1041321219cSEthan Coon   dd->by = by;
1051321219cSEthan Coon   dd->bz = bz;
10647c6ae99SBarry Smith   PetscFunctionReturn(0);
10747c6ae99SBarry Smith }
10847c6ae99SBarry Smith 
10947c6ae99SBarry Smith /*@
110aa219208SBarry Smith   DMDASetDof - Sets the number of degrees of freedom per vertex
11147c6ae99SBarry Smith 
11247c6ae99SBarry Smith   Not collective
11347c6ae99SBarry Smith 
11459f3ab6dSMatthew G. Knepley   Input Parameters:
115aa219208SBarry Smith + da  - The DMDA
11647c6ae99SBarry Smith - dof - Number of degrees of freedom
11747c6ae99SBarry Smith 
11847c6ae99SBarry Smith   Level: intermediate
11947c6ae99SBarry Smith 
12047c6ae99SBarry Smith .keywords:  distributed array, degrees of freedom
121fb6725baSMatthew G. Knepley .seealso: DMDAGetDof(), DMDACreate(), DMDestroy(), DMDA
12247c6ae99SBarry Smith @*/
12354cfb0beSLisandro Dalcin PetscErrorCode  DMDASetDof(DM da, PetscInt dof)
12447c6ae99SBarry Smith {
12547c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
12647c6ae99SBarry Smith 
12747c6ae99SBarry Smith   PetscFunctionBegin;
12847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
12954cfb0beSLisandro Dalcin   PetscValidLogicalCollectiveInt(da,dof,2);
130ce94432eSBarry Smith   if (da->setupcalled) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
13147c6ae99SBarry Smith   dd->w  = dof;
1321411c6eeSJed Brown   da->bs = dof;
13347c6ae99SBarry Smith   PetscFunctionReturn(0);
13447c6ae99SBarry Smith }
13547c6ae99SBarry Smith 
136fb6725baSMatthew G. Knepley /*@
137fb6725baSMatthew G. Knepley   DMDAGetDof - Gets the number of degrees of freedom per vertex
138fb6725baSMatthew G. Knepley 
139fb6725baSMatthew G. Knepley   Not collective
140fb6725baSMatthew G. Knepley 
141fb6725baSMatthew G. Knepley   Input Parameter:
142fb6725baSMatthew G. Knepley . da  - The DMDA
143fb6725baSMatthew G. Knepley 
144fb6725baSMatthew G. Knepley   Output Parameter:
145fb6725baSMatthew G. Knepley . dof - Number of degrees of freedom
146fb6725baSMatthew G. Knepley 
147fb6725baSMatthew G. Knepley   Level: intermediate
148fb6725baSMatthew G. Knepley 
149fb6725baSMatthew G. Knepley .keywords:  distributed array, degrees of freedom
150fb6725baSMatthew G. Knepley .seealso: DMDASetDof(), DMDACreate(), DMDestroy(), DMDA
151fb6725baSMatthew G. Knepley @*/
152fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetDof(DM da, PetscInt *dof)
153fb6725baSMatthew G. Knepley {
154fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA *) da->data;
155fb6725baSMatthew G. Knepley 
156fb6725baSMatthew G. Knepley   PetscFunctionBegin;
157fb6725baSMatthew G. Knepley   PetscValidHeaderSpecific(da,DM_CLASSID,1);
158fb6725baSMatthew G. Knepley   PetscValidPointer(dof,2);
159fb6725baSMatthew G. Knepley   *dof = dd->w;
160fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
161fb6725baSMatthew G. Knepley }
162fb6725baSMatthew G. Knepley 
1637ddda789SPeter Brune /*@
1647ddda789SPeter Brune   DMDAGetOverlap - Gets the size of the per-processor overlap.
1657ddda789SPeter Brune 
1667ddda789SPeter Brune   Not collective
1677ddda789SPeter Brune 
1687ddda789SPeter Brune   Input Parameters:
1697ddda789SPeter Brune . da  - The DMDA
1707ddda789SPeter Brune 
1717ddda789SPeter Brune   Output Parameters:
1727ddda789SPeter Brune + x   - Overlap in the x direction
1737ddda789SPeter Brune . y   - Overlap in the y direction
1747ddda789SPeter Brune - z   - Overlap in the z direction
1757ddda789SPeter Brune 
1767ddda789SPeter Brune   Level: intermediate
1777ddda789SPeter Brune 
1787ddda789SPeter Brune .keywords:  distributed array, overlap, domain decomposition
1797ddda789SPeter Brune .seealso: DMDACreateDomainDecomposition(), DMDASetOverlap(), DMDA
1807ddda789SPeter Brune @*/
1817ddda789SPeter Brune PetscErrorCode  DMDAGetOverlap(DM da,PetscInt *x,PetscInt *y,PetscInt *z)
1827ddda789SPeter Brune {
1837ddda789SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
1847ddda789SPeter Brune 
1857ddda789SPeter Brune   PetscFunctionBegin;
1867ddda789SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
1877ddda789SPeter Brune   if (x) *x = dd->xol;
1887ddda789SPeter Brune   if (y) *y = dd->yol;
1897ddda789SPeter Brune   if (z) *z = dd->zol;
1907ddda789SPeter Brune   PetscFunctionReturn(0);
1917ddda789SPeter Brune }
1927ddda789SPeter Brune 
19388661749SPeter Brune /*@
19488661749SPeter Brune   DMDASetOverlap - Sets the size of the per-processor overlap.
19588661749SPeter Brune 
19688661749SPeter Brune   Not collective
19788661749SPeter Brune 
1987ddda789SPeter Brune   Input Parameters:
19988661749SPeter Brune + da  - The DMDA
2007ddda789SPeter Brune . x   - Overlap in the x direction
2017ddda789SPeter Brune . y   - Overlap in the y direction
2027ddda789SPeter Brune - z   - Overlap in the z direction
20388661749SPeter Brune 
20488661749SPeter Brune   Level: intermediate
20588661749SPeter Brune 
2067ddda789SPeter Brune .keywords:  distributed array, overlap, domain decomposition
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;
21488661749SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
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 /*@
2263e7870d2SPeter Brune   DMDAGetNumLocalSubDomains - Gets the number of local subdomains created upon decomposition.
2273e7870d2SPeter Brune 
2283e7870d2SPeter Brune   Not collective
2293e7870d2SPeter Brune 
2303e7870d2SPeter Brune   Input Parameters:
2313e7870d2SPeter Brune . da  - The DMDA
2323e7870d2SPeter Brune 
2333e7870d2SPeter Brune   Output Parameters:
2343e7870d2SPeter Brune + Nsub   - Number of local subdomains created upon decomposition
2353e7870d2SPeter Brune 
2363e7870d2SPeter Brune   Level: intermediate
2373e7870d2SPeter Brune 
2383e7870d2SPeter Brune .keywords:  distributed array, domain decomposition
2393e7870d2SPeter Brune .seealso: DMDACreateDomainDecomposition(), DMDASetNumLocalSubDomains(), DMDA
2403e7870d2SPeter Brune @*/
2413e7870d2SPeter Brune PetscErrorCode  DMDAGetNumLocalSubDomains(DM da,PetscInt *Nsub)
2423e7870d2SPeter Brune {
2433e7870d2SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
2443e7870d2SPeter Brune 
2453e7870d2SPeter Brune   PetscFunctionBegin;
2463e7870d2SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
2473e7870d2SPeter Brune   if (Nsub) *Nsub = dd->Nsub;
2483e7870d2SPeter Brune   PetscFunctionReturn(0);
2493e7870d2SPeter Brune }
2503e7870d2SPeter Brune 
2513e7870d2SPeter Brune /*@
2523e7870d2SPeter Brune   DMDASetNumLocalSubDomains - Sets the number of local subdomains created upon decomposition.
2533e7870d2SPeter Brune 
2543e7870d2SPeter Brune   Not collective
2553e7870d2SPeter Brune 
2563e7870d2SPeter Brune   Input Parameters:
2573e7870d2SPeter Brune + da  - The DMDA
2583e7870d2SPeter Brune - Nsub - The number of local subdomains requested
2593e7870d2SPeter Brune 
2603e7870d2SPeter Brune   Level: intermediate
2613e7870d2SPeter Brune 
2623e7870d2SPeter Brune .keywords:  distributed array, domain decomposition
2633e7870d2SPeter Brune .seealso: DMDACreateDomainDecomposition(), DMDAGetNumLocalSubDomains(), DMDA
2643e7870d2SPeter Brune @*/
2653e7870d2SPeter Brune PetscErrorCode  DMDASetNumLocalSubDomains(DM da,PetscInt Nsub)
2663e7870d2SPeter Brune {
2673e7870d2SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
2683e7870d2SPeter Brune 
2693e7870d2SPeter Brune   PetscFunctionBegin;
2703e7870d2SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
2713e7870d2SPeter Brune   PetscValidLogicalCollectiveInt(da,Nsub,2);
2723e7870d2SPeter Brune   dd->Nsub = Nsub;
2733e7870d2SPeter Brune   PetscFunctionReturn(0);
2743e7870d2SPeter Brune }
2753e7870d2SPeter Brune 
276d886c4f4SPeter Brune /*@
277d886c4f4SPeter Brune   DMDASetOffset - Sets the index offset of the DA.
278d886c4f4SPeter Brune 
279d886c4f4SPeter Brune   Collective on DA
280d886c4f4SPeter Brune 
281d886c4f4SPeter Brune   Input Parameter:
282d886c4f4SPeter Brune + da  - The DMDA
283d886c4f4SPeter Brune . xo  - The offset in the x direction
284d886c4f4SPeter Brune . yo  - The offset in the y direction
285d886c4f4SPeter Brune - zo  - The offset in the z direction
286d886c4f4SPeter Brune 
287d886c4f4SPeter Brune   Level: intermediate
288d886c4f4SPeter Brune 
289*95452b02SPatrick Sanan   Notes:
290*95452b02SPatrick Sanan     This is used primarily to overlap a computation on a local DA with that on a global DA without
291d886c4f4SPeter Brune   changing boundary conditions or subdomain features that depend upon the global offsets.
292d886c4f4SPeter Brune 
293d886c4f4SPeter Brune .keywords:  distributed array, degrees of freedom
294d886c4f4SPeter Brune .seealso: DMDAGetOffset(), DMDAVecGetArray()
295d886c4f4SPeter Brune @*/
29695c13181SPeter Brune PetscErrorCode  DMDASetOffset(DM da, PetscInt xo, PetscInt yo, PetscInt zo, PetscInt Mo, PetscInt No, PetscInt Po)
297d886c4f4SPeter Brune {
29895c13181SPeter Brune   PetscErrorCode ierr;
299d886c4f4SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
300d886c4f4SPeter Brune 
301d886c4f4SPeter Brune   PetscFunctionBegin;
302d886c4f4SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
303d886c4f4SPeter Brune   PetscValidLogicalCollectiveInt(da,xo,2);
30495c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,yo,3);
30595c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,zo,4);
30695c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,Mo,5);
30795c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,No,6);
30895c13181SPeter Brune   PetscValidLogicalCollectiveInt(da,Po,7);
309d886c4f4SPeter Brune   dd->xo = xo;
310d886c4f4SPeter Brune   dd->yo = yo;
311d886c4f4SPeter Brune   dd->zo = zo;
31295c13181SPeter Brune   dd->Mo = Mo;
31395c13181SPeter Brune   dd->No = No;
31495c13181SPeter Brune   dd->Po = Po;
31595c13181SPeter Brune 
31695c13181SPeter Brune   if (da->coordinateDM) {
31795c13181SPeter Brune     ierr = DMDASetOffset(da->coordinateDM,xo,yo,zo,Mo,No,Po);CHKERRQ(ierr);
31895c13181SPeter Brune   }
319d886c4f4SPeter Brune   PetscFunctionReturn(0);
320d886c4f4SPeter Brune }
321d886c4f4SPeter Brune 
322d886c4f4SPeter Brune /*@
323d886c4f4SPeter Brune   DMDAGetOffset - Gets the index offset of the DA.
324d886c4f4SPeter Brune 
325d886c4f4SPeter Brune   Not collective
326d886c4f4SPeter Brune 
327d886c4f4SPeter Brune   Input Parameter:
328d886c4f4SPeter Brune . da  - The DMDA
329d886c4f4SPeter Brune 
330d886c4f4SPeter Brune   Output Parameters:
331d886c4f4SPeter Brune + xo  - The offset in the x direction
332d886c4f4SPeter Brune . yo  - The offset in the y direction
33395c13181SPeter Brune . zo  - The offset in the z direction
33495c13181SPeter Brune . Mo  - The global size in the x direction
33595c13181SPeter Brune . No  - The global size in the y direction
33695c13181SPeter Brune - Po  - The global size in the z direction
337d886c4f4SPeter Brune 
338d886c4f4SPeter Brune   Level: intermediate
339d886c4f4SPeter Brune 
340d886c4f4SPeter Brune .keywords:  distributed array, degrees of freedom
341d886c4f4SPeter Brune .seealso: DMDASetOffset(), DMDAVecGetArray()
342d886c4f4SPeter Brune @*/
34395c13181SPeter Brune PetscErrorCode  DMDAGetOffset(DM da,PetscInt *xo,PetscInt *yo,PetscInt *zo,PetscInt *Mo,PetscInt *No,PetscInt *Po)
344d886c4f4SPeter Brune {
345d886c4f4SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
346d886c4f4SPeter Brune 
347d886c4f4SPeter Brune   PetscFunctionBegin;
348d886c4f4SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
349d886c4f4SPeter Brune   if (xo) *xo = dd->xo;
350d886c4f4SPeter Brune   if (yo) *yo = dd->yo;
351d886c4f4SPeter Brune   if (zo) *zo = dd->zo;
35295c13181SPeter Brune   if (Mo) *Mo = dd->Mo;
35395c13181SPeter Brune   if (No) *No = dd->No;
35495c13181SPeter Brune   if (Po) *Po = dd->Po;
355d886c4f4SPeter Brune   PetscFunctionReturn(0);
356d886c4f4SPeter Brune }
357d886c4f4SPeter Brune 
35840234c92SPeter Brune /*@
35940234c92SPeter Brune   DMDAGetNonOverlappingRegion - Gets the indices of the nonoverlapping region of a subdomain DM.
36040234c92SPeter Brune 
36140234c92SPeter Brune   Not collective
36240234c92SPeter Brune 
36340234c92SPeter Brune   Input Parameter:
36440234c92SPeter Brune . da  - The DMDA
36540234c92SPeter Brune 
36640234c92SPeter Brune   Output Parameters:
36740234c92SPeter Brune + xs  - The start of the region in x
36840234c92SPeter Brune . ys  - The start of the region in y
36940234c92SPeter Brune . zs  - The start of the region in z
37040234c92SPeter Brune . xs  - The size of the region in x
37140234c92SPeter Brune . ys  - The size of the region in y
37240234c92SPeter Brune . zs  - The size of the region in z
37340234c92SPeter Brune 
37440234c92SPeter Brune   Level: intermediate
37540234c92SPeter Brune 
37640234c92SPeter Brune .keywords:  distributed array, degrees of freedom
37740234c92SPeter Brune .seealso: DMDAGetOffset(), DMDAVecGetArray()
37840234c92SPeter Brune @*/
37940234c92SPeter Brune PetscErrorCode  DMDAGetNonOverlappingRegion(DM da, PetscInt *xs, PetscInt *ys, PetscInt *zs, PetscInt *xm, PetscInt *ym, PetscInt *zm)
38040234c92SPeter Brune {
38140234c92SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
38240234c92SPeter Brune 
38340234c92SPeter Brune   PetscFunctionBegin;
38440234c92SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
38540234c92SPeter Brune   if (xs) *xs = dd->nonxs;
38640234c92SPeter Brune   if (ys) *ys = dd->nonys;
38740234c92SPeter Brune   if (zs) *zs = dd->nonzs;
38840234c92SPeter Brune   if (xm) *xm = dd->nonxm;
38940234c92SPeter Brune   if (ym) *ym = dd->nonym;
39040234c92SPeter Brune   if (zm) *zm = dd->nonzm;
39140234c92SPeter Brune   PetscFunctionReturn(0);
39240234c92SPeter Brune }
39340234c92SPeter Brune 
39440234c92SPeter Brune 
39540234c92SPeter Brune /*@
39640234c92SPeter Brune   DMDASetNonOverlappingRegion - Sets the indices of the nonoverlapping region of a subdomain DM.
39740234c92SPeter Brune 
39840234c92SPeter Brune   Collective on DA
39940234c92SPeter Brune 
40040234c92SPeter Brune   Input Parameter:
40140234c92SPeter Brune + da  - The DMDA
40240234c92SPeter Brune . xs  - The start of the region in x
40340234c92SPeter Brune . ys  - The start of the region in y
40440234c92SPeter Brune . zs  - The start of the region in z
40540234c92SPeter Brune . xs  - The size of the region in x
40640234c92SPeter Brune . ys  - The size of the region in y
40740234c92SPeter Brune . zs  - The size of the region in z
40840234c92SPeter Brune 
40940234c92SPeter Brune   Level: intermediate
41040234c92SPeter Brune 
41140234c92SPeter Brune .keywords:  distributed array, degrees of freedom
41240234c92SPeter Brune .seealso: DMDAGetOffset(), DMDAVecGetArray()
41340234c92SPeter Brune @*/
41440234c92SPeter Brune PetscErrorCode  DMDASetNonOverlappingRegion(DM da, PetscInt xs, PetscInt ys, PetscInt zs, PetscInt xm, PetscInt ym, PetscInt zm)
41540234c92SPeter Brune {
41640234c92SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
41740234c92SPeter Brune 
41840234c92SPeter Brune   PetscFunctionBegin;
41940234c92SPeter Brune   PetscValidHeaderSpecific(da,DM_CLASSID,1);
42040234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,xs,2);
42140234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,ys,3);
42240234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,zs,4);
42340234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,xm,5);
42440234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,ym,6);
42540234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,zm,7);
42640234c92SPeter Brune   dd->nonxs = xs;
42740234c92SPeter Brune   dd->nonys = ys;
42840234c92SPeter Brune   dd->nonzs = zs;
42940234c92SPeter Brune   dd->nonxm = xm;
43040234c92SPeter Brune   dd->nonym = ym;
43140234c92SPeter Brune   dd->nonzm = zm;
43240234c92SPeter Brune 
43340234c92SPeter Brune   PetscFunctionReturn(0);
43440234c92SPeter Brune }
43588661749SPeter Brune 
43647c6ae99SBarry Smith /*@
437aa219208SBarry Smith   DMDASetStencilType - Sets the type of the communication stencil
43847c6ae99SBarry Smith 
439aa219208SBarry Smith   Logically Collective on DMDA
44047c6ae99SBarry Smith 
44147c6ae99SBarry Smith   Input Parameter:
442aa219208SBarry Smith + da    - The DMDA
443aa219208SBarry Smith - stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
44447c6ae99SBarry Smith 
44547c6ae99SBarry Smith   Level: intermediate
44647c6ae99SBarry Smith 
44747c6ae99SBarry Smith .keywords:  distributed array, stencil
44896e147daSBarry Smith .seealso: DMDACreate(), DMDestroy(), DMDA
44947c6ae99SBarry Smith @*/
4507087cfbeSBarry Smith PetscErrorCode  DMDASetStencilType(DM da, DMDAStencilType stype)
45147c6ae99SBarry Smith {
45247c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
45347c6ae99SBarry Smith 
45447c6ae99SBarry Smith   PetscFunctionBegin;
45547c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
45647c6ae99SBarry Smith   PetscValidLogicalCollectiveEnum(da,stype,2);
457ce94432eSBarry Smith   if (da->setupcalled) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
45847c6ae99SBarry Smith   dd->stencil_type = stype;
45947c6ae99SBarry Smith   PetscFunctionReturn(0);
46047c6ae99SBarry Smith }
46147c6ae99SBarry Smith 
462fb6725baSMatthew G. Knepley /*@
463fb6725baSMatthew G. Knepley   DMDAGetStencilType - Gets the type of the communication stencil
464fb6725baSMatthew G. Knepley 
465fb6725baSMatthew G. Knepley   Not collective
466fb6725baSMatthew G. Knepley 
467fb6725baSMatthew G. Knepley   Input Parameter:
468fb6725baSMatthew G. Knepley . da    - The DMDA
469fb6725baSMatthew G. Knepley 
470fb6725baSMatthew G. Knepley   Output Parameter:
471fb6725baSMatthew G. Knepley . stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
472fb6725baSMatthew G. Knepley 
473fb6725baSMatthew G. Knepley   Level: intermediate
474fb6725baSMatthew G. Knepley 
475fb6725baSMatthew G. Knepley .keywords:  distributed array, stencil
476fb6725baSMatthew G. Knepley .seealso: DMDACreate(), DMDestroy(), DMDA
477fb6725baSMatthew G. Knepley @*/
478fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetStencilType(DM da, DMDAStencilType *stype)
479fb6725baSMatthew G. Knepley {
480fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA*)da->data;
481fb6725baSMatthew G. Knepley 
482fb6725baSMatthew G. Knepley   PetscFunctionBegin;
483fb6725baSMatthew G. Knepley   PetscValidHeaderSpecific(da,DM_CLASSID,1);
484fb6725baSMatthew G. Knepley   PetscValidPointer(stype,2);
485fb6725baSMatthew G. Knepley   *stype = dd->stencil_type;
486fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
487fb6725baSMatthew G. Knepley }
488fb6725baSMatthew G. Knepley 
48947c6ae99SBarry Smith /*@
490aa219208SBarry Smith   DMDASetStencilWidth - Sets the width of the communication stencil
49147c6ae99SBarry Smith 
492aa219208SBarry Smith   Logically Collective on DMDA
49347c6ae99SBarry Smith 
49447c6ae99SBarry Smith   Input Parameter:
495aa219208SBarry Smith + da    - The DMDA
49647c6ae99SBarry Smith - width - The stencil width
49747c6ae99SBarry Smith 
49847c6ae99SBarry Smith   Level: intermediate
49947c6ae99SBarry Smith 
50047c6ae99SBarry Smith .keywords:  distributed array, stencil
50196e147daSBarry Smith .seealso: DMDACreate(), DMDestroy(), DMDA
50247c6ae99SBarry Smith @*/
5037087cfbeSBarry Smith PetscErrorCode  DMDASetStencilWidth(DM da, PetscInt width)
50447c6ae99SBarry Smith {
50547c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
50647c6ae99SBarry Smith 
50747c6ae99SBarry Smith   PetscFunctionBegin;
50847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
50947c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,width,2);
510ce94432eSBarry Smith   if (da->setupcalled) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
51147c6ae99SBarry Smith   dd->s = width;
51247c6ae99SBarry Smith   PetscFunctionReturn(0);
51347c6ae99SBarry Smith }
51447c6ae99SBarry Smith 
515fb6725baSMatthew G. Knepley /*@
516fb6725baSMatthew G. Knepley   DMDAGetStencilWidth - Gets the width of the communication stencil
517fb6725baSMatthew G. Knepley 
518fb6725baSMatthew G. Knepley   Not collective
519fb6725baSMatthew G. Knepley 
520fb6725baSMatthew G. Knepley   Input Parameter:
521fb6725baSMatthew G. Knepley . da    - The DMDA
522fb6725baSMatthew G. Knepley 
523fb6725baSMatthew G. Knepley   Output Parameter:
524fb6725baSMatthew G. Knepley . width - The stencil width
525fb6725baSMatthew G. Knepley 
526fb6725baSMatthew G. Knepley   Level: intermediate
527fb6725baSMatthew G. Knepley 
528fb6725baSMatthew G. Knepley .keywords:  distributed array, stencil
529fb6725baSMatthew G. Knepley .seealso: DMDACreate(), DMDestroy(), DMDA
530fb6725baSMatthew G. Knepley @*/
531fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetStencilWidth(DM da, PetscInt *width)
532fb6725baSMatthew G. Knepley {
533fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA *) da->data;
534fb6725baSMatthew G. Knepley 
535fb6725baSMatthew G. Knepley   PetscFunctionBegin;
536fb6725baSMatthew G. Knepley   PetscValidHeaderSpecific(da,DM_CLASSID,1);
537fb6725baSMatthew G. Knepley   PetscValidPointer(width,2);
538fb6725baSMatthew G. Knepley   *width = dd->s;
539fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
540fb6725baSMatthew G. Knepley }
541fb6725baSMatthew G. Knepley 
542aa219208SBarry Smith static PetscErrorCode DMDACheckOwnershipRanges_Private(DM da,PetscInt M,PetscInt m,const PetscInt lx[])
54347c6ae99SBarry Smith {
54447c6ae99SBarry Smith   PetscInt i,sum;
54547c6ae99SBarry Smith 
54647c6ae99SBarry Smith   PetscFunctionBegin;
547ce94432eSBarry Smith   if (M < 0) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Global dimension not set");
54847c6ae99SBarry Smith   for (i=sum=0; i<m; i++) sum += lx[i];
549ce94432eSBarry Smith   if (sum != M) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"Ownership ranges sum to %D but global dimension is %D",sum,M);
55047c6ae99SBarry Smith   PetscFunctionReturn(0);
55147c6ae99SBarry Smith }
55247c6ae99SBarry Smith 
55347c6ae99SBarry Smith /*@
554aa219208SBarry Smith   DMDASetOwnershipRanges - Sets the number of nodes in each direction on each process
55547c6ae99SBarry Smith 
556aa219208SBarry Smith   Logically Collective on DMDA
55747c6ae99SBarry Smith 
55847c6ae99SBarry Smith   Input Parameter:
559aa219208SBarry Smith + da - The DMDA
5600298fd71SBarry 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
5610298fd71SBarry 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
5620298fd71SBarry 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.
56347c6ae99SBarry Smith 
56447c6ae99SBarry Smith   Level: intermediate
56547c6ae99SBarry Smith 
566e3f3e4b6SBarry Smith   Note: these numbers are NOT multiplied by the number of dof per node.
567e3f3e4b6SBarry Smith 
56847c6ae99SBarry Smith .keywords:  distributed array
56996e147daSBarry Smith .seealso: DMDACreate(), DMDestroy(), DMDA
57047c6ae99SBarry Smith @*/
5717087cfbeSBarry Smith PetscErrorCode  DMDASetOwnershipRanges(DM da, const PetscInt lx[], const PetscInt ly[], const PetscInt lz[])
57247c6ae99SBarry Smith {
57347c6ae99SBarry Smith   PetscErrorCode ierr;
57447c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
57547c6ae99SBarry Smith 
57647c6ae99SBarry Smith   PetscFunctionBegin;
57747c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
578ce94432eSBarry Smith   if (da->setupcalled) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
57947c6ae99SBarry Smith   if (lx) {
580ce94432eSBarry Smith     if (dd->m < 0) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
581aa219208SBarry Smith     ierr = DMDACheckOwnershipRanges_Private(da,dd->M,dd->m,lx);CHKERRQ(ierr);
58247c6ae99SBarry Smith     if (!dd->lx) {
583785e854fSJed Brown       ierr = PetscMalloc1(dd->m, &dd->lx);CHKERRQ(ierr);
58447c6ae99SBarry Smith     }
58547c6ae99SBarry Smith     ierr = PetscMemcpy(dd->lx, lx, dd->m*sizeof(PetscInt));CHKERRQ(ierr);
58647c6ae99SBarry Smith   }
58747c6ae99SBarry Smith   if (ly) {
588ce94432eSBarry Smith     if (dd->n < 0) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
589aa219208SBarry Smith     ierr = DMDACheckOwnershipRanges_Private(da,dd->N,dd->n,ly);CHKERRQ(ierr);
59047c6ae99SBarry Smith     if (!dd->ly) {
591785e854fSJed Brown       ierr = PetscMalloc1(dd->n, &dd->ly);CHKERRQ(ierr);
59247c6ae99SBarry Smith     }
59347c6ae99SBarry Smith     ierr = PetscMemcpy(dd->ly, ly, dd->n*sizeof(PetscInt));CHKERRQ(ierr);
59447c6ae99SBarry Smith   }
59547c6ae99SBarry Smith   if (lz) {
596ce94432eSBarry Smith     if (dd->p < 0) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
597aa219208SBarry Smith     ierr = DMDACheckOwnershipRanges_Private(da,dd->P,dd->p,lz);CHKERRQ(ierr);
59847c6ae99SBarry Smith     if (!dd->lz) {
599785e854fSJed Brown       ierr = PetscMalloc1(dd->p, &dd->lz);CHKERRQ(ierr);
60047c6ae99SBarry Smith     }
60147c6ae99SBarry Smith     ierr = PetscMemcpy(dd->lz, lz, dd->p*sizeof(PetscInt));CHKERRQ(ierr);
60247c6ae99SBarry Smith   }
60347c6ae99SBarry Smith   PetscFunctionReturn(0);
60447c6ae99SBarry Smith }
60547c6ae99SBarry Smith 
60647c6ae99SBarry Smith /*@
607aa219208SBarry Smith        DMDASetInterpolationType - Sets the type of interpolation that will be
608e727c939SJed Brown           returned by DMCreateInterpolation()
60947c6ae99SBarry Smith 
610aa219208SBarry Smith    Logically Collective on DMDA
61147c6ae99SBarry Smith 
61247c6ae99SBarry Smith    Input Parameter:
61347c6ae99SBarry Smith +  da - initial distributed array
614aa219208SBarry Smith .  ctype - DMDA_Q1 and DMDA_Q0 are currently the only supported forms
61547c6ae99SBarry Smith 
61647c6ae99SBarry Smith    Level: intermediate
61747c6ae99SBarry Smith 
618*95452b02SPatrick Sanan    Notes:
619*95452b02SPatrick Sanan     you should call this on the coarser of the two DMDAs you pass to DMCreateInterpolation()
62047c6ae99SBarry Smith 
62147c6ae99SBarry Smith .keywords:  distributed array, interpolation
62247c6ae99SBarry Smith 
62396e147daSBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType
62447c6ae99SBarry Smith @*/
6257087cfbeSBarry Smith PetscErrorCode  DMDASetInterpolationType(DM da,DMDAInterpolationType ctype)
62647c6ae99SBarry Smith {
62747c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
62847c6ae99SBarry Smith 
62947c6ae99SBarry Smith   PetscFunctionBegin;
63047c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
63147c6ae99SBarry Smith   PetscValidLogicalCollectiveEnum(da,ctype,2);
63247c6ae99SBarry Smith   dd->interptype = ctype;
63347c6ae99SBarry Smith   PetscFunctionReturn(0);
63447c6ae99SBarry Smith }
63547c6ae99SBarry Smith 
6362dde6fd4SLisandro Dalcin /*@
6372dde6fd4SLisandro Dalcin        DMDAGetInterpolationType - Gets the type of interpolation that will be
638e727c939SJed Brown           used by DMCreateInterpolation()
6392dde6fd4SLisandro Dalcin 
6402dde6fd4SLisandro Dalcin    Not Collective
6412dde6fd4SLisandro Dalcin 
6422dde6fd4SLisandro Dalcin    Input Parameter:
6432dde6fd4SLisandro Dalcin .  da - distributed array
6442dde6fd4SLisandro Dalcin 
6452dde6fd4SLisandro Dalcin    Output Parameter:
6462dde6fd4SLisandro Dalcin .  ctype - interpolation type (DMDA_Q1 and DMDA_Q0 are currently the only supported forms)
6472dde6fd4SLisandro Dalcin 
6482dde6fd4SLisandro Dalcin    Level: intermediate
6492dde6fd4SLisandro Dalcin 
6502dde6fd4SLisandro Dalcin .keywords:  distributed array, interpolation
6512dde6fd4SLisandro Dalcin 
652e727c939SJed Brown .seealso: DMDA, DMDAInterpolationType, DMDASetInterpolationType(), DMCreateInterpolation()
6532dde6fd4SLisandro Dalcin @*/
6542dde6fd4SLisandro Dalcin PetscErrorCode  DMDAGetInterpolationType(DM da,DMDAInterpolationType *ctype)
6552dde6fd4SLisandro Dalcin {
6562dde6fd4SLisandro Dalcin   DM_DA *dd = (DM_DA*)da->data;
6572dde6fd4SLisandro Dalcin 
6582dde6fd4SLisandro Dalcin   PetscFunctionBegin;
6592dde6fd4SLisandro Dalcin   PetscValidHeaderSpecific(da,DM_CLASSID,1);
6602dde6fd4SLisandro Dalcin   PetscValidPointer(ctype,2);
6612dde6fd4SLisandro Dalcin   *ctype = dd->interptype;
6622dde6fd4SLisandro Dalcin   PetscFunctionReturn(0);
6632dde6fd4SLisandro Dalcin }
66447c6ae99SBarry Smith 
6656a119db4SBarry Smith /*@C
666aa219208SBarry Smith       DMDAGetNeighbors - Gets an array containing the MPI rank of all the current
66747c6ae99SBarry Smith         processes neighbors.
66847c6ae99SBarry Smith 
66947c6ae99SBarry Smith     Not Collective
67047c6ae99SBarry Smith 
67147c6ae99SBarry Smith    Input Parameter:
672aa219208SBarry Smith .     da - the DMDA object
67347c6ae99SBarry Smith 
67447c6ae99SBarry Smith    Output Parameters:
67547c6ae99SBarry Smith .     ranks - the neighbors ranks, stored with the x index increasing most rapidly.
67647c6ae99SBarry Smith               this process itself is in the list
67747c6ae99SBarry Smith 
678*95452b02SPatrick Sanan    Notes:
679*95452b02SPatrick Sanan     In 2d the array is of length 9, in 3d of length 27
68047c6ae99SBarry Smith           Not supported in 1d
681aa219208SBarry Smith           Do not free the array, it is freed when the DMDA is destroyed.
68247c6ae99SBarry Smith 
683*95452b02SPatrick Sanan    Fortran Notes:
684*95452b02SPatrick Sanan     In fortran you must pass in an array of the appropriate length.
68547c6ae99SBarry Smith 
68647c6ae99SBarry Smith    Level: intermediate
68747c6ae99SBarry Smith 
68847c6ae99SBarry Smith @*/
6897087cfbeSBarry Smith PetscErrorCode  DMDAGetNeighbors(DM da,const PetscMPIInt *ranks[])
69047c6ae99SBarry Smith {
69147c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
6925fd66863SKarl Rupp 
69347c6ae99SBarry Smith   PetscFunctionBegin;
69447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
69547c6ae99SBarry Smith   *ranks = dd->neighbors;
69647c6ae99SBarry Smith   PetscFunctionReturn(0);
69747c6ae99SBarry Smith }
69847c6ae99SBarry Smith 
69947c6ae99SBarry Smith /*@C
700aa219208SBarry Smith       DMDAGetOwnershipRanges - Gets the ranges of indices in the x, y and z direction that are owned by each process
70147c6ae99SBarry Smith 
70247c6ae99SBarry Smith     Not Collective
70347c6ae99SBarry Smith 
70447c6ae99SBarry Smith    Input Parameter:
705aa219208SBarry Smith .     da - the DMDA object
70647c6ae99SBarry Smith 
70747c6ae99SBarry Smith    Output Parameter:
70847c6ae99SBarry Smith +     lx - ownership along x direction (optional)
70947c6ae99SBarry Smith .     ly - ownership along y direction (optional)
71047c6ae99SBarry Smith -     lz - ownership along z direction (optional)
71147c6ae99SBarry Smith 
71247c6ae99SBarry Smith    Level: intermediate
71347c6ae99SBarry Smith 
714aa219208SBarry Smith     Note: these correspond to the optional final arguments passed to DMDACreate(), DMDACreate2d(), DMDACreate3d()
71547c6ae99SBarry Smith 
71647c6ae99SBarry Smith     In Fortran one must pass in arrays lx, ly, and lz that are long enough to hold the values; the sixth, seventh and
717aa219208SBarry Smith     eighth arguments from DMDAGetInfo()
71847c6ae99SBarry Smith 
71947c6ae99SBarry Smith      In C you should not free these arrays, nor change the values in them. They will only have valid values while the
720aa219208SBarry Smith     DMDA they came from still exists (has not been destroyed).
72147c6ae99SBarry Smith 
722e3f3e4b6SBarry Smith     These numbers are NOT multiplied by the number of dof per node.
723e3f3e4b6SBarry Smith 
7241fd49c25SBarry Smith      Not available from Fortran
7251fd49c25SBarry Smith 
726aa219208SBarry Smith .seealso: DMDAGetCorners(), DMDAGetGhostCorners(), DMDACreate(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), VecGetOwnershipRanges()
72747c6ae99SBarry Smith @*/
7287087cfbeSBarry Smith PetscErrorCode  DMDAGetOwnershipRanges(DM da,const PetscInt *lx[],const PetscInt *ly[],const PetscInt *lz[])
72947c6ae99SBarry Smith {
73047c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
73147c6ae99SBarry Smith 
73247c6ae99SBarry Smith   PetscFunctionBegin;
73347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
73447c6ae99SBarry Smith   if (lx) *lx = dd->lx;
73547c6ae99SBarry Smith   if (ly) *ly = dd->ly;
73647c6ae99SBarry Smith   if (lz) *lz = dd->lz;
73747c6ae99SBarry Smith   PetscFunctionReturn(0);
73847c6ae99SBarry Smith }
73947c6ae99SBarry Smith 
74047c6ae99SBarry Smith /*@
741aa219208SBarry Smith      DMDASetRefinementFactor - Set the ratios that the DMDA grid is refined
74247c6ae99SBarry Smith 
743aa219208SBarry Smith     Logically Collective on DMDA
74447c6ae99SBarry Smith 
74547c6ae99SBarry Smith   Input Parameters:
746aa219208SBarry Smith +    da - the DMDA object
74747c6ae99SBarry Smith .    refine_x - ratio of fine grid to coarse in x direction (2 by default)
74847c6ae99SBarry Smith .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
74947c6ae99SBarry Smith -    refine_z - ratio of fine grid to coarse in z direction (2 by default)
75047c6ae99SBarry Smith 
75147c6ae99SBarry Smith   Options Database:
75247c6ae99SBarry Smith +  -da_refine_x - refinement ratio in x direction
75347c6ae99SBarry Smith .  -da_refine_y - refinement ratio in y direction
75447c6ae99SBarry Smith -  -da_refine_z - refinement ratio in z direction
75547c6ae99SBarry Smith 
75647c6ae99SBarry Smith   Level: intermediate
75747c6ae99SBarry Smith 
758*95452b02SPatrick Sanan     Notes:
759*95452b02SPatrick Sanan     Pass PETSC_IGNORE to leave a value unchanged
76047c6ae99SBarry Smith 
761aa219208SBarry Smith .seealso: DMRefine(), DMDAGetRefinementFactor()
76247c6ae99SBarry Smith @*/
7637087cfbeSBarry Smith PetscErrorCode  DMDASetRefinementFactor(DM da, PetscInt refine_x, PetscInt refine_y,PetscInt refine_z)
76447c6ae99SBarry Smith {
76547c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
76647c6ae99SBarry Smith 
76747c6ae99SBarry Smith   PetscFunctionBegin;
76847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
76947c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_x,2);
77047c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_y,3);
77147c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_z,4);
77247c6ae99SBarry Smith 
77347c6ae99SBarry Smith   if (refine_x > 0) dd->refine_x = refine_x;
77447c6ae99SBarry Smith   if (refine_y > 0) dd->refine_y = refine_y;
77547c6ae99SBarry Smith   if (refine_z > 0) dd->refine_z = refine_z;
77647c6ae99SBarry Smith   PetscFunctionReturn(0);
77747c6ae99SBarry Smith }
77847c6ae99SBarry Smith 
77947c6ae99SBarry Smith /*@C
780aa219208SBarry Smith      DMDAGetRefinementFactor - Gets the ratios that the DMDA grid is refined
78147c6ae99SBarry Smith 
78247c6ae99SBarry Smith     Not Collective
78347c6ae99SBarry Smith 
78447c6ae99SBarry Smith   Input Parameter:
785aa219208SBarry Smith .    da - the DMDA object
78647c6ae99SBarry Smith 
78747c6ae99SBarry Smith   Output Parameters:
78847c6ae99SBarry Smith +    refine_x - ratio of fine grid to coarse in x direction (2 by default)
78947c6ae99SBarry Smith .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
79047c6ae99SBarry Smith -    refine_z - ratio of fine grid to coarse in z direction (2 by default)
79147c6ae99SBarry Smith 
79247c6ae99SBarry Smith   Level: intermediate
79347c6ae99SBarry Smith 
794*95452b02SPatrick Sanan     Notes:
795*95452b02SPatrick Sanan     Pass NULL for values you do not need
79647c6ae99SBarry Smith 
797aa219208SBarry Smith .seealso: DMRefine(), DMDASetRefinementFactor()
79847c6ae99SBarry Smith @*/
7997087cfbeSBarry Smith PetscErrorCode  DMDAGetRefinementFactor(DM da, PetscInt *refine_x, PetscInt *refine_y,PetscInt *refine_z)
80047c6ae99SBarry Smith {
80147c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
80247c6ae99SBarry Smith 
80347c6ae99SBarry Smith   PetscFunctionBegin;
80447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
80547c6ae99SBarry Smith   if (refine_x) *refine_x = dd->refine_x;
80647c6ae99SBarry Smith   if (refine_y) *refine_y = dd->refine_y;
80747c6ae99SBarry Smith   if (refine_z) *refine_z = dd->refine_z;
80847c6ae99SBarry Smith   PetscFunctionReturn(0);
80947c6ae99SBarry Smith }
81047c6ae99SBarry Smith 
81147c6ae99SBarry Smith /*@C
812aa219208SBarry Smith      DMDASetGetMatrix - Sets the routine used by the DMDA to allocate a matrix.
81347c6ae99SBarry Smith 
814aa219208SBarry Smith     Logically Collective on DMDA
81547c6ae99SBarry Smith 
81647c6ae99SBarry Smith   Input Parameters:
817aa219208SBarry Smith +    da - the DMDA object
818aa219208SBarry Smith -    f - the function that allocates the matrix for that specific DMDA
81947c6ae99SBarry Smith 
82047c6ae99SBarry Smith   Level: developer
82147c6ae99SBarry Smith 
822*95452b02SPatrick Sanan    Notes:
823*95452b02SPatrick Sanan     See DMDASetBlockFills() that provides a simple way to provide the nonzero structure for
82447c6ae99SBarry Smith        the diagonal and off-diagonal blocks of the matrix
82547c6ae99SBarry Smith 
8261fd49c25SBarry Smith    Not supported from Fortran
8271fd49c25SBarry Smith 
828950540a4SJed Brown .seealso: DMCreateMatrix(), DMDASetBlockFills()
82947c6ae99SBarry Smith @*/
830b412c318SBarry Smith PetscErrorCode  DMDASetGetMatrix(DM da,PetscErrorCode (*f)(DM, Mat*))
83147c6ae99SBarry Smith {
83247c6ae99SBarry Smith   PetscFunctionBegin;
83347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
83425296bd5SBarry Smith   da->ops->creatematrix = f;
83547c6ae99SBarry Smith   PetscFunctionReturn(0);
83647c6ae99SBarry Smith }
83747c6ae99SBarry Smith 
83847c6ae99SBarry Smith /*
83947c6ae99SBarry Smith   Creates "balanced" ownership ranges after refinement, constrained by the need for the
84047c6ae99SBarry Smith   fine grid boundaries to fall within one stencil width of the coarse partition.
84147c6ae99SBarry Smith 
84247c6ae99SBarry Smith   Uses a greedy algorithm to handle non-ideal layouts, could probably do something better.
84347c6ae99SBarry Smith */
84494013140SBarry Smith static PetscErrorCode DMDARefineOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lc[],PetscInt lf[])
84547c6ae99SBarry Smith {
84647c6ae99SBarry Smith   PetscInt       i,totalc = 0,remaining,startc = 0,startf = 0;
84747c6ae99SBarry Smith   PetscErrorCode ierr;
84847c6ae99SBarry Smith 
84947c6ae99SBarry Smith   PetscFunctionBegin;
850ce94432eSBarry Smith   if (ratio < 1) SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Requested refinement ratio %D must be at least 1",ratio);
85147c6ae99SBarry Smith   if (ratio == 1) {
85247c6ae99SBarry Smith     ierr = PetscMemcpy(lf,lc,m*sizeof(lc[0]));CHKERRQ(ierr);
85347c6ae99SBarry Smith     PetscFunctionReturn(0);
85447c6ae99SBarry Smith   }
85547c6ae99SBarry Smith   for (i=0; i<m; i++) totalc += lc[i];
85647c6ae99SBarry Smith   remaining = (!periodic) + ratio * (totalc - (!periodic));
85747c6ae99SBarry Smith   for (i=0; i<m; i++) {
85847c6ae99SBarry Smith     PetscInt want = remaining/(m-i) + !!(remaining%(m-i));
85947c6ae99SBarry Smith     if (i == m-1) lf[i] = want;
86047c6ae99SBarry Smith     else {
8617aca7175SJed Brown       const PetscInt nextc = startc + lc[i];
8627aca7175SJed Brown       /* Move the first fine node of the next subdomain to the right until the coarse node on its left is within one
8637aca7175SJed Brown        * coarse stencil width of the first coarse node in the next subdomain. */
8647aca7175SJed Brown       while ((startf+want)/ratio < nextc - stencil_width) want++;
8657aca7175SJed Brown       /* Move the last fine node in the current subdomain to the left until the coarse node on its right is within one
8667aca7175SJed Brown        * coarse stencil width of the last coarse node in the current subdomain. */
8677aca7175SJed Brown       while ((startf+want-1+ratio-1)/ratio > nextc-1+stencil_width) want--;
8687aca7175SJed Brown       /* Make sure all constraints are satisfied */
86930729d88SBarry Smith       if (want < 0 || want > remaining || ((startf+want)/ratio < nextc - stencil_width)
870ce94432eSBarry 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");
87147c6ae99SBarry Smith     }
87247c6ae99SBarry Smith     lf[i]      = want;
87347c6ae99SBarry Smith     startc    += lc[i];
87447c6ae99SBarry Smith     startf    += lf[i];
87547c6ae99SBarry Smith     remaining -= lf[i];
87647c6ae99SBarry Smith   }
87747c6ae99SBarry Smith   PetscFunctionReturn(0);
87847c6ae99SBarry Smith }
87947c6ae99SBarry Smith 
8802be375d4SJed Brown /*
8812be375d4SJed Brown   Creates "balanced" ownership ranges after coarsening, constrained by the need for the
8822be375d4SJed Brown   fine grid boundaries to fall within one stencil width of the coarse partition.
8832be375d4SJed Brown 
8842be375d4SJed Brown   Uses a greedy algorithm to handle non-ideal layouts, could probably do something better.
8852be375d4SJed Brown */
8862be375d4SJed Brown static PetscErrorCode DMDACoarsenOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lf[],PetscInt lc[])
8872be375d4SJed Brown {
8882be375d4SJed Brown   PetscInt       i,totalf,remaining,startc,startf;
8892be375d4SJed Brown   PetscErrorCode ierr;
8902be375d4SJed Brown 
8912be375d4SJed Brown   PetscFunctionBegin;
892ce94432eSBarry Smith   if (ratio < 1) SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Requested refinement ratio %D must be at least 1",ratio);
8932be375d4SJed Brown   if (ratio == 1) {
8942be375d4SJed Brown     ierr = PetscMemcpy(lc,lf,m*sizeof(lf[0]));CHKERRQ(ierr);
8952be375d4SJed Brown     PetscFunctionReturn(0);
8962be375d4SJed Brown   }
8972be375d4SJed Brown   for (i=0,totalf=0; i<m; i++) totalf += lf[i];
8982be375d4SJed Brown   remaining = (!periodic) + (totalf - (!periodic)) / ratio;
8992be375d4SJed Brown   for (i=0,startc=0,startf=0; i<m; i++) {
9002be375d4SJed Brown     PetscInt want = remaining/(m-i) + !!(remaining%(m-i));
9012be375d4SJed Brown     if (i == m-1) lc[i] = want;
9022be375d4SJed Brown     else {
9032be375d4SJed Brown       const PetscInt nextf = startf+lf[i];
9042be375d4SJed Brown       /* Slide first coarse node of next subdomain to the left until the coarse node to the left of the first fine
9052be375d4SJed Brown        * node is within one stencil width. */
9062be375d4SJed Brown       while (nextf/ratio < startc+want-stencil_width) want--;
9072be375d4SJed Brown       /* Slide the last coarse node of the current subdomain to the right until the coarse node to the right of the last
9082be375d4SJed Brown        * fine node is within one stencil width. */
9092be375d4SJed Brown       while ((nextf-1+ratio-1)/ratio > startc+want-1+stencil_width) want++;
9102be375d4SJed Brown       if (want < 0 || want > remaining
911ce94432eSBarry 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");
9122be375d4SJed Brown     }
9132be375d4SJed Brown     lc[i]      = want;
9142be375d4SJed Brown     startc    += lc[i];
9152be375d4SJed Brown     startf    += lf[i];
9162be375d4SJed Brown     remaining -= lc[i];
9172be375d4SJed Brown   }
9182be375d4SJed Brown   PetscFunctionReturn(0);
9192be375d4SJed Brown }
9202be375d4SJed Brown 
9217087cfbeSBarry Smith PetscErrorCode  DMRefine_DA(DM da,MPI_Comm comm,DM *daref)
92247c6ae99SBarry Smith {
92347c6ae99SBarry Smith   PetscErrorCode ierr;
924c73cfb54SMatthew G. Knepley   PetscInt       M,N,P,i,dim;
9259a42bb27SBarry Smith   DM             da2;
92647c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data,*dd2;
92747c6ae99SBarry Smith 
92847c6ae99SBarry Smith   PetscFunctionBegin;
92947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
93047c6ae99SBarry Smith   PetscValidPointer(daref,3);
93147c6ae99SBarry Smith 
932c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(da, &dim);CHKERRQ(ierr);
933bff4a2f0SMatthew G. Knepley   if (dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
93447c6ae99SBarry Smith     M = dd->refine_x*dd->M;
93547c6ae99SBarry Smith   } else {
93647c6ae99SBarry Smith     M = 1 + dd->refine_x*(dd->M - 1);
93747c6ae99SBarry Smith   }
938bff4a2f0SMatthew G. Knepley   if (dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
939c73cfb54SMatthew G. Knepley     if (dim > 1) {
94047c6ae99SBarry Smith       N = dd->refine_y*dd->N;
94147c6ae99SBarry Smith     } else {
9421860e6e9SBarry Smith       N = 1;
9431860e6e9SBarry Smith     }
9441860e6e9SBarry Smith   } else {
94547c6ae99SBarry Smith     N = 1 + dd->refine_y*(dd->N - 1);
94647c6ae99SBarry Smith   }
947bff4a2f0SMatthew G. Knepley   if (dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
948c73cfb54SMatthew G. Knepley     if (dim > 2) {
94947c6ae99SBarry Smith       P = dd->refine_z*dd->P;
95047c6ae99SBarry Smith     } else {
9511860e6e9SBarry Smith       P = 1;
9521860e6e9SBarry Smith     }
9531860e6e9SBarry Smith   } else {
95447c6ae99SBarry Smith     P = 1 + dd->refine_z*(dd->P - 1);
95547c6ae99SBarry Smith   }
956ce94432eSBarry Smith   ierr = DMDACreate(PetscObjectComm((PetscObject)da),&da2);CHKERRQ(ierr);
957397b6216SJed Brown   ierr = DMSetOptionsPrefix(da2,((PetscObject)da)->prefix);CHKERRQ(ierr);
958c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(da2,dim);CHKERRQ(ierr);
959397b6216SJed Brown   ierr = DMDASetSizes(da2,M,N,P);CHKERRQ(ierr);
960397b6216SJed Brown   ierr = DMDASetNumProcs(da2,dd->m,dd->n,dd->p);CHKERRQ(ierr);
961397b6216SJed Brown   ierr = DMDASetBoundaryType(da2,dd->bx,dd->by,dd->bz);CHKERRQ(ierr);
962397b6216SJed Brown   ierr = DMDASetDof(da2,dd->w);CHKERRQ(ierr);
963397b6216SJed Brown   ierr = DMDASetStencilType(da2,dd->stencil_type);CHKERRQ(ierr);
964397b6216SJed Brown   ierr = DMDASetStencilWidth(da2,dd->s);CHKERRQ(ierr);
965c73cfb54SMatthew G. Knepley   if (dim == 3) {
96647c6ae99SBarry Smith     PetscInt *lx,*ly,*lz;
967dcca6d9dSJed Brown     ierr = PetscMalloc3(dd->m,&lx,dd->n,&ly,dd->p,&lz);CHKERRQ(ierr);
968bff4a2f0SMatthew G. Knepley     ierr = DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr);
969bff4a2f0SMatthew G. Knepley     ierr = DMDARefineOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr);
970bff4a2f0SMatthew G. Knepley     ierr = DMDARefineOwnershipRanges(da,(PetscBool)(dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz);CHKERRQ(ierr);
971397b6216SJed Brown     ierr = DMDASetOwnershipRanges(da2,lx,ly,lz);CHKERRQ(ierr);
97247c6ae99SBarry Smith     ierr = PetscFree3(lx,ly,lz);CHKERRQ(ierr);
973c73cfb54SMatthew G. Knepley   } else if (dim == 2) {
97447c6ae99SBarry Smith     PetscInt *lx,*ly;
975dcca6d9dSJed Brown     ierr = PetscMalloc2(dd->m,&lx,dd->n,&ly);CHKERRQ(ierr);
976bff4a2f0SMatthew G. Knepley     ierr = DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr);
977bff4a2f0SMatthew G. Knepley     ierr = DMDARefineOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly);CHKERRQ(ierr);
9780298fd71SBarry Smith     ierr = DMDASetOwnershipRanges(da2,lx,ly,NULL);CHKERRQ(ierr);
97947c6ae99SBarry Smith     ierr = PetscFree2(lx,ly);CHKERRQ(ierr);
980c73cfb54SMatthew G. Knepley   } else if (dim == 1) {
98147c6ae99SBarry Smith     PetscInt *lx;
982785e854fSJed Brown     ierr = PetscMalloc1(dd->m,&lx);CHKERRQ(ierr);
983bff4a2f0SMatthew G. Knepley     ierr = DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx);CHKERRQ(ierr);
9840298fd71SBarry Smith     ierr = DMDASetOwnershipRanges(da2,lx,NULL,NULL);CHKERRQ(ierr);
98547c6ae99SBarry Smith     ierr = PetscFree(lx);CHKERRQ(ierr);
98647c6ae99SBarry Smith   }
98747c6ae99SBarry Smith   dd2 = (DM_DA*)da2->data;
98847c6ae99SBarry Smith 
98947c6ae99SBarry Smith   /* allow overloaded (user replaced) operations to be inherited by refinement clones */
99025296bd5SBarry Smith   da2->ops->creatematrix = da->ops->creatematrix;
99125296bd5SBarry Smith   /* da2->ops->createinterpolation = da->ops->createinterpolation; this causes problem with SNESVI */
99247c6ae99SBarry Smith   da2->ops->getcoloring = da->ops->getcoloring;
99347c6ae99SBarry Smith   dd2->interptype       = dd->interptype;
99447c6ae99SBarry Smith 
99547c6ae99SBarry Smith   /* copy fill information if given */
99647c6ae99SBarry Smith   if (dd->dfill) {
997854ce69bSBarry Smith     ierr = PetscMalloc1(dd->dfill[dd->w]+dd->w+1,&dd2->dfill);CHKERRQ(ierr);
99847c6ae99SBarry Smith     ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr);
99947c6ae99SBarry Smith   }
100047c6ae99SBarry Smith   if (dd->ofill) {
1001854ce69bSBarry Smith     ierr = PetscMalloc1(dd->ofill[dd->w]+dd->w+1,&dd2->ofill);CHKERRQ(ierr);
100247c6ae99SBarry Smith     ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr);
100347c6ae99SBarry Smith   }
100447c6ae99SBarry Smith   /* copy the refine information */
1005397b6216SJed Brown   dd2->coarsen_x = dd2->refine_x = dd->refine_x;
1006397b6216SJed Brown   dd2->coarsen_y = dd2->refine_y = dd->refine_y;
1007397b6216SJed Brown   dd2->coarsen_z = dd2->refine_z = dd->refine_z;
100847c6ae99SBarry Smith 
1009897f7067SBarry Smith   if (dd->refine_z_hier) {
1010897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_z_hier_n) {
1011897f7067SBarry Smith       dd2->refine_z = dd->refine_z_hier[da->levelup - da->leveldown + 1];
1012897f7067SBarry Smith     }
1013897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_z_hier_n) {
1014897f7067SBarry Smith       dd2->coarsen_z = dd->refine_z_hier[da->levelup - da->leveldown];
1015897f7067SBarry Smith     }
1016897f7067SBarry Smith     dd2->refine_z_hier_n = dd->refine_z_hier_n;
1017897f7067SBarry Smith     ierr = PetscMalloc1(dd2->refine_z_hier_n,&dd2->refine_z_hier);CHKERRQ(ierr);
1018897f7067SBarry Smith     ierr = PetscMemcpy(dd2->refine_z_hier,dd->refine_z_hier,dd2->refine_z_hier_n*sizeof(PetscInt));CHKERRQ(ierr);
1019897f7067SBarry Smith   }
1020897f7067SBarry Smith   if (dd->refine_y_hier) {
1021897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_y_hier_n) {
1022897f7067SBarry Smith       dd2->refine_y = dd->refine_y_hier[da->levelup - da->leveldown + 1];
1023897f7067SBarry Smith     }
1024897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_y_hier_n) {
1025897f7067SBarry Smith       dd2->coarsen_y = dd->refine_y_hier[da->levelup - da->leveldown];
1026897f7067SBarry Smith     }
1027897f7067SBarry Smith     dd2->refine_y_hier_n = dd->refine_y_hier_n;
1028897f7067SBarry Smith     ierr = PetscMalloc1(dd2->refine_y_hier_n,&dd2->refine_y_hier);CHKERRQ(ierr);
1029897f7067SBarry Smith     ierr = PetscMemcpy(dd2->refine_y_hier,dd->refine_y_hier,dd2->refine_y_hier_n*sizeof(PetscInt));CHKERRQ(ierr);
1030897f7067SBarry Smith   }
1031897f7067SBarry Smith   if (dd->refine_x_hier) {
1032897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_x_hier_n) {
1033897f7067SBarry Smith       dd2->refine_x = dd->refine_x_hier[da->levelup - da->leveldown + 1];
1034897f7067SBarry Smith     }
1035897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_x_hier_n) {
1036897f7067SBarry Smith       dd2->coarsen_x = dd->refine_x_hier[da->levelup - da->leveldown];
1037897f7067SBarry Smith     }
1038897f7067SBarry Smith     dd2->refine_x_hier_n = dd->refine_x_hier_n;
1039897f7067SBarry Smith     ierr = PetscMalloc1(dd2->refine_x_hier_n,&dd2->refine_x_hier);CHKERRQ(ierr);
1040897f7067SBarry Smith     ierr = PetscMemcpy(dd2->refine_x_hier,dd->refine_x_hier,dd2->refine_x_hier_n*sizeof(PetscInt));CHKERRQ(ierr);
1041897f7067SBarry Smith   }
1042897f7067SBarry Smith 
1043897f7067SBarry Smith 
104447c6ae99SBarry Smith   /* copy vector type information */
1045c0dedaeaSBarry Smith   ierr = DMSetVecType(da2,da->vectype);CHKERRQ(ierr);
1046ddcf8b74SDave May 
1047efd51863SBarry Smith   dd2->lf = dd->lf;
1048efd51863SBarry Smith   dd2->lj = dd->lj;
1049efd51863SBarry Smith 
10506e87535bSJed Brown   da2->leveldown = da->leveldown;
10516e87535bSJed Brown   da2->levelup   = da->levelup + 1;
10528865f1eaSKarl Rupp 
10536e87535bSJed Brown   ierr = DMSetUp(da2);CHKERRQ(ierr);
10546e87535bSJed Brown 
1055ddcf8b74SDave May   /* interpolate coordinates if they are set on the coarse grid */
10566636e97aSMatthew G Knepley   if (da->coordinates) {
1057ddcf8b74SDave May     DM  cdaf,cdac;
1058ddcf8b74SDave May     Vec coordsc,coordsf;
1059ddcf8b74SDave May     Mat II;
1060ddcf8b74SDave May 
10616636e97aSMatthew G Knepley     ierr = DMGetCoordinateDM(da,&cdac);CHKERRQ(ierr);
10626636e97aSMatthew G Knepley     ierr = DMGetCoordinates(da,&coordsc);CHKERRQ(ierr);
10636636e97aSMatthew G Knepley     ierr = DMGetCoordinateDM(da2,&cdaf);CHKERRQ(ierr);
1064b61d3410SDave May     /* force creation of the coordinate vector */
1065b61d3410SDave May     ierr = DMDASetUniformCoordinates(da2,0.0,1.0,0.0,1.0,0.0,1.0);CHKERRQ(ierr);
10666636e97aSMatthew G Knepley     ierr = DMGetCoordinates(da2,&coordsf);CHKERRQ(ierr);
10670298fd71SBarry Smith     ierr = DMCreateInterpolation(cdac,cdaf,&II,NULL);CHKERRQ(ierr);
1068ddcf8b74SDave May     ierr = MatInterpolate(II,coordsc,coordsf);CHKERRQ(ierr);
1069fcfd50ebSBarry Smith     ierr = MatDestroy(&II);CHKERRQ(ierr);
1070ddcf8b74SDave May   }
1071397b6216SJed Brown 
1072f3141302SJed Brown   for (i=0; i<da->bs; i++) {
1073f3141302SJed Brown     const char *fieldname;
1074f3141302SJed Brown     ierr = DMDAGetFieldName(da,i,&fieldname);CHKERRQ(ierr);
1075f3141302SJed Brown     ierr = DMDASetFieldName(da2,i,fieldname);CHKERRQ(ierr);
1076f3141302SJed Brown   }
1077397b6216SJed Brown 
107847c6ae99SBarry Smith   *daref = da2;
107947c6ae99SBarry Smith   PetscFunctionReturn(0);
108047c6ae99SBarry Smith }
108147c6ae99SBarry Smith 
1082397b6216SJed Brown 
10837087cfbeSBarry Smith PetscErrorCode  DMCoarsen_DA(DM da, MPI_Comm comm,DM *daref)
108447c6ae99SBarry Smith {
108547c6ae99SBarry Smith   PetscErrorCode ierr;
1086c73cfb54SMatthew G. Knepley   PetscInt       M,N,P,i,dim;
10879a42bb27SBarry Smith   DM             da2;
108847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data,*dd2;
108947c6ae99SBarry Smith 
109047c6ae99SBarry Smith   PetscFunctionBegin;
109147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
109247c6ae99SBarry Smith   PetscValidPointer(daref,3);
109347c6ae99SBarry Smith 
1094c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(da, &dim);CHKERRQ(ierr);
1095bff4a2f0SMatthew G. Knepley   if (dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1096397b6216SJed Brown     M = dd->M / dd->coarsen_x;
109747c6ae99SBarry Smith   } else {
1098397b6216SJed Brown     M = 1 + (dd->M - 1) / dd->coarsen_x;
109947c6ae99SBarry Smith   }
1100bff4a2f0SMatthew G. Knepley   if (dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1101c73cfb54SMatthew G. Knepley     if (dim > 1) {
1102397b6216SJed Brown       N = dd->N / dd->coarsen_y;
110347c6ae99SBarry Smith     } else {
11041860e6e9SBarry Smith       N = 1;
11051860e6e9SBarry Smith     }
11061860e6e9SBarry Smith   } else {
1107397b6216SJed Brown     N = 1 + (dd->N - 1) / dd->coarsen_y;
110847c6ae99SBarry Smith   }
1109bff4a2f0SMatthew G. Knepley   if (dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1110c73cfb54SMatthew G. Knepley     if (dim > 2) {
1111397b6216SJed Brown       P = dd->P / dd->coarsen_z;
111247c6ae99SBarry Smith     } else {
11131860e6e9SBarry Smith       P = 1;
11141860e6e9SBarry Smith     }
11151860e6e9SBarry Smith   } else {
1116397b6216SJed Brown     P = 1 + (dd->P - 1) / dd->coarsen_z;
111747c6ae99SBarry Smith   }
1118ce94432eSBarry Smith   ierr = DMDACreate(PetscObjectComm((PetscObject)da),&da2);CHKERRQ(ierr);
1119397b6216SJed Brown   ierr = DMSetOptionsPrefix(da2,((PetscObject)da)->prefix);CHKERRQ(ierr);
1120c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(da2,dim);CHKERRQ(ierr);
1121397b6216SJed Brown   ierr = DMDASetSizes(da2,M,N,P);CHKERRQ(ierr);
1122397b6216SJed Brown   ierr = DMDASetNumProcs(da2,dd->m,dd->n,dd->p);CHKERRQ(ierr);
1123397b6216SJed Brown   ierr = DMDASetBoundaryType(da2,dd->bx,dd->by,dd->bz);CHKERRQ(ierr);
1124397b6216SJed Brown   ierr = DMDASetDof(da2,dd->w);CHKERRQ(ierr);
1125397b6216SJed Brown   ierr = DMDASetStencilType(da2,dd->stencil_type);CHKERRQ(ierr);
1126397b6216SJed Brown   ierr = DMDASetStencilWidth(da2,dd->s);CHKERRQ(ierr);
1127c73cfb54SMatthew G. Knepley   if (dim == 3) {
11282be375d4SJed Brown     PetscInt *lx,*ly,*lz;
1129dcca6d9dSJed Brown     ierr = PetscMalloc3(dd->m,&lx,dd->n,&ly,dd->p,&lz);CHKERRQ(ierr);
1130bff4a2f0SMatthew G. Knepley     ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx);CHKERRQ(ierr);
1131bff4a2f0SMatthew G. Knepley     ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_y,dd->n,dd->ly,ly);CHKERRQ(ierr);
1132bff4a2f0SMatthew G. Knepley     ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_z,dd->p,dd->lz,lz);CHKERRQ(ierr);
1133397b6216SJed Brown     ierr = DMDASetOwnershipRanges(da2,lx,ly,lz);CHKERRQ(ierr);
11342be375d4SJed Brown     ierr = PetscFree3(lx,ly,lz);CHKERRQ(ierr);
1135c73cfb54SMatthew G. Knepley   } else if (dim == 2) {
11362be375d4SJed Brown     PetscInt *lx,*ly;
1137dcca6d9dSJed Brown     ierr = PetscMalloc2(dd->m,&lx,dd->n,&ly);CHKERRQ(ierr);
1138bff4a2f0SMatthew G. Knepley     ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx);CHKERRQ(ierr);
1139bff4a2f0SMatthew G. Knepley     ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_y,dd->n,dd->ly,ly);CHKERRQ(ierr);
11400298fd71SBarry Smith     ierr = DMDASetOwnershipRanges(da2,lx,ly,NULL);CHKERRQ(ierr);
11412be375d4SJed Brown     ierr = PetscFree2(lx,ly);CHKERRQ(ierr);
1142c73cfb54SMatthew G. Knepley   } else if (dim == 1) {
11432be375d4SJed Brown     PetscInt *lx;
1144785e854fSJed Brown     ierr = PetscMalloc1(dd->m,&lx);CHKERRQ(ierr);
1145bff4a2f0SMatthew G. Knepley     ierr = DMDACoarsenOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx);CHKERRQ(ierr);
11460298fd71SBarry Smith     ierr = DMDASetOwnershipRanges(da2,lx,NULL,NULL);CHKERRQ(ierr);
11472be375d4SJed Brown     ierr = PetscFree(lx);CHKERRQ(ierr);
114847c6ae99SBarry Smith   }
114947c6ae99SBarry Smith   dd2 = (DM_DA*)da2->data;
115047c6ae99SBarry Smith 
11514dcab191SBarry Smith   /* allow overloaded (user replaced) operations to be inherited by refinement clones; why are only some inherited and not all? */
115225296bd5SBarry Smith   /* da2->ops->createinterpolation = da->ops->createinterpolation; copying this one causes trouble for DMSetVI */
115325296bd5SBarry Smith   da2->ops->creatematrix = da->ops->creatematrix;
115447c6ae99SBarry Smith   da2->ops->getcoloring  = da->ops->getcoloring;
115547c6ae99SBarry Smith   dd2->interptype        = dd->interptype;
115647c6ae99SBarry Smith 
115747c6ae99SBarry Smith   /* copy fill information if given */
115847c6ae99SBarry Smith   if (dd->dfill) {
1159854ce69bSBarry Smith     ierr = PetscMalloc1(dd->dfill[dd->w]+dd->w+1,&dd2->dfill);CHKERRQ(ierr);
116047c6ae99SBarry Smith     ierr = PetscMemcpy(dd2->dfill,dd->dfill,(dd->dfill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr);
116147c6ae99SBarry Smith   }
116247c6ae99SBarry Smith   if (dd->ofill) {
1163854ce69bSBarry Smith     ierr = PetscMalloc1(dd->ofill[dd->w]+dd->w+1,&dd2->ofill);CHKERRQ(ierr);
116447c6ae99SBarry Smith     ierr = PetscMemcpy(dd2->ofill,dd->ofill,(dd->ofill[dd->w]+dd->w+1)*sizeof(PetscInt));CHKERRQ(ierr);
116547c6ae99SBarry Smith   }
116647c6ae99SBarry Smith   /* copy the refine information */
1167397b6216SJed Brown   dd2->coarsen_x = dd2->refine_x = dd->coarsen_x;
1168397b6216SJed Brown   dd2->coarsen_y = dd2->refine_y = dd->coarsen_y;
1169397b6216SJed Brown   dd2->coarsen_z = dd2->refine_z = dd->coarsen_z;
117047c6ae99SBarry Smith 
1171897f7067SBarry Smith   if (dd->refine_z_hier) {
1172897f7067SBarry Smith     if (da->levelup - da->leveldown -1 > -1 && da->levelup - da->leveldown - 1< dd->refine_z_hier_n) {
1173897f7067SBarry Smith       dd2->refine_z = dd->refine_z_hier[da->levelup - da->leveldown - 1];
1174897f7067SBarry Smith     }
1175897f7067SBarry Smith     if (da->levelup - da->leveldown - 2 > -1 && da->levelup - da->leveldown - 2 < dd->refine_z_hier_n) {
1176897f7067SBarry Smith       dd2->coarsen_z = dd->refine_z_hier[da->levelup - da->leveldown - 2];
1177897f7067SBarry Smith     }
1178897f7067SBarry Smith     dd2->refine_z_hier_n = dd->refine_z_hier_n;
1179897f7067SBarry Smith     ierr = PetscMalloc1(dd2->refine_z_hier_n,&dd2->refine_z_hier);CHKERRQ(ierr);
1180897f7067SBarry Smith     ierr = PetscMemcpy(dd2->refine_z_hier,dd->refine_z_hier,dd2->refine_z_hier_n*sizeof(PetscInt));CHKERRQ(ierr);
1181897f7067SBarry Smith   }
1182897f7067SBarry Smith   if (dd->refine_y_hier) {
1183897f7067SBarry Smith     if (da->levelup - da->leveldown - 1 > -1 && da->levelup - da->leveldown - 1< dd->refine_y_hier_n) {
1184897f7067SBarry Smith       dd2->refine_y = dd->refine_y_hier[da->levelup - da->leveldown - 1];
1185897f7067SBarry Smith     }
1186897f7067SBarry Smith     if (da->levelup - da->leveldown - 2 > -1 && da->levelup - da->leveldown - 2 < dd->refine_y_hier_n) {
1187897f7067SBarry Smith       dd2->coarsen_y = dd->refine_y_hier[da->levelup - da->leveldown - 2];
1188897f7067SBarry Smith     }
1189897f7067SBarry Smith     dd2->refine_y_hier_n = dd->refine_y_hier_n;
1190897f7067SBarry Smith     ierr = PetscMalloc1(dd2->refine_y_hier_n,&dd2->refine_y_hier);CHKERRQ(ierr);
1191897f7067SBarry Smith     ierr = PetscMemcpy(dd2->refine_y_hier,dd->refine_y_hier,dd2->refine_y_hier_n*sizeof(PetscInt));CHKERRQ(ierr);
1192897f7067SBarry Smith   }
1193897f7067SBarry Smith   if (dd->refine_x_hier) {
1194897f7067SBarry Smith     if (da->levelup - da->leveldown - 1 > -1 && da->levelup - da->leveldown - 1 < dd->refine_x_hier_n) {
1195897f7067SBarry Smith       dd2->refine_x = dd->refine_x_hier[da->levelup - da->leveldown - 1];
1196897f7067SBarry Smith     }
1197897f7067SBarry Smith     if (da->levelup - da->leveldown - 2 > -1 && da->levelup - da->leveldown - 2 < dd->refine_x_hier_n) {
1198897f7067SBarry Smith       dd2->coarsen_x = dd->refine_x_hier[da->levelup - da->leveldown - 2];
1199897f7067SBarry Smith     }
1200897f7067SBarry Smith     dd2->refine_x_hier_n = dd->refine_x_hier_n;
1201897f7067SBarry Smith     ierr = PetscMalloc1(dd2->refine_x_hier_n,&dd2->refine_x_hier);CHKERRQ(ierr);
1202897f7067SBarry Smith     ierr = PetscMemcpy(dd2->refine_x_hier,dd->refine_x_hier,dd2->refine_x_hier_n*sizeof(PetscInt));CHKERRQ(ierr);
1203897f7067SBarry Smith   }
1204897f7067SBarry Smith 
120547c6ae99SBarry Smith   /* copy vector type information */
1206c0dedaeaSBarry Smith   ierr = DMSetVecType(da2,da->vectype);CHKERRQ(ierr);
120747c6ae99SBarry Smith 
1208644e2e5bSBarry Smith   dd2->lf = dd->lf;
1209644e2e5bSBarry Smith   dd2->lj = dd->lj;
1210644e2e5bSBarry Smith 
12116e87535bSJed Brown   da2->leveldown = da->leveldown + 1;
12126e87535bSJed Brown   da2->levelup   = da->levelup;
12138865f1eaSKarl Rupp 
12146e87535bSJed Brown   ierr = DMSetUp(da2);CHKERRQ(ierr);
12156e87535bSJed Brown 
1216ddcf8b74SDave May   /* inject coordinates if they are set on the fine grid */
12176636e97aSMatthew G Knepley   if (da->coordinates) {
1218ddcf8b74SDave May     DM         cdaf,cdac;
1219ddcf8b74SDave May     Vec        coordsc,coordsf;
12206dbf9973SLawrence Mitchell     Mat        inject;
12216dbf9973SLawrence Mitchell     VecScatter vscat;
1222ddcf8b74SDave May 
12236636e97aSMatthew G Knepley     ierr = DMGetCoordinateDM(da,&cdaf);CHKERRQ(ierr);
12246636e97aSMatthew G Knepley     ierr = DMGetCoordinates(da,&coordsf);CHKERRQ(ierr);
12256636e97aSMatthew G Knepley     ierr = DMGetCoordinateDM(da2,&cdac);CHKERRQ(ierr);
1226b61d3410SDave May     /* force creation of the coordinate vector */
1227b61d3410SDave May     ierr = DMDASetUniformCoordinates(da2,0.0,1.0,0.0,1.0,0.0,1.0);CHKERRQ(ierr);
12286636e97aSMatthew G Knepley     ierr = DMGetCoordinates(da2,&coordsc);CHKERRQ(ierr);
1229ddcf8b74SDave May 
1230e727c939SJed Brown     ierr = DMCreateInjection(cdac,cdaf,&inject);CHKERRQ(ierr);
12316dbf9973SLawrence Mitchell     ierr = MatScatterGetVecScatter(inject,&vscat);CHKERRQ(ierr);
12326dbf9973SLawrence Mitchell     ierr = VecScatterBegin(vscat,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12336dbf9973SLawrence Mitchell     ierr = VecScatterEnd(vscat,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12346dbf9973SLawrence Mitchell     ierr = MatDestroy(&inject);CHKERRQ(ierr);
1235ddcf8b74SDave May   }
1236f98405f7SJed Brown 
1237f98405f7SJed Brown   for (i=0; i<da->bs; i++) {
1238f98405f7SJed Brown     const char *fieldname;
1239f98405f7SJed Brown     ierr = DMDAGetFieldName(da,i,&fieldname);CHKERRQ(ierr);
1240f98405f7SJed Brown     ierr = DMDASetFieldName(da2,i,fieldname);CHKERRQ(ierr);
1241f98405f7SJed Brown   }
1242f98405f7SJed Brown 
124347c6ae99SBarry Smith   *daref = da2;
124447c6ae99SBarry Smith   PetscFunctionReturn(0);
124547c6ae99SBarry Smith }
124647c6ae99SBarry Smith 
12477087cfbeSBarry Smith PetscErrorCode  DMRefineHierarchy_DA(DM da,PetscInt nlevels,DM daf[])
124847c6ae99SBarry Smith {
124947c6ae99SBarry Smith   PetscErrorCode ierr;
125047c6ae99SBarry Smith   PetscInt       i,n,*refx,*refy,*refz;
125147c6ae99SBarry Smith 
125247c6ae99SBarry Smith   PetscFunctionBegin;
125347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
1254ce94432eSBarry Smith   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
125547c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
125647c6ae99SBarry Smith   PetscValidPointer(daf,3);
125747c6ae99SBarry Smith 
1258aa219208SBarry Smith   /* Get refinement factors, defaults taken from the coarse DMDA */
1259dcca6d9dSJed Brown   ierr = PetscMalloc3(nlevels,&refx,nlevels,&refy,nlevels,&refz);CHKERRQ(ierr);
126047c6ae99SBarry Smith   for (i=0; i<nlevels; i++) {
1261aa219208SBarry Smith     ierr = DMDAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]);CHKERRQ(ierr);
126247c6ae99SBarry Smith   }
126347c6ae99SBarry Smith   n    = nlevels;
1264c5929fdfSBarry Smith   ierr = PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,NULL);CHKERRQ(ierr);
126547c6ae99SBarry Smith   n    = nlevels;
1266c5929fdfSBarry Smith   ierr = PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,NULL);CHKERRQ(ierr);
126747c6ae99SBarry Smith   n    = nlevels;
1268c5929fdfSBarry Smith   ierr = PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,NULL);CHKERRQ(ierr);
126947c6ae99SBarry Smith 
1270aa219208SBarry Smith   ierr = DMDASetRefinementFactor(da,refx[0],refy[0],refz[0]);CHKERRQ(ierr);
1271ce94432eSBarry Smith   ierr = DMRefine(da,PetscObjectComm((PetscObject)da),&daf[0]);CHKERRQ(ierr);
127247c6ae99SBarry Smith   for (i=1; i<nlevels; i++) {
1273aa219208SBarry Smith     ierr = DMDASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]);CHKERRQ(ierr);
1274ce94432eSBarry Smith     ierr = DMRefine(daf[i-1],PetscObjectComm((PetscObject)da),&daf[i]);CHKERRQ(ierr);
127547c6ae99SBarry Smith   }
127647c6ae99SBarry Smith   ierr = PetscFree3(refx,refy,refz);CHKERRQ(ierr);
127747c6ae99SBarry Smith   PetscFunctionReturn(0);
127847c6ae99SBarry Smith }
127947c6ae99SBarry Smith 
12807087cfbeSBarry Smith PetscErrorCode  DMCoarsenHierarchy_DA(DM da,PetscInt nlevels,DM dac[])
128147c6ae99SBarry Smith {
128247c6ae99SBarry Smith   PetscErrorCode ierr;
128347c6ae99SBarry Smith   PetscInt       i;
128447c6ae99SBarry Smith 
128547c6ae99SBarry Smith   PetscFunctionBegin;
128647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
1287ce94432eSBarry Smith   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
128847c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
128947c6ae99SBarry Smith   PetscValidPointer(dac,3);
1290ce94432eSBarry Smith   ierr = DMCoarsen(da,PetscObjectComm((PetscObject)da),&dac[0]);CHKERRQ(ierr);
129147c6ae99SBarry Smith   for (i=1; i<nlevels; i++) {
1292ce94432eSBarry Smith     ierr = DMCoarsen(dac[i-1],PetscObjectComm((PetscObject)da),&dac[i]);CHKERRQ(ierr);
129347c6ae99SBarry Smith   }
129447c6ae99SBarry Smith   PetscFunctionReturn(0);
129547c6ae99SBarry Smith }
129662197512SBarry Smith 
129762197512SBarry Smith #include <petscgll.h>
129862197512SBarry Smith 
129962197512SBarry Smith PetscErrorCode DMDASetGLLCoordinates_1d(DM dm,PetscGLL *gll)
130062197512SBarry Smith {
130162197512SBarry Smith   PetscErrorCode ierr;
130262197512SBarry Smith   PetscInt       i,j,n = gll->n,xs,xn,q;
130362197512SBarry Smith   PetscScalar    *xx;
130462197512SBarry Smith   PetscReal      h;
130562197512SBarry Smith   Vec            x;
130662197512SBarry Smith   DM_DA          *da = (DM_DA*)dm->data;
130762197512SBarry Smith 
130862197512SBarry Smith   PetscFunctionBegin;
130962197512SBarry Smith   if (da->bx != DM_BOUNDARY_PERIODIC) {
131062197512SBarry Smith     ierr = DMDAGetInfo(dm,NULL,&q,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
131162197512SBarry Smith     q    = (q-1)/(n-1);  /* number of spectral elements */
131262197512SBarry Smith     h    = 2.0/q;
131362197512SBarry Smith     ierr = DMDAGetCorners(dm,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr);
131462197512SBarry Smith     xs   = xs/(n-1);
131562197512SBarry Smith     xn   = xn/(n-1);
131662197512SBarry Smith     ierr = DMDASetUniformCoordinates(dm,-1.,1.,0.,0.,0.,0.);CHKERRQ(ierr);
131762197512SBarry Smith     ierr = DMGetCoordinates(dm,&x);CHKERRQ(ierr);
131862197512SBarry Smith     ierr = DMDAVecGetArray(dm,x,&xx);CHKERRQ(ierr);
131962197512SBarry Smith 
132062197512SBarry Smith     /* loop over local spectral elements */
132162197512SBarry Smith     for (j=xs; j<xs+xn; j++) {
132262197512SBarry Smith       /*
132362197512SBarry Smith        Except for the first process, each process starts on the second GLL point of the first element on that process
132462197512SBarry Smith        */
132562197512SBarry Smith       for (i= (j == xs && xs > 0)? 1 : 0; i<n; i++) {
132662197512SBarry Smith         xx[j*(n-1) + i] = -1.0 + h*j + h*(gll->nodes[i]+1.0)/2.;
132762197512SBarry Smith       }
132862197512SBarry Smith     }
132962197512SBarry Smith     ierr = DMDAVecRestoreArray(dm,x,&xx);CHKERRQ(ierr);
133062197512SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not yet implemented for periodic");
133162197512SBarry Smith   PetscFunctionReturn(0);
133262197512SBarry Smith }
133362197512SBarry Smith 
13341fd49c25SBarry Smith /*@
133562197512SBarry Smith 
133662197512SBarry 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
133762197512SBarry Smith 
133862197512SBarry Smith    Collective on DM
133962197512SBarry Smith 
134062197512SBarry Smith    Input Parameters:
134162197512SBarry Smith +   da - the DMDA object
134262197512SBarry Smith -   gll - the GLL object
134362197512SBarry Smith 
1344*95452b02SPatrick Sanan    Notes:
1345*95452b02SPatrick Sanan     the parallel decomposition of grid points must correspond to the degree of the GLL. That is, the number of grid points
134662197512SBarry Smith           on each process much be divisible by the number of GLL elements needed per process. This depends on whether the DM is
134762197512SBarry Smith           periodic or not.
134862197512SBarry Smith 
1349edc382c3SSatish Balay    Level: advanced
1350edc382c3SSatish Balay 
135162197512SBarry Smith .seealso:   DMDACreate(), PetscGLLCreate(), DMGetCoordinates()
135262197512SBarry Smith @*/
135362197512SBarry Smith PetscErrorCode DMDASetGLLCoordinates(DM da,PetscGLL *gll)
135462197512SBarry Smith {
135562197512SBarry Smith   PetscErrorCode ierr;
135662197512SBarry Smith 
135762197512SBarry Smith   PetscFunctionBegin;
135862197512SBarry Smith   if (da->dim == 1) {
135962197512SBarry Smith     ierr = DMDASetGLLCoordinates_1d(da,gll);CHKERRQ(ierr);
136062197512SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not yet implemented for 2 or 3d");
136162197512SBarry Smith   PetscFunctionReturn(0);
136262197512SBarry Smith }
1363