xref: /petsc/src/dm/impls/da/dalocal.c (revision f5eeb527ae0f97c556f6ac1e2c5356c155108742)
147c6ae99SBarry Smith 
247c6ae99SBarry Smith /*
347c6ae99SBarry Smith   Code for manipulating distributed regular arrays in parallel.
447c6ae99SBarry Smith */
547c6ae99SBarry Smith 
6b45d2f2cSJed Brown #include <petsc-private/daimpl.h>    /*I   "petscdmda.h"   I*/
747c6ae99SBarry Smith 
847c6ae99SBarry Smith /*
9e3c5b3baSBarry Smith    This allows the DMDA vectors to properly tell MATLAB their dimensions
1047c6ae99SBarry Smith */
1147c6ae99SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
12c6db04a5SJed Brown #include <engine.h>   /* MATLAB include file */
13c6db04a5SJed Brown #include <mex.h>      /* MATLAB include file */
1447c6ae99SBarry Smith EXTERN_C_BEGIN
1547c6ae99SBarry Smith #undef __FUNCT__
1647c6ae99SBarry Smith #define __FUNCT__ "VecMatlabEnginePut_DA2d"
177087cfbeSBarry Smith PetscErrorCode  VecMatlabEnginePut_DA2d(PetscObject obj,void *mengine)
1847c6ae99SBarry Smith {
1947c6ae99SBarry Smith   PetscErrorCode ierr;
2047c6ae99SBarry Smith   PetscInt       n,m;
2147c6ae99SBarry Smith   Vec            vec = (Vec)obj;
2247c6ae99SBarry Smith   PetscScalar    *array;
2347c6ae99SBarry Smith   mxArray        *mat;
249a42bb27SBarry Smith   DM             da;
2547c6ae99SBarry Smith 
2647c6ae99SBarry Smith   PetscFunctionBegin;
273c0c59f3SBarry Smith   ierr = PetscObjectQuery((PetscObject)vec,"DM",(PetscObject*)&da);CHKERRQ(ierr);
28aa219208SBarry Smith   if (!da) SETERRQ(((PetscObject)vec)->comm,PETSC_ERR_ARG_WRONGSTATE,"Vector not associated with a DMDA");
29aa219208SBarry Smith   ierr = DMDAGetGhostCorners(da,0,0,0,&m,&n,0);CHKERRQ(ierr);
3047c6ae99SBarry Smith 
3147c6ae99SBarry Smith   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
3247c6ae99SBarry Smith #if !defined(PETSC_USE_COMPLEX)
3347c6ae99SBarry Smith   mat  = mxCreateDoubleMatrix(m,n,mxREAL);
3447c6ae99SBarry Smith #else
3547c6ae99SBarry Smith   mat  = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
3647c6ae99SBarry Smith #endif
3747c6ae99SBarry Smith   ierr = PetscMemcpy(mxGetPr(mat),array,n*m*sizeof(PetscScalar));CHKERRQ(ierr);
3847c6ae99SBarry Smith   ierr = PetscObjectName(obj);CHKERRQ(ierr);
3947c6ae99SBarry Smith   engPutVariable((Engine *)mengine,obj->name,mat);
4047c6ae99SBarry Smith 
4147c6ae99SBarry Smith   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
4247c6ae99SBarry Smith   PetscFunctionReturn(0);
4347c6ae99SBarry Smith }
4447c6ae99SBarry Smith EXTERN_C_END
4547c6ae99SBarry Smith #endif
4647c6ae99SBarry Smith 
4747c6ae99SBarry Smith 
4847c6ae99SBarry Smith #undef __FUNCT__
49564755cdSBarry Smith #define __FUNCT__ "DMCreateLocalVector_DA"
507087cfbeSBarry Smith PetscErrorCode  DMCreateLocalVector_DA(DM da,Vec* g)
5147c6ae99SBarry Smith {
5247c6ae99SBarry Smith   PetscErrorCode ierr;
5347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
5447c6ae99SBarry Smith 
5547c6ae99SBarry Smith   PetscFunctionBegin;
5647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
5747c6ae99SBarry Smith   PetscValidPointer(g,2);
5847c6ae99SBarry Smith   ierr = VecCreate(PETSC_COMM_SELF,g);CHKERRQ(ierr);
5947c6ae99SBarry Smith   ierr = VecSetSizes(*g,dd->nlocal,PETSC_DETERMINE);CHKERRQ(ierr);
6047c6ae99SBarry Smith   ierr = VecSetBlockSize(*g,dd->w);CHKERRQ(ierr);
61401ddaa8SBarry Smith   ierr = VecSetType(*g,da->vectype);CHKERRQ(ierr);
623c0c59f3SBarry Smith   ierr = PetscObjectCompose((PetscObject)*g,"DM",(PetscObject)da);CHKERRQ(ierr);
6347c6ae99SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
6447c6ae99SBarry Smith   if (dd->w == 1  && dd->dim == 2) {
6547c6ae99SBarry Smith     ierr = PetscObjectComposeFunctionDynamic((PetscObject)*g,"PetscMatlabEnginePut_C","VecMatlabEnginePut_DA2d",VecMatlabEnginePut_DA2d);CHKERRQ(ierr);
6647c6ae99SBarry Smith   }
6747c6ae99SBarry Smith #endif
6847c6ae99SBarry Smith   PetscFunctionReturn(0);
6947c6ae99SBarry Smith }
7047c6ae99SBarry Smith 
71a66d4d66SMatthew G Knepley #undef __FUNCT__
7257459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumCells"
7357459e9aSMatthew G Knepley PetscErrorCode DMDAGetNumCells(DM dm, PetscInt *numCells)
7457459e9aSMatthew G Knepley {
7557459e9aSMatthew G Knepley   DM_DA         *da  = (DM_DA *) dm->data;
7657459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
7757459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
7857459e9aSMatthew G Knepley   const PetscInt nC  = (mx  )*(dim > 1 ? (my  )*(dim > 2 ? (mz  ) : 1) : 1);
7957459e9aSMatthew G Knepley 
8057459e9aSMatthew G Knepley   PetscFunctionBegin;
8157459e9aSMatthew G Knepley   if (numCells) {
8257459e9aSMatthew G Knepley     PetscValidIntPointer(numCells,2);
8357459e9aSMatthew G Knepley     *numCells = nC;
8457459e9aSMatthew G Knepley   }
8557459e9aSMatthew G Knepley   PetscFunctionReturn(0);
8657459e9aSMatthew G Knepley }
8757459e9aSMatthew G Knepley 
8857459e9aSMatthew G Knepley #undef __FUNCT__
8957459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumVertices"
9057459e9aSMatthew G Knepley PetscErrorCode DMDAGetNumVertices(DM dm, PetscInt *numVerticesX, PetscInt *numVerticesY, PetscInt *numVerticesZ, PetscInt *numVertices)
9157459e9aSMatthew G Knepley {
9257459e9aSMatthew G Knepley   DM_DA         *da  = (DM_DA *) dm->data;
9357459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
9457459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
9557459e9aSMatthew G Knepley   const PetscInt nVx = mx+1;
9657459e9aSMatthew G Knepley   const PetscInt nVy = dim > 1 ? (my+1) : 1;
9757459e9aSMatthew G Knepley   const PetscInt nVz = dim > 2 ? (mz+1) : 1;
9857459e9aSMatthew G Knepley   const PetscInt nV  = nVx*nVy*nVz;
9957459e9aSMatthew G Knepley 
10057459e9aSMatthew G Knepley   PetscFunctionBegin;
10157459e9aSMatthew G Knepley   if (numVerticesX) {
10257459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesX,2);
10357459e9aSMatthew G Knepley     *numVerticesX = nVx;
10457459e9aSMatthew G Knepley   }
10557459e9aSMatthew G Knepley   if (numVerticesY) {
10657459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesY,3);
10757459e9aSMatthew G Knepley     *numVerticesY = nVy;
10857459e9aSMatthew G Knepley   }
10957459e9aSMatthew G Knepley   if (numVerticesZ) {
11057459e9aSMatthew G Knepley     PetscValidIntPointer(numVerticesZ,4);
11157459e9aSMatthew G Knepley     *numVerticesZ = nVz;
11257459e9aSMatthew G Knepley   }
11357459e9aSMatthew G Knepley   if (numVertices) {
11457459e9aSMatthew G Knepley     PetscValidIntPointer(numVertices,5);
11557459e9aSMatthew G Knepley     *numVertices = nV;
11657459e9aSMatthew G Knepley   }
11757459e9aSMatthew G Knepley   PetscFunctionReturn(0);
11857459e9aSMatthew G Knepley }
11957459e9aSMatthew G Knepley 
12057459e9aSMatthew G Knepley #undef __FUNCT__
12157459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetNumFaces"
12257459e9aSMatthew G Knepley PetscErrorCode DMDAGetNumFaces(DM dm, PetscInt *numXFacesX, PetscInt *numXFaces, PetscInt *numYFacesY, PetscInt *numYFaces, PetscInt *numZFacesZ, PetscInt *numZFaces)
12357459e9aSMatthew G Knepley {
12457459e9aSMatthew G Knepley   DM_DA         *da  = (DM_DA *) dm->data;
12557459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
12657459e9aSMatthew G Knepley   const PetscInt mx  = (da->Xe - da->Xs)/da->w, my = da->Ye - da->Ys, mz = da->Ze - da->Zs;
12757459e9aSMatthew G Knepley   const PetscInt nxF = (dim > 1 ? (my  )*(dim > 2 ? (mz  ) : 1) : 1);
12857459e9aSMatthew G Knepley   const PetscInt nXF = (mx+1)*nxF;
12957459e9aSMatthew G Knepley   const PetscInt nyF = mx*(dim > 2 ? mz : 1);
13057459e9aSMatthew G Knepley   const PetscInt nYF = dim > 1 ? (my+1)*nyF : 0;
13157459e9aSMatthew G Knepley   const PetscInt nzF = mx*(dim > 1 ? my : 0);
13257459e9aSMatthew G Knepley   const PetscInt nZF = dim > 2 ? (mz+1)*nzF : 0;
13357459e9aSMatthew G Knepley 
13457459e9aSMatthew G Knepley   PetscFunctionBegin;
13557459e9aSMatthew G Knepley   if (numXFacesX) {
13657459e9aSMatthew G Knepley     PetscValidIntPointer(numXFacesX,2);
13757459e9aSMatthew G Knepley     *numXFacesX = nxF;
13857459e9aSMatthew G Knepley   }
13957459e9aSMatthew G Knepley   if (numXFaces) {
14057459e9aSMatthew G Knepley     PetscValidIntPointer(numXFaces,3);
14157459e9aSMatthew G Knepley     *numXFaces = nXF;
14257459e9aSMatthew G Knepley   }
14357459e9aSMatthew G Knepley   if (numYFacesY) {
14457459e9aSMatthew G Knepley     PetscValidIntPointer(numYFacesY,4);
14557459e9aSMatthew G Knepley     *numYFacesY = nyF;
14657459e9aSMatthew G Knepley   }
14757459e9aSMatthew G Knepley   if (numYFaces) {
14857459e9aSMatthew G Knepley     PetscValidIntPointer(numYFaces,5);
14957459e9aSMatthew G Knepley     *numYFaces = nYF;
15057459e9aSMatthew G Knepley   }
15157459e9aSMatthew G Knepley   if (numZFacesZ) {
15257459e9aSMatthew G Knepley     PetscValidIntPointer(numZFacesZ,6);
15357459e9aSMatthew G Knepley     *numZFacesZ = nzF;
15457459e9aSMatthew G Knepley   }
15557459e9aSMatthew G Knepley   if (numZFaces) {
15657459e9aSMatthew G Knepley     PetscValidIntPointer(numZFaces,7);
15757459e9aSMatthew G Knepley     *numZFaces = nZF;
15857459e9aSMatthew G Knepley   }
15957459e9aSMatthew G Knepley   PetscFunctionReturn(0);
16057459e9aSMatthew G Knepley }
16157459e9aSMatthew G Knepley 
16257459e9aSMatthew G Knepley #undef __FUNCT__
16357459e9aSMatthew G Knepley #define __FUNCT__ "DMDAGetHeightStratum"
16457459e9aSMatthew G Knepley PetscErrorCode DMDAGetHeightStratum(DM dm, PetscInt height, PetscInt *pStart, PetscInt *pEnd)
16557459e9aSMatthew G Knepley {
16657459e9aSMatthew G Knepley   DM_DA         *da  = (DM_DA *) dm->data;
16757459e9aSMatthew G Knepley   const PetscInt dim = da->dim;
16857459e9aSMatthew G Knepley   PetscInt       nC, nV, nXF, nYF, nZF;
16957459e9aSMatthew G Knepley   PetscErrorCode ierr;
17057459e9aSMatthew G Knepley 
17157459e9aSMatthew G Knepley   PetscFunctionBegin;
17257459e9aSMatthew G Knepley   if (pStart) {PetscValidIntPointer(pStart,3);}
17357459e9aSMatthew G Knepley   if (pEnd)   {PetscValidIntPointer(pEnd,4);}
17457459e9aSMatthew G Knepley   ierr = DMDAGetNumCells(dm, &nC);CHKERRQ(ierr);
17557459e9aSMatthew G Knepley   ierr = DMDAGetNumVertices(dm, PETSC_NULL, PETSC_NULL, PETSC_NULL, &nV);CHKERRQ(ierr);
17657459e9aSMatthew G Knepley   ierr = DMDAGetNumFaces(dm, PETSC_NULL, &nXF, PETSC_NULL, &nYF, PETSC_NULL, &nZF);CHKERRQ(ierr);
17757459e9aSMatthew G Knepley   if (height == 0) {
17857459e9aSMatthew G Knepley     /* Cells */
17957459e9aSMatthew G Knepley     if (pStart) {*pStart = 0;}
18057459e9aSMatthew G Knepley     if (pEnd)   {*pEnd   = nC;}
18157459e9aSMatthew G Knepley   } else if (height == 1) {
18257459e9aSMatthew G Knepley     /* Faces */
18357459e9aSMatthew G Knepley     if (pStart) {*pStart = nC+nV;}
18457459e9aSMatthew G Knepley     if (pEnd)   {*pEnd   = nC+nV+nXF+nYF+nZF;}
18557459e9aSMatthew G Knepley   } else if (height == dim) {
18657459e9aSMatthew G Knepley     /* Vertices */
18757459e9aSMatthew G Knepley     if (pStart) {*pStart = nC;}
18857459e9aSMatthew G Knepley     if (pEnd)   {*pEnd   = nC+nV;}
18957459e9aSMatthew G Knepley   } else if (height < 0) {
19057459e9aSMatthew G Knepley     /* All points */
19157459e9aSMatthew G Knepley     if (pStart) {*pStart = 0;}
19257459e9aSMatthew G Knepley     if (pEnd)   {*pEnd   = nC+nV+nXF+nYF+nZF;}
19357459e9aSMatthew G Knepley   } else {
19457459e9aSMatthew G Knepley     SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No points of height %d in the DA", height);
19557459e9aSMatthew G Knepley   }
19657459e9aSMatthew G Knepley   PetscFunctionReturn(0);
19757459e9aSMatthew G Knepley }
19857459e9aSMatthew G Knepley 
19957459e9aSMatthew G Knepley #undef __FUNCT__
200a66d4d66SMatthew G Knepley #define __FUNCT__ "DMDACreateSection"
201a66d4d66SMatthew G Knepley /*@C
202a66d4d66SMatthew G Knepley   DMDACreateSection - Create a PetscSection inside the DMDA that describes data layout. This allows multiple fields with
203a66d4d66SMatthew G Knepley   different numbers of dofs on vertices, cells, and faces in each direction.
204a66d4d66SMatthew G Knepley 
205a66d4d66SMatthew G Knepley   Input Parameters:
206a66d4d66SMatthew G Knepley + dm- The DMDA
207a66d4d66SMatthew G Knepley . numFields - The number of fields
208a66d4d66SMatthew G Knepley . numComp - The number of components in each field, or PETSC_NULL for 1
209a66d4d66SMatthew G Knepley . numVertexDof - The number of dofs per vertex for each field, or PETSC_NULL
210a66d4d66SMatthew G Knepley . numFaceDof - The number of dofs per face for each field and direction, or PETSC_NULL
211a66d4d66SMatthew G Knepley - numCellDof - The number of dofs per cell for each field, or PETSC_NULL
212a66d4d66SMatthew G Knepley 
213a66d4d66SMatthew G Knepley   Level: developer
214a66d4d66SMatthew G Knepley 
215a66d4d66SMatthew G Knepley   Note:
216a66d4d66SMatthew G Knepley   The default DMDA numbering is as follows:
217a66d4d66SMatthew G Knepley 
218a66d4d66SMatthew G Knepley     - Cells:    [0,             nC)
219a66d4d66SMatthew G Knepley     - Vertices: [nC,            nC+nV)
22088ed4aceSMatthew G Knepley     - X-Faces:  [nC+nV,         nC+nV+nXF)         normal is +- x-dir
22188ed4aceSMatthew G Knepley     - Y-Faces:  [nC+nV+nXF,     nC+nV+nXF+nYF)     normal is +- y-dir
22288ed4aceSMatthew G Knepley     - Z-Faces:  [nC+nV+nXF+nYF, nC+nV+nXF+nYF+nZF) normal is +- z-dir
223a66d4d66SMatthew G Knepley 
224a66d4d66SMatthew G Knepley   We interpret the default DMDA partition as a cell partition, and the data assignment as a cell assignment.
225a66d4d66SMatthew G Knepley @*/
22680800b1aSMatthew G Knepley PetscErrorCode DMDACreateSection(DM dm, PetscInt numComp[], PetscInt numVertexDof[], PetscInt numFaceDof[], PetscInt numCellDof[])
227a66d4d66SMatthew G Knepley {
228a66d4d66SMatthew G Knepley   DM_DA         *da  = (DM_DA *) dm->data;
22988ed4aceSMatthew G Knepley   const PetscInt dim = da->dim;
23080800b1aSMatthew G Knepley   PetscInt       numFields, numVertexTotDof = 0, numCellTotDof = 0, numFaceTotDof[3] = {0, 0, 0};
23188ed4aceSMatthew G Knepley   PetscSF        sf;
232feafbc5cSMatthew G Knepley   PetscMPIInt    rank;
23388ed4aceSMatthew G Knepley   const PetscMPIInt *neighbors;
23488ed4aceSMatthew G Knepley   PetscInt      *localPoints;
23588ed4aceSMatthew G Knepley   PetscSFNode   *remotePoints;
236*f5eeb527SMatthew G Knepley   PetscInt       nleaves = 0,  nleavesCheck = 0, nL = 0;
23757459e9aSMatthew G Knepley   PetscInt       nC, nVx, nVy, nVz, nV, nxF, nXF, nyF, nYF, nzF, nZF;
23857459e9aSMatthew G Knepley   PetscInt       pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart, zfEnd;
23988ed4aceSMatthew G Knepley   PetscInt       f, v, c, xf, yf, zf, xn, yn, zn;
240a66d4d66SMatthew G Knepley   PetscErrorCode ierr;
241a66d4d66SMatthew G Knepley 
242a66d4d66SMatthew G Knepley   PetscFunctionBegin;
243a66d4d66SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
244feafbc5cSMatthew G Knepley   ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr);
24557459e9aSMatthew G Knepley   ierr = DMDAGetNumCells(dm, &nC);CHKERRQ(ierr);
24657459e9aSMatthew G Knepley   ierr = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, &nV);CHKERRQ(ierr);
24757459e9aSMatthew G Knepley   ierr = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr);
24857459e9aSMatthew G Knepley   ierr = DMDAGetHeightStratum(dm, -1,  &pStart, &pEnd);CHKERRQ(ierr);
24957459e9aSMatthew G Knepley   ierr = DMDAGetHeightStratum(dm, 0,   &cStart, &cEnd);CHKERRQ(ierr);
25057459e9aSMatthew G Knepley   ierr = DMDAGetHeightStratum(dm, 1,   &fStart, &fEnd);CHKERRQ(ierr);
25157459e9aSMatthew G Knepley   ierr = DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);CHKERRQ(ierr);
25257459e9aSMatthew G Knepley   xfStart = vEnd;  xfEnd = xfStart+nXF;
25357459e9aSMatthew G Knepley   yfStart = xfEnd; yfEnd = yfStart+nYF;
25457459e9aSMatthew G Knepley   zfStart = yfEnd; zfEnd = zfStart+nZF;
25557459e9aSMatthew G Knepley   if (zfEnd != fEnd) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid face end %d, should be %d", zfEnd, fEnd);
25688ed4aceSMatthew G Knepley   /* Create local section */
25780800b1aSMatthew G Knepley   ierr = DMDAGetInfo(dm, 0,0,0,0,0,0,0, &numFields, 0,0,0,0,0);CHKERRQ(ierr);
258a66d4d66SMatthew G Knepley   for(f = 0; f < numFields; ++f) {
259a66d4d66SMatthew G Knepley     if (numVertexDof) {numVertexTotDof  += numVertexDof[f];}
260a66d4d66SMatthew G Knepley     if (numCellDof)   {numCellTotDof    += numCellDof[f];}
26188ed4aceSMatthew G Knepley     if (numFaceDof)   {numFaceTotDof[0] += numFaceDof[f*dim+0];
26288ed4aceSMatthew G Knepley                        numFaceTotDof[1] += dim > 1 ? numFaceDof[f*dim+1] : 0;
26388ed4aceSMatthew G Knepley                        numFaceTotDof[2] += dim > 2 ? numFaceDof[f*dim+2] : 0;}
264a66d4d66SMatthew G Knepley   }
26588ed4aceSMatthew G Knepley   ierr = PetscSectionCreate(((PetscObject) dm)->comm, &dm->defaultSection);CHKERRQ(ierr);
266a66d4d66SMatthew G Knepley   if (numFields > 1) {
26788ed4aceSMatthew G Knepley     ierr = PetscSectionSetNumFields(dm->defaultSection, numFields);CHKERRQ(ierr);
268a66d4d66SMatthew G Knepley     for(f = 0; f < numFields; ++f) {
26980800b1aSMatthew G Knepley       const char *name;
27080800b1aSMatthew G Knepley 
27180800b1aSMatthew G Knepley       ierr = DMDAGetFieldName(dm, f, &name);CHKERRQ(ierr);
27288ed4aceSMatthew G Knepley       ierr = PetscSectionSetFieldName(dm->defaultSection, f, name);CHKERRQ(ierr);
27380800b1aSMatthew G Knepley       if (numComp) {
27488ed4aceSMatthew G Knepley         ierr = PetscSectionSetFieldComponents(dm->defaultSection, f, numComp[f]);CHKERRQ(ierr);
275a66d4d66SMatthew G Knepley       }
276a66d4d66SMatthew G Knepley     }
277a66d4d66SMatthew G Knepley   } else {
278a66d4d66SMatthew G Knepley     numFields = 0;
279a66d4d66SMatthew G Knepley   }
28088ed4aceSMatthew G Knepley   ierr = PetscSectionSetChart(dm->defaultSection, pStart, pEnd);CHKERRQ(ierr);
281a66d4d66SMatthew G Knepley   if (numVertexDof) {
282a66d4d66SMatthew G Knepley     for(v = vStart; v < vEnd; ++v) {
283a66d4d66SMatthew G Knepley       for(f = 0; f < numFields; ++f) {
28488ed4aceSMatthew G Knepley         ierr = PetscSectionSetFieldDof(dm->defaultSection, v, f, numVertexDof[f]);CHKERRQ(ierr);
285a66d4d66SMatthew G Knepley       }
28688ed4aceSMatthew G Knepley       ierr = PetscSectionSetDof(dm->defaultSection, v, numVertexTotDof);CHKERRQ(ierr);
287a66d4d66SMatthew G Knepley     }
288a66d4d66SMatthew G Knepley   }
289a66d4d66SMatthew G Knepley   if (numFaceDof) {
290a66d4d66SMatthew G Knepley     for(xf = xfStart; xf < xfEnd; ++xf) {
291a66d4d66SMatthew G Knepley       for(f = 0; f < numFields; ++f) {
29288ed4aceSMatthew G Knepley         ierr = PetscSectionSetFieldDof(dm->defaultSection, xf, f, numFaceDof[f*dim+0]);CHKERRQ(ierr);
293a66d4d66SMatthew G Knepley       }
29488ed4aceSMatthew G Knepley       ierr = PetscSectionSetDof(dm->defaultSection, xf, numFaceTotDof[0]);CHKERRQ(ierr);
295a66d4d66SMatthew G Knepley     }
296a66d4d66SMatthew G Knepley     for(yf = yfStart; yf < yfEnd; ++yf) {
297a66d4d66SMatthew G Knepley       for(f = 0; f < numFields; ++f) {
29888ed4aceSMatthew G Knepley         ierr = PetscSectionSetFieldDof(dm->defaultSection, yf, f, numFaceDof[f*dim+1]);CHKERRQ(ierr);
299a66d4d66SMatthew G Knepley       }
30088ed4aceSMatthew G Knepley       ierr = PetscSectionSetDof(dm->defaultSection, yf, numFaceTotDof[1]);CHKERRQ(ierr);
301a66d4d66SMatthew G Knepley     }
302a66d4d66SMatthew G Knepley     for(zf = zfStart; zf < zfEnd; ++zf) {
303a66d4d66SMatthew G Knepley       for(f = 0; f < numFields; ++f) {
30488ed4aceSMatthew G Knepley         ierr = PetscSectionSetFieldDof(dm->defaultSection, zf, f, numFaceDof[f*dim+2]);CHKERRQ(ierr);
305a66d4d66SMatthew G Knepley       }
30688ed4aceSMatthew G Knepley       ierr = PetscSectionSetDof(dm->defaultSection, zf, numFaceTotDof[2]);CHKERRQ(ierr);
307a66d4d66SMatthew G Knepley     }
308a66d4d66SMatthew G Knepley   }
309a66d4d66SMatthew G Knepley   if (numCellDof) {
310a66d4d66SMatthew G Knepley     for(c = cStart; c < cEnd; ++c) {
311a66d4d66SMatthew G Knepley       for(f = 0; f < numFields; ++f) {
31288ed4aceSMatthew G Knepley         ierr = PetscSectionSetFieldDof(dm->defaultSection, c, f, numCellDof[f]);CHKERRQ(ierr);
313a66d4d66SMatthew G Knepley       }
31488ed4aceSMatthew G Knepley       ierr = PetscSectionSetDof(dm->defaultSection, c, numCellTotDof);CHKERRQ(ierr);
315a66d4d66SMatthew G Knepley     }
316a66d4d66SMatthew G Knepley   }
31788ed4aceSMatthew G Knepley   ierr = PetscSectionSetUp(dm->defaultSection);CHKERRQ(ierr);
31888ed4aceSMatthew G Knepley   /* Create mesh point SF */
31988ed4aceSMatthew G Knepley   ierr = DMDAGetNeighbors(dm, &neighbors);CHKERRQ(ierr);
32088ed4aceSMatthew G Knepley   for(zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
32188ed4aceSMatthew G Knepley     for(yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
32288ed4aceSMatthew G Knepley       for(xn = 0; xn < 3; ++xn) {
3237128ae9fSMatthew G Knepley         const PetscInt xp = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
32488ed4aceSMatthew G Knepley         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
32588ed4aceSMatthew G Knepley 
326feafbc5cSMatthew G Knepley         if (neighbor >= 0 && neighbor != rank) {
327feafbc5cSMatthew G Knepley           nleaves += (!xp ? nVx : 1) * (!yp ? nVy : 1) * (!zp ? nVz : 1); /* vertices */
32888ed4aceSMatthew G Knepley           if (xp && !yp && !zp) {
32988ed4aceSMatthew G Knepley             nleaves += nxF; /* x faces */
33088ed4aceSMatthew G Knepley           } else if (yp && !zp && !xp) {
33188ed4aceSMatthew G Knepley             nleaves += nyF; /* y faces */
33288ed4aceSMatthew G Knepley           } else if (zp && !xp && !yp) {
33388ed4aceSMatthew G Knepley             nleaves += nzF; /* z faces */
33488ed4aceSMatthew G Knepley           }
33588ed4aceSMatthew G Knepley         }
33688ed4aceSMatthew G Knepley       }
33788ed4aceSMatthew G Knepley     }
33888ed4aceSMatthew G Knepley   }
33988ed4aceSMatthew G Knepley   ierr = PetscMalloc2(nleaves,PetscInt,&localPoints,nleaves,PetscSFNode,&remotePoints);CHKERRQ(ierr);
34088ed4aceSMatthew G Knepley   for(zn = 0; zn < (dim > 2 ? 3 : 1); ++zn) {
34188ed4aceSMatthew G Knepley     for(yn = 0; yn < (dim > 1 ? 3 : 1); ++yn) {
34288ed4aceSMatthew G Knepley       for(xn = 0; xn < 3; ++xn) {
3437128ae9fSMatthew G Knepley         const PetscInt xp = xn-1, yp = dim > 1 ? yn-1 : 0, zp = dim > 2 ? zn-1 : 0;
34488ed4aceSMatthew G Knepley         const PetscInt neighbor = neighbors[(zn*3+yn)*3+xn];
345*f5eeb527SMatthew G Knepley         PetscInt       xv, yv, zv;
34688ed4aceSMatthew G Knepley 
347feafbc5cSMatthew G Knepley         if (neighbor >= 0 && neighbor != rank) {
34888ed4aceSMatthew G Knepley           if (xp < 0) { /* left */
34988ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
35088ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
35188ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* left bottom back vertex */
352*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx +     0 + nC;
353*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
354*f5eeb527SMatthew G Knepley 
355*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
356*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
357*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
358*f5eeb527SMatthew G Knepley                 ++nL;
35988ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
36088ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* left bottom front vertex */
361*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx +     0 + nC;
362*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
363*f5eeb527SMatthew G Knepley 
364*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
365*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
366*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
367*f5eeb527SMatthew G Knepley                 ++nL;
36888ed4aceSMatthew G Knepley               } else {
36988ed4aceSMatthew G Knepley                 nleavesCheck += nVz; /* left bottom vertices */
370*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv, ++nL) {
371*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx +     0 + nC;
372*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
373*f5eeb527SMatthew G Knepley 
374*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
375*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
376*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
377*f5eeb527SMatthew G Knepley                 }
37888ed4aceSMatthew G Knepley               }
37988ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
38088ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
38188ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* left top back vertex */
382*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx +     0 + nC;
383*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
384*f5eeb527SMatthew G Knepley 
385*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
386*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
387*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
388*f5eeb527SMatthew G Knepley                 ++nL;
38988ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
39088ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* left top front vertex */
391*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC;
392*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
393*f5eeb527SMatthew G Knepley 
394*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
395*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
396*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
397*f5eeb527SMatthew G Knepley                 ++nL;
39888ed4aceSMatthew G Knepley               } else {
39988ed4aceSMatthew G Knepley                 nleavesCheck += nVz; /* left top vertices */
400*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv, ++nL) {
401*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx +     0 + nC;
402*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
403*f5eeb527SMatthew G Knepley 
404*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
405*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
406*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
407*f5eeb527SMatthew G Knepley                 }
40888ed4aceSMatthew G Knepley               }
40988ed4aceSMatthew G Knepley             } else {
41088ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
41188ed4aceSMatthew G Knepley                 nleavesCheck += nVy; /* left back vertices */
412*f5eeb527SMatthew G Knepley                 for(yv = 0; yv < nVy; ++yv, ++nL) {
413*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx +     0 + nC;
414*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
415*f5eeb527SMatthew G Knepley 
416*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
417*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
418*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
419*f5eeb527SMatthew G Knepley                 }
42088ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
42188ed4aceSMatthew G Knepley                 nleavesCheck += nVy; /* left front vertices */
422*f5eeb527SMatthew G Knepley                 for(yv = 0; yv < nVy; ++yv, ++nL) {
423*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx +     0 + nC;
424*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
425*f5eeb527SMatthew G Knepley 
426*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
427*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
428*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
429*f5eeb527SMatthew G Knepley                 }
43088ed4aceSMatthew G Knepley               } else {
43188ed4aceSMatthew G Knepley                 nleavesCheck += nVy*nVz; /* left vertices */
432*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv) {
433*f5eeb527SMatthew G Knepley                   for(yv = 0; yv < nVy; ++yv, ++nL) {
434*f5eeb527SMatthew G Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx +     0 + nC;
435*f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + nVx-1 + nC; /* TODO: Correct this for neighbor sizes */
436*f5eeb527SMatthew G Knepley 
437*f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
438*f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
439*f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
440*f5eeb527SMatthew G Knepley                   }
441*f5eeb527SMatthew G Knepley                 }
44288ed4aceSMatthew G Knepley                 nleavesCheck += nxF;     /* left faces */
443*f5eeb527SMatthew G Knepley                 for(xf = 0; xf < nxF; ++xf, ++nL) {
444*f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
445*f5eeb527SMatthew G Knepley                   const PetscInt localFace  = 0 + nC+nV;
446*f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
447*f5eeb527SMatthew G Knepley 
448*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localFace;
449*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
450*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteFace;
451*f5eeb527SMatthew G Knepley                 }
45288ed4aceSMatthew G Knepley               }
45388ed4aceSMatthew G Knepley             }
45488ed4aceSMatthew G Knepley           } else if (xp > 0) { /* right */
45588ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
45688ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
45788ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* right bottom back vertex */
458*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = (      0*nVy +     0)*nVx + nVx-1 + nC;
459*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
460*f5eeb527SMatthew G Knepley 
461*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
462*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
463*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
464*f5eeb527SMatthew G Knepley                 ++nL;
46588ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
46688ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* right bottom front vertex */
467*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + nVx-1 + nC;
468*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
469*f5eeb527SMatthew G Knepley 
470*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
471*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
472*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
473*f5eeb527SMatthew G Knepley                 ++nL;
47488ed4aceSMatthew G Knepley               } else {
47588ed4aceSMatthew G Knepley                 nleavesCheck += nVz; /* right bottom vertices */
476*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv, ++nL) {
477*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (zv*nVy +     0)*nVx + nVx-1 + nC;
478*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
479*f5eeb527SMatthew G Knepley 
480*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
481*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
482*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
483*f5eeb527SMatthew G Knepley                 }
48488ed4aceSMatthew G Knepley               }
48588ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
48688ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
48788ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* right top back vertex */
488*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + nVx-1 + nC;
489*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
490*f5eeb527SMatthew G Knepley 
491*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
492*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
493*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
494*f5eeb527SMatthew G Knepley                 ++nL;
49588ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
49688ed4aceSMatthew G Knepley                 nleavesCheck += 1; /* right top front vertex */
497*f5eeb527SMatthew G Knepley                 const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + nVx-1 + nC;
498*f5eeb527SMatthew G Knepley                 const PetscInt remoteVertex = (      0*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
499*f5eeb527SMatthew G Knepley 
500*f5eeb527SMatthew G Knepley                 localPoints[nL]        = localVertex;
501*f5eeb527SMatthew G Knepley                 remotePoints[nL].rank  = neighbor;
502*f5eeb527SMatthew G Knepley                 remotePoints[nL].index = remoteVertex;
503*f5eeb527SMatthew G Knepley                 ++nL;
50488ed4aceSMatthew G Knepley               } else {
50588ed4aceSMatthew G Knepley                 nleavesCheck += nVz; /* right top vertices */
506*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv, ++nL) {
507*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + nVx-1 + nC;
508*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (zv*nVy +     0)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
509*f5eeb527SMatthew G Knepley 
510*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
511*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
512*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
513*f5eeb527SMatthew G Knepley                 }
51488ed4aceSMatthew G Knepley               }
51588ed4aceSMatthew G Knepley             } else {
51688ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
51788ed4aceSMatthew G Knepley                 nleavesCheck += nVy; /* right back vertices */
518*f5eeb527SMatthew G Knepley                 for(yv = 0; yv < nVy; ++yv, ++nL) {
519*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (      0*nVy + yv)*nVx + nVx-1 + nC;
520*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
521*f5eeb527SMatthew G Knepley 
522*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
523*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
524*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
525*f5eeb527SMatthew G Knepley                 }
52688ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
52788ed4aceSMatthew G Knepley                 nleavesCheck += nVy; /* right front vertices */
528*f5eeb527SMatthew G Knepley                 for(yv = 0; yv < nVy; ++yv, ++nL) {
529*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + nVx-1 + nC;
530*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + yv)*nVx +     0 + nC; /* TODO: Correct this for neighbor sizes */
531*f5eeb527SMatthew G Knepley 
532*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
533*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
534*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
535*f5eeb527SMatthew G Knepley                 }
53688ed4aceSMatthew G Knepley               } else {
53788ed4aceSMatthew G Knepley                 nleavesCheck += nVy*nVz; /* right vertices */
538*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv) {
539*f5eeb527SMatthew G Knepley                   for(yv = 0; yv < nVy; ++yv, ++nL) {
540*f5eeb527SMatthew G Knepley                     const PetscInt localVertex  = (zv*nVy + yv)*nVx + nVx-1 + nC;
541*f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + yv)*nVx + 0     + nC; /* TODO: Correct this for neighbor sizes */
542*f5eeb527SMatthew G Knepley 
543*f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
544*f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
545*f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
546*f5eeb527SMatthew G Knepley                   }
547*f5eeb527SMatthew G Knepley                 }
54888ed4aceSMatthew G Knepley                 nleavesCheck += nxF;     /* right faces */
549*f5eeb527SMatthew G Knepley                 for(xf = 0; xf < nxF; ++xf, ++nL) {
550*f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
551*f5eeb527SMatthew G Knepley                   const PetscInt localFace  = 0 + nC+nV;
552*f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
553*f5eeb527SMatthew G Knepley 
554*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localFace;
555*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
556*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteFace;
557*f5eeb527SMatthew G Knepley                 }
55888ed4aceSMatthew G Knepley               }
55988ed4aceSMatthew G Knepley             }
56088ed4aceSMatthew G Knepley           } else {
56188ed4aceSMatthew G Knepley             if (yp < 0) { /* bottom */
56288ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
56388ed4aceSMatthew G Knepley                 nleavesCheck += nVx; /* bottom back vertices */
564*f5eeb527SMatthew G Knepley                 for(xv = 0; xv < nVx; ++xv, ++nL) {
565*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (      0*nVy +     0)*nVx + xv + nC;
566*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
567*f5eeb527SMatthew G Knepley 
568*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
569*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
570*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
571*f5eeb527SMatthew G Knepley                 }
57288ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
57388ed4aceSMatthew G Knepley                 nleavesCheck += nVx; /* bottom front vertices */
574*f5eeb527SMatthew G Knepley                 for(xv = 0; xv < nVx; ++xv, ++nL) {
575*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy +     0)*nVx + xv + nC;
576*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
577*f5eeb527SMatthew G Knepley 
578*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
579*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
580*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
581*f5eeb527SMatthew G Knepley                 }
58288ed4aceSMatthew G Knepley               } else {
58388ed4aceSMatthew G Knepley                 nleavesCheck += nVx*nVz; /* bottom vertices */
584*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv) {
585*f5eeb527SMatthew G Knepley                   for(xv = 0; xv < nVx; ++xv, ++nL) {
586*f5eeb527SMatthew G Knepley                     const PetscInt localVertex  = (zv*nVy +     0)*nVx + xv + nC;
587*f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy + nVy-1)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
588*f5eeb527SMatthew G Knepley 
589*f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
590*f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
591*f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
592*f5eeb527SMatthew G Knepley                   }
593*f5eeb527SMatthew G Knepley                 }
59488ed4aceSMatthew G Knepley                 nleavesCheck += nyF;     /* bottom faces */
595*f5eeb527SMatthew G Knepley                 for(yf = 0; yf < nyF; ++yf, ++nL) {
596*f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
597*f5eeb527SMatthew G Knepley                   const PetscInt localFace  = 0 + nC+nV;
598*f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
599*f5eeb527SMatthew G Knepley 
600*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localFace;
601*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
602*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteFace;
603*f5eeb527SMatthew G Knepley                 }
60488ed4aceSMatthew G Knepley               }
60588ed4aceSMatthew G Knepley             } else if (yp > 0) { /* top */
60688ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
60788ed4aceSMatthew G Knepley                 nleavesCheck += nVx; /* top back vertices */
608*f5eeb527SMatthew G Knepley                 for(xv = 0; xv < nVx; ++xv, ++nL) {
609*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = (      0*nVy + nVy-1)*nVx + xv + nC;
610*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = ((nVz-1)*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
611*f5eeb527SMatthew G Knepley 
612*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
613*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
614*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
615*f5eeb527SMatthew G Knepley                 }
61688ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
61788ed4aceSMatthew G Knepley                 nleavesCheck += nVx; /* top front vertices */
618*f5eeb527SMatthew G Knepley                 for(xv = 0; xv < nVx; ++xv, ++nL) {
619*f5eeb527SMatthew G Knepley                   const PetscInt localVertex  = ((nVz-1)*nVy + nVy-1)*nVx + xv + nC;
620*f5eeb527SMatthew G Knepley                   const PetscInt remoteVertex = (      0*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
621*f5eeb527SMatthew G Knepley 
622*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localVertex;
623*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
624*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteVertex;
625*f5eeb527SMatthew G Knepley                 }
62688ed4aceSMatthew G Knepley               } else {
62788ed4aceSMatthew G Knepley                 nleavesCheck += nVx*nVz; /* top vertices */
628*f5eeb527SMatthew G Knepley                 for(zv = 0; zv < nVz; ++zv) {
629*f5eeb527SMatthew G Knepley                   for(xv = 0; xv < nVx; ++xv, ++nL) {
630*f5eeb527SMatthew G Knepley                     const PetscInt localVertex  = (zv*nVy + nVy-1)*nVx + xv + nC;
631*f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (zv*nVy +     0)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
632*f5eeb527SMatthew G Knepley 
633*f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
634*f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
635*f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
636*f5eeb527SMatthew G Knepley                   }
637*f5eeb527SMatthew G Knepley                 }
63888ed4aceSMatthew G Knepley                 nleavesCheck += nyF;     /* top faces */
639*f5eeb527SMatthew G Knepley                 for(yf = 0; yf < nyF; ++yf, ++nL) {
640*f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
641*f5eeb527SMatthew G Knepley                   const PetscInt localFace  = 0 + nC+nV;
642*f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
643*f5eeb527SMatthew G Knepley 
644*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localFace;
645*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
646*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteFace;
647*f5eeb527SMatthew G Knepley                 }
64888ed4aceSMatthew G Knepley               }
64988ed4aceSMatthew G Knepley             } else {
65088ed4aceSMatthew G Knepley               if (zp < 0) { /* back */
65188ed4aceSMatthew G Knepley                 nleavesCheck += nVx*nVy; /* back vertices */
652*f5eeb527SMatthew G Knepley                 for(yv = 0; yv < nVy; ++yv) {
653*f5eeb527SMatthew G Knepley                   for(xv = 0; xv < nVx; ++xv, ++nL) {
654*f5eeb527SMatthew G Knepley                     const PetscInt localVertex  = (      0*nVy + yv)*nVx + xv + nC;
655*f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = ((nVz-1)*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
656*f5eeb527SMatthew G Knepley 
657*f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
658*f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
659*f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
660*f5eeb527SMatthew G Knepley                   }
661*f5eeb527SMatthew G Knepley                 }
66288ed4aceSMatthew G Knepley                 nleavesCheck += nzF;     /* back faces */
663*f5eeb527SMatthew G Knepley                 for(zf = 0; zf < nzF; ++zf, ++nL) {
664*f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
665*f5eeb527SMatthew G Knepley                   const PetscInt localFace  = 0 + nC+nV;
666*f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
667*f5eeb527SMatthew G Knepley 
668*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localFace;
669*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
670*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteFace;
671*f5eeb527SMatthew G Knepley                 }
67288ed4aceSMatthew G Knepley               } else if (zp > 0) { /* front */
67388ed4aceSMatthew G Knepley                 nleavesCheck += nVx*nVy; /* front vertices */
674*f5eeb527SMatthew G Knepley                 for(yv = 0; yv < nVy; ++yv) {
675*f5eeb527SMatthew G Knepley                   for(xv = 0; xv < nVx; ++xv, ++nL) {
676*f5eeb527SMatthew G Knepley                     const PetscInt localVertex  = ((nVz-1)*nVy + yv)*nVx + xv + nC;
677*f5eeb527SMatthew G Knepley                     const PetscInt remoteVertex = (      0*nVy + yv)*nVx + xv + nC; /* TODO: Correct this for neighbor sizes */
678*f5eeb527SMatthew G Knepley 
679*f5eeb527SMatthew G Knepley                     localPoints[nL]        = localVertex;
680*f5eeb527SMatthew G Knepley                     remotePoints[nL].rank  = neighbor;
681*f5eeb527SMatthew G Knepley                     remotePoints[nL].index = remoteVertex;
682*f5eeb527SMatthew G Knepley                   }
683*f5eeb527SMatthew G Knepley                 }
68488ed4aceSMatthew G Knepley                 nleavesCheck += nzF;     /* front faces */
685*f5eeb527SMatthew G Knepley                 for(zf = 0; zf < nzF; ++zf, ++nL) {
686*f5eeb527SMatthew G Knepley                   /* THIS IS WRONG */
687*f5eeb527SMatthew G Knepley                   const PetscInt localFace  = 0 + nC+nV;
688*f5eeb527SMatthew G Knepley                   const PetscInt remoteFace = 0 + nC+nV;
689*f5eeb527SMatthew G Knepley 
690*f5eeb527SMatthew G Knepley                   localPoints[nL]        = localFace;
691*f5eeb527SMatthew G Knepley                   remotePoints[nL].rank  = neighbor;
692*f5eeb527SMatthew G Knepley                   remotePoints[nL].index = remoteFace;
693*f5eeb527SMatthew G Knepley                 }
69488ed4aceSMatthew G Knepley               } else {
69588ed4aceSMatthew G Knepley                 /* Nothing is shared from the interior */
69688ed4aceSMatthew G Knepley               }
69788ed4aceSMatthew G Knepley             }
69888ed4aceSMatthew G Knepley           }
69988ed4aceSMatthew G Knepley         }
70088ed4aceSMatthew G Knepley       }
70188ed4aceSMatthew G Knepley     }
70288ed4aceSMatthew G Knepley   }
70388ed4aceSMatthew G Knepley   if (nleaves != nleavesCheck) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "The number of leaves %d did not match the number of remote leaves %d", nleaves, nleavesCheck);
70488ed4aceSMatthew G Knepley   ierr = PetscSFCreate(((PetscObject) dm)->comm, &sf);CHKERRQ(ierr);
70588ed4aceSMatthew G Knepley   ierr = PetscSFSetGraph(sf, pEnd, nleaves, localPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
70688ed4aceSMatthew G Knepley   /* Create global section */
70788ed4aceSMatthew G Knepley   ierr = PetscSectionCreateGlobalSection(dm->defaultSection, sf, &dm->defaultGlobalSection);CHKERRQ(ierr);
70888ed4aceSMatthew G Knepley   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
70988ed4aceSMatthew G Knepley   /* Create default SF */
71088ed4aceSMatthew G Knepley   ierr = DMCreateDefaultSF(dm, dm->defaultSection, dm->defaultGlobalSection);CHKERRQ(ierr);
711a66d4d66SMatthew G Knepley   PetscFunctionReturn(0);
712a66d4d66SMatthew G Knepley }
713a66d4d66SMatthew G Knepley 
71447c6ae99SBarry Smith /* ------------------------------------------------------------------- */
71547c6ae99SBarry Smith #if defined(PETSC_HAVE_ADIC)
71647c6ae99SBarry Smith 
71747c6ae99SBarry Smith EXTERN_C_BEGIN
718c6db04a5SJed Brown #include <adic/ad_utils.h>
71947c6ae99SBarry Smith EXTERN_C_END
72047c6ae99SBarry Smith 
72147c6ae99SBarry Smith #undef __FUNCT__
722aa219208SBarry Smith #define __FUNCT__ "DMDAGetAdicArray"
72347c6ae99SBarry Smith /*@C
724aa219208SBarry Smith      DMDAGetAdicArray - Gets an array of derivative types for a DMDA
72547c6ae99SBarry Smith 
72647c6ae99SBarry Smith     Input Parameter:
72747c6ae99SBarry Smith +    da - information about my local patch
72847c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch
72947c6ae99SBarry Smith 
73047c6ae99SBarry Smith     Output Parameters:
73147c6ae99SBarry Smith +    vptr - array data structured to be passed to ad_FormFunctionLocal()
73247c6ae99SBarry Smith .    array_start - actual start of 1d array of all values that adiC can access directly (may be null)
73347c6ae99SBarry Smith -    tdof - total number of degrees of freedom represented in array_start (may be null)
73447c6ae99SBarry Smith 
73547c6ae99SBarry Smith      Notes:
73647c6ae99SBarry Smith        The vector values are NOT initialized and may have garbage in them, so you may need
73747c6ae99SBarry Smith        to zero them.
73847c6ae99SBarry Smith 
739aa219208SBarry Smith        Returns the same type of object as the DMDAVecGetArray() except its elements are
74047c6ae99SBarry Smith            derivative types instead of PetscScalars
74147c6ae99SBarry Smith 
74247c6ae99SBarry Smith      Level: advanced
74347c6ae99SBarry Smith 
744aa219208SBarry Smith .seealso: DMDARestoreAdicArray()
74547c6ae99SBarry Smith 
74647c6ae99SBarry Smith @*/
7477087cfbeSBarry Smith PetscErrorCode  DMDAGetAdicArray(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
74847c6ae99SBarry Smith {
74947c6ae99SBarry Smith   PetscErrorCode ierr;
75047c6ae99SBarry Smith   PetscInt       j,i,deriv_type_size,xs,ys,xm,ym,zs,zm,itdof;
75147c6ae99SBarry Smith   char           *iarray_start;
75247c6ae99SBarry Smith   void           **iptr = (void**)vptr;
75347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
75447c6ae99SBarry Smith 
75547c6ae99SBarry Smith   PetscFunctionBegin;
75647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
75747c6ae99SBarry Smith   if (ghosted) {
758aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
75947c6ae99SBarry Smith       if (dd->adarrayghostedin[i]) {
76047c6ae99SBarry Smith         *iptr                   = dd->adarrayghostedin[i];
76147c6ae99SBarry Smith         iarray_start            = (char*)dd->adstartghostedin[i];
76247c6ae99SBarry Smith         itdof                   = dd->ghostedtdof;
76347c6ae99SBarry Smith         dd->adarrayghostedin[i] = PETSC_NULL;
76447c6ae99SBarry Smith         dd->adstartghostedin[i] = PETSC_NULL;
76547c6ae99SBarry Smith 
76647c6ae99SBarry Smith         goto done;
76747c6ae99SBarry Smith       }
76847c6ae99SBarry Smith     }
76947c6ae99SBarry Smith     xs = dd->Xs;
77047c6ae99SBarry Smith     ys = dd->Ys;
77147c6ae99SBarry Smith     zs = dd->Zs;
77247c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
77347c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
77447c6ae99SBarry Smith     zm = dd->Ze-dd->Zs;
77547c6ae99SBarry Smith   } else {
776aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
77747c6ae99SBarry Smith       if (dd->adarrayin[i]) {
77847c6ae99SBarry Smith         *iptr            = dd->adarrayin[i];
77947c6ae99SBarry Smith         iarray_start     = (char*)dd->adstartin[i];
78047c6ae99SBarry Smith         itdof            = dd->tdof;
78147c6ae99SBarry Smith         dd->adarrayin[i] = PETSC_NULL;
78247c6ae99SBarry Smith         dd->adstartin[i] = PETSC_NULL;
78347c6ae99SBarry Smith 
78447c6ae99SBarry Smith         goto done;
78547c6ae99SBarry Smith       }
78647c6ae99SBarry Smith     }
78747c6ae99SBarry Smith     xs = dd->xs;
78847c6ae99SBarry Smith     ys = dd->ys;
78947c6ae99SBarry Smith     zs = dd->zs;
79047c6ae99SBarry Smith     xm = dd->xe-dd->xs;
79147c6ae99SBarry Smith     ym = dd->ye-dd->ys;
79247c6ae99SBarry Smith     zm = dd->ze-dd->zs;
79347c6ae99SBarry Smith   }
79447c6ae99SBarry Smith   deriv_type_size = PetscADGetDerivTypeSize();
79547c6ae99SBarry Smith 
79647c6ae99SBarry Smith   switch (dd->dim) {
79747c6ae99SBarry Smith     case 1: {
79847c6ae99SBarry Smith       void *ptr;
79947c6ae99SBarry Smith       itdof = xm;
80047c6ae99SBarry Smith 
80147c6ae99SBarry Smith       ierr  = PetscMalloc(xm*deriv_type_size,&iarray_start);CHKERRQ(ierr);
80247c6ae99SBarry Smith 
80347c6ae99SBarry Smith       ptr   = (void*)(iarray_start - xs*deriv_type_size);
80447c6ae99SBarry Smith       *iptr = (void*)ptr;
80547c6ae99SBarry Smith       break;}
80647c6ae99SBarry Smith     case 2: {
80747c6ae99SBarry Smith       void **ptr;
80847c6ae99SBarry Smith       itdof = xm*ym;
80947c6ae99SBarry Smith 
81047c6ae99SBarry Smith       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*deriv_type_size,&iarray_start);CHKERRQ(ierr);
81147c6ae99SBarry Smith 
81247c6ae99SBarry Smith       ptr  = (void**)(iarray_start + xm*ym*deriv_type_size - ys*sizeof(void*));
81347c6ae99SBarry Smith       for(j=ys;j<ys+ym;j++) {
81447c6ae99SBarry Smith         ptr[j] = iarray_start + deriv_type_size*(xm*(j-ys) - xs);
81547c6ae99SBarry Smith       }
81647c6ae99SBarry Smith       *iptr = (void*)ptr;
81747c6ae99SBarry Smith       break;}
81847c6ae99SBarry Smith     case 3: {
81947c6ae99SBarry Smith       void ***ptr,**bptr;
82047c6ae99SBarry Smith       itdof = xm*ym*zm;
82147c6ae99SBarry Smith 
82247c6ae99SBarry Smith       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*deriv_type_size,&iarray_start);CHKERRQ(ierr);
82347c6ae99SBarry Smith 
82447c6ae99SBarry Smith       ptr  = (void***)(iarray_start + xm*ym*zm*deriv_type_size - zs*sizeof(void*));
82547c6ae99SBarry Smith       bptr = (void**)(iarray_start + xm*ym*zm*deriv_type_size + zm*sizeof(void**));
82647c6ae99SBarry Smith 
82747c6ae99SBarry Smith       for(i=zs;i<zs+zm;i++) {
82847c6ae99SBarry Smith         ptr[i] = bptr + ((i-zs)*ym - ys);
82947c6ae99SBarry Smith       }
83047c6ae99SBarry Smith       for (i=zs; i<zs+zm; i++) {
83147c6ae99SBarry Smith         for (j=ys; j<ys+ym; j++) {
83247c6ae99SBarry Smith           ptr[i][j] = iarray_start + deriv_type_size*(xm*ym*(i-zs) + xm*(j-ys) - xs);
83347c6ae99SBarry Smith         }
83447c6ae99SBarry Smith       }
83547c6ae99SBarry Smith 
83647c6ae99SBarry Smith       *iptr = (void*)ptr;
83747c6ae99SBarry Smith       break;}
83847c6ae99SBarry Smith     default:
83947c6ae99SBarry Smith       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
84047c6ae99SBarry Smith   }
84147c6ae99SBarry Smith 
84247c6ae99SBarry Smith   done:
84347c6ae99SBarry Smith   /* add arrays to the checked out list */
84447c6ae99SBarry Smith   if (ghosted) {
845aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
84647c6ae99SBarry Smith       if (!dd->adarrayghostedout[i]) {
84747c6ae99SBarry Smith         dd->adarrayghostedout[i] = *iptr ;
84847c6ae99SBarry Smith         dd->adstartghostedout[i] = iarray_start;
84947c6ae99SBarry Smith         dd->ghostedtdof          = itdof;
85047c6ae99SBarry Smith         break;
85147c6ae99SBarry Smith       }
85247c6ae99SBarry Smith     }
85347c6ae99SBarry Smith   } else {
854aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
85547c6ae99SBarry Smith       if (!dd->adarrayout[i]) {
85647c6ae99SBarry Smith         dd->adarrayout[i] = *iptr ;
85747c6ae99SBarry Smith         dd->adstartout[i] = iarray_start;
85847c6ae99SBarry Smith         dd->tdof          = itdof;
85947c6ae99SBarry Smith         break;
86047c6ae99SBarry Smith       }
86147c6ae99SBarry Smith     }
86247c6ae99SBarry Smith   }
863aa219208SBarry Smith   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Too many DMDA ADIC arrays obtained");
86447c6ae99SBarry Smith   if (tdof)        *tdof = itdof;
86547c6ae99SBarry Smith   if (array_start) *(void**)array_start = iarray_start;
86647c6ae99SBarry Smith   PetscFunctionReturn(0);
86747c6ae99SBarry Smith }
86847c6ae99SBarry Smith 
86947c6ae99SBarry Smith #undef __FUNCT__
870aa219208SBarry Smith #define __FUNCT__ "DMDARestoreAdicArray"
87147c6ae99SBarry Smith /*@C
872aa219208SBarry Smith      DMDARestoreAdicArray - Restores an array of derivative types for a DMDA
87347c6ae99SBarry Smith 
87447c6ae99SBarry Smith     Input Parameter:
87547c6ae99SBarry Smith +    da - information about my local patch
87647c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch
87747c6ae99SBarry Smith 
87847c6ae99SBarry Smith     Output Parameters:
87947c6ae99SBarry Smith +    ptr - array data structured to be passed to ad_FormFunctionLocal()
88047c6ae99SBarry Smith .    array_start - actual start of 1d array of all values that adiC can access directly
88147c6ae99SBarry Smith -    tdof - total number of degrees of freedom represented in array_start
88247c6ae99SBarry Smith 
88347c6ae99SBarry Smith      Level: advanced
88447c6ae99SBarry Smith 
885aa219208SBarry Smith .seealso: DMDAGetAdicArray()
88647c6ae99SBarry Smith 
88747c6ae99SBarry Smith @*/
8887087cfbeSBarry Smith PetscErrorCode  DMDARestoreAdicArray(DM da,PetscBool  ghosted,void *ptr,void *array_start,PetscInt *tdof)
88947c6ae99SBarry Smith {
89047c6ae99SBarry Smith   PetscInt  i;
89147c6ae99SBarry Smith   void      **iptr = (void**)ptr,iarray_start = 0;
89247c6ae99SBarry Smith 
89347c6ae99SBarry Smith   PetscFunctionBegin;
89447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
89547c6ae99SBarry Smith   if (ghosted) {
896aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
89747c6ae99SBarry Smith       if (dd->adarrayghostedout[i] == *iptr) {
89847c6ae99SBarry Smith         iarray_start             = dd->adstartghostedout[i];
89947c6ae99SBarry Smith         dd->adarrayghostedout[i] = PETSC_NULL;
90047c6ae99SBarry Smith         dd->adstartghostedout[i] = PETSC_NULL;
90147c6ae99SBarry Smith         break;
90247c6ae99SBarry Smith       }
90347c6ae99SBarry Smith     }
90447c6ae99SBarry Smith     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
905aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
90647c6ae99SBarry Smith       if (!dd->adarrayghostedin[i]){
90747c6ae99SBarry Smith         dd->adarrayghostedin[i] = *iptr;
90847c6ae99SBarry Smith         dd->adstartghostedin[i] = iarray_start;
90947c6ae99SBarry Smith         break;
91047c6ae99SBarry Smith       }
91147c6ae99SBarry Smith     }
91247c6ae99SBarry Smith   } else {
913aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
91447c6ae99SBarry Smith       if (dd->adarrayout[i] == *iptr) {
91547c6ae99SBarry Smith         iarray_start      = dd->adstartout[i];
91647c6ae99SBarry Smith         dd->adarrayout[i] = PETSC_NULL;
91747c6ae99SBarry Smith         dd->adstartout[i] = PETSC_NULL;
91847c6ae99SBarry Smith         break;
91947c6ae99SBarry Smith       }
92047c6ae99SBarry Smith     }
92147c6ae99SBarry Smith     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
922aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
92347c6ae99SBarry Smith       if (!dd->adarrayin[i]){
92447c6ae99SBarry Smith         dd->adarrayin[i]   = *iptr;
92547c6ae99SBarry Smith         dd->adstartin[i]   = iarray_start;
92647c6ae99SBarry Smith         break;
92747c6ae99SBarry Smith       }
92847c6ae99SBarry Smith     }
92947c6ae99SBarry Smith   }
93047c6ae99SBarry Smith   PetscFunctionReturn(0);
93147c6ae99SBarry Smith }
93247c6ae99SBarry Smith 
93347c6ae99SBarry Smith #undef __FUNCT__
93447c6ae99SBarry Smith #define __FUNCT__ "ad_DAGetArray"
9357087cfbeSBarry Smith PetscErrorCode  ad_DAGetArray(DM da,PetscBool  ghosted,void *iptr)
93647c6ae99SBarry Smith {
93747c6ae99SBarry Smith   PetscErrorCode ierr;
93847c6ae99SBarry Smith   PetscFunctionBegin;
939aa219208SBarry Smith   ierr = DMDAGetAdicArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
94047c6ae99SBarry Smith   PetscFunctionReturn(0);
94147c6ae99SBarry Smith }
94247c6ae99SBarry Smith 
94347c6ae99SBarry Smith #undef __FUNCT__
94447c6ae99SBarry Smith #define __FUNCT__ "ad_DARestoreArray"
9457087cfbeSBarry Smith PetscErrorCode  ad_DARestoreArray(DM da,PetscBool  ghosted,void *iptr)
94647c6ae99SBarry Smith {
94747c6ae99SBarry Smith   PetscErrorCode ierr;
94847c6ae99SBarry Smith   PetscFunctionBegin;
949aa219208SBarry Smith   ierr = DMDARestoreAdicArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
95047c6ae99SBarry Smith   PetscFunctionReturn(0);
95147c6ae99SBarry Smith }
95247c6ae99SBarry Smith 
95347c6ae99SBarry Smith #endif
95447c6ae99SBarry Smith 
95547c6ae99SBarry Smith #undef __FUNCT__
956aa219208SBarry Smith #define __FUNCT__ "DMDAGetArray"
95747c6ae99SBarry Smith /*@C
958aa219208SBarry Smith      DMDAGetArray - Gets a work array for a DMDA
95947c6ae99SBarry Smith 
96047c6ae99SBarry Smith     Input Parameter:
96147c6ae99SBarry Smith +    da - information about my local patch
96247c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch
96347c6ae99SBarry Smith 
96447c6ae99SBarry Smith     Output Parameters:
96547c6ae99SBarry Smith .    vptr - array data structured
96647c6ae99SBarry Smith 
96747c6ae99SBarry Smith     Note:  The vector values are NOT initialized and may have garbage in them, so you may need
96847c6ae99SBarry Smith            to zero them.
96947c6ae99SBarry Smith 
97047c6ae99SBarry Smith   Level: advanced
97147c6ae99SBarry Smith 
972aa219208SBarry Smith .seealso: DMDARestoreArray(), DMDAGetAdicArray()
97347c6ae99SBarry Smith 
97447c6ae99SBarry Smith @*/
9757087cfbeSBarry Smith PetscErrorCode  DMDAGetArray(DM da,PetscBool  ghosted,void *vptr)
97647c6ae99SBarry Smith {
97747c6ae99SBarry Smith   PetscErrorCode ierr;
97847c6ae99SBarry Smith   PetscInt       j,i,xs,ys,xm,ym,zs,zm;
97947c6ae99SBarry Smith   char           *iarray_start;
98047c6ae99SBarry Smith   void           **iptr = (void**)vptr;
98147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
98247c6ae99SBarry Smith 
98347c6ae99SBarry Smith   PetscFunctionBegin;
98447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
98547c6ae99SBarry Smith   if (ghosted) {
986aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
98747c6ae99SBarry Smith       if (dd->arrayghostedin[i]) {
98847c6ae99SBarry Smith         *iptr                 = dd->arrayghostedin[i];
98947c6ae99SBarry Smith         iarray_start          = (char*)dd->startghostedin[i];
99047c6ae99SBarry Smith         dd->arrayghostedin[i] = PETSC_NULL;
99147c6ae99SBarry Smith         dd->startghostedin[i] = PETSC_NULL;
99247c6ae99SBarry Smith 
99347c6ae99SBarry Smith         goto done;
99447c6ae99SBarry Smith       }
99547c6ae99SBarry Smith     }
99647c6ae99SBarry Smith     xs = dd->Xs;
99747c6ae99SBarry Smith     ys = dd->Ys;
99847c6ae99SBarry Smith     zs = dd->Zs;
99947c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
100047c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
100147c6ae99SBarry Smith     zm = dd->Ze-dd->Zs;
100247c6ae99SBarry Smith   } else {
1003aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
100447c6ae99SBarry Smith       if (dd->arrayin[i]) {
100547c6ae99SBarry Smith         *iptr          = dd->arrayin[i];
100647c6ae99SBarry Smith         iarray_start   = (char*)dd->startin[i];
100747c6ae99SBarry Smith         dd->arrayin[i] = PETSC_NULL;
100847c6ae99SBarry Smith         dd->startin[i] = PETSC_NULL;
100947c6ae99SBarry Smith 
101047c6ae99SBarry Smith         goto done;
101147c6ae99SBarry Smith       }
101247c6ae99SBarry Smith     }
101347c6ae99SBarry Smith     xs = dd->xs;
101447c6ae99SBarry Smith     ys = dd->ys;
101547c6ae99SBarry Smith     zs = dd->zs;
101647c6ae99SBarry Smith     xm = dd->xe-dd->xs;
101747c6ae99SBarry Smith     ym = dd->ye-dd->ys;
101847c6ae99SBarry Smith     zm = dd->ze-dd->zs;
101947c6ae99SBarry Smith   }
102047c6ae99SBarry Smith 
102147c6ae99SBarry Smith   switch (dd->dim) {
102247c6ae99SBarry Smith     case 1: {
102347c6ae99SBarry Smith       void *ptr;
102447c6ae99SBarry Smith 
102547c6ae99SBarry Smith       ierr  = PetscMalloc(xm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
102647c6ae99SBarry Smith 
102747c6ae99SBarry Smith       ptr   = (void*)(iarray_start - xs*sizeof(PetscScalar));
102847c6ae99SBarry Smith       *iptr = (void*)ptr;
102947c6ae99SBarry Smith       break;}
103047c6ae99SBarry Smith     case 2: {
103147c6ae99SBarry Smith       void **ptr;
103247c6ae99SBarry Smith 
103347c6ae99SBarry Smith       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
103447c6ae99SBarry Smith 
103547c6ae99SBarry Smith       ptr  = (void**)(iarray_start + xm*ym*sizeof(PetscScalar) - ys*sizeof(void*));
103647c6ae99SBarry Smith       for(j=ys;j<ys+ym;j++) {
103747c6ae99SBarry Smith         ptr[j] = iarray_start + sizeof(PetscScalar)*(xm*(j-ys) - xs);
103847c6ae99SBarry Smith       }
103947c6ae99SBarry Smith       *iptr = (void*)ptr;
104047c6ae99SBarry Smith       break;}
104147c6ae99SBarry Smith     case 3: {
104247c6ae99SBarry Smith       void ***ptr,**bptr;
104347c6ae99SBarry Smith 
104447c6ae99SBarry Smith       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
104547c6ae99SBarry Smith 
104647c6ae99SBarry Smith       ptr  = (void***)(iarray_start + xm*ym*zm*sizeof(PetscScalar) - zs*sizeof(void*));
104747c6ae99SBarry Smith       bptr = (void**)(iarray_start + xm*ym*zm*sizeof(PetscScalar) + zm*sizeof(void**));
104847c6ae99SBarry Smith       for(i=zs;i<zs+zm;i++) {
104947c6ae99SBarry Smith         ptr[i] = bptr + ((i-zs)*ym - ys);
105047c6ae99SBarry Smith       }
105147c6ae99SBarry Smith       for (i=zs; i<zs+zm; i++) {
105247c6ae99SBarry Smith         for (j=ys; j<ys+ym; j++) {
105347c6ae99SBarry Smith           ptr[i][j] = iarray_start + sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
105447c6ae99SBarry Smith         }
105547c6ae99SBarry Smith       }
105647c6ae99SBarry Smith 
105747c6ae99SBarry Smith       *iptr = (void*)ptr;
105847c6ae99SBarry Smith       break;}
105947c6ae99SBarry Smith     default:
106047c6ae99SBarry Smith       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
106147c6ae99SBarry Smith   }
106247c6ae99SBarry Smith 
106347c6ae99SBarry Smith   done:
106447c6ae99SBarry Smith   /* add arrays to the checked out list */
106547c6ae99SBarry Smith   if (ghosted) {
1066aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
106747c6ae99SBarry Smith       if (!dd->arrayghostedout[i]) {
106847c6ae99SBarry Smith         dd->arrayghostedout[i] = *iptr ;
106947c6ae99SBarry Smith         dd->startghostedout[i] = iarray_start;
107047c6ae99SBarry Smith         break;
107147c6ae99SBarry Smith       }
107247c6ae99SBarry Smith     }
107347c6ae99SBarry Smith   } else {
1074aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
107547c6ae99SBarry Smith       if (!dd->arrayout[i]) {
107647c6ae99SBarry Smith         dd->arrayout[i] = *iptr ;
107747c6ae99SBarry Smith         dd->startout[i] = iarray_start;
107847c6ae99SBarry Smith         break;
107947c6ae99SBarry Smith       }
108047c6ae99SBarry Smith     }
108147c6ae99SBarry Smith   }
108247c6ae99SBarry Smith   PetscFunctionReturn(0);
108347c6ae99SBarry Smith }
108447c6ae99SBarry Smith 
108547c6ae99SBarry Smith #undef __FUNCT__
1086aa219208SBarry Smith #define __FUNCT__ "DMDARestoreArray"
108747c6ae99SBarry Smith /*@C
1088aa219208SBarry Smith      DMDARestoreArray - Restores an array of derivative types for a DMDA
108947c6ae99SBarry Smith 
109047c6ae99SBarry Smith     Input Parameter:
109147c6ae99SBarry Smith +    da - information about my local patch
109247c6ae99SBarry Smith .    ghosted - do you want arrays for the ghosted or nonghosted patch
109347c6ae99SBarry Smith -    vptr - array data structured to be passed to ad_FormFunctionLocal()
109447c6ae99SBarry Smith 
109547c6ae99SBarry Smith      Level: advanced
109647c6ae99SBarry Smith 
1097aa219208SBarry Smith .seealso: DMDAGetArray(), DMDAGetAdicArray()
109847c6ae99SBarry Smith 
109947c6ae99SBarry Smith @*/
11007087cfbeSBarry Smith PetscErrorCode  DMDARestoreArray(DM da,PetscBool  ghosted,void *vptr)
110147c6ae99SBarry Smith {
110247c6ae99SBarry Smith   PetscInt  i;
110347c6ae99SBarry Smith   void      **iptr = (void**)vptr,*iarray_start = 0;
110447c6ae99SBarry Smith   DM_DA     *dd = (DM_DA*)da->data;
110547c6ae99SBarry Smith 
110647c6ae99SBarry Smith   PetscFunctionBegin;
110747c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
110847c6ae99SBarry Smith   if (ghosted) {
1109aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
111047c6ae99SBarry Smith       if (dd->arrayghostedout[i] == *iptr) {
111147c6ae99SBarry Smith         iarray_start           = dd->startghostedout[i];
111247c6ae99SBarry Smith         dd->arrayghostedout[i] = PETSC_NULL;
111347c6ae99SBarry Smith         dd->startghostedout[i] = PETSC_NULL;
111447c6ae99SBarry Smith         break;
111547c6ae99SBarry Smith       }
111647c6ae99SBarry Smith     }
1117aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
111847c6ae99SBarry Smith       if (!dd->arrayghostedin[i]){
111947c6ae99SBarry Smith         dd->arrayghostedin[i] = *iptr;
112047c6ae99SBarry Smith         dd->startghostedin[i] = iarray_start;
112147c6ae99SBarry Smith         break;
112247c6ae99SBarry Smith       }
112347c6ae99SBarry Smith     }
112447c6ae99SBarry Smith   } else {
1125aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
112647c6ae99SBarry Smith       if (dd->arrayout[i] == *iptr) {
112747c6ae99SBarry Smith         iarray_start    = dd->startout[i];
112847c6ae99SBarry Smith         dd->arrayout[i] = PETSC_NULL;
112947c6ae99SBarry Smith         dd->startout[i] = PETSC_NULL;
113047c6ae99SBarry Smith         break;
113147c6ae99SBarry Smith       }
113247c6ae99SBarry Smith     }
1133aa219208SBarry Smith     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
113447c6ae99SBarry Smith       if (!dd->arrayin[i]){
113547c6ae99SBarry Smith         dd->arrayin[i]  = *iptr;
113647c6ae99SBarry Smith         dd->startin[i]  = iarray_start;
113747c6ae99SBarry Smith         break;
113847c6ae99SBarry Smith       }
113947c6ae99SBarry Smith     }
114047c6ae99SBarry Smith   }
114147c6ae99SBarry Smith   PetscFunctionReturn(0);
114247c6ae99SBarry Smith }
114347c6ae99SBarry Smith 
114447c6ae99SBarry Smith #undef __FUNCT__
1145aa219208SBarry Smith #define __FUNCT__ "DMDAGetAdicMFArray"
114647c6ae99SBarry Smith /*@C
1147aa219208SBarry Smith      DMDAGetAdicMFArray - Gets an array of derivative types for a DMDA for matrix-free ADIC.
114847c6ae99SBarry Smith 
114947c6ae99SBarry Smith      Input Parameter:
115047c6ae99SBarry Smith +    da - information about my local patch
115147c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch?
115247c6ae99SBarry Smith 
115347c6ae99SBarry Smith      Output Parameters:
115447c6ae99SBarry Smith +    vptr - array data structured to be passed to ad_FormFunctionLocal()
115547c6ae99SBarry Smith .    array_start - actual start of 1d array of all values that adiC can access directly (may be null)
115647c6ae99SBarry Smith -    tdof - total number of degrees of freedom represented in array_start (may be null)
115747c6ae99SBarry Smith 
115847c6ae99SBarry Smith      Notes:
115947c6ae99SBarry Smith      The vector values are NOT initialized and may have garbage in them, so you may need
116047c6ae99SBarry Smith      to zero them.
116147c6ae99SBarry Smith 
1162aa219208SBarry Smith      This routine returns the same type of object as the DMDAVecGetArray(), except its
116347c6ae99SBarry Smith      elements are derivative types instead of PetscScalars.
116447c6ae99SBarry Smith 
116547c6ae99SBarry Smith      Level: advanced
116647c6ae99SBarry Smith 
1167aa219208SBarry Smith .seealso: DMDARestoreAdicMFArray(), DMDAGetArray(), DMDAGetAdicArray()
116847c6ae99SBarry Smith 
116947c6ae99SBarry Smith @*/
11707087cfbeSBarry Smith PetscErrorCode  DMDAGetAdicMFArray(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
117147c6ae99SBarry Smith {
117247c6ae99SBarry Smith   PetscErrorCode ierr;
117347c6ae99SBarry Smith   PetscInt       j,i,xs,ys,xm,ym,zs,zm,itdof = 0;
117447c6ae99SBarry Smith   char           *iarray_start;
117547c6ae99SBarry Smith   void           **iptr = (void**)vptr;
117647c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
117747c6ae99SBarry Smith 
117847c6ae99SBarry Smith   PetscFunctionBegin;
117947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
118047c6ae99SBarry Smith   if (ghosted) {
1181aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
118247c6ae99SBarry Smith       if (dd->admfarrayghostedin[i]) {
118347c6ae99SBarry Smith         *iptr                     = dd->admfarrayghostedin[i];
118447c6ae99SBarry Smith         iarray_start              = (char*)dd->admfstartghostedin[i];
118547c6ae99SBarry Smith         itdof                     = dd->ghostedtdof;
118647c6ae99SBarry Smith         dd->admfarrayghostedin[i] = PETSC_NULL;
118747c6ae99SBarry Smith         dd->admfstartghostedin[i] = PETSC_NULL;
118847c6ae99SBarry Smith 
118947c6ae99SBarry Smith         goto done;
119047c6ae99SBarry Smith       }
119147c6ae99SBarry Smith     }
119247c6ae99SBarry Smith     xs = dd->Xs;
119347c6ae99SBarry Smith     ys = dd->Ys;
119447c6ae99SBarry Smith     zs = dd->Zs;
119547c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
119647c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
119747c6ae99SBarry Smith     zm = dd->Ze-dd->Zs;
119847c6ae99SBarry Smith   } else {
1199aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
120047c6ae99SBarry Smith       if (dd->admfarrayin[i]) {
120147c6ae99SBarry Smith         *iptr              = dd->admfarrayin[i];
120247c6ae99SBarry Smith         iarray_start       = (char*)dd->admfstartin[i];
120347c6ae99SBarry Smith         itdof              = dd->tdof;
120447c6ae99SBarry Smith         dd->admfarrayin[i] = PETSC_NULL;
120547c6ae99SBarry Smith         dd->admfstartin[i] = PETSC_NULL;
120647c6ae99SBarry Smith 
120747c6ae99SBarry Smith         goto done;
120847c6ae99SBarry Smith       }
120947c6ae99SBarry Smith     }
121047c6ae99SBarry Smith     xs = dd->xs;
121147c6ae99SBarry Smith     ys = dd->ys;
121247c6ae99SBarry Smith     zs = dd->zs;
121347c6ae99SBarry Smith     xm = dd->xe-dd->xs;
121447c6ae99SBarry Smith     ym = dd->ye-dd->ys;
121547c6ae99SBarry Smith     zm = dd->ze-dd->zs;
121647c6ae99SBarry Smith   }
121747c6ae99SBarry Smith 
121847c6ae99SBarry Smith   switch (dd->dim) {
121947c6ae99SBarry Smith     case 1: {
122047c6ae99SBarry Smith       void *ptr;
122147c6ae99SBarry Smith       itdof = xm;
122247c6ae99SBarry Smith 
122347c6ae99SBarry Smith       ierr  = PetscMalloc(xm*2*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
122447c6ae99SBarry Smith 
122547c6ae99SBarry Smith       ptr   = (void*)(iarray_start - xs*2*sizeof(PetscScalar));
122647c6ae99SBarry Smith       *iptr = (void*)ptr;
122747c6ae99SBarry Smith       break;}
122847c6ae99SBarry Smith     case 2: {
122947c6ae99SBarry Smith       void **ptr;
123047c6ae99SBarry Smith       itdof = xm*ym;
123147c6ae99SBarry Smith 
123247c6ae99SBarry Smith       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*2*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
123347c6ae99SBarry Smith 
123447c6ae99SBarry Smith       ptr  = (void**)(iarray_start + xm*ym*2*sizeof(PetscScalar) - ys*sizeof(void*));
123547c6ae99SBarry Smith       for(j=ys;j<ys+ym;j++) {
123647c6ae99SBarry Smith         ptr[j] = iarray_start + 2*sizeof(PetscScalar)*(xm*(j-ys) - xs);
123747c6ae99SBarry Smith       }
123847c6ae99SBarry Smith       *iptr = (void*)ptr;
123947c6ae99SBarry Smith       break;}
124047c6ae99SBarry Smith     case 3: {
124147c6ae99SBarry Smith       void ***ptr,**bptr;
124247c6ae99SBarry Smith       itdof = xm*ym*zm;
124347c6ae99SBarry Smith 
124447c6ae99SBarry Smith       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*2*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
124547c6ae99SBarry Smith 
124647c6ae99SBarry Smith       ptr  = (void***)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) - zs*sizeof(void*));
124747c6ae99SBarry Smith       bptr = (void**)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) + zm*sizeof(void**));
124847c6ae99SBarry Smith       for(i=zs;i<zs+zm;i++) {
124947c6ae99SBarry Smith         ptr[i] = bptr + ((i-zs)*ym* - ys)*sizeof(void*);
125047c6ae99SBarry Smith       }
125147c6ae99SBarry Smith       for (i=zs; i<zs+zm; i++) {
125247c6ae99SBarry Smith         for (j=ys; j<ys+ym; j++) {
125347c6ae99SBarry Smith           ptr[i][j] = iarray_start + 2*sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
125447c6ae99SBarry Smith         }
125547c6ae99SBarry Smith       }
125647c6ae99SBarry Smith 
125747c6ae99SBarry Smith       *iptr = (void*)ptr;
125847c6ae99SBarry Smith       break;}
125947c6ae99SBarry Smith     default:
126047c6ae99SBarry Smith       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
126147c6ae99SBarry Smith   }
126247c6ae99SBarry Smith 
126347c6ae99SBarry Smith   done:
126447c6ae99SBarry Smith   /* add arrays to the checked out list */
126547c6ae99SBarry Smith   if (ghosted) {
1266aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
126747c6ae99SBarry Smith       if (!dd->admfarrayghostedout[i]) {
126847c6ae99SBarry Smith         dd->admfarrayghostedout[i] = *iptr ;
126947c6ae99SBarry Smith         dd->admfstartghostedout[i] = iarray_start;
127047c6ae99SBarry Smith         dd->ghostedtdof            = itdof;
127147c6ae99SBarry Smith         break;
127247c6ae99SBarry Smith       }
127347c6ae99SBarry Smith     }
127447c6ae99SBarry Smith   } else {
1275aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
127647c6ae99SBarry Smith       if (!dd->admfarrayout[i]) {
127747c6ae99SBarry Smith         dd->admfarrayout[i] = *iptr ;
127847c6ae99SBarry Smith         dd->admfstartout[i] = iarray_start;
127947c6ae99SBarry Smith         dd->tdof            = itdof;
128047c6ae99SBarry Smith         break;
128147c6ae99SBarry Smith       }
128247c6ae99SBarry Smith     }
128347c6ae99SBarry Smith   }
1284aa219208SBarry Smith   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
128547c6ae99SBarry Smith   if (tdof)        *tdof = itdof;
128647c6ae99SBarry Smith   if (array_start) *(void**)array_start = iarray_start;
128747c6ae99SBarry Smith   PetscFunctionReturn(0);
128847c6ae99SBarry Smith }
128947c6ae99SBarry Smith 
129047c6ae99SBarry Smith #undef __FUNCT__
1291aa219208SBarry Smith #define __FUNCT__ "DMDAGetAdicMFArray4"
12927087cfbeSBarry Smith PetscErrorCode  DMDAGetAdicMFArray4(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
129347c6ae99SBarry Smith {
129447c6ae99SBarry Smith   PetscErrorCode ierr;
129587130e5eSHong Zhang   PetscInt       j,i,xs,ys,xm,ym,itdof = 0;
129647c6ae99SBarry Smith   char           *iarray_start;
129747c6ae99SBarry Smith   void           **iptr = (void**)vptr;
129847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
129947c6ae99SBarry Smith 
130047c6ae99SBarry Smith   PetscFunctionBegin;
130147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
130247c6ae99SBarry Smith   if (ghosted) {
1303aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
130447c6ae99SBarry Smith       if (dd->admfarrayghostedin[i]) {
130547c6ae99SBarry Smith         *iptr                     = dd->admfarrayghostedin[i];
130647c6ae99SBarry Smith         iarray_start              = (char*)dd->admfstartghostedin[i];
130747c6ae99SBarry Smith         itdof                     = dd->ghostedtdof;
130847c6ae99SBarry Smith         dd->admfarrayghostedin[i] = PETSC_NULL;
130947c6ae99SBarry Smith         dd->admfstartghostedin[i] = PETSC_NULL;
131047c6ae99SBarry Smith 
131147c6ae99SBarry Smith         goto done;
131247c6ae99SBarry Smith       }
131347c6ae99SBarry Smith     }
131447c6ae99SBarry Smith     xs = dd->Xs;
131547c6ae99SBarry Smith     ys = dd->Ys;
131647c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
131747c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
131847c6ae99SBarry Smith   } else {
1319aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
132047c6ae99SBarry Smith       if (dd->admfarrayin[i]) {
132147c6ae99SBarry Smith         *iptr              = dd->admfarrayin[i];
132247c6ae99SBarry Smith         iarray_start       = (char*)dd->admfstartin[i];
132347c6ae99SBarry Smith         itdof              = dd->tdof;
132447c6ae99SBarry Smith         dd->admfarrayin[i] = PETSC_NULL;
132547c6ae99SBarry Smith         dd->admfstartin[i] = PETSC_NULL;
132647c6ae99SBarry Smith 
132747c6ae99SBarry Smith         goto done;
132847c6ae99SBarry Smith       }
132947c6ae99SBarry Smith     }
133047c6ae99SBarry Smith     xs = dd->xs;
133147c6ae99SBarry Smith     ys = dd->ys;
133247c6ae99SBarry Smith     xm = dd->xe-dd->xs;
133347c6ae99SBarry Smith     ym = dd->ye-dd->ys;
133447c6ae99SBarry Smith   }
133547c6ae99SBarry Smith 
133647c6ae99SBarry Smith   switch (dd->dim) {
133747c6ae99SBarry Smith     case 2: {
133847c6ae99SBarry Smith       void **ptr;
133947c6ae99SBarry Smith       itdof = xm*ym;
134047c6ae99SBarry Smith 
134147c6ae99SBarry Smith       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*5*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
134247c6ae99SBarry Smith 
134347c6ae99SBarry Smith       ptr  = (void**)(iarray_start + xm*ym*5*sizeof(PetscScalar) - ys*sizeof(void*));
134447c6ae99SBarry Smith       for(j=ys;j<ys+ym;j++) {
134547c6ae99SBarry Smith         ptr[j] = iarray_start + 5*sizeof(PetscScalar)*(xm*(j-ys) - xs);
134647c6ae99SBarry Smith       }
134747c6ae99SBarry Smith       *iptr = (void*)ptr;
134847c6ae99SBarry Smith       break;}
134947c6ae99SBarry Smith     default:
135047c6ae99SBarry Smith       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
135147c6ae99SBarry Smith   }
135247c6ae99SBarry Smith 
135347c6ae99SBarry Smith   done:
135447c6ae99SBarry Smith   /* add arrays to the checked out list */
135547c6ae99SBarry Smith   if (ghosted) {
1356aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
135747c6ae99SBarry Smith       if (!dd->admfarrayghostedout[i]) {
135847c6ae99SBarry Smith         dd->admfarrayghostedout[i] = *iptr ;
135947c6ae99SBarry Smith         dd->admfstartghostedout[i] = iarray_start;
136047c6ae99SBarry Smith         dd->ghostedtdof            = itdof;
136147c6ae99SBarry Smith         break;
136247c6ae99SBarry Smith       }
136347c6ae99SBarry Smith     }
136447c6ae99SBarry Smith   } else {
1365aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
136647c6ae99SBarry Smith       if (!dd->admfarrayout[i]) {
136747c6ae99SBarry Smith         dd->admfarrayout[i] = *iptr ;
136847c6ae99SBarry Smith         dd->admfstartout[i] = iarray_start;
136947c6ae99SBarry Smith         dd->tdof            = itdof;
137047c6ae99SBarry Smith         break;
137147c6ae99SBarry Smith       }
137247c6ae99SBarry Smith     }
137347c6ae99SBarry Smith   }
1374aa219208SBarry Smith   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
137547c6ae99SBarry Smith   if (tdof)        *tdof = itdof;
137647c6ae99SBarry Smith   if (array_start) *(void**)array_start = iarray_start;
137747c6ae99SBarry Smith   PetscFunctionReturn(0);
137847c6ae99SBarry Smith }
137947c6ae99SBarry Smith 
138047c6ae99SBarry Smith #undef __FUNCT__
1381aa219208SBarry Smith #define __FUNCT__ "DMDAGetAdicMFArray9"
13827087cfbeSBarry Smith PetscErrorCode  DMDAGetAdicMFArray9(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
138347c6ae99SBarry Smith {
138447c6ae99SBarry Smith   PetscErrorCode ierr;
138587130e5eSHong Zhang   PetscInt       j,i,xs,ys,xm,ym,itdof = 0;
138647c6ae99SBarry Smith   char           *iarray_start;
138747c6ae99SBarry Smith   void           **iptr = (void**)vptr;
138847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
138947c6ae99SBarry Smith 
139047c6ae99SBarry Smith   PetscFunctionBegin;
139147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
139247c6ae99SBarry Smith   if (ghosted) {
1393aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
139447c6ae99SBarry Smith       if (dd->admfarrayghostedin[i]) {
139547c6ae99SBarry Smith         *iptr                     = dd->admfarrayghostedin[i];
139647c6ae99SBarry Smith         iarray_start              = (char*)dd->admfstartghostedin[i];
139747c6ae99SBarry Smith         itdof                     = dd->ghostedtdof;
139847c6ae99SBarry Smith         dd->admfarrayghostedin[i] = PETSC_NULL;
139947c6ae99SBarry Smith         dd->admfstartghostedin[i] = PETSC_NULL;
140047c6ae99SBarry Smith 
140147c6ae99SBarry Smith         goto done;
140247c6ae99SBarry Smith       }
140347c6ae99SBarry Smith     }
140447c6ae99SBarry Smith     xs = dd->Xs;
140547c6ae99SBarry Smith     ys = dd->Ys;
140647c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
140747c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
140847c6ae99SBarry Smith   } else {
1409aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
141047c6ae99SBarry Smith       if (dd->admfarrayin[i]) {
141147c6ae99SBarry Smith         *iptr              = dd->admfarrayin[i];
141247c6ae99SBarry Smith         iarray_start       = (char*)dd->admfstartin[i];
141347c6ae99SBarry Smith         itdof              = dd->tdof;
141447c6ae99SBarry Smith         dd->admfarrayin[i] = PETSC_NULL;
141547c6ae99SBarry Smith         dd->admfstartin[i] = PETSC_NULL;
141647c6ae99SBarry Smith 
141747c6ae99SBarry Smith         goto done;
141847c6ae99SBarry Smith       }
141947c6ae99SBarry Smith     }
142047c6ae99SBarry Smith     xs = dd->xs;
142147c6ae99SBarry Smith     ys = dd->ys;
142247c6ae99SBarry Smith     xm = dd->xe-dd->xs;
142347c6ae99SBarry Smith     ym = dd->ye-dd->ys;
142447c6ae99SBarry Smith   }
142547c6ae99SBarry Smith 
142647c6ae99SBarry Smith   switch (dd->dim) {
142747c6ae99SBarry Smith     case 2: {
142847c6ae99SBarry Smith       void **ptr;
142947c6ae99SBarry Smith       itdof = xm*ym;
143047c6ae99SBarry Smith 
143147c6ae99SBarry Smith       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*10*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
143247c6ae99SBarry Smith 
143347c6ae99SBarry Smith       ptr  = (void**)(iarray_start + xm*ym*10*sizeof(PetscScalar) - ys*sizeof(void*));
143447c6ae99SBarry Smith       for(j=ys;j<ys+ym;j++) {
143547c6ae99SBarry Smith         ptr[j] = iarray_start + 10*sizeof(PetscScalar)*(xm*(j-ys) - xs);
143647c6ae99SBarry Smith       }
143747c6ae99SBarry Smith       *iptr = (void*)ptr;
143847c6ae99SBarry Smith       break;}
143947c6ae99SBarry Smith     default:
144047c6ae99SBarry Smith       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
144147c6ae99SBarry Smith   }
144247c6ae99SBarry Smith 
144347c6ae99SBarry Smith   done:
144447c6ae99SBarry Smith   /* add arrays to the checked out list */
144547c6ae99SBarry Smith   if (ghosted) {
1446aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
144747c6ae99SBarry Smith       if (!dd->admfarrayghostedout[i]) {
144847c6ae99SBarry Smith         dd->admfarrayghostedout[i] = *iptr ;
144947c6ae99SBarry Smith         dd->admfstartghostedout[i] = iarray_start;
145047c6ae99SBarry Smith         dd->ghostedtdof            = itdof;
145147c6ae99SBarry Smith         break;
145247c6ae99SBarry Smith       }
145347c6ae99SBarry Smith     }
145447c6ae99SBarry Smith   } else {
1455aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
145647c6ae99SBarry Smith       if (!dd->admfarrayout[i]) {
145747c6ae99SBarry Smith         dd->admfarrayout[i] = *iptr ;
145847c6ae99SBarry Smith         dd->admfstartout[i] = iarray_start;
145947c6ae99SBarry Smith         dd->tdof            = itdof;
146047c6ae99SBarry Smith         break;
146147c6ae99SBarry Smith       }
146247c6ae99SBarry Smith     }
146347c6ae99SBarry Smith   }
1464aa219208SBarry Smith   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
146547c6ae99SBarry Smith   if (tdof)        *tdof = itdof;
146647c6ae99SBarry Smith   if (array_start) *(void**)array_start = iarray_start;
146747c6ae99SBarry Smith   PetscFunctionReturn(0);
146847c6ae99SBarry Smith }
146947c6ae99SBarry Smith 
147047c6ae99SBarry Smith #undef __FUNCT__
1471aa219208SBarry Smith #define __FUNCT__ "DMDAGetAdicMFArrayb"
147247c6ae99SBarry Smith /*@C
1473aa219208SBarry Smith      DMDAGetAdicMFArrayb - Gets an array of derivative types for a DMDA for matrix-free ADIC.
147447c6ae99SBarry Smith 
147547c6ae99SBarry Smith      Input Parameter:
147647c6ae99SBarry Smith +    da - information about my local patch
147747c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch?
147847c6ae99SBarry Smith 
147947c6ae99SBarry Smith      Output Parameters:
148047c6ae99SBarry Smith +    vptr - array data structured to be passed to ad_FormFunctionLocal()
148147c6ae99SBarry Smith .    array_start - actual start of 1d array of all values that adiC can access directly (may be null)
148247c6ae99SBarry Smith -    tdof - total number of degrees of freedom represented in array_start (may be null)
148347c6ae99SBarry Smith 
148447c6ae99SBarry Smith      Notes:
148547c6ae99SBarry Smith      The vector values are NOT initialized and may have garbage in them, so you may need
148647c6ae99SBarry Smith      to zero them.
148747c6ae99SBarry Smith 
1488aa219208SBarry Smith      This routine returns the same type of object as the DMDAVecGetArray(), except its
148947c6ae99SBarry Smith      elements are derivative types instead of PetscScalars.
149047c6ae99SBarry Smith 
149147c6ae99SBarry Smith      Level: advanced
149247c6ae99SBarry Smith 
1493aa219208SBarry Smith .seealso: DMDARestoreAdicMFArray(), DMDAGetArray(), DMDAGetAdicArray()
149447c6ae99SBarry Smith 
149547c6ae99SBarry Smith @*/
14967087cfbeSBarry Smith PetscErrorCode  DMDAGetAdicMFArrayb(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
149747c6ae99SBarry Smith {
149847c6ae99SBarry Smith   PetscErrorCode ierr;
149947c6ae99SBarry Smith   PetscInt       j,i,xs,ys,xm,ym,zs,zm,itdof = 0;
150047c6ae99SBarry Smith   char           *iarray_start;
150147c6ae99SBarry Smith   void           **iptr = (void**)vptr;
150247c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
150347c6ae99SBarry Smith   PetscInt       bs = dd->w,bs1 = bs+1;
150447c6ae99SBarry Smith 
150547c6ae99SBarry Smith   PetscFunctionBegin;
150647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
150747c6ae99SBarry Smith   if (ghosted) {
1508aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
150947c6ae99SBarry Smith       if (dd->admfarrayghostedin[i]) {
151047c6ae99SBarry Smith         *iptr                     = dd->admfarrayghostedin[i];
151147c6ae99SBarry Smith         iarray_start              = (char*)dd->admfstartghostedin[i];
151247c6ae99SBarry Smith         itdof                     = dd->ghostedtdof;
151347c6ae99SBarry Smith         dd->admfarrayghostedin[i] = PETSC_NULL;
151447c6ae99SBarry Smith         dd->admfstartghostedin[i] = PETSC_NULL;
151547c6ae99SBarry Smith 
151647c6ae99SBarry Smith         goto done;
151747c6ae99SBarry Smith       }
151847c6ae99SBarry Smith     }
151947c6ae99SBarry Smith     xs = dd->Xs;
152047c6ae99SBarry Smith     ys = dd->Ys;
152147c6ae99SBarry Smith     zs = dd->Zs;
152247c6ae99SBarry Smith     xm = dd->Xe-dd->Xs;
152347c6ae99SBarry Smith     ym = dd->Ye-dd->Ys;
152447c6ae99SBarry Smith     zm = dd->Ze-dd->Zs;
152547c6ae99SBarry Smith   } else {
1526aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
152747c6ae99SBarry Smith       if (dd->admfarrayin[i]) {
152847c6ae99SBarry Smith         *iptr              = dd->admfarrayin[i];
152947c6ae99SBarry Smith         iarray_start       = (char*)dd->admfstartin[i];
153047c6ae99SBarry Smith         itdof              = dd->tdof;
153147c6ae99SBarry Smith         dd->admfarrayin[i] = PETSC_NULL;
153247c6ae99SBarry Smith         dd->admfstartin[i] = PETSC_NULL;
153347c6ae99SBarry Smith 
153447c6ae99SBarry Smith         goto done;
153547c6ae99SBarry Smith       }
153647c6ae99SBarry Smith     }
153747c6ae99SBarry Smith     xs = dd->xs;
153847c6ae99SBarry Smith     ys = dd->ys;
153947c6ae99SBarry Smith     zs = dd->zs;
154047c6ae99SBarry Smith     xm = dd->xe-dd->xs;
154147c6ae99SBarry Smith     ym = dd->ye-dd->ys;
154247c6ae99SBarry Smith     zm = dd->ze-dd->zs;
154347c6ae99SBarry Smith   }
154447c6ae99SBarry Smith 
154547c6ae99SBarry Smith   switch (dd->dim) {
154647c6ae99SBarry Smith     case 1: {
154747c6ae99SBarry Smith       void *ptr;
154847c6ae99SBarry Smith       itdof = xm;
154947c6ae99SBarry Smith 
155047c6ae99SBarry Smith       ierr  = PetscMalloc(xm*bs1*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
155147c6ae99SBarry Smith 
155247c6ae99SBarry Smith       ptr   = (void*)(iarray_start - xs*bs1*sizeof(PetscScalar));
155347c6ae99SBarry Smith       *iptr = (void*)ptr;
155447c6ae99SBarry Smith       break;}
155547c6ae99SBarry Smith     case 2: {
155647c6ae99SBarry Smith       void **ptr;
155747c6ae99SBarry Smith       itdof = xm*ym;
155847c6ae99SBarry Smith 
155947c6ae99SBarry Smith       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*bs1*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
156047c6ae99SBarry Smith 
156147c6ae99SBarry Smith       ptr  = (void**)(iarray_start + xm*ym*bs1*sizeof(PetscScalar) - ys*sizeof(void*));
156247c6ae99SBarry Smith       for(j=ys;j<ys+ym;j++) {
156347c6ae99SBarry Smith         ptr[j] = iarray_start + bs1*sizeof(PetscScalar)*(xm*(j-ys) - xs);
156447c6ae99SBarry Smith       }
156547c6ae99SBarry Smith       *iptr = (void*)ptr;
156647c6ae99SBarry Smith       break;}
156747c6ae99SBarry Smith     case 3: {
156847c6ae99SBarry Smith       void ***ptr,**bptr;
156947c6ae99SBarry Smith       itdof = xm*ym*zm;
157047c6ae99SBarry Smith 
157147c6ae99SBarry Smith       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*bs1*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
157247c6ae99SBarry Smith 
157347c6ae99SBarry Smith       ptr  = (void***)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) - zs*sizeof(void*));
157447c6ae99SBarry Smith       bptr = (void**)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) + zm*sizeof(void**));
157547c6ae99SBarry Smith       for(i=zs;i<zs+zm;i++) {
157647c6ae99SBarry Smith         ptr[i] = bptr + ((i-zs)*ym* - ys)*sizeof(void*);
157747c6ae99SBarry Smith       }
157847c6ae99SBarry Smith       for (i=zs; i<zs+zm; i++) {
157947c6ae99SBarry Smith         for (j=ys; j<ys+ym; j++) {
158047c6ae99SBarry Smith           ptr[i][j] = iarray_start + bs1*sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
158147c6ae99SBarry Smith         }
158247c6ae99SBarry Smith       }
158347c6ae99SBarry Smith 
158447c6ae99SBarry Smith       *iptr = (void*)ptr;
158547c6ae99SBarry Smith       break;}
158647c6ae99SBarry Smith     default:
158747c6ae99SBarry Smith       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
158847c6ae99SBarry Smith   }
158947c6ae99SBarry Smith 
159047c6ae99SBarry Smith   done:
159147c6ae99SBarry Smith   /* add arrays to the checked out list */
159247c6ae99SBarry Smith   if (ghosted) {
1593aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
159447c6ae99SBarry Smith       if (!dd->admfarrayghostedout[i]) {
159547c6ae99SBarry Smith         dd->admfarrayghostedout[i] = *iptr ;
159647c6ae99SBarry Smith         dd->admfstartghostedout[i] = iarray_start;
159747c6ae99SBarry Smith         dd->ghostedtdof            = itdof;
159847c6ae99SBarry Smith         break;
159947c6ae99SBarry Smith       }
160047c6ae99SBarry Smith     }
160147c6ae99SBarry Smith   } else {
1602aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
160347c6ae99SBarry Smith       if (!dd->admfarrayout[i]) {
160447c6ae99SBarry Smith         dd->admfarrayout[i] = *iptr ;
160547c6ae99SBarry Smith         dd->admfstartout[i] = iarray_start;
160647c6ae99SBarry Smith         dd->tdof            = itdof;
160747c6ae99SBarry Smith         break;
160847c6ae99SBarry Smith       }
160947c6ae99SBarry Smith     }
161047c6ae99SBarry Smith   }
1611aa219208SBarry Smith   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
161247c6ae99SBarry Smith   if (tdof)        *tdof = itdof;
161347c6ae99SBarry Smith   if (array_start) *(void**)array_start = iarray_start;
161447c6ae99SBarry Smith   PetscFunctionReturn(0);
161547c6ae99SBarry Smith }
161647c6ae99SBarry Smith 
161747c6ae99SBarry Smith #undef __FUNCT__
1618aa219208SBarry Smith #define __FUNCT__ "DMDARestoreAdicMFArray"
161947c6ae99SBarry Smith /*@C
1620aa219208SBarry Smith      DMDARestoreAdicMFArray - Restores an array of derivative types for a DMDA.
162147c6ae99SBarry Smith 
162247c6ae99SBarry Smith      Input Parameter:
162347c6ae99SBarry Smith +    da - information about my local patch
162447c6ae99SBarry Smith -    ghosted - do you want arrays for the ghosted or nonghosted patch?
162547c6ae99SBarry Smith 
162647c6ae99SBarry Smith      Output Parameters:
162747c6ae99SBarry Smith +    ptr - array data structure to be passed to ad_FormFunctionLocal()
162847c6ae99SBarry Smith .    array_start - actual start of 1d array of all values that adiC can access directly
162947c6ae99SBarry Smith -    tdof - total number of degrees of freedom represented in array_start
163047c6ae99SBarry Smith 
163147c6ae99SBarry Smith      Level: advanced
163247c6ae99SBarry Smith 
1633aa219208SBarry Smith .seealso: DMDAGetAdicArray()
163447c6ae99SBarry Smith 
163547c6ae99SBarry Smith @*/
16367087cfbeSBarry Smith PetscErrorCode  DMDARestoreAdicMFArray(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
163747c6ae99SBarry Smith {
163847c6ae99SBarry Smith   PetscInt  i;
163947c6ae99SBarry Smith   void      **iptr = (void**)vptr,*iarray_start = 0;
164047c6ae99SBarry Smith   DM_DA     *dd = (DM_DA*)da->data;
164147c6ae99SBarry Smith 
164247c6ae99SBarry Smith   PetscFunctionBegin;
164347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
164447c6ae99SBarry Smith   if (ghosted) {
1645aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
164647c6ae99SBarry Smith       if (dd->admfarrayghostedout[i] == *iptr) {
164747c6ae99SBarry Smith         iarray_start               = dd->admfstartghostedout[i];
164847c6ae99SBarry Smith         dd->admfarrayghostedout[i] = PETSC_NULL;
164947c6ae99SBarry Smith         dd->admfstartghostedout[i] = PETSC_NULL;
165047c6ae99SBarry Smith         break;
165147c6ae99SBarry Smith       }
165247c6ae99SBarry Smith     }
165347c6ae99SBarry Smith     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
1654aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
165547c6ae99SBarry Smith       if (!dd->admfarrayghostedin[i]){
165647c6ae99SBarry Smith         dd->admfarrayghostedin[i] = *iptr;
165747c6ae99SBarry Smith         dd->admfstartghostedin[i] = iarray_start;
165847c6ae99SBarry Smith         break;
165947c6ae99SBarry Smith       }
166047c6ae99SBarry Smith     }
166147c6ae99SBarry Smith   } else {
1662aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
166347c6ae99SBarry Smith       if (dd->admfarrayout[i] == *iptr) {
166447c6ae99SBarry Smith         iarray_start        = dd->admfstartout[i];
166547c6ae99SBarry Smith         dd->admfarrayout[i] = PETSC_NULL;
166647c6ae99SBarry Smith         dd->admfstartout[i] = PETSC_NULL;
166747c6ae99SBarry Smith         break;
166847c6ae99SBarry Smith       }
166947c6ae99SBarry Smith     }
167047c6ae99SBarry Smith     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
1671aa219208SBarry Smith     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
167247c6ae99SBarry Smith       if (!dd->admfarrayin[i]){
167347c6ae99SBarry Smith         dd->admfarrayin[i] = *iptr;
167447c6ae99SBarry Smith         dd->admfstartin[i] = iarray_start;
167547c6ae99SBarry Smith         break;
167647c6ae99SBarry Smith       }
167747c6ae99SBarry Smith     }
167847c6ae99SBarry Smith   }
167947c6ae99SBarry Smith   PetscFunctionReturn(0);
168047c6ae99SBarry Smith }
168147c6ae99SBarry Smith 
168247c6ae99SBarry Smith #undef __FUNCT__
168347c6ae99SBarry Smith #define __FUNCT__ "admf_DAGetArray"
16847087cfbeSBarry Smith PetscErrorCode  admf_DAGetArray(DM da,PetscBool  ghosted,void *iptr)
168547c6ae99SBarry Smith {
168647c6ae99SBarry Smith   PetscErrorCode ierr;
168747c6ae99SBarry Smith   PetscFunctionBegin;
1688aa219208SBarry Smith   ierr = DMDAGetAdicMFArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
168947c6ae99SBarry Smith   PetscFunctionReturn(0);
169047c6ae99SBarry Smith }
169147c6ae99SBarry Smith 
169247c6ae99SBarry Smith #undef __FUNCT__
169347c6ae99SBarry Smith #define __FUNCT__ "admf_DARestoreArray"
16947087cfbeSBarry Smith PetscErrorCode  admf_DARestoreArray(DM da,PetscBool  ghosted,void *iptr)
169547c6ae99SBarry Smith {
169647c6ae99SBarry Smith   PetscErrorCode ierr;
169747c6ae99SBarry Smith   PetscFunctionBegin;
1698aa219208SBarry Smith   ierr = DMDARestoreAdicMFArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
169947c6ae99SBarry Smith   PetscFunctionReturn(0);
170047c6ae99SBarry Smith }
170147c6ae99SBarry Smith 
1702