xref: /petsc/src/dm/impls/da/da.c (revision 2f27f4d1f547c0e4e709f14698496f430b70e63e)
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 
19db781477SPatrick 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 
54db781477SPatrick 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;
719566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)da),&size));
72e3f3e4b6SBarry Smith     if ((dd->m > 0) && (dd->n < 0)) {
73e3f3e4b6SBarry Smith       dd->n = size/dd->m;
7463a3b9bcSJacob Faibussowitsch       PetscCheck(dd->n*dd->m == size,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"%" PetscInt_FMT " 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;
7863a3b9bcSJacob Faibussowitsch       PetscCheck(dd->n*dd->m == size,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"%" PetscInt_FMT " 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 
95db781477SPatrick Sanan .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 
124db781477SPatrick Sanan .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 
152db781477SPatrick Sanan .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);
160dadcf809SJacob Faibussowitsch   PetscValidIntPointer(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 
1802b3cbbdaSStefano Zampini .seealso: `DMCreateDomainDecomposition()`, `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 
2072b3cbbdaSStefano Zampini .seealso: `DMCreateDomainDecomposition()`, `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 
2372b3cbbdaSStefano Zampini .seealso: `DMCreateDomainDecomposition()`, `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 
2602b3cbbdaSStefano Zampini .seealso: `DMCreateDomainDecomposition()`, `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 
290db781477SPatrick Sanan .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 
3116858538eSMatthew G. Knepley   if (da->coordinates[0].dm) PetscCall(DMDASetOffset(da->coordinates[0].dm,xo,yo,zo,Mo,No,Po));
312d886c4f4SPeter Brune   PetscFunctionReturn(0);
313d886c4f4SPeter Brune }
314d886c4f4SPeter Brune 
315d886c4f4SPeter Brune /*@
316d886c4f4SPeter Brune   DMDAGetOffset - Gets the index offset of the DA.
317d886c4f4SPeter Brune 
318d886c4f4SPeter Brune   Not collective
319d886c4f4SPeter Brune 
320d886c4f4SPeter Brune   Input Parameter:
321d886c4f4SPeter Brune . da  - The DMDA
322d886c4f4SPeter Brune 
323d886c4f4SPeter Brune   Output Parameters:
324d886c4f4SPeter Brune + xo  - The offset in the x direction
325d886c4f4SPeter Brune . yo  - The offset in the y direction
32695c13181SPeter Brune . zo  - The offset in the z direction
32795c13181SPeter Brune . Mo  - The global size in the x direction
32895c13181SPeter Brune . No  - The global size in the y direction
32995c13181SPeter Brune - Po  - The global size in the z direction
330d886c4f4SPeter Brune 
331d886c4f4SPeter Brune   Level: intermediate
332d886c4f4SPeter Brune 
333db781477SPatrick Sanan .seealso: `DMDASetOffset()`, `DMDAVecGetArray()`
334d886c4f4SPeter Brune @*/
33595c13181SPeter Brune PetscErrorCode  DMDAGetOffset(DM da,PetscInt *xo,PetscInt *yo,PetscInt *zo,PetscInt *Mo,PetscInt *No,PetscInt *Po)
336d886c4f4SPeter Brune {
337d886c4f4SPeter Brune   DM_DA *dd = (DM_DA*)da->data;
338d886c4f4SPeter Brune 
339d886c4f4SPeter Brune   PetscFunctionBegin;
340a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
341d886c4f4SPeter Brune   if (xo) *xo = dd->xo;
342d886c4f4SPeter Brune   if (yo) *yo = dd->yo;
343d886c4f4SPeter Brune   if (zo) *zo = dd->zo;
34495c13181SPeter Brune   if (Mo) *Mo = dd->Mo;
34595c13181SPeter Brune   if (No) *No = dd->No;
34695c13181SPeter Brune   if (Po) *Po = dd->Po;
347d886c4f4SPeter Brune   PetscFunctionReturn(0);
348d886c4f4SPeter Brune }
349d886c4f4SPeter Brune 
35040234c92SPeter Brune /*@
35140234c92SPeter Brune   DMDAGetNonOverlappingRegion - Gets the indices of the nonoverlapping region of a subdomain DM.
35240234c92SPeter Brune 
35340234c92SPeter Brune   Not collective
35440234c92SPeter Brune 
35540234c92SPeter Brune   Input Parameter:
35640234c92SPeter Brune . da  - The DMDA
35740234c92SPeter Brune 
35840234c92SPeter Brune   Output Parameters:
35940234c92SPeter Brune + xs  - The start of the region in x
36040234c92SPeter Brune . ys  - The start of the region in y
36140234c92SPeter Brune . zs  - The start of the region in z
36240234c92SPeter Brune . xs  - The size of the region in x
36340234c92SPeter Brune . ys  - The size of the region in y
364a2b725a8SWilliam Gropp - zs  - The size of the region in z
36540234c92SPeter Brune 
36640234c92SPeter Brune   Level: intermediate
36740234c92SPeter Brune 
368db781477SPatrick Sanan .seealso: `DMDAGetOffset()`, `DMDAVecGetArray()`
36940234c92SPeter Brune @*/
37040234c92SPeter Brune PetscErrorCode  DMDAGetNonOverlappingRegion(DM da, PetscInt *xs, PetscInt *ys, PetscInt *zs, PetscInt *xm, PetscInt *ym, PetscInt *zm)
37140234c92SPeter Brune {
37240234c92SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
37340234c92SPeter Brune 
37440234c92SPeter Brune   PetscFunctionBegin;
375a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
37640234c92SPeter Brune   if (xs) *xs = dd->nonxs;
37740234c92SPeter Brune   if (ys) *ys = dd->nonys;
37840234c92SPeter Brune   if (zs) *zs = dd->nonzs;
37940234c92SPeter Brune   if (xm) *xm = dd->nonxm;
38040234c92SPeter Brune   if (ym) *ym = dd->nonym;
38140234c92SPeter Brune   if (zm) *zm = dd->nonzm;
38240234c92SPeter Brune   PetscFunctionReturn(0);
38340234c92SPeter Brune }
38440234c92SPeter Brune 
38540234c92SPeter Brune /*@
38640234c92SPeter Brune   DMDASetNonOverlappingRegion - Sets the indices of the nonoverlapping region of a subdomain DM.
38740234c92SPeter Brune 
38840234c92SPeter Brune   Collective on DA
38940234c92SPeter Brune 
390d8d19677SJose E. Roman   Input Parameters:
39140234c92SPeter Brune + da  - The DMDA
39240234c92SPeter Brune . xs  - The start of the region in x
39340234c92SPeter Brune . ys  - The start of the region in y
39440234c92SPeter Brune . zs  - The start of the region in z
39540234c92SPeter Brune . xs  - The size of the region in x
39640234c92SPeter Brune . ys  - The size of the region in y
397a2b725a8SWilliam Gropp - zs  - The size of the region in z
39840234c92SPeter Brune 
39940234c92SPeter Brune   Level: intermediate
40040234c92SPeter Brune 
401db781477SPatrick Sanan .seealso: `DMDAGetOffset()`, `DMDAVecGetArray()`
40240234c92SPeter Brune @*/
40340234c92SPeter Brune PetscErrorCode  DMDASetNonOverlappingRegion(DM da, PetscInt xs, PetscInt ys, PetscInt zs, PetscInt xm, PetscInt ym, PetscInt zm)
40440234c92SPeter Brune {
40540234c92SPeter Brune   DM_DA          *dd = (DM_DA*)da->data;
40640234c92SPeter Brune 
40740234c92SPeter Brune   PetscFunctionBegin;
408a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
40940234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,xs,2);
41040234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,ys,3);
41140234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,zs,4);
41240234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,xm,5);
41340234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,ym,6);
41440234c92SPeter Brune   PetscValidLogicalCollectiveInt(da,zm,7);
41540234c92SPeter Brune   dd->nonxs = xs;
41640234c92SPeter Brune   dd->nonys = ys;
41740234c92SPeter Brune   dd->nonzs = zs;
41840234c92SPeter Brune   dd->nonxm = xm;
41940234c92SPeter Brune   dd->nonym = ym;
42040234c92SPeter Brune   dd->nonzm = zm;
42140234c92SPeter Brune 
42240234c92SPeter Brune   PetscFunctionReturn(0);
42340234c92SPeter Brune }
42488661749SPeter Brune 
42547c6ae99SBarry Smith /*@
426aa219208SBarry Smith   DMDASetStencilType - Sets the type of the communication stencil
42747c6ae99SBarry Smith 
428d083f849SBarry Smith   Logically Collective on da
42947c6ae99SBarry Smith 
430d8d19677SJose E. Roman   Input Parameters:
431aa219208SBarry Smith + da    - The DMDA
432aa219208SBarry Smith - stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
43347c6ae99SBarry Smith 
43447c6ae99SBarry Smith   Level: intermediate
43547c6ae99SBarry Smith 
436db781477SPatrick Sanan .seealso: `DMDACreate()`, `DMDestroy()`, `DMDA`
43747c6ae99SBarry Smith @*/
4387087cfbeSBarry Smith PetscErrorCode  DMDASetStencilType(DM da, DMDAStencilType stype)
43947c6ae99SBarry Smith {
44047c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
44147c6ae99SBarry Smith 
44247c6ae99SBarry Smith   PetscFunctionBegin;
443a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
44447c6ae99SBarry Smith   PetscValidLogicalCollectiveEnum(da,stype,2);
4457a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
44647c6ae99SBarry Smith   dd->stencil_type = stype;
44747c6ae99SBarry Smith   PetscFunctionReturn(0);
44847c6ae99SBarry Smith }
44947c6ae99SBarry Smith 
450fb6725baSMatthew G. Knepley /*@
451fb6725baSMatthew G. Knepley   DMDAGetStencilType - Gets the type of the communication stencil
452fb6725baSMatthew G. Knepley 
453fb6725baSMatthew G. Knepley   Not collective
454fb6725baSMatthew G. Knepley 
455fb6725baSMatthew G. Knepley   Input Parameter:
456fb6725baSMatthew G. Knepley . da    - The DMDA
457fb6725baSMatthew G. Knepley 
458fb6725baSMatthew G. Knepley   Output Parameter:
459fb6725baSMatthew G. Knepley . stype - The stencil type, use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
460fb6725baSMatthew G. Knepley 
461fb6725baSMatthew G. Knepley   Level: intermediate
462fb6725baSMatthew G. Knepley 
463db781477SPatrick Sanan .seealso: `DMDACreate()`, `DMDestroy()`, `DMDA`
464fb6725baSMatthew G. Knepley @*/
465fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetStencilType(DM da, DMDAStencilType *stype)
466fb6725baSMatthew G. Knepley {
467fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA*)da->data;
468fb6725baSMatthew G. Knepley 
469fb6725baSMatthew G. Knepley   PetscFunctionBegin;
470a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
471fb6725baSMatthew G. Knepley   PetscValidPointer(stype,2);
472fb6725baSMatthew G. Knepley   *stype = dd->stencil_type;
473fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
474fb6725baSMatthew G. Knepley }
475fb6725baSMatthew G. Knepley 
47647c6ae99SBarry Smith /*@
477aa219208SBarry Smith   DMDASetStencilWidth - Sets the width of the communication stencil
47847c6ae99SBarry Smith 
479d083f849SBarry Smith   Logically Collective on da
48047c6ae99SBarry Smith 
481d8d19677SJose E. Roman   Input Parameters:
482aa219208SBarry Smith + da    - The DMDA
48347c6ae99SBarry Smith - width - The stencil width
48447c6ae99SBarry Smith 
48547c6ae99SBarry Smith   Level: intermediate
48647c6ae99SBarry Smith 
487db781477SPatrick Sanan .seealso: `DMDACreate()`, `DMDestroy()`, `DMDA`
48847c6ae99SBarry Smith @*/
4897087cfbeSBarry Smith PetscErrorCode  DMDASetStencilWidth(DM da, PetscInt width)
49047c6ae99SBarry Smith {
49147c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
49247c6ae99SBarry Smith 
49347c6ae99SBarry Smith   PetscFunctionBegin;
494a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
49547c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,width,2);
4967a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
49747c6ae99SBarry Smith   dd->s = width;
49847c6ae99SBarry Smith   PetscFunctionReturn(0);
49947c6ae99SBarry Smith }
50047c6ae99SBarry Smith 
501fb6725baSMatthew G. Knepley /*@
502fb6725baSMatthew G. Knepley   DMDAGetStencilWidth - Gets the width of the communication stencil
503fb6725baSMatthew G. Knepley 
504fb6725baSMatthew G. Knepley   Not collective
505fb6725baSMatthew G. Knepley 
506fb6725baSMatthew G. Knepley   Input Parameter:
507fb6725baSMatthew G. Knepley . da    - The DMDA
508fb6725baSMatthew G. Knepley 
509fb6725baSMatthew G. Knepley   Output Parameter:
510fb6725baSMatthew G. Knepley . width - The stencil width
511fb6725baSMatthew G. Knepley 
512fb6725baSMatthew G. Knepley   Level: intermediate
513fb6725baSMatthew G. Knepley 
514db781477SPatrick Sanan .seealso: `DMDACreate()`, `DMDestroy()`, `DMDA`
515fb6725baSMatthew G. Knepley @*/
516fb6725baSMatthew G. Knepley PetscErrorCode DMDAGetStencilWidth(DM da, PetscInt *width)
517fb6725baSMatthew G. Knepley {
518fb6725baSMatthew G. Knepley   DM_DA *dd = (DM_DA *) da->data;
519fb6725baSMatthew G. Knepley 
520fb6725baSMatthew G. Knepley   PetscFunctionBegin;
521a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
522dadcf809SJacob Faibussowitsch   PetscValidIntPointer(width,2);
523fb6725baSMatthew G. Knepley   *width = dd->s;
524fb6725baSMatthew G. Knepley   PetscFunctionReturn(0);
525fb6725baSMatthew G. Knepley }
526fb6725baSMatthew G. Knepley 
527aa219208SBarry Smith static PetscErrorCode DMDACheckOwnershipRanges_Private(DM da,PetscInt M,PetscInt m,const PetscInt lx[])
52847c6ae99SBarry Smith {
52947c6ae99SBarry Smith   PetscInt i,sum;
53047c6ae99SBarry Smith 
53147c6ae99SBarry Smith   PetscFunctionBegin;
5327a8be351SBarry Smith   PetscCheck(M >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Global dimension not set");
53347c6ae99SBarry Smith   for (i=sum=0; i<m; i++) sum += lx[i];
53463a3b9bcSJacob Faibussowitsch   PetscCheck(sum == M,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"Ownership ranges sum to %" PetscInt_FMT " but global dimension is %" PetscInt_FMT,sum,M);
53547c6ae99SBarry Smith   PetscFunctionReturn(0);
53647c6ae99SBarry Smith }
53747c6ae99SBarry Smith 
53847c6ae99SBarry Smith /*@
539aa219208SBarry Smith   DMDASetOwnershipRanges - Sets the number of nodes in each direction on each process
54047c6ae99SBarry Smith 
541d083f849SBarry Smith   Logically Collective on da
54247c6ae99SBarry Smith 
543d8d19677SJose E. Roman   Input Parameters:
544aa219208SBarry Smith + da - The DMDA
5450298fd71SBarry 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
5460298fd71SBarry 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
5470298fd71SBarry 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.
54847c6ae99SBarry Smith 
54947c6ae99SBarry Smith   Level: intermediate
55047c6ae99SBarry Smith 
551e3f3e4b6SBarry Smith   Note: these numbers are NOT multiplied by the number of dof per node.
552e3f3e4b6SBarry Smith 
553db781477SPatrick Sanan .seealso: `DMDACreate()`, `DMDestroy()`, `DMDA`
55447c6ae99SBarry Smith @*/
5557087cfbeSBarry Smith PetscErrorCode  DMDASetOwnershipRanges(DM da, const PetscInt lx[], const PetscInt ly[], const PetscInt lz[])
55647c6ae99SBarry Smith {
55747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
55847c6ae99SBarry Smith 
55947c6ae99SBarry Smith   PetscFunctionBegin;
560a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
5617a8be351SBarry Smith   PetscCheck(!da->setupcalled,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"This function must be called before DMSetUp()");
56247c6ae99SBarry Smith   if (lx) {
5637a8be351SBarry Smith     PetscCheck(dd->m >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
5649566063dSJacob Faibussowitsch     PetscCall(DMDACheckOwnershipRanges_Private(da,dd->M,dd->m,lx));
56547c6ae99SBarry Smith     if (!dd->lx) {
5669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(dd->m, &dd->lx));
56747c6ae99SBarry Smith     }
5689566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd->lx, lx, dd->m));
56947c6ae99SBarry Smith   }
57047c6ae99SBarry Smith   if (ly) {
5717a8be351SBarry Smith     PetscCheck(dd->n >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
5729566063dSJacob Faibussowitsch     PetscCall(DMDACheckOwnershipRanges_Private(da,dd->N,dd->n,ly));
57347c6ae99SBarry Smith     if (!dd->ly) {
5749566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(dd->n, &dd->ly));
57547c6ae99SBarry Smith     }
5769566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd->ly, ly, dd->n));
57747c6ae99SBarry Smith   }
57847c6ae99SBarry Smith   if (lz) {
5797a8be351SBarry Smith     PetscCheck(dd->p >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONGSTATE,"Cannot set ownership ranges before setting number of procs");
5809566063dSJacob Faibussowitsch     PetscCall(DMDACheckOwnershipRanges_Private(da,dd->P,dd->p,lz));
58147c6ae99SBarry Smith     if (!dd->lz) {
5829566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(dd->p, &dd->lz));
58347c6ae99SBarry Smith     }
5849566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd->lz, lz, dd->p));
58547c6ae99SBarry Smith   }
58647c6ae99SBarry Smith   PetscFunctionReturn(0);
58747c6ae99SBarry Smith }
58847c6ae99SBarry Smith 
58947c6ae99SBarry Smith /*@
590aa219208SBarry Smith        DMDASetInterpolationType - Sets the type of interpolation that will be
591e727c939SJed Brown           returned by DMCreateInterpolation()
59247c6ae99SBarry Smith 
593d083f849SBarry Smith    Logically Collective on da
59447c6ae99SBarry Smith 
595d8d19677SJose E. Roman    Input Parameters:
59647c6ae99SBarry Smith +  da - initial distributed array
597a2b725a8SWilliam Gropp -  ctype - DMDA_Q1 and DMDA_Q0 are currently the only supported forms
59847c6ae99SBarry Smith 
59947c6ae99SBarry Smith    Level: intermediate
60047c6ae99SBarry Smith 
60195452b02SPatrick Sanan    Notes:
60295452b02SPatrick Sanan     you should call this on the coarser of the two DMDAs you pass to DMCreateInterpolation()
60347c6ae99SBarry Smith 
604db781477SPatrick Sanan .seealso: `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMDestroy()`, `DMDA`, `DMDAInterpolationType`
60547c6ae99SBarry Smith @*/
6067087cfbeSBarry Smith PetscErrorCode  DMDASetInterpolationType(DM da,DMDAInterpolationType ctype)
60747c6ae99SBarry Smith {
60847c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
60947c6ae99SBarry Smith 
61047c6ae99SBarry Smith   PetscFunctionBegin;
611a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
61247c6ae99SBarry Smith   PetscValidLogicalCollectiveEnum(da,ctype,2);
61347c6ae99SBarry Smith   dd->interptype = ctype;
61447c6ae99SBarry Smith   PetscFunctionReturn(0);
61547c6ae99SBarry Smith }
61647c6ae99SBarry Smith 
6172dde6fd4SLisandro Dalcin /*@
6182dde6fd4SLisandro Dalcin        DMDAGetInterpolationType - Gets the type of interpolation that will be
619e727c939SJed Brown           used by DMCreateInterpolation()
6202dde6fd4SLisandro Dalcin 
6212dde6fd4SLisandro Dalcin    Not Collective
6222dde6fd4SLisandro Dalcin 
6232dde6fd4SLisandro Dalcin    Input Parameter:
6242dde6fd4SLisandro Dalcin .  da - distributed array
6252dde6fd4SLisandro Dalcin 
6262dde6fd4SLisandro Dalcin    Output Parameter:
6272dde6fd4SLisandro Dalcin .  ctype - interpolation type (DMDA_Q1 and DMDA_Q0 are currently the only supported forms)
6282dde6fd4SLisandro Dalcin 
6292dde6fd4SLisandro Dalcin    Level: intermediate
6302dde6fd4SLisandro Dalcin 
631db781477SPatrick Sanan .seealso: `DMDA`, `DMDAInterpolationType`, `DMDASetInterpolationType()`, `DMCreateInterpolation()`
6322dde6fd4SLisandro Dalcin @*/
6332dde6fd4SLisandro Dalcin PetscErrorCode  DMDAGetInterpolationType(DM da,DMDAInterpolationType *ctype)
6342dde6fd4SLisandro Dalcin {
6352dde6fd4SLisandro Dalcin   DM_DA *dd = (DM_DA*)da->data;
6362dde6fd4SLisandro Dalcin 
6372dde6fd4SLisandro Dalcin   PetscFunctionBegin;
638a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
6392dde6fd4SLisandro Dalcin   PetscValidPointer(ctype,2);
6402dde6fd4SLisandro Dalcin   *ctype = dd->interptype;
6412dde6fd4SLisandro Dalcin   PetscFunctionReturn(0);
6422dde6fd4SLisandro Dalcin }
64347c6ae99SBarry Smith 
6446a119db4SBarry Smith /*@C
645aa219208SBarry Smith       DMDAGetNeighbors - Gets an array containing the MPI rank of all the current
64647c6ae99SBarry Smith         processes neighbors.
64747c6ae99SBarry Smith 
64847c6ae99SBarry Smith     Not Collective
64947c6ae99SBarry Smith 
65047c6ae99SBarry Smith    Input Parameter:
651aa219208SBarry Smith .     da - the DMDA object
65247c6ae99SBarry Smith 
65347c6ae99SBarry Smith    Output Parameters:
65447c6ae99SBarry Smith .     ranks - the neighbors ranks, stored with the x index increasing most rapidly.
65547c6ae99SBarry Smith               this process itself is in the list
65647c6ae99SBarry Smith 
65795452b02SPatrick Sanan    Notes:
65895452b02SPatrick Sanan     In 2d the array is of length 9, in 3d of length 27
65947c6ae99SBarry Smith           Not supported in 1d
660aa219208SBarry Smith           Do not free the array, it is freed when the DMDA is destroyed.
66147c6ae99SBarry Smith 
66295452b02SPatrick Sanan    Fortran Notes:
66395452b02SPatrick Sanan     In fortran you must pass in an array of the appropriate length.
66447c6ae99SBarry Smith 
66547c6ae99SBarry Smith    Level: intermediate
66647c6ae99SBarry Smith 
66747c6ae99SBarry Smith @*/
6687087cfbeSBarry Smith PetscErrorCode  DMDAGetNeighbors(DM da,const PetscMPIInt *ranks[])
66947c6ae99SBarry Smith {
67047c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
6715fd66863SKarl Rupp 
67247c6ae99SBarry Smith   PetscFunctionBegin;
673a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
67447c6ae99SBarry Smith   *ranks = dd->neighbors;
67547c6ae99SBarry Smith   PetscFunctionReturn(0);
67647c6ae99SBarry Smith }
67747c6ae99SBarry Smith 
67847c6ae99SBarry Smith /*@C
679aa219208SBarry Smith       DMDAGetOwnershipRanges - Gets the ranges of indices in the x, y and z direction that are owned by each process
68047c6ae99SBarry Smith 
68147c6ae99SBarry Smith     Not Collective
68247c6ae99SBarry Smith 
68347c6ae99SBarry Smith    Input Parameter:
684aa219208SBarry Smith .     da - the DMDA object
68547c6ae99SBarry Smith 
686d8d19677SJose E. Roman    Output Parameters:
68747c6ae99SBarry Smith +     lx - ownership along x direction (optional)
68847c6ae99SBarry Smith .     ly - ownership along y direction (optional)
68947c6ae99SBarry Smith -     lz - ownership along z direction (optional)
69047c6ae99SBarry Smith 
69147c6ae99SBarry Smith    Level: intermediate
69247c6ae99SBarry Smith 
693aa219208SBarry Smith     Note: these correspond to the optional final arguments passed to DMDACreate(), DMDACreate2d(), DMDACreate3d()
69447c6ae99SBarry Smith 
69547c6ae99SBarry Smith     In Fortran one must pass in arrays lx, ly, and lz that are long enough to hold the values; the sixth, seventh and
696aa219208SBarry Smith     eighth arguments from DMDAGetInfo()
69747c6ae99SBarry Smith 
69847c6ae99SBarry Smith      In C you should not free these arrays, nor change the values in them. They will only have valid values while the
699aa219208SBarry Smith     DMDA they came from still exists (has not been destroyed).
70047c6ae99SBarry Smith 
701e3f3e4b6SBarry Smith     These numbers are NOT multiplied by the number of dof per node.
702e3f3e4b6SBarry Smith 
703db781477SPatrick Sanan .seealso: `DMDAGetCorners()`, `DMDAGetGhostCorners()`, `DMDACreate()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `VecGetOwnershipRanges()`
70447c6ae99SBarry Smith @*/
7057087cfbeSBarry Smith PetscErrorCode  DMDAGetOwnershipRanges(DM da,const PetscInt *lx[],const PetscInt *ly[],const PetscInt *lz[])
70647c6ae99SBarry Smith {
70747c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
70847c6ae99SBarry Smith 
70947c6ae99SBarry Smith   PetscFunctionBegin;
710a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
71147c6ae99SBarry Smith   if (lx) *lx = dd->lx;
71247c6ae99SBarry Smith   if (ly) *ly = dd->ly;
71347c6ae99SBarry Smith   if (lz) *lz = dd->lz;
71447c6ae99SBarry Smith   PetscFunctionReturn(0);
71547c6ae99SBarry Smith }
71647c6ae99SBarry Smith 
71747c6ae99SBarry Smith /*@
718aa219208SBarry Smith      DMDASetRefinementFactor - Set the ratios that the DMDA grid is refined
71947c6ae99SBarry Smith 
720d083f849SBarry Smith     Logically Collective on da
72147c6ae99SBarry Smith 
72247c6ae99SBarry Smith   Input Parameters:
723aa219208SBarry Smith +    da - the DMDA object
72447c6ae99SBarry Smith .    refine_x - ratio of fine grid to coarse in x direction (2 by default)
72547c6ae99SBarry Smith .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
72647c6ae99SBarry Smith -    refine_z - ratio of fine grid to coarse in z direction (2 by default)
72747c6ae99SBarry Smith 
72847c6ae99SBarry Smith   Options Database:
72948eeb7c8SBarry Smith +  -da_refine_x refine_x - refinement ratio in x direction
73048eeb7c8SBarry Smith .  -da_refine_y rafine_y - refinement ratio in y direction
73148eeb7c8SBarry Smith .  -da_refine_z refine_z - refinement ratio in z direction
73248eeb7c8SBarry Smith -  -da_refine <n> - refine the DMDA object n times when it is created.
73347c6ae99SBarry Smith 
73447c6ae99SBarry Smith   Level: intermediate
73547c6ae99SBarry Smith 
73695452b02SPatrick Sanan     Notes:
73795452b02SPatrick Sanan     Pass PETSC_IGNORE to leave a value unchanged
73847c6ae99SBarry Smith 
739db781477SPatrick Sanan .seealso: `DMRefine()`, `DMDAGetRefinementFactor()`
74047c6ae99SBarry Smith @*/
7417087cfbeSBarry Smith PetscErrorCode  DMDASetRefinementFactor(DM da, PetscInt refine_x, PetscInt refine_y,PetscInt refine_z)
74247c6ae99SBarry Smith {
74347c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
74447c6ae99SBarry Smith 
74547c6ae99SBarry Smith   PetscFunctionBegin;
746a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
74747c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_x,2);
74847c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_y,3);
74947c6ae99SBarry Smith   PetscValidLogicalCollectiveInt(da,refine_z,4);
75047c6ae99SBarry Smith 
75147c6ae99SBarry Smith   if (refine_x > 0) dd->refine_x = refine_x;
75247c6ae99SBarry Smith   if (refine_y > 0) dd->refine_y = refine_y;
75347c6ae99SBarry Smith   if (refine_z > 0) dd->refine_z = refine_z;
75447c6ae99SBarry Smith   PetscFunctionReturn(0);
75547c6ae99SBarry Smith }
75647c6ae99SBarry Smith 
75747c6ae99SBarry Smith /*@C
758aa219208SBarry Smith      DMDAGetRefinementFactor - Gets the ratios that the DMDA grid is refined
75947c6ae99SBarry Smith 
76047c6ae99SBarry Smith     Not Collective
76147c6ae99SBarry Smith 
76247c6ae99SBarry Smith   Input Parameter:
763aa219208SBarry Smith .    da - the DMDA object
76447c6ae99SBarry Smith 
76547c6ae99SBarry Smith   Output Parameters:
76647c6ae99SBarry Smith +    refine_x - ratio of fine grid to coarse in x direction (2 by default)
76747c6ae99SBarry Smith .    refine_y - ratio of fine grid to coarse in y direction (2 by default)
76847c6ae99SBarry Smith -    refine_z - ratio of fine grid to coarse in z direction (2 by default)
76947c6ae99SBarry Smith 
77047c6ae99SBarry Smith   Level: intermediate
77147c6ae99SBarry Smith 
77295452b02SPatrick Sanan     Notes:
77395452b02SPatrick Sanan     Pass NULL for values you do not need
77447c6ae99SBarry Smith 
775db781477SPatrick Sanan .seealso: `DMRefine()`, `DMDASetRefinementFactor()`
77647c6ae99SBarry Smith @*/
7777087cfbeSBarry Smith PetscErrorCode  DMDAGetRefinementFactor(DM da, PetscInt *refine_x, PetscInt *refine_y,PetscInt *refine_z)
77847c6ae99SBarry Smith {
77947c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
78047c6ae99SBarry Smith 
78147c6ae99SBarry Smith   PetscFunctionBegin;
782a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
78347c6ae99SBarry Smith   if (refine_x) *refine_x = dd->refine_x;
78447c6ae99SBarry Smith   if (refine_y) *refine_y = dd->refine_y;
78547c6ae99SBarry Smith   if (refine_z) *refine_z = dd->refine_z;
78647c6ae99SBarry Smith   PetscFunctionReturn(0);
78747c6ae99SBarry Smith }
78847c6ae99SBarry Smith 
78947c6ae99SBarry Smith /*@C
790aa219208SBarry Smith      DMDASetGetMatrix - Sets the routine used by the DMDA to allocate a matrix.
79147c6ae99SBarry Smith 
792d083f849SBarry Smith     Logically Collective on da
79347c6ae99SBarry Smith 
79447c6ae99SBarry Smith   Input Parameters:
795aa219208SBarry Smith +    da - the DMDA object
796aa219208SBarry Smith -    f - the function that allocates the matrix for that specific DMDA
79747c6ae99SBarry Smith 
79847c6ae99SBarry Smith   Level: developer
79947c6ae99SBarry Smith 
80095452b02SPatrick Sanan    Notes:
80195452b02SPatrick Sanan     See DMDASetBlockFills() that provides a simple way to provide the nonzero structure for
80247c6ae99SBarry Smith        the diagonal and off-diagonal blocks of the matrix
80347c6ae99SBarry Smith 
8041fd49c25SBarry Smith    Not supported from Fortran
8051fd49c25SBarry Smith 
806db781477SPatrick Sanan .seealso: `DMCreateMatrix()`, `DMDASetBlockFills()`
80747c6ae99SBarry Smith @*/
808b412c318SBarry Smith PetscErrorCode  DMDASetGetMatrix(DM da,PetscErrorCode (*f)(DM, Mat*))
80947c6ae99SBarry Smith {
81047c6ae99SBarry Smith   PetscFunctionBegin;
811a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
81225296bd5SBarry Smith   da->ops->creatematrix = f;
81347c6ae99SBarry Smith   PetscFunctionReturn(0);
81447c6ae99SBarry Smith }
81547c6ae99SBarry Smith 
81638fb4e8eSJunchao Zhang /*@
81738fb4e8eSJunchao Zhang    DMDAMapMatStencilToGlobal - Map a list of MatStencils on a grid to global indices.
81838fb4e8eSJunchao Zhang 
81938fb4e8eSJunchao Zhang    Not Collective
82038fb4e8eSJunchao Zhang 
82138fb4e8eSJunchao Zhang    Input Parameters:
82238fb4e8eSJunchao Zhang +  da - the DMDA object
82338fb4e8eSJunchao Zhang .  m - number of MatStencils
82438fb4e8eSJunchao Zhang -  idxm - grid points (and component number when dof > 1)
82538fb4e8eSJunchao Zhang 
8261179163eSBarry Smith    Output Parameter:
8271179163eSBarry Smith .  gidxm - global row indices
8281179163eSBarry Smith 
8291179163eSBarry Smith    Level: intermediate
83038fb4e8eSJunchao Zhang 
83138fb4e8eSJunchao Zhang .seealso: `MatStencil`
83238fb4e8eSJunchao Zhang @*/
83338fb4e8eSJunchao Zhang PetscErrorCode DMDAMapMatStencilToGlobal(DM da,PetscInt m,const MatStencil idxm[],PetscInt gidxm[])
83438fb4e8eSJunchao Zhang {
83538fb4e8eSJunchao Zhang   const DM_DA            *dd = (const DM_DA*)da->data;
83638fb4e8eSJunchao Zhang   const PetscInt         *dxm = (const PetscInt*)idxm;
83738fb4e8eSJunchao Zhang   PetscInt               i,j,sdim,tmp,dim;
83838fb4e8eSJunchao Zhang   PetscInt               dims[4],starts[4],dims2[3],starts2[3],dof = dd->w;
83938fb4e8eSJunchao Zhang   ISLocalToGlobalMapping ltog;
84038fb4e8eSJunchao Zhang 
84138fb4e8eSJunchao Zhang   PetscFunctionBegin;
84238fb4e8eSJunchao Zhang   if (m <= 0) PetscFunctionReturn(0);
84338fb4e8eSJunchao Zhang 
844*2f27f4d1SJunchao Zhang   /* Code adapted from DMDAGetGhostCorners() */
84538fb4e8eSJunchao Zhang   starts2[0] = dd->Xs/dof + dd->xo;
84638fb4e8eSJunchao Zhang   starts2[1] = dd->Ys  + dd->yo;
84738fb4e8eSJunchao Zhang   starts2[2] = dd->Zs  + dd->zo;
84838fb4e8eSJunchao Zhang   dims2[0]   = (dd->Xe - dd->Xs)/dof;
84938fb4e8eSJunchao Zhang   dims2[1]   = (dd->Ye - dd->Ys);
85038fb4e8eSJunchao Zhang   dims2[2]   = (dd->Ze - dd->Zs);
85138fb4e8eSJunchao Zhang 
852*2f27f4d1SJunchao Zhang   /* As if we do MatSetStencil() to get dims[]/starts[] of mat->stencil */
853*2f27f4d1SJunchao Zhang   dim  = da->dim; /* DA dim: 1 to 3 */
854*2f27f4d1SJunchao Zhang   sdim = dim + (dof > 1? 1 : 0); /* Dimensions in MatStencil's (k,j,i,c) view */
855*2f27f4d1SJunchao Zhang   for (i=0; i<dim; i++) { /* Reverse the order and also skip the unused dimensions */
856*2f27f4d1SJunchao Zhang     dims[i]   = dims2[dim-i-1]; /* ex. dims/starts[] are in order of {i} for 1D, {j,i} for 2D and {k,j,i} for 3D */
85738fb4e8eSJunchao Zhang     starts[i] = starts2[dim-i-1];
85838fb4e8eSJunchao Zhang   }
859*2f27f4d1SJunchao Zhang   starts[dim] = 0; /* Append the extra dim for dof (won't be used below if dof=1) */
86038fb4e8eSJunchao Zhang   dims[dim]   = dof;
86138fb4e8eSJunchao Zhang 
86238fb4e8eSJunchao Zhang   /* Map stencils to local indices (code adapted from MatSetValuesStencil()) */
86338fb4e8eSJunchao Zhang   for (i=0; i<m; i++) {
864*2f27f4d1SJunchao Zhang     dxm += 3-dim; /* Input is {k,j,i,c}; move the pointer to the first used index, e.g., j in 2D */
865*2f27f4d1SJunchao Zhang     tmp  = 0;
866*2f27f4d1SJunchao Zhang     for (j=0; j<sdim; j++) { /* Iter over, ex. j,i or j,i,c in 2D */
867*2f27f4d1SJunchao Zhang       if (tmp < 0 || dxm[j] < starts[j] || dxm[j] >= (starts[j] + dims[j])) tmp = -1; /* Beyond the ghost region, therefore ignored with negative indices */
868*2f27f4d1SJunchao Zhang       else tmp = tmp*dims[j] + (dxm[j] - starts[j]);
86938fb4e8eSJunchao Zhang     }
87038fb4e8eSJunchao Zhang     gidxm[i] = tmp;
871*2f27f4d1SJunchao Zhang     /* Move to the next MatStencil point */
872*2f27f4d1SJunchao Zhang     if (dof > 1) dxm += sdim; /* c is already counted in sdim */
873*2f27f4d1SJunchao Zhang     else dxm += sdim + 1; /* skip the unused c */
87438fb4e8eSJunchao Zhang   }
87538fb4e8eSJunchao Zhang 
87638fb4e8eSJunchao Zhang   /* Map local indices to global indices */
87738fb4e8eSJunchao Zhang   PetscCall(DMGetLocalToGlobalMapping(da,&ltog));
87838fb4e8eSJunchao Zhang   PetscCall(ISLocalToGlobalMappingApply(ltog,m,gidxm,gidxm));
87938fb4e8eSJunchao Zhang   PetscFunctionReturn(0);
88038fb4e8eSJunchao Zhang }
88138fb4e8eSJunchao Zhang 
88247c6ae99SBarry Smith /*
88347c6ae99SBarry Smith   Creates "balanced" ownership ranges after refinement, constrained by the need for the
88447c6ae99SBarry Smith   fine grid boundaries to fall within one stencil width of the coarse partition.
88547c6ae99SBarry Smith 
88647c6ae99SBarry Smith   Uses a greedy algorithm to handle non-ideal layouts, could probably do something better.
88747c6ae99SBarry Smith */
88894013140SBarry Smith static PetscErrorCode DMDARefineOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lc[],PetscInt lf[])
88947c6ae99SBarry Smith {
89047c6ae99SBarry Smith   PetscInt       i,totalc = 0,remaining,startc = 0,startf = 0;
89147c6ae99SBarry Smith 
89247c6ae99SBarry Smith   PetscFunctionBegin;
89363a3b9bcSJacob Faibussowitsch   PetscCheck(ratio >= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Requested refinement ratio %" PetscInt_FMT " must be at least 1",ratio);
89447c6ae99SBarry Smith   if (ratio == 1) {
8959566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(lf,lc,m));
89647c6ae99SBarry Smith     PetscFunctionReturn(0);
89747c6ae99SBarry Smith   }
89847c6ae99SBarry Smith   for (i=0; i<m; i++) totalc += lc[i];
89947c6ae99SBarry Smith   remaining = (!periodic) + ratio * (totalc - (!periodic));
90047c6ae99SBarry Smith   for (i=0; i<m; i++) {
90147c6ae99SBarry Smith     PetscInt want = remaining/(m-i) + !!(remaining%(m-i));
90247c6ae99SBarry Smith     if (i == m-1) lf[i] = want;
90347c6ae99SBarry Smith     else {
9047aca7175SJed Brown       const PetscInt nextc = startc + lc[i];
9057aca7175SJed Brown       /* Move the first fine node of the next subdomain to the right until the coarse node on its left is within one
9067aca7175SJed Brown        * coarse stencil width of the first coarse node in the next subdomain. */
9077aca7175SJed Brown       while ((startf+want)/ratio < nextc - stencil_width) want++;
9087aca7175SJed Brown       /* Move the last fine node in the current subdomain to the left until the coarse node on its right is within one
9097aca7175SJed Brown        * coarse stencil width of the last coarse node in the current subdomain. */
9107aca7175SJed Brown       while ((startf+want-1+ratio-1)/ratio > nextc-1+stencil_width) want--;
9117aca7175SJed Brown       /* Make sure all constraints are satisfied */
91230729d88SBarry Smith       if (want < 0 || want > remaining || ((startf+want)/ratio < nextc - stencil_width)
913ce94432eSBarry 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");
91447c6ae99SBarry Smith     }
91547c6ae99SBarry Smith     lf[i]      = want;
91647c6ae99SBarry Smith     startc    += lc[i];
91747c6ae99SBarry Smith     startf    += lf[i];
91847c6ae99SBarry Smith     remaining -= lf[i];
91947c6ae99SBarry Smith   }
92047c6ae99SBarry Smith   PetscFunctionReturn(0);
92147c6ae99SBarry Smith }
92247c6ae99SBarry Smith 
9232be375d4SJed Brown /*
9242be375d4SJed Brown   Creates "balanced" ownership ranges after coarsening, constrained by the need for the
9252be375d4SJed Brown   fine grid boundaries to fall within one stencil width of the coarse partition.
9262be375d4SJed Brown 
9272be375d4SJed Brown   Uses a greedy algorithm to handle non-ideal layouts, could probably do something better.
9282be375d4SJed Brown */
9292be375d4SJed Brown static PetscErrorCode DMDACoarsenOwnershipRanges(DM da,PetscBool periodic,PetscInt stencil_width,PetscInt ratio,PetscInt m,const PetscInt lf[],PetscInt lc[])
9302be375d4SJed Brown {
9312be375d4SJed Brown   PetscInt       i,totalf,remaining,startc,startf;
9322be375d4SJed Brown 
9332be375d4SJed Brown   PetscFunctionBegin;
93463a3b9bcSJacob Faibussowitsch   PetscCheck(ratio >= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Requested refinement ratio %" PetscInt_FMT " must be at least 1",ratio);
9352be375d4SJed Brown   if (ratio == 1) {
9369566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(lc,lf,m));
9372be375d4SJed Brown     PetscFunctionReturn(0);
9382be375d4SJed Brown   }
9392be375d4SJed Brown   for (i=0,totalf=0; i<m; i++) totalf += lf[i];
9402be375d4SJed Brown   remaining = (!periodic) + (totalf - (!periodic)) / ratio;
9412be375d4SJed Brown   for (i=0,startc=0,startf=0; i<m; i++) {
9422be375d4SJed Brown     PetscInt want = remaining/(m-i) + !!(remaining%(m-i));
9432be375d4SJed Brown     if (i == m-1) lc[i] = want;
9442be375d4SJed Brown     else {
9452be375d4SJed Brown       const PetscInt nextf = startf+lf[i];
9462be375d4SJed Brown       /* Slide first coarse node of next subdomain to the left until the coarse node to the left of the first fine
9472be375d4SJed Brown        * node is within one stencil width. */
9482be375d4SJed Brown       while (nextf/ratio < startc+want-stencil_width) want--;
9492be375d4SJed Brown       /* Slide the last coarse node of the current subdomain to the right until the coarse node to the right of the last
9502be375d4SJed Brown        * fine node is within one stencil width. */
9512be375d4SJed Brown       while ((nextf-1+ratio-1)/ratio > startc+want-1+stencil_width) want++;
9522be375d4SJed Brown       if (want < 0 || want > remaining
953ce94432eSBarry 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");
9542be375d4SJed Brown     }
9552be375d4SJed Brown     lc[i]      = want;
9562be375d4SJed Brown     startc    += lc[i];
9572be375d4SJed Brown     startf    += lf[i];
9582be375d4SJed Brown     remaining -= lc[i];
9592be375d4SJed Brown   }
9602be375d4SJed Brown   PetscFunctionReturn(0);
9612be375d4SJed Brown }
9622be375d4SJed Brown 
9637087cfbeSBarry Smith PetscErrorCode DMRefine_DA(DM da,MPI_Comm comm,DM *daref)
96447c6ae99SBarry Smith {
965c73cfb54SMatthew G. Knepley   PetscInt M,N,P,i,dim;
9666858538eSMatthew G. Knepley   Vec      coordsc, coordsf;
9679a42bb27SBarry Smith   DM       da2;
96847c6ae99SBarry Smith   DM_DA   *dd = (DM_DA*)da->data,*dd2;
96947c6ae99SBarry Smith 
97047c6ae99SBarry Smith   PetscFunctionBegin;
971a9a02de4SBarry Smith   PetscValidHeaderSpecificType(da,DM_CLASSID,1,DMDA);
97247c6ae99SBarry Smith   PetscValidPointer(daref,3);
97347c6ae99SBarry Smith 
9749566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(da, &dim));
975bff4a2f0SMatthew G. Knepley   if (dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
97647c6ae99SBarry Smith     M = dd->refine_x*dd->M;
97747c6ae99SBarry Smith   } else {
97847c6ae99SBarry Smith     M = 1 + dd->refine_x*(dd->M - 1);
97947c6ae99SBarry Smith   }
980bff4a2f0SMatthew G. Knepley   if (dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
981c73cfb54SMatthew G. Knepley     if (dim > 1) {
98247c6ae99SBarry Smith       N = dd->refine_y*dd->N;
98347c6ae99SBarry Smith     } else {
9841860e6e9SBarry Smith       N = 1;
9851860e6e9SBarry Smith     }
9861860e6e9SBarry Smith   } else {
98747c6ae99SBarry Smith     N = 1 + dd->refine_y*(dd->N - 1);
98847c6ae99SBarry Smith   }
989bff4a2f0SMatthew G. Knepley   if (dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
990c73cfb54SMatthew G. Knepley     if (dim > 2) {
99147c6ae99SBarry Smith       P = dd->refine_z*dd->P;
99247c6ae99SBarry Smith     } else {
9931860e6e9SBarry Smith       P = 1;
9941860e6e9SBarry Smith     }
9951860e6e9SBarry Smith   } else {
99647c6ae99SBarry Smith     P = 1 + dd->refine_z*(dd->P - 1);
99747c6ae99SBarry Smith   }
9989566063dSJacob Faibussowitsch   PetscCall(DMDACreate(PetscObjectComm((PetscObject)da),&da2));
9999566063dSJacob Faibussowitsch   PetscCall(DMSetOptionsPrefix(da2,((PetscObject)da)->prefix));
10009566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(da2,dim));
10019566063dSJacob Faibussowitsch   PetscCall(DMDASetSizes(da2,M,N,P));
10029566063dSJacob Faibussowitsch   PetscCall(DMDASetNumProcs(da2,dd->m,dd->n,dd->p));
10039566063dSJacob Faibussowitsch   PetscCall(DMDASetBoundaryType(da2,dd->bx,dd->by,dd->bz));
10049566063dSJacob Faibussowitsch   PetscCall(DMDASetDof(da2,dd->w));
10059566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilType(da2,dd->stencil_type));
10069566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilWidth(da2,dd->s));
1007c73cfb54SMatthew G. Knepley   if (dim == 3) {
100847c6ae99SBarry Smith     PetscInt *lx,*ly,*lz;
10099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(dd->m,&lx,dd->n,&ly,dd->p,&lz));
10109566063dSJacob Faibussowitsch     PetscCall(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx));
10119566063dSJacob Faibussowitsch     PetscCall(DMDARefineOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly));
10129566063dSJacob Faibussowitsch     PetscCall(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_z,dd->p,dd->lz,lz));
10139566063dSJacob Faibussowitsch     PetscCall(DMDASetOwnershipRanges(da2,lx,ly,lz));
10149566063dSJacob Faibussowitsch     PetscCall(PetscFree3(lx,ly,lz));
1015c73cfb54SMatthew G. Knepley   } else if (dim == 2) {
101647c6ae99SBarry Smith     PetscInt *lx,*ly;
10179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(dd->m,&lx,dd->n,&ly));
10189566063dSJacob Faibussowitsch     PetscCall(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx));
10199566063dSJacob Faibussowitsch     PetscCall(DMDARefineOwnershipRanges(da,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_y,dd->n,dd->ly,ly));
10209566063dSJacob Faibussowitsch     PetscCall(DMDASetOwnershipRanges(da2,lx,ly,NULL));
10219566063dSJacob Faibussowitsch     PetscCall(PetscFree2(lx,ly));
1022c73cfb54SMatthew G. Knepley   } else if (dim == 1) {
102347c6ae99SBarry Smith     PetscInt *lx;
10249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd->m,&lx));
10259566063dSJacob Faibussowitsch     PetscCall(DMDARefineOwnershipRanges(da,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->refine_x,dd->m,dd->lx,lx));
10269566063dSJacob Faibussowitsch     PetscCall(DMDASetOwnershipRanges(da2,lx,NULL,NULL));
10279566063dSJacob Faibussowitsch     PetscCall(PetscFree(lx));
102847c6ae99SBarry Smith   }
102947c6ae99SBarry Smith   dd2 = (DM_DA*)da2->data;
103047c6ae99SBarry Smith 
103147c6ae99SBarry Smith   /* allow overloaded (user replaced) operations to be inherited by refinement clones */
103225296bd5SBarry Smith   da2->ops->creatematrix = da->ops->creatematrix;
103325296bd5SBarry Smith   /* da2->ops->createinterpolation = da->ops->createinterpolation; this causes problem with SNESVI */
103447c6ae99SBarry Smith   da2->ops->getcoloring = da->ops->getcoloring;
103547c6ae99SBarry Smith   dd2->interptype       = dd->interptype;
103647c6ae99SBarry Smith 
103747c6ae99SBarry Smith   /* copy fill information if given */
103847c6ae99SBarry Smith   if (dd->dfill) {
10399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd->dfill[dd->w]+dd->w+1,&dd2->dfill));
10409566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->dfill,dd->dfill,dd->dfill[dd->w]+dd->w+1));
104147c6ae99SBarry Smith   }
104247c6ae99SBarry Smith   if (dd->ofill) {
10439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd->ofill[dd->w]+dd->w+1,&dd2->ofill));
10449566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->ofill,dd->ofill,dd->ofill[dd->w]+dd->w+1));
104547c6ae99SBarry Smith   }
104647c6ae99SBarry Smith   /* copy the refine information */
1047397b6216SJed Brown   dd2->coarsen_x = dd2->refine_x = dd->refine_x;
1048397b6216SJed Brown   dd2->coarsen_y = dd2->refine_y = dd->refine_y;
1049397b6216SJed Brown   dd2->coarsen_z = dd2->refine_z = dd->refine_z;
105047c6ae99SBarry Smith 
1051897f7067SBarry Smith   if (dd->refine_z_hier) {
1052897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_z_hier_n) {
1053897f7067SBarry Smith       dd2->refine_z = dd->refine_z_hier[da->levelup - da->leveldown + 1];
1054897f7067SBarry Smith     }
1055897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_z_hier_n) {
1056897f7067SBarry Smith       dd2->coarsen_z = dd->refine_z_hier[da->levelup - da->leveldown];
1057897f7067SBarry Smith     }
1058897f7067SBarry Smith     dd2->refine_z_hier_n = dd->refine_z_hier_n;
10599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd2->refine_z_hier_n,&dd2->refine_z_hier));
10609566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->refine_z_hier,dd->refine_z_hier,dd2->refine_z_hier_n));
1061897f7067SBarry Smith   }
1062897f7067SBarry Smith   if (dd->refine_y_hier) {
1063897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_y_hier_n) {
1064897f7067SBarry Smith       dd2->refine_y = dd->refine_y_hier[da->levelup - da->leveldown + 1];
1065897f7067SBarry Smith     }
1066897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_y_hier_n) {
1067897f7067SBarry Smith       dd2->coarsen_y = dd->refine_y_hier[da->levelup - da->leveldown];
1068897f7067SBarry Smith     }
1069897f7067SBarry Smith     dd2->refine_y_hier_n = dd->refine_y_hier_n;
10709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd2->refine_y_hier_n,&dd2->refine_y_hier));
10719566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->refine_y_hier,dd->refine_y_hier,dd2->refine_y_hier_n));
1072897f7067SBarry Smith   }
1073897f7067SBarry Smith   if (dd->refine_x_hier) {
1074897f7067SBarry Smith     if (da->levelup - da->leveldown + 1 > -1 && da->levelup - da->leveldown + 1 < dd->refine_x_hier_n) {
1075897f7067SBarry Smith       dd2->refine_x = dd->refine_x_hier[da->levelup - da->leveldown + 1];
1076897f7067SBarry Smith     }
1077897f7067SBarry Smith     if (da->levelup - da->leveldown > -1 && da->levelup - da->leveldown < dd->refine_x_hier_n) {
1078897f7067SBarry Smith       dd2->coarsen_x = dd->refine_x_hier[da->levelup - da->leveldown];
1079897f7067SBarry Smith     }
1080897f7067SBarry Smith     dd2->refine_x_hier_n = dd->refine_x_hier_n;
10819566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd2->refine_x_hier_n,&dd2->refine_x_hier));
10829566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->refine_x_hier,dd->refine_x_hier,dd2->refine_x_hier_n));
1083897f7067SBarry Smith   }
1084897f7067SBarry Smith 
108547c6ae99SBarry Smith   /* copy vector type information */
10869566063dSJacob Faibussowitsch   PetscCall(DMSetVecType(da2,da->vectype));
1087ddcf8b74SDave May 
1088efd51863SBarry Smith   dd2->lf = dd->lf;
1089efd51863SBarry Smith   dd2->lj = dd->lj;
1090efd51863SBarry Smith 
10916e87535bSJed Brown   da2->leveldown = da->leveldown;
10926e87535bSJed Brown   da2->levelup   = da->levelup + 1;
10938865f1eaSKarl Rupp 
10949566063dSJacob Faibussowitsch   PetscCall(DMSetUp(da2));
10956e87535bSJed Brown 
1096ddcf8b74SDave May   /* interpolate coordinates if they are set on the coarse grid */
10976858538eSMatthew G. Knepley   PetscCall(DMGetCoordinates(da, &coordsc));
10986858538eSMatthew G. Knepley   if (coordsc) {
1099ddcf8b74SDave May     DM  cdaf,cdac;
1100ddcf8b74SDave May     Mat II;
1101ddcf8b74SDave May 
11029566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(da,&cdac));
11039566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(da2,&cdaf));
1104b61d3410SDave May     /* force creation of the coordinate vector */
11059566063dSJacob Faibussowitsch     PetscCall(DMDASetUniformCoordinates(da2,0.0,1.0,0.0,1.0,0.0,1.0));
11069566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(da2,&coordsf));
11079566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(cdac,cdaf,&II,NULL));
11089566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(II,coordsc,coordsf));
11099566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&II));
1110ddcf8b74SDave May   }
1111397b6216SJed Brown 
1112f3141302SJed Brown   for (i=0; i<da->bs; i++) {
1113f3141302SJed Brown     const char *fieldname;
11149566063dSJacob Faibussowitsch     PetscCall(DMDAGetFieldName(da,i,&fieldname));
11159566063dSJacob Faibussowitsch     PetscCall(DMDASetFieldName(da2,i,fieldname));
1116f3141302SJed Brown   }
1117397b6216SJed Brown 
111847c6ae99SBarry Smith   *daref = da2;
111947c6ae99SBarry Smith   PetscFunctionReturn(0);
112047c6ae99SBarry Smith }
112147c6ae99SBarry Smith 
1122a5bc1bf3SBarry Smith PetscErrorCode  DMCoarsen_DA(DM dmf, MPI_Comm comm,DM *dmc)
112347c6ae99SBarry Smith {
1124c73cfb54SMatthew G. Knepley   PetscInt       M,N,P,i,dim;
11256858538eSMatthew G. Knepley   Vec            coordsc, coordsf;
1126a5bc1bf3SBarry Smith   DM             dmc2;
1127a5bc1bf3SBarry Smith   DM_DA          *dd = (DM_DA*)dmf->data,*dd2;
112847c6ae99SBarry Smith 
112947c6ae99SBarry Smith   PetscFunctionBegin;
1130a5bc1bf3SBarry Smith   PetscValidHeaderSpecificType(dmf,DM_CLASSID,1,DMDA);
1131a5bc1bf3SBarry Smith   PetscValidPointer(dmc,3);
113247c6ae99SBarry Smith 
11339566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmf, &dim));
1134bff4a2f0SMatthew G. Knepley   if (dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1135397b6216SJed Brown     M = dd->M / dd->coarsen_x;
113647c6ae99SBarry Smith   } else {
1137397b6216SJed Brown     M = 1 + (dd->M - 1) / dd->coarsen_x;
113847c6ae99SBarry Smith   }
1139bff4a2f0SMatthew G. Knepley   if (dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1140c73cfb54SMatthew G. Knepley     if (dim > 1) {
1141397b6216SJed Brown       N = dd->N / dd->coarsen_y;
114247c6ae99SBarry Smith     } else {
11431860e6e9SBarry Smith       N = 1;
11441860e6e9SBarry Smith     }
11451860e6e9SBarry Smith   } else {
1146397b6216SJed Brown     N = 1 + (dd->N - 1) / dd->coarsen_y;
114747c6ae99SBarry Smith   }
1148bff4a2f0SMatthew G. Knepley   if (dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0) {
1149c73cfb54SMatthew G. Knepley     if (dim > 2) {
1150397b6216SJed Brown       P = dd->P / dd->coarsen_z;
115147c6ae99SBarry Smith     } else {
11521860e6e9SBarry Smith       P = 1;
11531860e6e9SBarry Smith     }
11541860e6e9SBarry Smith   } else {
1155397b6216SJed Brown     P = 1 + (dd->P - 1) / dd->coarsen_z;
115647c6ae99SBarry Smith   }
11579566063dSJacob Faibussowitsch   PetscCall(DMDACreate(PetscObjectComm((PetscObject)dmf),&dmc2));
11589566063dSJacob Faibussowitsch   PetscCall(DMSetOptionsPrefix(dmc2,((PetscObject)dmf)->prefix));
11599566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dmc2,dim));
11609566063dSJacob Faibussowitsch   PetscCall(DMDASetSizes(dmc2,M,N,P));
11619566063dSJacob Faibussowitsch   PetscCall(DMDASetNumProcs(dmc2,dd->m,dd->n,dd->p));
11629566063dSJacob Faibussowitsch   PetscCall(DMDASetBoundaryType(dmc2,dd->bx,dd->by,dd->bz));
11639566063dSJacob Faibussowitsch   PetscCall(DMDASetDof(dmc2,dd->w));
11649566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilType(dmc2,dd->stencil_type));
11659566063dSJacob Faibussowitsch   PetscCall(DMDASetStencilWidth(dmc2,dd->s));
1166c73cfb54SMatthew G. Knepley   if (dim == 3) {
11672be375d4SJed Brown     PetscInt *lx,*ly,*lz;
11689566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(dd->m,&lx,dd->n,&ly,dd->p,&lz));
11699566063dSJacob Faibussowitsch     PetscCall(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx));
11709566063dSJacob Faibussowitsch     PetscCall(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_y,dd->n,dd->ly,ly));
11719566063dSJacob Faibussowitsch     PetscCall(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bz == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_z,dd->p,dd->lz,lz));
11729566063dSJacob Faibussowitsch     PetscCall(DMDASetOwnershipRanges(dmc2,lx,ly,lz));
11739566063dSJacob Faibussowitsch     PetscCall(PetscFree3(lx,ly,lz));
1174c73cfb54SMatthew G. Knepley   } else if (dim == 2) {
11752be375d4SJed Brown     PetscInt *lx,*ly;
11769566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(dd->m,&lx,dd->n,&ly));
11779566063dSJacob Faibussowitsch     PetscCall(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx));
11789566063dSJacob Faibussowitsch     PetscCall(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->by == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_y,dd->n,dd->ly,ly));
11799566063dSJacob Faibussowitsch     PetscCall(DMDASetOwnershipRanges(dmc2,lx,ly,NULL));
11809566063dSJacob Faibussowitsch     PetscCall(PetscFree2(lx,ly));
1181c73cfb54SMatthew G. Knepley   } else if (dim == 1) {
11822be375d4SJed Brown     PetscInt *lx;
11839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd->m,&lx));
11849566063dSJacob Faibussowitsch     PetscCall(DMDACoarsenOwnershipRanges(dmf,(PetscBool)(dd->bx == DM_BOUNDARY_PERIODIC || dd->interptype == DMDA_Q0),dd->s,dd->coarsen_x,dd->m,dd->lx,lx));
11859566063dSJacob Faibussowitsch     PetscCall(DMDASetOwnershipRanges(dmc2,lx,NULL,NULL));
11869566063dSJacob Faibussowitsch     PetscCall(PetscFree(lx));
118747c6ae99SBarry Smith   }
1188a5bc1bf3SBarry Smith   dd2 = (DM_DA*)dmc2->data;
118947c6ae99SBarry Smith 
11904dcab191SBarry Smith   /* allow overloaded (user replaced) operations to be inherited by refinement clones; why are only some inherited and not all? */
1191a5bc1bf3SBarry Smith   /* dmc2->ops->createinterpolation = dmf->ops->createinterpolation; copying this one causes trouble for DMSetVI */
1192a5bc1bf3SBarry Smith   dmc2->ops->creatematrix = dmf->ops->creatematrix;
1193a5bc1bf3SBarry Smith   dmc2->ops->getcoloring  = dmf->ops->getcoloring;
119447c6ae99SBarry Smith   dd2->interptype         = dd->interptype;
119547c6ae99SBarry Smith 
119647c6ae99SBarry Smith   /* copy fill information if given */
119747c6ae99SBarry Smith   if (dd->dfill) {
11989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd->dfill[dd->w]+dd->w+1,&dd2->dfill));
11999566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->dfill,dd->dfill,dd->dfill[dd->w]+dd->w+1));
120047c6ae99SBarry Smith   }
120147c6ae99SBarry Smith   if (dd->ofill) {
12029566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd->ofill[dd->w]+dd->w+1,&dd2->ofill));
12039566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->ofill,dd->ofill,dd->ofill[dd->w]+dd->w+1));
120447c6ae99SBarry Smith   }
120547c6ae99SBarry Smith   /* copy the refine information */
1206397b6216SJed Brown   dd2->coarsen_x = dd2->refine_x = dd->coarsen_x;
1207397b6216SJed Brown   dd2->coarsen_y = dd2->refine_y = dd->coarsen_y;
1208397b6216SJed Brown   dd2->coarsen_z = dd2->refine_z = dd->coarsen_z;
120947c6ae99SBarry Smith 
1210897f7067SBarry Smith   if (dd->refine_z_hier) {
1211a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown -1 > -1 && dmf->levelup - dmf->leveldown - 1< dd->refine_z_hier_n) {
1212a5bc1bf3SBarry Smith       dd2->refine_z = dd->refine_z_hier[dmf->levelup - dmf->leveldown - 1];
1213897f7067SBarry Smith     }
1214a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 2 > -1 && dmf->levelup - dmf->leveldown - 2 < dd->refine_z_hier_n) {
1215a5bc1bf3SBarry Smith       dd2->coarsen_z = dd->refine_z_hier[dmf->levelup - dmf->leveldown - 2];
1216897f7067SBarry Smith     }
1217897f7067SBarry Smith     dd2->refine_z_hier_n = dd->refine_z_hier_n;
12189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd2->refine_z_hier_n,&dd2->refine_z_hier));
12199566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->refine_z_hier,dd->refine_z_hier,dd2->refine_z_hier_n));
1220897f7067SBarry Smith   }
1221897f7067SBarry Smith   if (dd->refine_y_hier) {
1222a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 1 > -1 && dmf->levelup - dmf->leveldown - 1< dd->refine_y_hier_n) {
1223a5bc1bf3SBarry Smith       dd2->refine_y = dd->refine_y_hier[dmf->levelup - dmf->leveldown - 1];
1224897f7067SBarry Smith     }
1225a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 2 > -1 && dmf->levelup - dmf->leveldown - 2 < dd->refine_y_hier_n) {
1226a5bc1bf3SBarry Smith       dd2->coarsen_y = dd->refine_y_hier[dmf->levelup - dmf->leveldown - 2];
1227897f7067SBarry Smith     }
1228897f7067SBarry Smith     dd2->refine_y_hier_n = dd->refine_y_hier_n;
12299566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd2->refine_y_hier_n,&dd2->refine_y_hier));
12309566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->refine_y_hier,dd->refine_y_hier,dd2->refine_y_hier_n));
1231897f7067SBarry Smith   }
1232897f7067SBarry Smith   if (dd->refine_x_hier) {
1233a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 1 > -1 && dmf->levelup - dmf->leveldown - 1 < dd->refine_x_hier_n) {
1234a5bc1bf3SBarry Smith       dd2->refine_x = dd->refine_x_hier[dmf->levelup - dmf->leveldown - 1];
1235897f7067SBarry Smith     }
1236a5bc1bf3SBarry Smith     if (dmf->levelup - dmf->leveldown - 2 > -1 && dmf->levelup - dmf->leveldown - 2 < dd->refine_x_hier_n) {
1237a5bc1bf3SBarry Smith       dd2->coarsen_x = dd->refine_x_hier[dmf->levelup - dmf->leveldown - 2];
1238897f7067SBarry Smith     }
1239897f7067SBarry Smith     dd2->refine_x_hier_n = dd->refine_x_hier_n;
12409566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dd2->refine_x_hier_n,&dd2->refine_x_hier));
12419566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(dd2->refine_x_hier,dd->refine_x_hier,dd2->refine_x_hier_n));
1242897f7067SBarry Smith   }
1243897f7067SBarry Smith 
124447c6ae99SBarry Smith   /* copy vector type information */
12459566063dSJacob Faibussowitsch   PetscCall(DMSetVecType(dmc2,dmf->vectype));
124647c6ae99SBarry Smith 
1247644e2e5bSBarry Smith   dd2->lf = dd->lf;
1248644e2e5bSBarry Smith   dd2->lj = dd->lj;
1249644e2e5bSBarry Smith 
1250a5bc1bf3SBarry Smith   dmc2->leveldown = dmf->leveldown + 1;
1251a5bc1bf3SBarry Smith   dmc2->levelup   = dmf->levelup;
12528865f1eaSKarl Rupp 
12539566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dmc2));
12546e87535bSJed Brown 
1255ddcf8b74SDave May   /* inject coordinates if they are set on the fine grid */
12566858538eSMatthew G. Knepley   PetscCall(DMGetCoordinates(dmf, &coordsf));
12576858538eSMatthew G. Knepley   if (coordsf) {
1258ddcf8b74SDave May     DM         cdaf,cdac;
12596dbf9973SLawrence Mitchell     Mat        inject;
12606dbf9973SLawrence Mitchell     VecScatter vscat;
1261ddcf8b74SDave May 
12629566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmf,&cdaf));
12639566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dmc2,&cdac));
1264b61d3410SDave May     /* force creation of the coordinate vector */
12659566063dSJacob Faibussowitsch     PetscCall(DMDASetUniformCoordinates(dmc2,0.0,1.0,0.0,1.0,0.0,1.0));
12669566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(dmc2,&coordsc));
1267ddcf8b74SDave May 
12689566063dSJacob Faibussowitsch     PetscCall(DMCreateInjection(cdac,cdaf,&inject));
12699566063dSJacob Faibussowitsch     PetscCall(MatScatterGetVecScatter(inject,&vscat));
12709566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(vscat,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD));
12719566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(vscat,coordsf,coordsc,INSERT_VALUES,SCATTER_FORWARD));
12729566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&inject));
1273ddcf8b74SDave May   }
1274f98405f7SJed Brown 
1275a5bc1bf3SBarry Smith   for (i=0; i<dmf->bs; i++) {
1276f98405f7SJed Brown     const char *fieldname;
12779566063dSJacob Faibussowitsch     PetscCall(DMDAGetFieldName(dmf,i,&fieldname));
12789566063dSJacob Faibussowitsch     PetscCall(DMDASetFieldName(dmc2,i,fieldname));
1279f98405f7SJed Brown   }
1280f98405f7SJed Brown 
1281a5bc1bf3SBarry Smith   *dmc = dmc2;
128247c6ae99SBarry Smith   PetscFunctionReturn(0);
128347c6ae99SBarry Smith }
128447c6ae99SBarry Smith 
12857087cfbeSBarry Smith PetscErrorCode  DMRefineHierarchy_DA(DM da,PetscInt nlevels,DM daf[])
128647c6ae99SBarry Smith {
128747c6ae99SBarry Smith   PetscInt       i,n,*refx,*refy,*refz;
128847c6ae99SBarry Smith 
128947c6ae99SBarry Smith   PetscFunctionBegin;
129047c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
12917a8be351SBarry Smith   PetscCheck(nlevels >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
129247c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
129347c6ae99SBarry Smith   PetscValidPointer(daf,3);
129447c6ae99SBarry Smith 
1295aa219208SBarry Smith   /* Get refinement factors, defaults taken from the coarse DMDA */
12969566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(nlevels,&refx,nlevels,&refy,nlevels,&refz));
129747c6ae99SBarry Smith   for (i=0; i<nlevels; i++) {
12989566063dSJacob Faibussowitsch     PetscCall(DMDAGetRefinementFactor(da,&refx[i],&refy[i],&refz[i]));
129947c6ae99SBarry Smith   }
130047c6ae99SBarry Smith   n    = nlevels;
13019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_x",refx,&n,NULL));
130247c6ae99SBarry Smith   n    = nlevels;
13039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_y",refy,&n,NULL));
130447c6ae99SBarry Smith   n    = nlevels;
13059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetIntArray(((PetscObject)da)->options,((PetscObject)da)->prefix,"-da_refine_hierarchy_z",refz,&n,NULL));
130647c6ae99SBarry Smith 
13079566063dSJacob Faibussowitsch   PetscCall(DMDASetRefinementFactor(da,refx[0],refy[0],refz[0]));
13089566063dSJacob Faibussowitsch   PetscCall(DMRefine(da,PetscObjectComm((PetscObject)da),&daf[0]));
130947c6ae99SBarry Smith   for (i=1; i<nlevels; i++) {
13109566063dSJacob Faibussowitsch     PetscCall(DMDASetRefinementFactor(daf[i-1],refx[i],refy[i],refz[i]));
13119566063dSJacob Faibussowitsch     PetscCall(DMRefine(daf[i-1],PetscObjectComm((PetscObject)da),&daf[i]));
131247c6ae99SBarry Smith   }
13139566063dSJacob Faibussowitsch   PetscCall(PetscFree3(refx,refy,refz));
131447c6ae99SBarry Smith   PetscFunctionReturn(0);
131547c6ae99SBarry Smith }
131647c6ae99SBarry Smith 
13177087cfbeSBarry Smith PetscErrorCode  DMCoarsenHierarchy_DA(DM da,PetscInt nlevels,DM dac[])
131847c6ae99SBarry Smith {
131947c6ae99SBarry Smith   PetscInt       i;
132047c6ae99SBarry Smith 
132147c6ae99SBarry Smith   PetscFunctionBegin;
132247c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
13237a8be351SBarry Smith   PetscCheck(nlevels >= 0,PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
132447c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
132547c6ae99SBarry Smith   PetscValidPointer(dac,3);
13269566063dSJacob Faibussowitsch   PetscCall(DMCoarsen(da,PetscObjectComm((PetscObject)da),&dac[0]));
132747c6ae99SBarry Smith   for (i=1; i<nlevels; i++) {
13289566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(dac[i-1],PetscObjectComm((PetscObject)da),&dac[i]));
132947c6ae99SBarry Smith   }
133047c6ae99SBarry Smith   PetscFunctionReturn(0);
133147c6ae99SBarry Smith }
133262197512SBarry Smith 
13338272889dSSatish Balay PetscErrorCode DMDASetGLLCoordinates_1d(DM dm,PetscInt n,PetscReal *nodes)
133462197512SBarry Smith {
13358272889dSSatish Balay   PetscInt       i,j,xs,xn,q;
133662197512SBarry Smith   PetscScalar    *xx;
133762197512SBarry Smith   PetscReal      h;
133862197512SBarry Smith   Vec            x;
133962197512SBarry Smith   DM_DA          *da = (DM_DA*)dm->data;
134062197512SBarry Smith 
134162197512SBarry Smith   PetscFunctionBegin;
134262197512SBarry Smith   if (da->bx != DM_BOUNDARY_PERIODIC) {
13439566063dSJacob Faibussowitsch     PetscCall(DMDAGetInfo(dm,NULL,&q,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
134462197512SBarry Smith     q    = (q-1)/(n-1);  /* number of spectral elements */
134562197512SBarry Smith     h    = 2.0/q;
13469566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(dm,&xs,NULL,NULL,&xn,NULL,NULL));
134762197512SBarry Smith     xs   = xs/(n-1);
134862197512SBarry Smith     xn   = xn/(n-1);
13499566063dSJacob Faibussowitsch     PetscCall(DMDASetUniformCoordinates(dm,-1.,1.,0.,0.,0.,0.));
13509566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(dm,&x));
13519566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(dm,x,&xx));
135262197512SBarry Smith 
135362197512SBarry Smith     /* loop over local spectral elements */
135462197512SBarry Smith     for (j=xs; j<xs+xn; j++) {
135562197512SBarry Smith       /*
135662197512SBarry Smith        Except for the first process, each process starts on the second GLL point of the first element on that process
135762197512SBarry Smith        */
135862197512SBarry Smith       for (i= (j == xs && xs > 0)? 1 : 0; i<n; i++) {
13598272889dSSatish Balay         xx[j*(n-1) + i] = -1.0 + h*j + h*(nodes[i]+1.0)/2.;
136062197512SBarry Smith       }
136162197512SBarry Smith     }
13629566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(dm,x,&xx));
136362197512SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not yet implemented for periodic");
136462197512SBarry Smith   PetscFunctionReturn(0);
136562197512SBarry Smith }
136662197512SBarry Smith 
13671fd49c25SBarry Smith /*@
136862197512SBarry Smith 
136962197512SBarry 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
137062197512SBarry Smith 
1371d083f849SBarry Smith    Collective on da
137262197512SBarry Smith 
137362197512SBarry Smith    Input Parameters:
137462197512SBarry Smith +   da - the DMDA object
13758272889dSSatish Balay -   n - the number of GLL nodes
13768272889dSSatish Balay -   nodes - the GLL nodes
137762197512SBarry Smith 
137895452b02SPatrick Sanan    Notes:
137995452b02SPatrick Sanan     the parallel decomposition of grid points must correspond to the degree of the GLL. That is, the number of grid points
138062197512SBarry Smith           on each process much be divisible by the number of GLL elements needed per process. This depends on whether the DM is
138162197512SBarry Smith           periodic or not.
138262197512SBarry Smith 
1383edc382c3SSatish Balay    Level: advanced
1384edc382c3SSatish Balay 
1385db781477SPatrick Sanan .seealso: `DMDACreate()`, `PetscDTGaussLobattoLegendreQuadrature()`, `DMGetCoordinates()`
138662197512SBarry Smith @*/
13878272889dSSatish Balay PetscErrorCode DMDASetGLLCoordinates(DM da,PetscInt n,PetscReal *nodes)
138862197512SBarry Smith {
138962197512SBarry Smith   PetscFunctionBegin;
139062197512SBarry Smith   if (da->dim == 1) {
13919566063dSJacob Faibussowitsch     PetscCall(DMDASetGLLCoordinates_1d(da,n,nodes));
139262197512SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Not yet implemented for 2 or 3d");
139362197512SBarry Smith   PetscFunctionReturn(0);
139462197512SBarry Smith }
13957c3cd84eSPatrick Sanan 
13967c3cd84eSPatrick Sanan PETSC_INTERN PetscErrorCode DMGetCompatibility_DA(DM da1,DM dm2,PetscBool *compatible,PetscBool *set)
13977c3cd84eSPatrick Sanan {
13987c3cd84eSPatrick Sanan   DM_DA          *dd1 = (DM_DA*)da1->data,*dd2;
13997c3cd84eSPatrick Sanan   DM             da2;
14007c3cd84eSPatrick Sanan   DMType         dmtype2;
14017c3cd84eSPatrick Sanan   PetscBool      isda,compatibleLocal;
14027c3cd84eSPatrick Sanan   PetscInt       i;
14037c3cd84eSPatrick Sanan 
14047c3cd84eSPatrick Sanan   PetscFunctionBegin;
14057a8be351SBarry Smith   PetscCheck(da1->setupcalled,PetscObjectComm((PetscObject)da1),PETSC_ERR_ARG_WRONGSTATE,"DMSetUp() must be called on first DM before DMGetCompatibility()");
14069566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2,&dmtype2));
14079566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmtype2,DMDA,&isda));
14087c3cd84eSPatrick Sanan   if (isda) {
14097c3cd84eSPatrick Sanan     da2 = dm2;
14107c3cd84eSPatrick Sanan     dd2 = (DM_DA*)da2->data;
14117a8be351SBarry Smith     PetscCheck(da2->setupcalled,PetscObjectComm((PetscObject)da2),PETSC_ERR_ARG_WRONGSTATE,"DMSetUp() must be called on second DM before DMGetCompatibility()");
1412110623a0SKarl Rupp     compatibleLocal = (PetscBool)(da1->dim == da2->dim);
1413c790a739SKarl Rupp     if (compatibleLocal) compatibleLocal = (PetscBool)(compatibleLocal && (dd1->s == dd2->s)); /* Stencil width */
1414110623a0SKarl Rupp     /*                                                                           Global size              ranks               Boundary type */
1415c790a739SKarl Rupp     if (compatibleLocal)                 compatibleLocal = (PetscBool)(compatibleLocal && (dd1->M == dd2->M) && (dd1->m == dd2->m) && (dd1->bx == dd2->bx));
1416c790a739SKarl Rupp     if (compatibleLocal && da1->dim > 1) compatibleLocal = (PetscBool)(compatibleLocal && (dd1->N == dd2->N) && (dd1->n == dd2->n) && (dd1->by == dd2->by));
1417c790a739SKarl Rupp     if (compatibleLocal && da1->dim > 2) compatibleLocal = (PetscBool)(compatibleLocal && (dd1->P == dd2->P) && (dd1->p == dd2->p) && (dd1->bz == dd2->bz));
14187c3cd84eSPatrick Sanan     if (compatibleLocal) {
14197c3cd84eSPatrick Sanan       for (i=0; i<dd1->m; ++i) {
1420c790a739SKarl Rupp         compatibleLocal = (PetscBool)(compatibleLocal && (dd1->lx[i] == dd2->lx[i]));           /* Local size     */
14217c3cd84eSPatrick Sanan       }
14227c3cd84eSPatrick Sanan     }
14237c3cd84eSPatrick Sanan     if (compatibleLocal && da1->dim > 1) {
14247c3cd84eSPatrick Sanan       for (i=0; i<dd1->n; ++i) {
1425c790a739SKarl Rupp         compatibleLocal = (PetscBool)(compatibleLocal && (dd1->ly[i] == dd2->ly[i]));
14267c3cd84eSPatrick Sanan       }
14277c3cd84eSPatrick Sanan     }
14287c3cd84eSPatrick Sanan     if (compatibleLocal && da1->dim > 2) {
14297c3cd84eSPatrick Sanan       for (i=0; i<dd1->p; ++i) {
1430c790a739SKarl Rupp         compatibleLocal = (PetscBool)(compatibleLocal && (dd1->lz[i] == dd2->lz[i]));
14317c3cd84eSPatrick Sanan       }
14327c3cd84eSPatrick Sanan     }
14337c3cd84eSPatrick Sanan     *compatible = compatibleLocal;
14347c3cd84eSPatrick Sanan     *set = PETSC_TRUE;
14357c3cd84eSPatrick Sanan   } else {
14367c3cd84eSPatrick Sanan     /* Decline to determine compatibility with other DM types */
14377c3cd84eSPatrick Sanan     *set = PETSC_FALSE;
14387c3cd84eSPatrick Sanan   }
14397c3cd84eSPatrick Sanan   PetscFunctionReturn(0);
14407c3cd84eSPatrick Sanan }
1441