xref: /petsc/src/dm/impls/da/da2.c (revision 644e2e5bf092a882fe82d6ae711fcaa07fc3526b)
19a42bb27SBarry Smith 
2c6db04a5SJed Brown #include <private/daimpl.h>    /*I   "petscdmda.h"   I*/
347c6ae99SBarry Smith 
447c6ae99SBarry Smith #undef __FUNCT__
59a42bb27SBarry Smith #define __FUNCT__ "DMView_DA_2d"
69a42bb27SBarry Smith PetscErrorCode DMView_DA_2d(DM da,PetscViewer viewer)
747c6ae99SBarry Smith {
847c6ae99SBarry Smith   PetscErrorCode ierr;
947c6ae99SBarry Smith   PetscMPIInt    rank;
109a42bb27SBarry Smith   PetscBool      iascii,isdraw,isbinary;
1147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
129a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
139a42bb27SBarry Smith   PetscBool      ismatlab;
149a42bb27SBarry Smith #endif
1547c6ae99SBarry Smith 
1647c6ae99SBarry Smith   PetscFunctionBegin;
1747c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)da)->comm,&rank);CHKERRQ(ierr);
1847c6ae99SBarry Smith 
1947c6ae99SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2047c6ae99SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
219a42bb27SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
229a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
239a42bb27SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);CHKERRQ(ierr);
249a42bb27SBarry Smith #endif
2547c6ae99SBarry Smith   if (iascii) {
2647c6ae99SBarry Smith     PetscViewerFormat format;
2747c6ae99SBarry Smith 
2847c6ae99SBarry Smith     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
2947c6ae99SBarry Smith     if (format != PETSC_VIEWER_ASCII_VTK && format != PETSC_VIEWER_ASCII_VTK_CELL) {
30aa219208SBarry Smith       DMDALocalInfo info;
31aa219208SBarry Smith       ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
327b23a99aSBarry Smith       ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
3347c6ae99SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Processor [%d] M %D N %D m %D n %D w %D s %D\n",rank,dd->M,dd->N,dd->m,dd->n,dd->w,dd->s);CHKERRQ(ierr);
3447c6ae99SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"X range of indices: %D %D, Y range of indices: %D %D\n",info.xs,info.xs+info.xm,info.ys,info.ys+info.ym);CHKERRQ(ierr);
3547c6ae99SBarry Smith       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
367b23a99aSBarry Smith       ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
373da9ae13SJed Brown     } else {
383da9ae13SJed Brown       ierr = DMView_DA_VTK(da,viewer);CHKERRQ(ierr);
3947c6ae99SBarry Smith     }
4047c6ae99SBarry Smith   } else if (isdraw) {
4147c6ae99SBarry Smith     PetscDraw  draw;
4247c6ae99SBarry Smith     double     ymin = -1*dd->s-1,ymax = dd->N+dd->s;
4347c6ae99SBarry Smith     double     xmin = -1*dd->s-1,xmax = dd->M+dd->s;
4447c6ae99SBarry Smith     double     x,y;
4547c6ae99SBarry Smith     PetscInt   base,*idx;
4647c6ae99SBarry Smith     char       node[10];
4747c6ae99SBarry Smith     PetscBool  isnull;
4847c6ae99SBarry Smith 
4947c6ae99SBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
5047c6ae99SBarry Smith     ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
5147c6ae99SBarry Smith     if (!dd->coordinates) {
5247c6ae99SBarry Smith       ierr = PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);CHKERRQ(ierr);
5347c6ae99SBarry Smith     }
5447c6ae99SBarry Smith     ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr);
5547c6ae99SBarry Smith 
5647c6ae99SBarry Smith     /* first processor draw all node lines */
5747c6ae99SBarry Smith     if (!rank) {
5847c6ae99SBarry Smith       ymin = 0.0; ymax = dd->N - 1;
5947c6ae99SBarry Smith       for (xmin=0; xmin<dd->M; xmin++) {
6047c6ae99SBarry Smith         ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_BLACK);CHKERRQ(ierr);
6147c6ae99SBarry Smith       }
6247c6ae99SBarry Smith       xmin = 0.0; xmax = dd->M - 1;
6347c6ae99SBarry Smith       for (ymin=0; ymin<dd->N; ymin++) {
6447c6ae99SBarry Smith         ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_BLACK);CHKERRQ(ierr);
6547c6ae99SBarry Smith       }
6647c6ae99SBarry Smith     }
6747c6ae99SBarry Smith     ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
6847c6ae99SBarry Smith     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
6947c6ae99SBarry Smith 
7047c6ae99SBarry Smith     /* draw my box */
7147c6ae99SBarry Smith     ymin = dd->ys; ymax = dd->ye - 1; xmin = dd->xs/dd->w;
7247c6ae99SBarry Smith     xmax =(dd->xe-1)/dd->w;
7347c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_RED);CHKERRQ(ierr);
7447c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
7547c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
7647c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmax,ymin,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
7747c6ae99SBarry Smith 
7847c6ae99SBarry Smith     /* put in numbers */
7947c6ae99SBarry Smith     base = (dd->base)/dd->w;
8047c6ae99SBarry Smith     for (y=ymin; y<=ymax; y++) {
8147c6ae99SBarry Smith       for (x=xmin; x<=xmax; x++) {
8247c6ae99SBarry Smith         sprintf(node,"%d",(int)base++);
8347c6ae99SBarry Smith         ierr = PetscDrawString(draw,x,y,PETSC_DRAW_BLACK,node);CHKERRQ(ierr);
8447c6ae99SBarry Smith       }
8547c6ae99SBarry Smith     }
8647c6ae99SBarry Smith 
8747c6ae99SBarry Smith     ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
8847c6ae99SBarry Smith     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
8947c6ae99SBarry Smith     /* overlay ghost numbers, useful for error checking */
9047c6ae99SBarry Smith     /* put in numbers */
9147c6ae99SBarry Smith 
9247c6ae99SBarry Smith     base = 0; idx = dd->idx;
9347c6ae99SBarry Smith     ymin = dd->Ys; ymax = dd->Ye; xmin = dd->Xs; xmax = dd->Xe;
9447c6ae99SBarry Smith     for (y=ymin; y<ymax; y++) {
9547c6ae99SBarry Smith       for (x=xmin; x<xmax; x++) {
9647c6ae99SBarry Smith         if ((base % dd->w) == 0) {
9747c6ae99SBarry Smith           sprintf(node,"%d",(int)(idx[base]/dd->w));
9847c6ae99SBarry Smith           ierr = PetscDrawString(draw,x/dd->w,y,PETSC_DRAW_BLUE,node);CHKERRQ(ierr);
9947c6ae99SBarry Smith         }
10047c6ae99SBarry Smith         base++;
10147c6ae99SBarry Smith       }
10247c6ae99SBarry Smith     }
10347c6ae99SBarry Smith     ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
10447c6ae99SBarry Smith     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1059a42bb27SBarry Smith   } else if (isbinary){
1069a42bb27SBarry Smith     ierr = DMView_DA_Binary(da,viewer);CHKERRQ(ierr);
1079a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
1089a42bb27SBarry Smith   } else if (ismatlab) {
1099a42bb27SBarry Smith     ierr = DMView_DA_Matlab(da,viewer);CHKERRQ(ierr);
1109a42bb27SBarry Smith #endif
111aa219208SBarry Smith   } else SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for DMDA 1d",((PetscObject)viewer)->type_name);
11247c6ae99SBarry Smith   PetscFunctionReturn(0);
11347c6ae99SBarry Smith }
11447c6ae99SBarry Smith 
11547c6ae99SBarry Smith /*
11647c6ae99SBarry Smith       M is number of grid points
11747c6ae99SBarry Smith       m is number of processors
11847c6ae99SBarry Smith 
11947c6ae99SBarry Smith */
12047c6ae99SBarry Smith #undef __FUNCT__
121aa219208SBarry Smith #define __FUNCT__ "DMDASplitComm2d"
1227087cfbeSBarry Smith PetscErrorCode  DMDASplitComm2d(MPI_Comm comm,PetscInt M,PetscInt N,PetscInt sw,MPI_Comm *outcomm)
12347c6ae99SBarry Smith {
12447c6ae99SBarry Smith   PetscErrorCode ierr;
12547c6ae99SBarry Smith   PetscInt       m,n = 0,x = 0,y = 0;
12647c6ae99SBarry Smith   PetscMPIInt    size,csize,rank;
12747c6ae99SBarry Smith 
12847c6ae99SBarry Smith   PetscFunctionBegin;
12947c6ae99SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
13047c6ae99SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
13147c6ae99SBarry Smith 
13247c6ae99SBarry Smith   csize = 4*size;
13347c6ae99SBarry Smith   do {
13447c6ae99SBarry Smith     if (csize % 4) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cannot split communicator of size %d tried %d %D %D",size,csize,x,y);
13547c6ae99SBarry Smith     csize   = csize/4;
13647c6ae99SBarry Smith 
13747c6ae99SBarry Smith     m = (PetscInt)(0.5 + sqrt(((double)M)*((double)csize)/((double)N)));
13847c6ae99SBarry Smith     if (!m) m = 1;
13947c6ae99SBarry Smith     while (m > 0) {
14047c6ae99SBarry Smith       n = csize/m;
14147c6ae99SBarry Smith       if (m*n == csize) break;
14247c6ae99SBarry Smith       m--;
14347c6ae99SBarry Smith     }
14447c6ae99SBarry Smith     if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;}
14547c6ae99SBarry Smith 
14647c6ae99SBarry Smith     x = M/m + ((M % m) > ((csize-1) % m));
14747c6ae99SBarry Smith     y = (N + (csize-1)/m)/n;
14847c6ae99SBarry Smith   } while ((x < 4 || y < 4) && csize > 1);
14947c6ae99SBarry Smith   if (size != csize) {
15047c6ae99SBarry Smith     MPI_Group    entire_group,sub_group;
15147c6ae99SBarry Smith     PetscMPIInt  i,*groupies;
15247c6ae99SBarry Smith 
15347c6ae99SBarry Smith     ierr = MPI_Comm_group(comm,&entire_group);CHKERRQ(ierr);
15447c6ae99SBarry Smith     ierr = PetscMalloc(csize*sizeof(PetscInt),&groupies);CHKERRQ(ierr);
15547c6ae99SBarry Smith     for (i=0; i<csize; i++) {
15647c6ae99SBarry Smith       groupies[i] = (rank/csize)*csize + i;
15747c6ae99SBarry Smith     }
15847c6ae99SBarry Smith     ierr = MPI_Group_incl(entire_group,csize,groupies,&sub_group);CHKERRQ(ierr);
15947c6ae99SBarry Smith     ierr = PetscFree(groupies);CHKERRQ(ierr);
16047c6ae99SBarry Smith     ierr = MPI_Comm_create(comm,sub_group,outcomm);CHKERRQ(ierr);
16147c6ae99SBarry Smith     ierr = MPI_Group_free(&entire_group);CHKERRQ(ierr);
16247c6ae99SBarry Smith     ierr = MPI_Group_free(&sub_group);CHKERRQ(ierr);
163aa219208SBarry Smith     ierr = PetscInfo1(0,"DMDASplitComm2d:Creating redundant coarse problems of size %d\n",csize);CHKERRQ(ierr);
16447c6ae99SBarry Smith   } else {
16547c6ae99SBarry Smith     *outcomm = comm;
16647c6ae99SBarry Smith   }
16747c6ae99SBarry Smith   PetscFunctionReturn(0);
16847c6ae99SBarry Smith }
16947c6ae99SBarry Smith 
17047c6ae99SBarry Smith #undef __FUNCT__
171*644e2e5bSBarry Smith #define __FUNCT__ "DMDAFunction"
172*644e2e5bSBarry Smith static PetscErrorCode DMDAFunction(DM dm,Vec x,Vec F)
173*644e2e5bSBarry Smith {
174*644e2e5bSBarry Smith   PetscErrorCode ierr;
175*644e2e5bSBarry Smith   Vec            localX;
176*644e2e5bSBarry Smith 
177*644e2e5bSBarry Smith   PetscFunctionBegin;
178*644e2e5bSBarry Smith   ierr = DMGetLocalVector(dm,&localX);CHKERRQ(ierr);
179*644e2e5bSBarry Smith   ierr = DMGlobalToLocalBegin(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr);
180*644e2e5bSBarry Smith   ierr = DMGlobalToLocalEnd(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr);
181*644e2e5bSBarry Smith   ierr = DMDAFormFunction1(dm,localX,F,dm->ctx);CHKERRQ(ierr);
182*644e2e5bSBarry Smith   ierr = DMRestoreLocalVector(dm,&localX);CHKERRQ(ierr);
183*644e2e5bSBarry Smith   PetscFunctionReturn(0);
184*644e2e5bSBarry Smith }
185*644e2e5bSBarry Smith 
186*644e2e5bSBarry Smith #undef __FUNCT__
187aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalFunction"
18847c6ae99SBarry Smith /*@C
189aa219208SBarry Smith        DMDASetLocalFunction - Caches in a DM a local function.
19047c6ae99SBarry Smith 
191aa219208SBarry Smith    Logically Collective on DMDA
19247c6ae99SBarry Smith 
19347c6ae99SBarry Smith    Input Parameter:
19447c6ae99SBarry Smith +  da - initial distributed array
19547c6ae99SBarry Smith -  lf - the local function
19647c6ae99SBarry Smith 
19747c6ae99SBarry Smith    Level: intermediate
19847c6ae99SBarry Smith 
19947c6ae99SBarry Smith    Notes: The routine SNESDAFormFunction() uses this the cached function to evaluate the user provided function.
20047c6ae99SBarry Smith 
20147c6ae99SBarry Smith .keywords:  distributed array, refine
20247c6ae99SBarry Smith 
203aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunctioni()
20447c6ae99SBarry Smith @*/
2057087cfbeSBarry Smith PetscErrorCode  DMDASetLocalFunction(DM da,DMDALocalFunction1 lf)
20647c6ae99SBarry Smith {
207*644e2e5bSBarry Smith   PetscErrorCode ierr;
20847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
209*644e2e5bSBarry Smith 
21047c6ae99SBarry Smith   PetscFunctionBegin;
21147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
212*644e2e5bSBarry Smith   ierr = DMSetFunction(da,DMDAFunction);CHKERRQ(ierr);
21347c6ae99SBarry Smith   dd->lf       = lf;
21447c6ae99SBarry Smith   PetscFunctionReturn(0);
21547c6ae99SBarry Smith }
21647c6ae99SBarry Smith 
21747c6ae99SBarry Smith #undef __FUNCT__
218aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalFunctioni"
21947c6ae99SBarry Smith /*@C
220aa219208SBarry Smith        DMDASetLocalFunctioni - Caches in a DM a local function that evaluates a single component
22147c6ae99SBarry Smith 
222aa219208SBarry Smith    Logically Collective on DMDA
22347c6ae99SBarry Smith 
22447c6ae99SBarry Smith    Input Parameter:
22547c6ae99SBarry Smith +  da - initial distributed array
22647c6ae99SBarry Smith -  lfi - the local function
22747c6ae99SBarry Smith 
22847c6ae99SBarry Smith    Level: intermediate
22947c6ae99SBarry Smith 
23047c6ae99SBarry Smith .keywords:  distributed array, refine
23147c6ae99SBarry Smith 
232aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction()
23347c6ae99SBarry Smith @*/
2347087cfbeSBarry Smith PetscErrorCode  DMDASetLocalFunctioni(DM da,PetscErrorCode (*lfi)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*))
23547c6ae99SBarry Smith {
23647c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
23747c6ae99SBarry Smith   PetscFunctionBegin;
23847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
23947c6ae99SBarry Smith   dd->lfi = lfi;
24047c6ae99SBarry Smith   PetscFunctionReturn(0);
24147c6ae99SBarry Smith }
24247c6ae99SBarry Smith 
24347c6ae99SBarry Smith #undef __FUNCT__
244aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalFunctionib"
24547c6ae99SBarry Smith /*@C
246aa219208SBarry Smith        DMDASetLocalFunctionib - Caches in a DM a block local function that evaluates a single component
24747c6ae99SBarry Smith 
248aa219208SBarry Smith    Logically Collective on DMDA
24947c6ae99SBarry Smith 
25047c6ae99SBarry Smith    Input Parameter:
25147c6ae99SBarry Smith +  da - initial distributed array
25247c6ae99SBarry Smith -  lfi - the local function
25347c6ae99SBarry Smith 
25447c6ae99SBarry Smith    Level: intermediate
25547c6ae99SBarry Smith 
25647c6ae99SBarry Smith .keywords:  distributed array, refine
25747c6ae99SBarry Smith 
258aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction()
25947c6ae99SBarry Smith @*/
2607087cfbeSBarry Smith PetscErrorCode  DMDASetLocalFunctionib(DM da,PetscErrorCode (*lfi)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*))
26147c6ae99SBarry Smith {
26247c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
26347c6ae99SBarry Smith   PetscFunctionBegin;
26447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
26547c6ae99SBarry Smith   dd->lfib = lfi;
26647c6ae99SBarry Smith   PetscFunctionReturn(0);
26747c6ae99SBarry Smith }
26847c6ae99SBarry Smith 
26947c6ae99SBarry Smith #undef __FUNCT__
270aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicFunction_Private"
271aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicFunction_Private(DM da,DMDALocalFunction1 ad_lf)
27247c6ae99SBarry Smith {
27347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
27447c6ae99SBarry Smith   PetscFunctionBegin;
27547c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
27647c6ae99SBarry Smith   dd->adic_lf = ad_lf;
27747c6ae99SBarry Smith   PetscFunctionReturn(0);
27847c6ae99SBarry Smith }
27947c6ae99SBarry Smith 
28047c6ae99SBarry Smith /*MC
281aa219208SBarry Smith        DMDASetLocalAdicFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR
28247c6ae99SBarry Smith 
28347c6ae99SBarry Smith    Synopsis:
284aa219208SBarry Smith    PetscErrorCode DMDASetLocalAdicFunctioni(DM da,PetscInt (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
28547c6ae99SBarry Smith 
286aa219208SBarry Smith    Logically Collective on DMDA
28747c6ae99SBarry Smith 
28847c6ae99SBarry Smith    Input Parameter:
28947c6ae99SBarry Smith +  da - initial distributed array
29047c6ae99SBarry Smith -  ad_lfi - the local function as computed by ADIC/ADIFOR
29147c6ae99SBarry Smith 
29247c6ae99SBarry Smith    Level: intermediate
29347c6ae99SBarry Smith 
29447c6ae99SBarry Smith .keywords:  distributed array, refine
29547c6ae99SBarry Smith 
296aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
297aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctioni()
29847c6ae99SBarry Smith M*/
29947c6ae99SBarry Smith 
30047c6ae99SBarry Smith #undef __FUNCT__
301aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicFunctioni_Private"
302aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicFunctioni_Private(DM da,PetscErrorCode (*ad_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
30347c6ae99SBarry Smith {
30447c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
30547c6ae99SBarry Smith   PetscFunctionBegin;
30647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
30747c6ae99SBarry Smith   dd->adic_lfi = ad_lfi;
30847c6ae99SBarry Smith   PetscFunctionReturn(0);
30947c6ae99SBarry Smith }
31047c6ae99SBarry Smith 
31147c6ae99SBarry Smith /*MC
312aa219208SBarry Smith        DMDASetLocalAdicMFFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR
31347c6ae99SBarry Smith 
31447c6ae99SBarry Smith    Synopsis:
315aa219208SBarry Smith    PetscErrorCode  DMDASetLocalAdicFunctioni(DM da,int (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
31647c6ae99SBarry Smith 
317aa219208SBarry Smith    Logically Collective on DMDA
31847c6ae99SBarry Smith 
31947c6ae99SBarry Smith    Input Parameter:
32047c6ae99SBarry Smith +  da - initial distributed array
32147c6ae99SBarry Smith -  admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR
32247c6ae99SBarry Smith 
32347c6ae99SBarry Smith    Level: intermediate
32447c6ae99SBarry Smith 
32547c6ae99SBarry Smith .keywords:  distributed array, refine
32647c6ae99SBarry Smith 
327aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
328aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctioni()
32947c6ae99SBarry Smith M*/
33047c6ae99SBarry Smith 
33147c6ae99SBarry Smith #undef __FUNCT__
332aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicMFFunctioni_Private"
333aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicMFFunctioni_Private(DM da,PetscErrorCode (*admf_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
33447c6ae99SBarry Smith {
33547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
33647c6ae99SBarry Smith   PetscFunctionBegin;
33747c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
33847c6ae99SBarry Smith   dd->adicmf_lfi = admf_lfi;
33947c6ae99SBarry Smith   PetscFunctionReturn(0);
34047c6ae99SBarry Smith }
34147c6ae99SBarry Smith 
34247c6ae99SBarry Smith /*MC
343aa219208SBarry Smith        DMDASetLocalAdicFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR
34447c6ae99SBarry Smith 
34547c6ae99SBarry Smith    Synopsis:
346aa219208SBarry Smith    PetscErrorCode DMDASetLocalAdicFunctionib(DM da,PetscInt (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
34747c6ae99SBarry Smith 
348aa219208SBarry Smith    Logically Collective on DMDA
34947c6ae99SBarry Smith 
35047c6ae99SBarry Smith    Input Parameter:
35147c6ae99SBarry Smith +  da - initial distributed array
35247c6ae99SBarry Smith -  ad_lfi - the local function as computed by ADIC/ADIFOR
35347c6ae99SBarry Smith 
35447c6ae99SBarry Smith    Level: intermediate
35547c6ae99SBarry Smith 
35647c6ae99SBarry Smith .keywords:  distributed array, refine
35747c6ae99SBarry Smith 
358aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
359aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctionib()
36047c6ae99SBarry Smith M*/
36147c6ae99SBarry Smith 
36247c6ae99SBarry Smith #undef __FUNCT__
363aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicFunctionib_Private"
364aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicFunctionib_Private(DM da,PetscErrorCode (*ad_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
36547c6ae99SBarry Smith {
36647c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
36747c6ae99SBarry Smith   PetscFunctionBegin;
36847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
36947c6ae99SBarry Smith   dd->adic_lfib = ad_lfi;
37047c6ae99SBarry Smith   PetscFunctionReturn(0);
37147c6ae99SBarry Smith }
37247c6ae99SBarry Smith 
37347c6ae99SBarry Smith /*MC
374aa219208SBarry Smith        DMDASetLocalAdicMFFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR
37547c6ae99SBarry Smith 
37647c6ae99SBarry Smith    Synopsis:
377aa219208SBarry Smith    PetscErrorCode  DMDASetLocalAdicFunctionib(DM da,int (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
37847c6ae99SBarry Smith 
379aa219208SBarry Smith    Logically Collective on DMDA
38047c6ae99SBarry Smith 
38147c6ae99SBarry Smith    Input Parameter:
38247c6ae99SBarry Smith +  da - initial distributed array
38347c6ae99SBarry Smith -  admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR
38447c6ae99SBarry Smith 
38547c6ae99SBarry Smith    Level: intermediate
38647c6ae99SBarry Smith 
38747c6ae99SBarry Smith .keywords:  distributed array, refine
38847c6ae99SBarry Smith 
389aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
390aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctionib()
39147c6ae99SBarry Smith M*/
39247c6ae99SBarry Smith 
39347c6ae99SBarry Smith #undef __FUNCT__
394aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicMFFunctionib_Private"
395aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicMFFunctionib_Private(DM da,PetscErrorCode (*admf_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
39647c6ae99SBarry Smith {
39747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
39847c6ae99SBarry Smith   PetscFunctionBegin;
39947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
40047c6ae99SBarry Smith   dd->adicmf_lfib = admf_lfi;
40147c6ae99SBarry Smith   PetscFunctionReturn(0);
40247c6ae99SBarry Smith }
40347c6ae99SBarry Smith 
40447c6ae99SBarry Smith /*MC
405aa219208SBarry Smith        DMDASetLocalAdicMFFunction - Caches in a DM a local function computed by ADIC/ADIFOR
40647c6ae99SBarry Smith 
40747c6ae99SBarry Smith    Synopsis:
408aa219208SBarry Smith    PetscErrorCode DMDASetLocalAdicMFFunction(DM da,DMDALocalFunction1 ad_lf)
40947c6ae99SBarry Smith 
410aa219208SBarry Smith    Logically Collective on DMDA
41147c6ae99SBarry Smith 
41247c6ae99SBarry Smith    Input Parameter:
41347c6ae99SBarry Smith +  da - initial distributed array
41447c6ae99SBarry Smith -  ad_lf - the local function as computed by ADIC/ADIFOR
41547c6ae99SBarry Smith 
41647c6ae99SBarry Smith    Level: intermediate
41747c6ae99SBarry Smith 
41847c6ae99SBarry Smith .keywords:  distributed array, refine
41947c6ae99SBarry Smith 
420aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
421aa219208SBarry Smith           DMDASetLocalJacobian()
42247c6ae99SBarry Smith M*/
42347c6ae99SBarry Smith 
42447c6ae99SBarry Smith #undef __FUNCT__
425aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicMFFunction_Private"
426aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicMFFunction_Private(DM da,DMDALocalFunction1 ad_lf)
42747c6ae99SBarry Smith {
42847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
42947c6ae99SBarry Smith   PetscFunctionBegin;
43047c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
43147c6ae99SBarry Smith   dd->adicmf_lf = ad_lf;
43247c6ae99SBarry Smith   PetscFunctionReturn(0);
43347c6ae99SBarry Smith }
43447c6ae99SBarry Smith 
435*644e2e5bSBarry Smith #undef __FUNCT__
436*644e2e5bSBarry Smith #define __FUNCT__ "DMDAJacobian"
437*644e2e5bSBarry Smith static PetscErrorCode DMDAJacobian(DM dm,Vec x,Mat A,Mat B, MatStructure *str)
438*644e2e5bSBarry Smith {
439*644e2e5bSBarry Smith   PetscErrorCode ierr;
440*644e2e5bSBarry Smith   Vec            localX;
441*644e2e5bSBarry Smith 
442*644e2e5bSBarry Smith   PetscFunctionBegin;
443*644e2e5bSBarry Smith   ierr = DMGetLocalVector(dm,&localX);CHKERRQ(ierr);
444*644e2e5bSBarry Smith   ierr = DMGlobalToLocalBegin(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr);
445*644e2e5bSBarry Smith   ierr = DMGlobalToLocalEnd(dm,x,INSERT_VALUES,localX);CHKERRQ(ierr);
446*644e2e5bSBarry Smith   ierr = DMDAComputeJacobian1(dm,localX,B,dm->ctx);CHKERRQ(ierr);
447*644e2e5bSBarry Smith   ierr = DMRestoreLocalVector(dm,&localX);CHKERRQ(ierr);
448*644e2e5bSBarry Smith   /* Assemble true Jacobian; if it is different */
449*644e2e5bSBarry Smith   if (A != B) {
450*644e2e5bSBarry Smith     ierr  = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
451*644e2e5bSBarry Smith     ierr  = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
452*644e2e5bSBarry Smith   }
453*644e2e5bSBarry Smith   ierr  = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
454*644e2e5bSBarry Smith   *str = SAME_NONZERO_PATTERN;
455*644e2e5bSBarry Smith   PetscFunctionReturn(0);
456*644e2e5bSBarry Smith }
457*644e2e5bSBarry Smith 
45847c6ae99SBarry Smith /*@C
459aa219208SBarry Smith        DMDASetLocalJacobian - Caches in a DM a local Jacobian computation function
46047c6ae99SBarry Smith 
461aa219208SBarry Smith    Logically Collective on DMDA
46247c6ae99SBarry Smith 
46347c6ae99SBarry Smith 
46447c6ae99SBarry Smith    Input Parameter:
46547c6ae99SBarry Smith +  da - initial distributed array
46647c6ae99SBarry Smith -  lj - the local Jacobian
46747c6ae99SBarry Smith 
46847c6ae99SBarry Smith    Level: intermediate
46947c6ae99SBarry Smith 
47047c6ae99SBarry Smith    Notes: The routine SNESDAFormFunction() uses this the cached function to evaluate the user provided function.
47147c6ae99SBarry Smith 
47247c6ae99SBarry Smith .keywords:  distributed array, refine
47347c6ae99SBarry Smith 
474aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction()
47547c6ae99SBarry Smith @*/
47647c6ae99SBarry Smith #undef __FUNCT__
477aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalJacobian"
4787087cfbeSBarry Smith PetscErrorCode  DMDASetLocalJacobian(DM da,DMDALocalFunction1 lj)
47947c6ae99SBarry Smith {
480*644e2e5bSBarry Smith   PetscErrorCode ierr;
48147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
482*644e2e5bSBarry Smith 
48347c6ae99SBarry Smith   PetscFunctionBegin;
48447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
485*644e2e5bSBarry Smith   ierr = DMSetJacobian(da,DMDAJacobian);CHKERRQ(ierr);
48647c6ae99SBarry Smith   dd->lj    = lj;
48747c6ae99SBarry Smith   PetscFunctionReturn(0);
48847c6ae99SBarry Smith }
48947c6ae99SBarry Smith 
49047c6ae99SBarry Smith #undef __FUNCT__
491aa219208SBarry Smith #define __FUNCT__ "DMDAGetLocalFunction"
49247c6ae99SBarry Smith /*@C
493aa219208SBarry Smith        DMDAGetLocalFunction - Gets from a DM a local function and its ADIC/ADIFOR Jacobian
49447c6ae99SBarry Smith 
49547c6ae99SBarry Smith    Note Collective
49647c6ae99SBarry Smith 
49747c6ae99SBarry Smith    Input Parameter:
49847c6ae99SBarry Smith .  da - initial distributed array
49947c6ae99SBarry Smith 
50047c6ae99SBarry Smith    Output Parameter:
50147c6ae99SBarry Smith .  lf - the local function
50247c6ae99SBarry Smith 
50347c6ae99SBarry Smith    Level: intermediate
50447c6ae99SBarry Smith 
50547c6ae99SBarry Smith .keywords:  distributed array, refine
50647c6ae99SBarry Smith 
507aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalJacobian(), DMDASetLocalFunction()
50847c6ae99SBarry Smith @*/
5097087cfbeSBarry Smith PetscErrorCode  DMDAGetLocalFunction(DM da,DMDALocalFunction1 *lf)
51047c6ae99SBarry Smith {
51147c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
51247c6ae99SBarry Smith   PetscFunctionBegin;
51347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
51447c6ae99SBarry Smith   if (lf) *lf = dd->lf;
51547c6ae99SBarry Smith   PetscFunctionReturn(0);
51647c6ae99SBarry Smith }
51747c6ae99SBarry Smith 
51847c6ae99SBarry Smith #undef __FUNCT__
519aa219208SBarry Smith #define __FUNCT__ "DMDAGetLocalJacobian"
52047c6ae99SBarry Smith /*@C
521aa219208SBarry Smith        DMDAGetLocalJacobian - Gets from a DM a local jacobian
52247c6ae99SBarry Smith 
52347c6ae99SBarry Smith    Not Collective
52447c6ae99SBarry Smith 
52547c6ae99SBarry Smith    Input Parameter:
52647c6ae99SBarry Smith .  da - initial distributed array
52747c6ae99SBarry Smith 
52847c6ae99SBarry Smith    Output Parameter:
52947c6ae99SBarry Smith .  lj - the local jacobian
53047c6ae99SBarry Smith 
53147c6ae99SBarry Smith    Level: intermediate
53247c6ae99SBarry Smith 
53347c6ae99SBarry Smith .keywords:  distributed array, refine
53447c6ae99SBarry Smith 
535aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalJacobian()
53647c6ae99SBarry Smith @*/
5377087cfbeSBarry Smith PetscErrorCode  DMDAGetLocalJacobian(DM da,DMDALocalFunction1 *lj)
53847c6ae99SBarry Smith {
53947c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
54047c6ae99SBarry Smith   PetscFunctionBegin;
54147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
54247c6ae99SBarry Smith   if (lj) *lj = dd->lj;
54347c6ae99SBarry Smith   PetscFunctionReturn(0);
54447c6ae99SBarry Smith }
54547c6ae99SBarry Smith 
54647c6ae99SBarry Smith #undef __FUNCT__
547aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunction"
54847c6ae99SBarry Smith /*@
549aa219208SBarry Smith     DMDAFormFunction - Evaluates a user provided function on each processor that
550aa219208SBarry Smith         share a DMDA
55147c6ae99SBarry Smith 
55247c6ae99SBarry Smith    Input Parameters:
5539a42bb27SBarry Smith +    da - the DM that defines the grid
55447c6ae99SBarry Smith .    vu - input vector
55547c6ae99SBarry Smith .    vfu - output vector
55647c6ae99SBarry Smith -    w - any user data
55747c6ae99SBarry Smith 
55847c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
55947c6ae99SBarry Smith 
560aa219208SBarry Smith            This should eventually replace DMDAFormFunction1
56147c6ae99SBarry Smith 
56247c6ae99SBarry Smith     Level: advanced
56347c6ae99SBarry Smith 
564aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
56547c6ae99SBarry Smith 
56647c6ae99SBarry Smith @*/
5677087cfbeSBarry Smith PetscErrorCode  DMDAFormFunction(DM da,PetscErrorCode (*lf)(void),Vec vu,Vec vfu,void *w)
56847c6ae99SBarry Smith {
56947c6ae99SBarry Smith   PetscErrorCode ierr;
57047c6ae99SBarry Smith   void           *u,*fu;
571aa219208SBarry Smith   DMDALocalInfo  info;
572aa219208SBarry Smith   PetscErrorCode (*f)(DMDALocalInfo*,void*,void*,void*) = (PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))lf;
57347c6ae99SBarry Smith 
57447c6ae99SBarry Smith   PetscFunctionBegin;
575aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
576aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
577aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vfu,&fu);CHKERRQ(ierr);
57847c6ae99SBarry Smith 
57939d508bbSBarry Smith   ierr = (*f)(&info,u,fu,w);CHKERRQ(ierr);
58047c6ae99SBarry Smith 
581aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
582aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr);
58347c6ae99SBarry Smith   PetscFunctionReturn(0);
58447c6ae99SBarry Smith }
58547c6ae99SBarry Smith 
58647c6ae99SBarry Smith #undef __FUNCT__
587aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctionLocal"
58847c6ae99SBarry Smith /*@C
589aa219208SBarry Smith    DMDAFormFunctionLocal - This is a universal function evaluation routine for
5909a42bb27SBarry Smith    a local DM function.
59147c6ae99SBarry Smith 
592aa219208SBarry Smith    Collective on DMDA
59347c6ae99SBarry Smith 
59447c6ae99SBarry Smith    Input Parameters:
5959a42bb27SBarry Smith +  da - the DM context
59647c6ae99SBarry Smith .  func - The local function
59747c6ae99SBarry Smith .  X - input vector
59847c6ae99SBarry Smith .  F - function vector
59947c6ae99SBarry Smith -  ctx - A user context
60047c6ae99SBarry Smith 
60147c6ae99SBarry Smith    Level: intermediate
60247c6ae99SBarry Smith 
603aa219208SBarry Smith .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(),
60447c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
60547c6ae99SBarry Smith 
60647c6ae99SBarry Smith @*/
6077087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctionLocal(DM da, DMDALocalFunction1 func, Vec X, Vec F, void *ctx)
60847c6ae99SBarry Smith {
60947c6ae99SBarry Smith   Vec            localX;
610aa219208SBarry Smith   DMDALocalInfo  info;
61147c6ae99SBarry Smith   void           *u;
61247c6ae99SBarry Smith   void           *fu;
61347c6ae99SBarry Smith   PetscErrorCode ierr;
61447c6ae99SBarry Smith 
61547c6ae99SBarry Smith   PetscFunctionBegin;
6169a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
61747c6ae99SBarry Smith   /*
61847c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
6199a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
62047c6ae99SBarry Smith   */
6219a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
6229a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
623aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
624aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr);
625aa219208SBarry Smith   ierr = DMDAVecGetArray(da,F,&fu);CHKERRQ(ierr);
62639d508bbSBarry Smith   ierr = (*func)(&info,u,fu,ctx);CHKERRQ(ierr);
627aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
628aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,F,&fu);CHKERRQ(ierr);
6299a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
63047c6ae99SBarry Smith   PetscFunctionReturn(0);
63147c6ae99SBarry Smith }
63247c6ae99SBarry Smith 
63347c6ae99SBarry Smith #undef __FUNCT__
634aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctionLocalGhost"
63547c6ae99SBarry Smith /*@C
636aa219208SBarry Smith    DMDAFormFunctionLocalGhost - This is a universal function evaluation routine for
6379a42bb27SBarry Smith    a local DM function, but the ghost values of the output are communicated and added.
63847c6ae99SBarry Smith 
639aa219208SBarry Smith    Collective on DMDA
64047c6ae99SBarry Smith 
64147c6ae99SBarry Smith    Input Parameters:
6429a42bb27SBarry Smith +  da - the DM context
64347c6ae99SBarry Smith .  func - The local function
64447c6ae99SBarry Smith .  X - input vector
64547c6ae99SBarry Smith .  F - function vector
64647c6ae99SBarry Smith -  ctx - A user context
64747c6ae99SBarry Smith 
64847c6ae99SBarry Smith    Level: intermediate
64947c6ae99SBarry Smith 
650aa219208SBarry Smith .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(),
65147c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
65247c6ae99SBarry Smith 
65347c6ae99SBarry Smith @*/
6547087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctionLocalGhost(DM da, DMDALocalFunction1 func, Vec X, Vec F, void *ctx)
65547c6ae99SBarry Smith {
65647c6ae99SBarry Smith   Vec            localX, localF;
657aa219208SBarry Smith   DMDALocalInfo  info;
65847c6ae99SBarry Smith   void           *u;
65947c6ae99SBarry Smith   void           *fu;
66047c6ae99SBarry Smith   PetscErrorCode ierr;
66147c6ae99SBarry Smith 
66247c6ae99SBarry Smith   PetscFunctionBegin;
6639a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
6649a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localF);CHKERRQ(ierr);
66547c6ae99SBarry Smith   /*
66647c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
6679a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
66847c6ae99SBarry Smith   */
6699a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
6709a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
67147c6ae99SBarry Smith   ierr = VecSet(F, 0.0);CHKERRQ(ierr);
67247c6ae99SBarry Smith   ierr = VecSet(localF, 0.0);CHKERRQ(ierr);
673aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
674aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr);
675aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localF,&fu);CHKERRQ(ierr);
67639d508bbSBarry Smith   ierr = (*func)(&info,u,fu,ctx);CHKERRQ(ierr);
6779a42bb27SBarry Smith   ierr = DMLocalToGlobalBegin(da,localF,ADD_VALUES,F);CHKERRQ(ierr);
6789a42bb27SBarry Smith   ierr = DMLocalToGlobalEnd(da,localF,ADD_VALUES,F);CHKERRQ(ierr);
679aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
680aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localF,&fu);CHKERRQ(ierr);
6819a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
6829a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localF);CHKERRQ(ierr);
68347c6ae99SBarry Smith   PetscFunctionReturn(0);
68447c6ae99SBarry Smith }
68547c6ae99SBarry Smith 
68647c6ae99SBarry Smith #undef __FUNCT__
687aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunction1"
68847c6ae99SBarry Smith /*@
689aa219208SBarry Smith     DMDAFormFunction1 - Evaluates a user provided function on each processor that
690aa219208SBarry Smith         share a DMDA
69147c6ae99SBarry Smith 
69247c6ae99SBarry Smith    Input Parameters:
6939a42bb27SBarry Smith +    da - the DM that defines the grid
69447c6ae99SBarry Smith .    vu - input vector
69547c6ae99SBarry Smith .    vfu - output vector
69647c6ae99SBarry Smith -    w - any user data
69747c6ae99SBarry Smith 
69847c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
69947c6ae99SBarry Smith 
70047c6ae99SBarry Smith     Level: advanced
70147c6ae99SBarry Smith 
702aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
70347c6ae99SBarry Smith 
70447c6ae99SBarry Smith @*/
7057087cfbeSBarry Smith PetscErrorCode  DMDAFormFunction1(DM da,Vec vu,Vec vfu,void *w)
70647c6ae99SBarry Smith {
70747c6ae99SBarry Smith   PetscErrorCode ierr;
70847c6ae99SBarry Smith   void           *u,*fu;
709aa219208SBarry Smith   DMDALocalInfo  info;
71047c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
71147c6ae99SBarry Smith 
71247c6ae99SBarry Smith   PetscFunctionBegin;
713aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
714aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
715aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vfu,&fu);CHKERRQ(ierr);
71647c6ae99SBarry Smith 
71747c6ae99SBarry Smith   CHKMEMQ;
71839d508bbSBarry Smith   ierr = (*dd->lf)(&info,u,fu,w);CHKERRQ(ierr);
71947c6ae99SBarry Smith   CHKMEMQ;
72047c6ae99SBarry Smith 
721aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
722aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr);
72347c6ae99SBarry Smith   PetscFunctionReturn(0);
72447c6ae99SBarry Smith }
72547c6ae99SBarry Smith 
72647c6ae99SBarry Smith #undef __FUNCT__
727aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctioniTest1"
7287087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctioniTest1(DM da,void *w)
72947c6ae99SBarry Smith {
73047c6ae99SBarry Smith   Vec            vu,fu,fui;
73147c6ae99SBarry Smith   PetscErrorCode ierr;
73247c6ae99SBarry Smith   PetscInt       i,n;
73347c6ae99SBarry Smith   PetscScalar    *ui;
73447c6ae99SBarry Smith   PetscRandom    rnd;
73547c6ae99SBarry Smith   PetscReal      norm;
73647c6ae99SBarry Smith 
73747c6ae99SBarry Smith   PetscFunctionBegin;
7389a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&vu);CHKERRQ(ierr);
73947c6ae99SBarry Smith   ierr = PetscRandomCreate(PETSC_COMM_SELF,&rnd);CHKERRQ(ierr);
74047c6ae99SBarry Smith   ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr);
74147c6ae99SBarry Smith   ierr = VecSetRandom(vu,rnd);CHKERRQ(ierr);
742fcfd50ebSBarry Smith   ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr);
74347c6ae99SBarry Smith 
7449a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&fu);CHKERRQ(ierr);
7459a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&fui);CHKERRQ(ierr);
74647c6ae99SBarry Smith 
747aa219208SBarry Smith   ierr = DMDAFormFunction1(da,vu,fu,w);CHKERRQ(ierr);
74847c6ae99SBarry Smith 
74947c6ae99SBarry Smith   ierr = VecGetArray(fui,&ui);CHKERRQ(ierr);
75047c6ae99SBarry Smith   ierr = VecGetLocalSize(fui,&n);CHKERRQ(ierr);
75147c6ae99SBarry Smith   for (i=0; i<n; i++) {
752aa219208SBarry Smith     ierr = DMDAFormFunctioni1(da,i,vu,ui+i,w);CHKERRQ(ierr);
75347c6ae99SBarry Smith   }
75447c6ae99SBarry Smith   ierr = VecRestoreArray(fui,&ui);CHKERRQ(ierr);
75547c6ae99SBarry Smith 
75647c6ae99SBarry Smith   ierr = VecAXPY(fui,-1.0,fu);CHKERRQ(ierr);
75747c6ae99SBarry Smith   ierr = VecNorm(fui,NORM_2,&norm);CHKERRQ(ierr);
75847c6ae99SBarry Smith   ierr = PetscPrintf(((PetscObject)da)->comm,"Norm of difference in vectors %G\n",norm);CHKERRQ(ierr);
75947c6ae99SBarry Smith   ierr = VecView(fu,0);CHKERRQ(ierr);
76047c6ae99SBarry Smith   ierr = VecView(fui,0);CHKERRQ(ierr);
76147c6ae99SBarry Smith 
7629a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&vu);CHKERRQ(ierr);
7639a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&fu);CHKERRQ(ierr);
7649a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&fui);CHKERRQ(ierr);
76547c6ae99SBarry Smith   PetscFunctionReturn(0);
76647c6ae99SBarry Smith }
76747c6ae99SBarry Smith 
76847c6ae99SBarry Smith #undef __FUNCT__
769aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctioni1"
77047c6ae99SBarry Smith /*@
771aa219208SBarry Smith     DMDAFormFunctioni1 - Evaluates a user provided point-wise function
77247c6ae99SBarry Smith 
77347c6ae99SBarry Smith    Input Parameters:
7749a42bb27SBarry Smith +    da - the DM that defines the grid
77547c6ae99SBarry Smith .    i - the component of the function we wish to compute (must be local)
77647c6ae99SBarry Smith .    vu - input vector
77747c6ae99SBarry Smith .    vfu - output value
77847c6ae99SBarry Smith -    w - any user data
77947c6ae99SBarry Smith 
78047c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
78147c6ae99SBarry Smith 
78247c6ae99SBarry Smith     Level: advanced
78347c6ae99SBarry Smith 
784aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
78547c6ae99SBarry Smith 
78647c6ae99SBarry Smith @*/
7877087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctioni1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w)
78847c6ae99SBarry Smith {
78947c6ae99SBarry Smith   PetscErrorCode ierr;
79047c6ae99SBarry Smith   void           *u;
791aa219208SBarry Smith   DMDALocalInfo  info;
79247c6ae99SBarry Smith   MatStencil     stencil;
79347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
79447c6ae99SBarry Smith 
79547c6ae99SBarry Smith   PetscFunctionBegin;
79647c6ae99SBarry Smith 
797aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
798aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
79947c6ae99SBarry Smith 
80047c6ae99SBarry Smith   /* figure out stencil value from i */
80147c6ae99SBarry Smith   stencil.c = i % info.dof;
80247c6ae99SBarry Smith   stencil.i = (i % (info.xm*info.dof))/info.dof;
80347c6ae99SBarry Smith   stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof);
80447c6ae99SBarry Smith   stencil.k = i/(info.xm*info.ym*info.dof);
80547c6ae99SBarry Smith 
80647c6ae99SBarry Smith   ierr = (*dd->lfi)(&info,&stencil,u,vfu,w);CHKERRQ(ierr);
80747c6ae99SBarry Smith 
808aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
80947c6ae99SBarry Smith   PetscFunctionReturn(0);
81047c6ae99SBarry Smith }
81147c6ae99SBarry Smith 
81247c6ae99SBarry Smith #undef __FUNCT__
813aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctionib1"
81447c6ae99SBarry Smith /*@
815aa219208SBarry Smith     DMDAFormFunctionib1 - Evaluates a user provided point-block function
81647c6ae99SBarry Smith 
81747c6ae99SBarry Smith    Input Parameters:
8189a42bb27SBarry Smith +    da - the DM that defines the grid
81947c6ae99SBarry Smith .    i - the component of the function we wish to compute (must be local)
82047c6ae99SBarry Smith .    vu - input vector
82147c6ae99SBarry Smith .    vfu - output value
82247c6ae99SBarry Smith -    w - any user data
82347c6ae99SBarry Smith 
82447c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
82547c6ae99SBarry Smith 
82647c6ae99SBarry Smith     Level: advanced
82747c6ae99SBarry Smith 
828aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
82947c6ae99SBarry Smith 
83047c6ae99SBarry Smith @*/
8317087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctionib1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w)
83247c6ae99SBarry Smith {
83347c6ae99SBarry Smith   PetscErrorCode ierr;
83447c6ae99SBarry Smith   void           *u;
835aa219208SBarry Smith   DMDALocalInfo  info;
83647c6ae99SBarry Smith   MatStencil     stencil;
83747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
83847c6ae99SBarry Smith 
83947c6ae99SBarry Smith   PetscFunctionBegin;
840aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
841aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
84247c6ae99SBarry Smith 
84347c6ae99SBarry Smith   /* figure out stencil value from i */
84447c6ae99SBarry Smith   stencil.c = i % info.dof;
84547c6ae99SBarry Smith   if (stencil.c) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONG,"Point-block functions can only be called for the entire block");
84647c6ae99SBarry Smith   stencil.i = (i % (info.xm*info.dof))/info.dof;
84747c6ae99SBarry Smith   stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof);
84847c6ae99SBarry Smith   stencil.k = i/(info.xm*info.ym*info.dof);
84947c6ae99SBarry Smith 
85047c6ae99SBarry Smith   ierr = (*dd->lfib)(&info,&stencil,u,vfu,w);CHKERRQ(ierr);
85147c6ae99SBarry Smith 
852aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
85347c6ae99SBarry Smith   PetscFunctionReturn(0);
85447c6ae99SBarry Smith }
85547c6ae99SBarry Smith 
85647c6ae99SBarry Smith #if defined(new)
85747c6ae99SBarry Smith #undef __FUNCT__
858aa219208SBarry Smith #define __FUNCT__ "DMDAGetDiagonal_MFFD"
85947c6ae99SBarry Smith /*
860aa219208SBarry Smith   DMDAGetDiagonal_MFFD - Gets the diagonal for a matrix free matrix where local
861aa219208SBarry Smith     function lives on a DMDA
86247c6ae99SBarry Smith 
86347c6ae99SBarry Smith         y ~= (F(u + ha) - F(u))/h,
86447c6ae99SBarry Smith   where F = nonlinear function, as set by SNESSetFunction()
86547c6ae99SBarry Smith         u = current iterate
86647c6ae99SBarry Smith         h = difference interval
86747c6ae99SBarry Smith */
868aa219208SBarry Smith PetscErrorCode DMDAGetDiagonal_MFFD(DM da,Vec U,Vec a)
86947c6ae99SBarry Smith {
87047c6ae99SBarry Smith   PetscScalar    h,*aa,*ww,v;
87147c6ae99SBarry Smith   PetscReal      epsilon = PETSC_SQRT_MACHINE_EPSILON,umin = 100.0*PETSC_SQRT_MACHINE_EPSILON;
87247c6ae99SBarry Smith   PetscErrorCode ierr;
87347c6ae99SBarry Smith   PetscInt       gI,nI;
87447c6ae99SBarry Smith   MatStencil     stencil;
875aa219208SBarry Smith   DMDALocalInfo  info;
87647c6ae99SBarry Smith 
87747c6ae99SBarry Smith   PetscFunctionBegin;
87847c6ae99SBarry Smith   ierr = (*ctx->func)(0,U,a,ctx->funcctx);CHKERRQ(ierr);
87947c6ae99SBarry Smith   ierr = (*ctx->funcisetbase)(U,ctx->funcctx);CHKERRQ(ierr);
88047c6ae99SBarry Smith 
88147c6ae99SBarry Smith   ierr = VecGetArray(U,&ww);CHKERRQ(ierr);
88247c6ae99SBarry Smith   ierr = VecGetArray(a,&aa);CHKERRQ(ierr);
88347c6ae99SBarry Smith 
88447c6ae99SBarry Smith   nI = 0;
88547c6ae99SBarry Smith     h  = ww[gI];
88647c6ae99SBarry Smith     if (h == 0.0) h = 1.0;
88747c6ae99SBarry Smith #if !defined(PETSC_USE_COMPLEX)
88847c6ae99SBarry Smith     if (h < umin && h >= 0.0)      h = umin;
88947c6ae99SBarry Smith     else if (h < 0.0 && h > -umin) h = -umin;
89047c6ae99SBarry Smith #else
89147c6ae99SBarry Smith     if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0)     h = umin;
89247c6ae99SBarry Smith     else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin;
89347c6ae99SBarry Smith #endif
89447c6ae99SBarry Smith     h     *= epsilon;
89547c6ae99SBarry Smith 
89647c6ae99SBarry Smith     ww[gI] += h;
89747c6ae99SBarry Smith     ierr          = (*ctx->funci)(i,w,&v,ctx->funcctx);CHKERRQ(ierr);
89847c6ae99SBarry Smith     aa[nI]  = (v - aa[nI])/h;
89947c6ae99SBarry Smith     ww[gI] -= h;
90047c6ae99SBarry Smith     nI++;
90147c6ae99SBarry Smith   }
90247c6ae99SBarry Smith   ierr = VecRestoreArray(U,&ww);CHKERRQ(ierr);
90347c6ae99SBarry Smith   ierr = VecRestoreArray(a,&aa);CHKERRQ(ierr);
90447c6ae99SBarry Smith   PetscFunctionReturn(0);
90547c6ae99SBarry Smith }
90647c6ae99SBarry Smith #endif
90747c6ae99SBarry Smith 
90847c6ae99SBarry Smith #if defined(PETSC_HAVE_ADIC)
90947c6ae99SBarry Smith EXTERN_C_BEGIN
910c6db04a5SJed Brown #include <adic/ad_utils.h>
91147c6ae99SBarry Smith EXTERN_C_END
91247c6ae99SBarry Smith 
91347c6ae99SBarry Smith #undef __FUNCT__
914aa219208SBarry Smith #define __FUNCT__ "DMDAComputeJacobian1WithAdic"
91547c6ae99SBarry Smith /*@C
916aa219208SBarry Smith     DMDAComputeJacobian1WithAdic - Evaluates a adiC provided Jacobian function on each processor that
917aa219208SBarry Smith         share a DMDA
91847c6ae99SBarry Smith 
91947c6ae99SBarry Smith    Input Parameters:
9209a42bb27SBarry Smith +    da - the DM that defines the grid
92147c6ae99SBarry Smith .    vu - input vector (ghosted)
92247c6ae99SBarry Smith .    J - output matrix
92347c6ae99SBarry Smith -    w - any user data
92447c6ae99SBarry Smith 
92547c6ae99SBarry Smith    Level: advanced
92647c6ae99SBarry Smith 
92747c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
92847c6ae99SBarry Smith 
929aa219208SBarry Smith .seealso: DMDAFormFunction1()
93047c6ae99SBarry Smith 
93147c6ae99SBarry Smith @*/
9327087cfbeSBarry Smith PetscErrorCode  DMDAComputeJacobian1WithAdic(DM da,Vec vu,Mat J,void *w)
93347c6ae99SBarry Smith {
93447c6ae99SBarry Smith   PetscErrorCode ierr;
93547c6ae99SBarry Smith   PetscInt       gtdof,tdof;
93647c6ae99SBarry Smith   PetscScalar    *ustart;
937aa219208SBarry Smith   DMDALocalInfo  info;
93847c6ae99SBarry Smith   void           *ad_u,*ad_f,*ad_ustart,*ad_fstart;
93947c6ae99SBarry Smith   ISColoring     iscoloring;
94047c6ae99SBarry Smith 
94147c6ae99SBarry Smith   PetscFunctionBegin;
942aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
94347c6ae99SBarry Smith 
94447c6ae99SBarry Smith   PetscADResetIndep();
94547c6ae99SBarry Smith 
94647c6ae99SBarry Smith   /* get space for derivative objects.  */
947aa219208SBarry Smith   ierr = DMDAGetAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,&gtdof);CHKERRQ(ierr);
948aa219208SBarry Smith   ierr = DMDAGetAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
94947c6ae99SBarry Smith   ierr = VecGetArray(vu,&ustart);CHKERRQ(ierr);
95094013140SBarry Smith   ierr = DMGetColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr);
95147c6ae99SBarry Smith 
95247c6ae99SBarry Smith   PetscADSetValueAndColor(ad_ustart,gtdof,iscoloring->colors,ustart);
95347c6ae99SBarry Smith 
95447c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&ustart);CHKERRQ(ierr);
955fcfd50ebSBarry Smith   ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
95647c6ae99SBarry Smith   ierr = PetscADIncrementTotalGradSize(iscoloring->n);CHKERRQ(ierr);
95747c6ae99SBarry Smith   PetscADSetIndepDone();
95847c6ae99SBarry Smith 
959aa219208SBarry Smith   ierr = PetscLogEventBegin(DMDA_LocalADFunction,0,0,0,0);CHKERRQ(ierr);
96047c6ae99SBarry Smith   ierr = (*dd->adic_lf)(&info,ad_u,ad_f,w);CHKERRQ(ierr);
961aa219208SBarry Smith   ierr = PetscLogEventEnd(DMDA_LocalADFunction,0,0,0,0);CHKERRQ(ierr);
96247c6ae99SBarry Smith 
96347c6ae99SBarry Smith   /* stick the values into the matrix */
96447c6ae99SBarry Smith   ierr = MatSetValuesAdic(J,(PetscScalar**)ad_fstart);CHKERRQ(ierr);
96547c6ae99SBarry Smith 
96647c6ae99SBarry Smith   /* return space for derivative objects.  */
967aa219208SBarry Smith   ierr = DMDARestoreAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,&gtdof);CHKERRQ(ierr);
968aa219208SBarry Smith   ierr = DMDARestoreAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
96947c6ae99SBarry Smith   PetscFunctionReturn(0);
97047c6ae99SBarry Smith }
97147c6ae99SBarry Smith 
97247c6ae99SBarry Smith #undef __FUNCT__
973aa219208SBarry Smith #define __FUNCT__ "DMDAMultiplyByJacobian1WithAdic"
97447c6ae99SBarry Smith /*@C
975aa219208SBarry Smith     DMDAMultiplyByJacobian1WithAdic - Applies an ADIC-provided Jacobian function to a vector on
976aa219208SBarry Smith     each processor that shares a DMDA.
97747c6ae99SBarry Smith 
97847c6ae99SBarry Smith     Input Parameters:
9799a42bb27SBarry Smith +   da - the DM that defines the grid
98047c6ae99SBarry Smith .   vu - Jacobian is computed at this point (ghosted)
98147c6ae99SBarry Smith .   v - product is done on this vector (ghosted)
98247c6ae99SBarry Smith .   fu - output vector = J(vu)*v (not ghosted)
98347c6ae99SBarry Smith -   w - any user data
98447c6ae99SBarry Smith 
98547c6ae99SBarry Smith     Notes:
98647c6ae99SBarry Smith     This routine does NOT do ghost updates on vu upon entry.
98747c6ae99SBarry Smith 
98847c6ae99SBarry Smith    Level: advanced
98947c6ae99SBarry Smith 
990aa219208SBarry Smith .seealso: DMDAFormFunction1()
99147c6ae99SBarry Smith 
99247c6ae99SBarry Smith @*/
9937087cfbeSBarry Smith PetscErrorCode  DMDAMultiplyByJacobian1WithAdic(DM da,Vec vu,Vec v,Vec f,void *w)
99447c6ae99SBarry Smith {
99547c6ae99SBarry Smith   PetscErrorCode ierr;
99647c6ae99SBarry Smith   PetscInt       i,gtdof,tdof;
99747c6ae99SBarry Smith   PetscScalar    *avu,*av,*af,*ad_vustart,*ad_fstart;
998aa219208SBarry Smith   DMDALocalInfo  info;
99947c6ae99SBarry Smith   void           *ad_vu,*ad_f;
100047c6ae99SBarry Smith 
100147c6ae99SBarry Smith   PetscFunctionBegin;
1002aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
100347c6ae99SBarry Smith 
100447c6ae99SBarry Smith   /* get space for derivative objects.  */
1005aa219208SBarry Smith   ierr = DMDAGetAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,&gtdof);CHKERRQ(ierr);
1006aa219208SBarry Smith   ierr = DMDAGetAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
100747c6ae99SBarry Smith 
100847c6ae99SBarry Smith   /* copy input vector into derivative object */
100947c6ae99SBarry Smith   ierr = VecGetArray(vu,&avu);CHKERRQ(ierr);
101047c6ae99SBarry Smith   ierr = VecGetArray(v,&av);CHKERRQ(ierr);
101147c6ae99SBarry Smith   for (i=0; i<gtdof; i++) {
101247c6ae99SBarry Smith     ad_vustart[2*i]   = avu[i];
101347c6ae99SBarry Smith     ad_vustart[2*i+1] = av[i];
101447c6ae99SBarry Smith   }
101547c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&avu);CHKERRQ(ierr);
101647c6ae99SBarry Smith   ierr = VecRestoreArray(v,&av);CHKERRQ(ierr);
101747c6ae99SBarry Smith 
101847c6ae99SBarry Smith   PetscADResetIndep();
101947c6ae99SBarry Smith   ierr = PetscADIncrementTotalGradSize(1);CHKERRQ(ierr);
102047c6ae99SBarry Smith   PetscADSetIndepDone();
102147c6ae99SBarry Smith 
102247c6ae99SBarry Smith   ierr = (*dd->adicmf_lf)(&info,ad_vu,ad_f,w);CHKERRQ(ierr);
102347c6ae99SBarry Smith 
102447c6ae99SBarry Smith   /* stick the values into the vector */
102547c6ae99SBarry Smith   ierr = VecGetArray(f,&af);CHKERRQ(ierr);
102647c6ae99SBarry Smith   for (i=0; i<tdof; i++) {
102747c6ae99SBarry Smith     af[i] = ad_fstart[2*i+1];
102847c6ae99SBarry Smith   }
102947c6ae99SBarry Smith   ierr = VecRestoreArray(f,&af);CHKERRQ(ierr);
103047c6ae99SBarry Smith 
103147c6ae99SBarry Smith   /* return space for derivative objects.  */
1032aa219208SBarry Smith   ierr = DMDARestoreAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,&gtdof);CHKERRQ(ierr);
1033aa219208SBarry Smith   ierr = DMDARestoreAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
103447c6ae99SBarry Smith   PetscFunctionReturn(0);
103547c6ae99SBarry Smith }
103647c6ae99SBarry Smith #endif
103747c6ae99SBarry Smith 
103847c6ae99SBarry Smith #undef __FUNCT__
1039aa219208SBarry Smith #define __FUNCT__ "DMDAComputeJacobian1"
104047c6ae99SBarry Smith /*@
1041aa219208SBarry Smith     DMDAComputeJacobian1 - Evaluates a local Jacobian function on each processor that
1042aa219208SBarry Smith         share a DMDA
104347c6ae99SBarry Smith 
104447c6ae99SBarry Smith    Input Parameters:
10459a42bb27SBarry Smith +    da - the DM that defines the grid
104647c6ae99SBarry Smith .    vu - input vector (ghosted)
104747c6ae99SBarry Smith .    J - output matrix
104847c6ae99SBarry Smith -    w - any user data
104947c6ae99SBarry Smith 
105047c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
105147c6ae99SBarry Smith 
105247c6ae99SBarry Smith     Level: advanced
105347c6ae99SBarry Smith 
1054aa219208SBarry Smith .seealso: DMDAFormFunction1()
105547c6ae99SBarry Smith 
105647c6ae99SBarry Smith @*/
10577087cfbeSBarry Smith PetscErrorCode  DMDAComputeJacobian1(DM da,Vec vu,Mat J,void *w)
105847c6ae99SBarry Smith {
105947c6ae99SBarry Smith   PetscErrorCode ierr;
106047c6ae99SBarry Smith   void           *u;
1061aa219208SBarry Smith   DMDALocalInfo  info;
106247c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
106347c6ae99SBarry Smith 
106447c6ae99SBarry Smith   PetscFunctionBegin;
1065aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
1066aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
106747c6ae99SBarry Smith   ierr = (*dd->lj)(&info,u,J,w);CHKERRQ(ierr);
1068aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
106947c6ae99SBarry Smith   PetscFunctionReturn(0);
107047c6ae99SBarry Smith }
107147c6ae99SBarry Smith 
107247c6ae99SBarry Smith 
107347c6ae99SBarry Smith #undef __FUNCT__
1074aa219208SBarry Smith #define __FUNCT__ "DMDAComputeJacobian1WithAdifor"
107547c6ae99SBarry Smith /*
1076aa219208SBarry Smith     DMDAComputeJacobian1WithAdifor - Evaluates a ADIFOR provided Jacobian local function on each processor that
1077aa219208SBarry Smith         share a DMDA
107847c6ae99SBarry Smith 
107947c6ae99SBarry Smith    Input Parameters:
10809a42bb27SBarry Smith +    da - the DM that defines the grid
108147c6ae99SBarry Smith .    vu - input vector (ghosted)
108247c6ae99SBarry Smith .    J - output matrix
108347c6ae99SBarry Smith -    w - any user data
108447c6ae99SBarry Smith 
108547c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
108647c6ae99SBarry Smith 
1087aa219208SBarry Smith .seealso: DMDAFormFunction1()
108847c6ae99SBarry Smith 
108947c6ae99SBarry Smith */
10907087cfbeSBarry Smith PetscErrorCode  DMDAComputeJacobian1WithAdifor(DM da,Vec vu,Mat J,void *w)
109147c6ae99SBarry Smith {
109247c6ae99SBarry Smith   PetscErrorCode  ierr;
109347c6ae99SBarry Smith   PetscInt        i,Nc,N;
109447c6ae99SBarry Smith   ISColoringValue *color;
1095aa219208SBarry Smith   DMDALocalInfo   info;
109647c6ae99SBarry Smith   PetscScalar     *u,*g_u,*g_f,*f = 0,*p_u;
109747c6ae99SBarry Smith   ISColoring      iscoloring;
109847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
1099aa219208SBarry Smith   void            (*lf)(PetscInt*,DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*) =
1100aa219208SBarry Smith                   (void (*)(PetscInt*,DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*))*dd->adifor_lf;
110147c6ae99SBarry Smith 
110247c6ae99SBarry Smith   PetscFunctionBegin;
110394013140SBarry Smith   ierr = DMGetColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr);
110447c6ae99SBarry Smith   Nc   = iscoloring->n;
1105aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
110647c6ae99SBarry Smith   N    = info.gxm*info.gym*info.gzm*info.dof;
110747c6ae99SBarry Smith 
110847c6ae99SBarry Smith   /* get space for derivative objects.  */
110947c6ae99SBarry Smith   ierr  = PetscMalloc(Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar),&g_u);CHKERRQ(ierr);
111047c6ae99SBarry Smith   ierr  = PetscMemzero(g_u,Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar));CHKERRQ(ierr);
111147c6ae99SBarry Smith   p_u   = g_u;
111247c6ae99SBarry Smith   color = iscoloring->colors;
111347c6ae99SBarry Smith   for (i=0; i<N; i++) {
111447c6ae99SBarry Smith     p_u[*color++] = 1.0;
111547c6ae99SBarry Smith     p_u          += Nc;
111647c6ae99SBarry Smith   }
1117fcfd50ebSBarry Smith   ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
111847c6ae99SBarry Smith   ierr = PetscMalloc2(Nc*info.xm*info.ym*info.zm*info.dof,PetscScalar,&g_f,info.xm*info.ym*info.zm*info.dof,PetscScalar,&f);CHKERRQ(ierr);
111947c6ae99SBarry Smith 
112047c6ae99SBarry Smith   /* Seed the input array g_u with coloring information */
112147c6ae99SBarry Smith 
112247c6ae99SBarry Smith   ierr = VecGetArray(vu,&u);CHKERRQ(ierr);
112347c6ae99SBarry Smith   (lf)(&Nc,&info,u,g_u,&Nc,f,g_f,&Nc,w,&ierr);CHKERRQ(ierr);
112447c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&u);CHKERRQ(ierr);
112547c6ae99SBarry Smith 
112647c6ae99SBarry Smith   /* stick the values into the matrix */
112747c6ae99SBarry Smith   /* PetscScalarView(Nc*info.xm*info.ym,g_f,0); */
112847c6ae99SBarry Smith   ierr = MatSetValuesAdifor(J,Nc,g_f);CHKERRQ(ierr);
112947c6ae99SBarry Smith 
113047c6ae99SBarry Smith   /* return space for derivative objects.  */
113147c6ae99SBarry Smith   ierr = PetscFree(g_u);CHKERRQ(ierr);
113247c6ae99SBarry Smith   ierr = PetscFree2(g_f,f);CHKERRQ(ierr);
113347c6ae99SBarry Smith   PetscFunctionReturn(0);
113447c6ae99SBarry Smith }
113547c6ae99SBarry Smith 
113647c6ae99SBarry Smith #undef __FUNCT__
1137aa219208SBarry Smith #define __FUNCT__ "DMDAFormJacobianLocal"
113847c6ae99SBarry Smith /*@C
1139aa219208SBarry Smith    DMDAFormjacobianLocal - This is a universal Jacobian evaluation routine for
11409a42bb27SBarry Smith    a local DM function.
114147c6ae99SBarry Smith 
1142aa219208SBarry Smith    Collective on DMDA
114347c6ae99SBarry Smith 
114447c6ae99SBarry Smith    Input Parameters:
11459a42bb27SBarry Smith +  da - the DM context
114647c6ae99SBarry Smith .  func - The local function
114747c6ae99SBarry Smith .  X - input vector
114847c6ae99SBarry Smith .  J - Jacobian matrix
114947c6ae99SBarry Smith -  ctx - A user context
115047c6ae99SBarry Smith 
115147c6ae99SBarry Smith    Level: intermediate
115247c6ae99SBarry Smith 
1153aa219208SBarry Smith .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(),
115447c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
115547c6ae99SBarry Smith 
115647c6ae99SBarry Smith @*/
11577087cfbeSBarry Smith PetscErrorCode  DMDAFormJacobianLocal(DM da, DMDALocalFunction1 func, Vec X, Mat J, void *ctx)
115847c6ae99SBarry Smith {
115947c6ae99SBarry Smith   Vec            localX;
1160aa219208SBarry Smith   DMDALocalInfo  info;
116147c6ae99SBarry Smith   void           *u;
116247c6ae99SBarry Smith   PetscErrorCode ierr;
116347c6ae99SBarry Smith 
116447c6ae99SBarry Smith   PetscFunctionBegin;
11659a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
116647c6ae99SBarry Smith   /*
116747c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
11689a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
116947c6ae99SBarry Smith   */
11709a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
11719a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
1172aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
1173aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr);
117439d508bbSBarry Smith   ierr = (*func)(&info,u,J,ctx);CHKERRQ(ierr);
1175aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
11769a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
117747c6ae99SBarry Smith   PetscFunctionReturn(0);
117847c6ae99SBarry Smith }
117947c6ae99SBarry Smith 
118047c6ae99SBarry Smith #undef __FUNCT__
1181aa219208SBarry Smith #define __FUNCT__ "DMDAMultiplyByJacobian1WithAD"
118247c6ae99SBarry Smith /*@C
1183aa219208SBarry Smith     DMDAMultiplyByJacobian1WithAD - Applies a Jacobian function supplied by ADIFOR or ADIC
1184aa219208SBarry Smith     to a vector on each processor that shares a DMDA.
118547c6ae99SBarry Smith 
118647c6ae99SBarry Smith    Input Parameters:
11879a42bb27SBarry Smith +    da - the DM that defines the grid
118847c6ae99SBarry Smith .    vu - Jacobian is computed at this point (ghosted)
118947c6ae99SBarry Smith .    v - product is done on this vector (ghosted)
119047c6ae99SBarry Smith .    fu - output vector = J(vu)*v (not ghosted)
119147c6ae99SBarry Smith -    w - any user data
119247c6ae99SBarry Smith 
119347c6ae99SBarry Smith     Notes:
119447c6ae99SBarry Smith     This routine does NOT do ghost updates on vu and v upon entry.
119547c6ae99SBarry Smith 
1196aa219208SBarry Smith     Automatically calls DMDAMultiplyByJacobian1WithAdifor() or DMDAMultiplyByJacobian1WithAdic()
1197aa219208SBarry Smith     depending on whether DMDASetLocalAdicMFFunction() or DMDASetLocalAdiforMFFunction() was called.
119847c6ae99SBarry Smith 
119947c6ae99SBarry Smith    Level: advanced
120047c6ae99SBarry Smith 
1201aa219208SBarry Smith .seealso: DMDAFormFunction1(), DMDAMultiplyByJacobian1WithAdifor(), DMDAMultiplyByJacobian1WithAdic()
120247c6ae99SBarry Smith 
120347c6ae99SBarry Smith @*/
12047087cfbeSBarry Smith PetscErrorCode  DMDAMultiplyByJacobian1WithAD(DM da,Vec u,Vec v,Vec f,void *w)
120547c6ae99SBarry Smith {
120647c6ae99SBarry Smith   PetscErrorCode ierr;
120747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
120847c6ae99SBarry Smith 
120947c6ae99SBarry Smith   PetscFunctionBegin;
121047c6ae99SBarry Smith   if (dd->adicmf_lf) {
121147c6ae99SBarry Smith #if defined(PETSC_HAVE_ADIC)
1212aa219208SBarry Smith     ierr = DMDAMultiplyByJacobian1WithAdic(da,u,v,f,w);CHKERRQ(ierr);
121347c6ae99SBarry Smith #else
121447c6ae99SBarry Smith     SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP_SYS,"Requires ADIC to be installed and cannot use complex numbers");
121547c6ae99SBarry Smith #endif
121647c6ae99SBarry Smith   } else if (dd->adiformf_lf) {
1217aa219208SBarry Smith     ierr = DMDAMultiplyByJacobian1WithAdifor(da,u,v,f,w);CHKERRQ(ierr);
121847c6ae99SBarry Smith   } else {
1219aa219208SBarry Smith     SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ORDER,"Must call DMDASetLocalAdiforMFFunction() or DMDASetLocalAdicMFFunction() before using");
122047c6ae99SBarry Smith   }
122147c6ae99SBarry Smith   PetscFunctionReturn(0);
122247c6ae99SBarry Smith }
122347c6ae99SBarry Smith 
122447c6ae99SBarry Smith 
122547c6ae99SBarry Smith #undef __FUNCT__
1226aa219208SBarry Smith #define __FUNCT__ "DMDAMultiplyByJacobian1WithAdifor"
122747c6ae99SBarry Smith /*@C
1228aa219208SBarry Smith     DMDAMultiplyByJacobian1WithAdifor - Applies a ADIFOR provided Jacobian function on each processor that
12299a42bb27SBarry Smith         share a DM to a vector
123047c6ae99SBarry Smith 
123147c6ae99SBarry Smith    Input Parameters:
12329a42bb27SBarry Smith +    da - the DM that defines the grid
123347c6ae99SBarry Smith .    vu - Jacobian is computed at this point (ghosted)
123447c6ae99SBarry Smith .    v - product is done on this vector (ghosted)
123547c6ae99SBarry Smith .    fu - output vector = J(vu)*v (not ghosted)
123647c6ae99SBarry Smith -    w - any user data
123747c6ae99SBarry Smith 
123847c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu and v upon entry
123947c6ae99SBarry Smith 
124047c6ae99SBarry Smith    Level: advanced
124147c6ae99SBarry Smith 
1242aa219208SBarry Smith .seealso: DMDAFormFunction1()
124347c6ae99SBarry Smith 
124447c6ae99SBarry Smith @*/
12457087cfbeSBarry Smith PetscErrorCode  DMDAMultiplyByJacobian1WithAdifor(DM da,Vec u,Vec v,Vec f,void *w)
124647c6ae99SBarry Smith {
124747c6ae99SBarry Smith   PetscErrorCode ierr;
124847c6ae99SBarry Smith   PetscScalar    *au,*av,*af,*awork;
124947c6ae99SBarry Smith   Vec            work;
1250aa219208SBarry Smith   DMDALocalInfo  info;
125147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
1252aa219208SBarry Smith   void           (*lf)(DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*) =
1253aa219208SBarry Smith                  (void (*)(DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*))*dd->adiformf_lf;
125447c6ae99SBarry Smith 
125547c6ae99SBarry Smith   PetscFunctionBegin;
1256aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
125747c6ae99SBarry Smith 
12589a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&work);CHKERRQ(ierr);
125947c6ae99SBarry Smith   ierr = VecGetArray(u,&au);CHKERRQ(ierr);
126047c6ae99SBarry Smith   ierr = VecGetArray(v,&av);CHKERRQ(ierr);
126147c6ae99SBarry Smith   ierr = VecGetArray(f,&af);CHKERRQ(ierr);
126247c6ae99SBarry Smith   ierr = VecGetArray(work,&awork);CHKERRQ(ierr);
126347c6ae99SBarry Smith   (lf)(&info,au,av,awork,af,w,&ierr);CHKERRQ(ierr);
126447c6ae99SBarry Smith   ierr = VecRestoreArray(u,&au);CHKERRQ(ierr);
126547c6ae99SBarry Smith   ierr = VecRestoreArray(v,&av);CHKERRQ(ierr);
126647c6ae99SBarry Smith   ierr = VecRestoreArray(f,&af);CHKERRQ(ierr);
126747c6ae99SBarry Smith   ierr = VecRestoreArray(work,&awork);CHKERRQ(ierr);
12689a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&work);CHKERRQ(ierr);
126947c6ae99SBarry Smith 
127047c6ae99SBarry Smith   PetscFunctionReturn(0);
127147c6ae99SBarry Smith }
127247c6ae99SBarry Smith 
127347c6ae99SBarry Smith #undef __FUNCT__
12749a42bb27SBarry Smith #define __FUNCT__ "DMSetUp_DA_2D"
12757087cfbeSBarry Smith PetscErrorCode  DMSetUp_DA_2D(DM da)
127647c6ae99SBarry Smith {
127747c6ae99SBarry Smith   DM_DA                  *dd = (DM_DA*)da->data;
127847c6ae99SBarry Smith   const PetscInt         M            = dd->M;
127947c6ae99SBarry Smith   const PetscInt         N            = dd->N;
128047c6ae99SBarry Smith   PetscInt               m            = dd->m;
128147c6ae99SBarry Smith   PetscInt               n            = dd->n;
128247c6ae99SBarry Smith   const PetscInt         dof          = dd->w;
128347c6ae99SBarry Smith   const PetscInt         s            = dd->s;
12841321219cSEthan Coon   const DMDABoundaryType bx         = dd->bx;
12851321219cSEthan Coon   const DMDABoundaryType by         = dd->by;
1286aa219208SBarry Smith   const DMDAStencilType  stencil_type = dd->stencil_type;
128747c6ae99SBarry Smith   PetscInt               *lx           = dd->lx;
128847c6ae99SBarry Smith   PetscInt               *ly           = dd->ly;
128947c6ae99SBarry Smith   MPI_Comm               comm;
129047c6ae99SBarry Smith   PetscMPIInt            rank,size;
1291ce00eea3SSatish Balay   PetscInt               xs,xe,ys,ye,x,y,Xs,Xe,Ys,Ye,start,end,IXs,IXe,IYs,IYe;
1292ce00eea3SSatish Balay   PetscInt               up,down,left,right,i,n0,n1,n2,n3,n5,n6,n7,n8,*idx,nn,*idx_cpy;
1293ce00eea3SSatish Balay   const PetscInt         *idx_full;
1294db87c5ecSEthan Coon   PetscInt               xbase,*bases,*ldims,j,x_t,y_t,s_t,base,count;
129547c6ae99SBarry Smith   PetscInt               s_x,s_y; /* s proportionalized to w */
129647c6ae99SBarry Smith   PetscInt               sn0 = 0,sn2 = 0,sn6 = 0,sn8 = 0;
129747c6ae99SBarry Smith   Vec                    local,global;
129847c6ae99SBarry Smith   VecScatter             ltog,gtol;
1299ce00eea3SSatish Balay   IS                     to,from,ltogis;
130047c6ae99SBarry Smith   PetscErrorCode         ierr;
130147c6ae99SBarry Smith 
130247c6ae99SBarry Smith   PetscFunctionBegin;
130347c6ae99SBarry Smith   ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr);
130447c6ae99SBarry Smith 
130547c6ae99SBarry Smith   if (dof < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof);
130647c6ae99SBarry Smith   if (s < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s);
130747c6ae99SBarry Smith 
130847c6ae99SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
130947c6ae99SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
131047c6ae99SBarry Smith 
131147c6ae99SBarry Smith   dd->dim         = 2;
131247c6ae99SBarry Smith   ierr = PetscMalloc(dof*sizeof(char*),&dd->fieldname);CHKERRQ(ierr);
131347c6ae99SBarry Smith   ierr = PetscMemzero(dd->fieldname,dof*sizeof(char*));CHKERRQ(ierr);
131447c6ae99SBarry Smith 
131547c6ae99SBarry Smith   if (m != PETSC_DECIDE) {
131647c6ae99SBarry Smith     if (m < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in X direction: %D",m);
131747c6ae99SBarry Smith     else if (m > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in X direction: %D %d",m,size);
131847c6ae99SBarry Smith   }
131947c6ae99SBarry Smith   if (n != PETSC_DECIDE) {
132047c6ae99SBarry Smith     if (n < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Y direction: %D",n);
132147c6ae99SBarry Smith     else if (n > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Y direction: %D %d",n,size);
132247c6ae99SBarry Smith   }
132347c6ae99SBarry Smith 
132447c6ae99SBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
132547c6ae99SBarry Smith     if (n != PETSC_DECIDE) {
132647c6ae99SBarry Smith       m = size/n;
132747c6ae99SBarry Smith     } else if (m != PETSC_DECIDE) {
132847c6ae99SBarry Smith       n = size/m;
132947c6ae99SBarry Smith     } else {
133047c6ae99SBarry Smith       /* try for squarish distribution */
133147c6ae99SBarry Smith       m = (PetscInt)(0.5 + sqrt(((double)M)*((double)size)/((double)N)));
133247c6ae99SBarry Smith       if (!m) m = 1;
133347c6ae99SBarry Smith       while (m > 0) {
133447c6ae99SBarry Smith 	n = size/m;
133547c6ae99SBarry Smith 	if (m*n == size) break;
133647c6ae99SBarry Smith 	m--;
133747c6ae99SBarry Smith       }
133847c6ae99SBarry Smith       if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;}
133947c6ae99SBarry Smith     }
134047c6ae99SBarry Smith     if (m*n != size) SETERRQ(comm,PETSC_ERR_PLIB,"Unable to create partition, check the size of the communicator and input m and n ");
134147c6ae99SBarry Smith   } else if (m*n != size) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Given Bad partition");
134247c6ae99SBarry Smith 
134347c6ae99SBarry Smith   if (M < m) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in x direction is too fine! %D %D",M,m);
134447c6ae99SBarry Smith   if (N < n) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in y direction is too fine! %D %D",N,n);
134547c6ae99SBarry Smith 
134647c6ae99SBarry Smith   /*
134747c6ae99SBarry Smith      Determine locally owned region
134847c6ae99SBarry Smith      xs is the first local node number, x is the number of local nodes
134947c6ae99SBarry Smith   */
135047c6ae99SBarry Smith   if (!lx) {
135147c6ae99SBarry Smith     ierr = PetscMalloc(m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr);
135247c6ae99SBarry Smith     lx = dd->lx;
135347c6ae99SBarry Smith     for (i=0; i<m; i++) {
135447c6ae99SBarry Smith       lx[i] = M/m + ((M % m) > i);
135547c6ae99SBarry Smith     }
135647c6ae99SBarry Smith   }
135747c6ae99SBarry Smith   x  = lx[rank % m];
135847c6ae99SBarry Smith   xs = 0;
135947c6ae99SBarry Smith   for (i=0; i<(rank % m); i++) {
136047c6ae99SBarry Smith     xs += lx[i];
136147c6ae99SBarry Smith   }
136247c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
136347c6ae99SBarry Smith   left = xs;
136447c6ae99SBarry Smith   for (i=(rank % m); i<m; i++) {
136547c6ae99SBarry Smith     left += lx[i];
136647c6ae99SBarry Smith   }
136747c6ae99SBarry Smith   if (left != M) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Sum of lx across processors not equal to M: %D %D",left,M);
136847c6ae99SBarry Smith #endif
136947c6ae99SBarry Smith 
137047c6ae99SBarry Smith   /*
137147c6ae99SBarry Smith      Determine locally owned region
137247c6ae99SBarry Smith      ys is the first local node number, y is the number of local nodes
137347c6ae99SBarry Smith   */
137447c6ae99SBarry Smith   if (!ly) {
137547c6ae99SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr);
137647c6ae99SBarry Smith     ly = dd->ly;
137747c6ae99SBarry Smith     for (i=0; i<n; i++) {
137847c6ae99SBarry Smith       ly[i] = N/n + ((N % n) > i);
137947c6ae99SBarry Smith     }
138047c6ae99SBarry Smith   }
138147c6ae99SBarry Smith   y  = ly[rank/m];
138247c6ae99SBarry Smith   ys = 0;
138347c6ae99SBarry Smith   for (i=0; i<(rank/m); i++) {
138447c6ae99SBarry Smith     ys += ly[i];
138547c6ae99SBarry Smith   }
138647c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
138747c6ae99SBarry Smith   left = ys;
138847c6ae99SBarry Smith   for (i=(rank/m); i<n; i++) {
138947c6ae99SBarry Smith     left += ly[i];
139047c6ae99SBarry Smith   }
139147c6ae99SBarry Smith   if (left != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Sum of ly across processors not equal to N: %D %D",left,N);
139247c6ae99SBarry Smith #endif
139347c6ae99SBarry Smith 
1394bcea557cSEthan Coon   /*
1395bcea557cSEthan Coon    check if the scatter requires more than one process neighbor or wraps around
1396bcea557cSEthan Coon    the domain more than once
1397bcea557cSEthan Coon   */
1398bcea557cSEthan Coon   if ((x < s) && ((m > 1) || (bx == DMDA_BOUNDARY_PERIODIC))) {
1399bcea557cSEthan Coon     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local x-width of domain x %D is smaller than stencil width s %D",x,s);
1400bcea557cSEthan Coon   }
1401bcea557cSEthan Coon   if ((y < s) && ((n > 1) || (by == DMDA_BOUNDARY_PERIODIC))) {
1402bcea557cSEthan Coon     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local y-width of domain y %D is smaller than stencil width s %D",y,s);
1403bcea557cSEthan Coon   }
140447c6ae99SBarry Smith   xe = xs + x;
140547c6ae99SBarry Smith   ye = ys + y;
140647c6ae99SBarry Smith 
1407ce00eea3SSatish Balay   /* determine ghost region (Xs) and region scattered into (IXs)  */
140847c6ae99SBarry Smith   /* Assume No Periodicity */
1409ce00eea3SSatish Balay   if (xs-s > 0) { Xs = xs - s; IXs = xs - s; } else { Xs = 0; IXs = 0; }
1410ce00eea3SSatish Balay   if (xe+s <= M) { Xe = xe + s; IXe = xe + s; } else { Xe = M; IXe = M; }
1411ce00eea3SSatish Balay   if (ys-s > 0) { Ys = ys - s; IYs = ys - s; } else { Ys = 0; IYs = 0; }
1412ce00eea3SSatish Balay   if (ye+s <= N) { Ye = ye + s; IYe = ye + s; } else { Ye = N; IYe = N; }
141347c6ae99SBarry Smith 
1414ce00eea3SSatish Balay   /* fix for periodicity/ghosted */
14151321219cSEthan Coon   if (bx) { Xs = xs - s; Xe = xe + s; }
14161321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) { IXs = xs - s; IXe = xe + s; }
14171321219cSEthan Coon   if (by) { Ys = ys - s; Ye = ye + s; }
14181321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) { IYs = ys - s; IYe = ye + s; }
141947c6ae99SBarry Smith 
142047c6ae99SBarry Smith   /* Resize all X parameters to reflect w */
1421ce00eea3SSatish Balay   s_x = s;
142247c6ae99SBarry Smith   s_y = s;
142347c6ae99SBarry Smith 
142447c6ae99SBarry Smith   /* determine starting point of each processor */
142547c6ae99SBarry Smith   nn    = x*y;
142647c6ae99SBarry Smith   ierr  = PetscMalloc2(size+1,PetscInt,&bases,size,PetscInt,&ldims);CHKERRQ(ierr);
142747c6ae99SBarry Smith   ierr  = MPI_Allgather(&nn,1,MPIU_INT,ldims,1,MPIU_INT,comm);CHKERRQ(ierr);
142847c6ae99SBarry Smith   bases[0] = 0;
142947c6ae99SBarry Smith   for (i=1; i<=size; i++) {
143047c6ae99SBarry Smith     bases[i] = ldims[i-1];
143147c6ae99SBarry Smith   }
143247c6ae99SBarry Smith   for (i=1; i<=size; i++) {
143347c6ae99SBarry Smith     bases[i] += bases[i-1];
143447c6ae99SBarry Smith   }
1435ce00eea3SSatish Balay   base = bases[rank]*dof;
143647c6ae99SBarry Smith 
143747c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
1438ce00eea3SSatish Balay   dd->Nlocal = x*y*dof;
143947c6ae99SBarry Smith   ierr = VecCreateMPIWithArray(comm,dd->Nlocal,PETSC_DECIDE,0,&global);CHKERRQ(ierr);
144047c6ae99SBarry Smith   ierr = VecSetBlockSize(global,dof);CHKERRQ(ierr);
1441ce00eea3SSatish Balay   dd->nlocal = (Xe-Xs)*(Ye-Ys)*dof;
144247c6ae99SBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dd->nlocal,0,&local);CHKERRQ(ierr);
144347c6ae99SBarry Smith   ierr = VecSetBlockSize(local,dof);CHKERRQ(ierr);
144447c6ae99SBarry Smith 
144547c6ae99SBarry Smith   /* generate appropriate vector scatters */
144647c6ae99SBarry Smith   /* local to global inserts non-ghost point region into global */
144747c6ae99SBarry Smith   ierr = VecGetOwnershipRange(global,&start,&end);CHKERRQ(ierr);
1448ce00eea3SSatish Balay   ierr = ISCreateStride(comm,x*y*dof,start,1,&to);CHKERRQ(ierr);
144947c6ae99SBarry Smith 
1450db87c5ecSEthan Coon   count = x*y;
1451ce00eea3SSatish Balay   ierr = PetscMalloc(x*y*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1452ce00eea3SSatish Balay   left = xs - Xs; right = left + x;
1453ce00eea3SSatish Balay   down = ys - Ys; up = down + y;
145447c6ae99SBarry Smith   count = 0;
145547c6ae99SBarry Smith   for (i=down; i<up; i++) {
1456ce00eea3SSatish Balay     for (j=left; j<right; j++) {
1457ce00eea3SSatish Balay       idx[count++] = i*(Xe-Xs) + j;
145847c6ae99SBarry Smith     }
145947c6ae99SBarry Smith   }
146047c6ae99SBarry Smith 
1461ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr);
146247c6ae99SBarry Smith   ierr = VecScatterCreate(local,from,global,to,&ltog);CHKERRQ(ierr);
146347c6ae99SBarry Smith   ierr = PetscLogObjectParent(dd,ltog);CHKERRQ(ierr);
1464fcfd50ebSBarry Smith   ierr = ISDestroy(&from);CHKERRQ(ierr);
1465fcfd50ebSBarry Smith   ierr = ISDestroy(&to);CHKERRQ(ierr);
146647c6ae99SBarry Smith 
1467ce00eea3SSatish Balay   /* global to local must include ghost points within the domain,
1468ce00eea3SSatish Balay      but not ghost points outside the domain that aren't periodic */
1469aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_BOX) {
1470db87c5ecSEthan Coon     count = (IXe-IXs)*(IYe-IYs);
1471db87c5ecSEthan Coon     ierr  = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1472ce00eea3SSatish Balay 
1473ce00eea3SSatish Balay     left = IXs - Xs; right = left + (IXe-IXs);
1474ce00eea3SSatish Balay     down = IYs - Ys; up = down + (IYe-IYs);
1475ce00eea3SSatish Balay     count = 0;
1476ce00eea3SSatish Balay     for (i=down; i<up; i++) {
1477ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1478ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
1479ce00eea3SSatish Balay       }
1480ce00eea3SSatish Balay     }
1481ce00eea3SSatish Balay     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
1482ce00eea3SSatish Balay 
148347c6ae99SBarry Smith   } else {
148447c6ae99SBarry Smith     /* must drop into cross shape region */
148547c6ae99SBarry Smith     /*       ---------|
148647c6ae99SBarry Smith             |  top    |
1487ce00eea3SSatish Balay          |---         ---| up
148847c6ae99SBarry Smith          |   middle      |
148947c6ae99SBarry Smith          |               |
1490ce00eea3SSatish Balay          ----         ---- down
149147c6ae99SBarry Smith             | bottom  |
149247c6ae99SBarry Smith             -----------
149347c6ae99SBarry Smith          Xs xs        xe Xe */
1494db87c5ecSEthan Coon     count = (ys-IYs)*x + y*(IXe-IXs) + (IYe-ye)*x;
1495db87c5ecSEthan Coon     ierr  = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1496ce00eea3SSatish Balay 
1497ce00eea3SSatish Balay     left = xs - Xs; right = left + x;
1498ce00eea3SSatish Balay     down = ys - Ys; up = down + y;
149947c6ae99SBarry Smith     count = 0;
1500ce00eea3SSatish Balay     /* bottom */
1501ce00eea3SSatish Balay     for (i=(IYs-Ys); i<down; i++) {
1502ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1503ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
150447c6ae99SBarry Smith       }
150547c6ae99SBarry Smith     }
150647c6ae99SBarry Smith     /* middle */
150747c6ae99SBarry Smith     for (i=down; i<up; i++) {
1508ce00eea3SSatish Balay       for (j=(IXs-Xs); j<(IXe-Xs); j++) {
1509ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
151047c6ae99SBarry Smith       }
151147c6ae99SBarry Smith     }
151247c6ae99SBarry Smith     /* top */
1513ce00eea3SSatish Balay     for (i=up; i<up+IYe-ye; i++) {
1514ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1515ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
151647c6ae99SBarry Smith       }
151747c6ae99SBarry Smith     }
151847c6ae99SBarry Smith     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
151947c6ae99SBarry Smith   }
152047c6ae99SBarry Smith 
152147c6ae99SBarry Smith 
152247c6ae99SBarry Smith   /* determine who lies on each side of us stored in    n6 n7 n8
152347c6ae99SBarry Smith                                                         n3    n5
152447c6ae99SBarry Smith                                                         n0 n1 n2
152547c6ae99SBarry Smith   */
152647c6ae99SBarry Smith 
152747c6ae99SBarry Smith   /* Assume the Non-Periodic Case */
152847c6ae99SBarry Smith   n1 = rank - m;
152947c6ae99SBarry Smith   if (rank % m) {
153047c6ae99SBarry Smith     n0 = n1 - 1;
153147c6ae99SBarry Smith   } else {
153247c6ae99SBarry Smith     n0 = -1;
153347c6ae99SBarry Smith   }
153447c6ae99SBarry Smith   if ((rank+1) % m) {
153547c6ae99SBarry Smith     n2 = n1 + 1;
153647c6ae99SBarry Smith     n5 = rank + 1;
153747c6ae99SBarry Smith     n8 = rank + m + 1; if (n8 >= m*n) n8 = -1;
153847c6ae99SBarry Smith   } else {
153947c6ae99SBarry Smith     n2 = -1; n5 = -1; n8 = -1;
154047c6ae99SBarry Smith   }
154147c6ae99SBarry Smith   if (rank % m) {
154247c6ae99SBarry Smith     n3 = rank - 1;
154347c6ae99SBarry Smith     n6 = n3 + m; if (n6 >= m*n) n6 = -1;
154447c6ae99SBarry Smith   } else {
154547c6ae99SBarry Smith     n3 = -1; n6 = -1;
154647c6ae99SBarry Smith   }
154747c6ae99SBarry Smith   n7 = rank + m; if (n7 >= m*n) n7 = -1;
154847c6ae99SBarry Smith 
15491321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC && by == DMDA_BOUNDARY_PERIODIC) {
155047c6ae99SBarry Smith   /* Modify for Periodic Cases */
155147c6ae99SBarry Smith     /* Handle all four corners */
155247c6ae99SBarry Smith     if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m-1;
155347c6ae99SBarry Smith     if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0;
155447c6ae99SBarry Smith     if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size-m;
155547c6ae99SBarry Smith     if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size-1;
155647c6ae99SBarry Smith 
155747c6ae99SBarry Smith     /* Handle Top and Bottom Sides */
155847c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n-1);
155947c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n-1);
156047c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
156147c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
156247c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
156347c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
156447c6ae99SBarry Smith 
156547c6ae99SBarry Smith     /* Handle Left and Right Sides */
156647c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m-1);
156747c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m-1);
156847c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
156947c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
157047c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
157147c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
15721321219cSEthan Coon   } else if (by == DMDA_BOUNDARY_PERIODIC) {  /* Handle Top and Bottom Sides */
1573ce00eea3SSatish Balay     if (n1 < 0) n1 = rank + m * (n-1);
1574ce00eea3SSatish Balay     if (n7 < 0) n7 = rank - m * (n-1);
1575ce00eea3SSatish Balay     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
1576ce00eea3SSatish Balay     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
1577ce00eea3SSatish Balay     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
1578ce00eea3SSatish Balay     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
15791321219cSEthan Coon   } else if (bx == DMDA_BOUNDARY_PERIODIC) { /* Handle Left and Right Sides */
1580ce00eea3SSatish Balay     if (n3 < 0) n3 = rank + (m-1);
1581ce00eea3SSatish Balay     if (n5 < 0) n5 = rank - (m-1);
1582ce00eea3SSatish Balay     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
1583ce00eea3SSatish Balay     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
1584ce00eea3SSatish Balay     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
1585ce00eea3SSatish Balay     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
158647c6ae99SBarry Smith   }
1587ce00eea3SSatish Balay 
158847c6ae99SBarry Smith   ierr = PetscMalloc(9*sizeof(PetscInt),&dd->neighbors);CHKERRQ(ierr);
158947c6ae99SBarry Smith   dd->neighbors[0] = n0;
159047c6ae99SBarry Smith   dd->neighbors[1] = n1;
159147c6ae99SBarry Smith   dd->neighbors[2] = n2;
159247c6ae99SBarry Smith   dd->neighbors[3] = n3;
159347c6ae99SBarry Smith   dd->neighbors[4] = rank;
159447c6ae99SBarry Smith   dd->neighbors[5] = n5;
159547c6ae99SBarry Smith   dd->neighbors[6] = n6;
159647c6ae99SBarry Smith   dd->neighbors[7] = n7;
159747c6ae99SBarry Smith   dd->neighbors[8] = n8;
159847c6ae99SBarry Smith 
1599aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
160047c6ae99SBarry Smith     /* save corner processor numbers */
160147c6ae99SBarry Smith     sn0 = n0; sn2 = n2; sn6 = n6; sn8 = n8;
160247c6ae99SBarry Smith     n0 = n2 = n6 = n8 = -1;
160347c6ae99SBarry Smith   }
160447c6ae99SBarry Smith 
1605ce00eea3SSatish Balay   ierr = PetscMalloc((Xe-Xs)*(Ye-Ys)*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1606ce00eea3SSatish Balay   ierr = PetscLogObjectMemory(da,(Xe-Xs)*(Ye-Ys)*sizeof(PetscInt));CHKERRQ(ierr);
160747c6ae99SBarry Smith 
1608ce00eea3SSatish Balay   nn = 0;
160947c6ae99SBarry Smith   xbase = bases[rank];
161047c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
161147c6ae99SBarry Smith     if (n0 >= 0) { /* left below */
1612ce00eea3SSatish Balay       x_t = lx[n0 % m];
161347c6ae99SBarry Smith       y_t = ly[(n0/m)];
161447c6ae99SBarry Smith       s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
161547c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
161647c6ae99SBarry Smith     }
161747c6ae99SBarry Smith     if (n1 >= 0) { /* directly below */
161847c6ae99SBarry Smith       x_t = x;
161947c6ae99SBarry Smith       y_t = ly[(n1/m)];
162047c6ae99SBarry Smith       s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
162147c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
162247c6ae99SBarry Smith     }
162347c6ae99SBarry Smith     if (n2 >= 0) { /* right below */
1624ce00eea3SSatish Balay       x_t = lx[n2 % m];
162547c6ae99SBarry Smith       y_t = ly[(n2/m)];
162647c6ae99SBarry Smith       s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
162747c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
162847c6ae99SBarry Smith     }
162947c6ae99SBarry Smith   }
163047c6ae99SBarry Smith 
163147c6ae99SBarry Smith   for (i=0; i<y; i++) {
163247c6ae99SBarry Smith     if (n3 >= 0) { /* directly left */
1633ce00eea3SSatish Balay       x_t = lx[n3 % m];
163447c6ae99SBarry Smith       /* y_t = y; */
163547c6ae99SBarry Smith       s_t = bases[n3] + (i+1)*x_t - s_x;
163647c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
163747c6ae99SBarry Smith     }
163847c6ae99SBarry Smith 
163947c6ae99SBarry Smith     for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
164047c6ae99SBarry Smith 
164147c6ae99SBarry Smith     if (n5 >= 0) { /* directly right */
1642ce00eea3SSatish Balay       x_t = lx[n5 % m];
164347c6ae99SBarry Smith       /* y_t = y; */
164447c6ae99SBarry Smith       s_t = bases[n5] + (i)*x_t;
164547c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
164647c6ae99SBarry Smith     }
164747c6ae99SBarry Smith   }
164847c6ae99SBarry Smith 
164947c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
165047c6ae99SBarry Smith     if (n6 >= 0) { /* left above */
1651ce00eea3SSatish Balay       x_t = lx[n6 % m];
165247c6ae99SBarry Smith       /* y_t = ly[(n6/m)]; */
165347c6ae99SBarry Smith       s_t = bases[n6] + (i)*x_t - s_x;
165447c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
165547c6ae99SBarry Smith     }
165647c6ae99SBarry Smith     if (n7 >= 0) { /* directly above */
165747c6ae99SBarry Smith       x_t = x;
165847c6ae99SBarry Smith       /* y_t = ly[(n7/m)]; */
165947c6ae99SBarry Smith       s_t = bases[n7] + (i-1)*x_t;
166047c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
166147c6ae99SBarry Smith     }
166247c6ae99SBarry Smith     if (n8 >= 0) { /* right above */
1663ce00eea3SSatish Balay       x_t = lx[n8 % m];
166447c6ae99SBarry Smith       /* y_t = ly[(n8/m)]; */
166547c6ae99SBarry Smith       s_t = bases[n8] + (i-1)*x_t;
166647c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
166747c6ae99SBarry Smith     }
166847c6ae99SBarry Smith   }
166947c6ae99SBarry Smith 
1670ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
167147c6ae99SBarry Smith   ierr = VecScatterCreate(global,from,local,to,&gtol);CHKERRQ(ierr);
167247c6ae99SBarry Smith   ierr = PetscLogObjectParent(da,gtol);CHKERRQ(ierr);
1673fcfd50ebSBarry Smith   ierr = ISDestroy(&to);CHKERRQ(ierr);
1674fcfd50ebSBarry Smith   ierr = ISDestroy(&from);CHKERRQ(ierr);
167547c6ae99SBarry Smith 
1676aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
1677ce00eea3SSatish Balay     n0 = sn0; n2 = sn2; n6 = sn6; n8 = sn8;
1678ce00eea3SSatish Balay   }
1679ce00eea3SSatish Balay 
1680ce00eea3SSatish Balay   if ((stencil_type == DMDA_STENCIL_STAR) ||
16811321219cSEthan Coon       (bx && bx != DMDA_BOUNDARY_PERIODIC) ||
16821321219cSEthan Coon       (by && by != DMDA_BOUNDARY_PERIODIC)) {
168347c6ae99SBarry Smith     /*
168447c6ae99SBarry Smith         Recompute the local to global mappings, this time keeping the
1685ce00eea3SSatish Balay       information about the cross corner processor numbers and any ghosted
1686ce00eea3SSatish Balay       but not periodic indices.
168747c6ae99SBarry Smith     */
168847c6ae99SBarry Smith     nn = 0;
168947c6ae99SBarry Smith     xbase = bases[rank];
169047c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
169147c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
1692ce00eea3SSatish Balay         x_t = lx[n0 % m];
169347c6ae99SBarry Smith         y_t = ly[(n0/m)];
169447c6ae99SBarry Smith         s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
169547c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1696ce00eea3SSatish Balay       } else if (xs-Xs > 0 && ys-Ys > 0) {
1697ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
169847c6ae99SBarry Smith       }
169947c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
170047c6ae99SBarry Smith         x_t = x;
170147c6ae99SBarry Smith         y_t = ly[(n1/m)];
170247c6ae99SBarry Smith         s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
170347c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1704ce00eea3SSatish Balay       } else if (ys-Ys > 0) {
1705ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
170647c6ae99SBarry Smith       }
170747c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
1708ce00eea3SSatish Balay         x_t = lx[n2 % m];
170947c6ae99SBarry Smith         y_t = ly[(n2/m)];
171047c6ae99SBarry Smith         s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
171147c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1712ce00eea3SSatish Balay       } else if (Xe-xe> 0 && ys-Ys > 0) {
1713ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
171447c6ae99SBarry Smith       }
171547c6ae99SBarry Smith     }
171647c6ae99SBarry Smith 
171747c6ae99SBarry Smith     for (i=0; i<y; i++) {
171847c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
1719ce00eea3SSatish Balay         x_t = lx[n3 % m];
172047c6ae99SBarry Smith         /* y_t = y; */
172147c6ae99SBarry Smith         s_t = bases[n3] + (i+1)*x_t - s_x;
172247c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1723ce00eea3SSatish Balay       } else if (xs-Xs > 0) {
1724ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
172547c6ae99SBarry Smith       }
172647c6ae99SBarry Smith 
172747c6ae99SBarry Smith       for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
172847c6ae99SBarry Smith 
172947c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
1730ce00eea3SSatish Balay         x_t = lx[n5 % m];
173147c6ae99SBarry Smith         /* y_t = y; */
173247c6ae99SBarry Smith         s_t = bases[n5] + (i)*x_t;
173347c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1734ce00eea3SSatish Balay       } else if (Xe-xe > 0) {
1735ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
173647c6ae99SBarry Smith       }
173747c6ae99SBarry Smith     }
173847c6ae99SBarry Smith 
173947c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
174047c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
1741ce00eea3SSatish Balay         x_t = lx[n6 % m];
174247c6ae99SBarry Smith         /* y_t = ly[(n6/m)]; */
174347c6ae99SBarry Smith         s_t = bases[n6] + (i)*x_t - s_x;
174447c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1745ce00eea3SSatish Balay       } else if (xs-Xs > 0 && Ye-ye > 0) {
1746ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
174747c6ae99SBarry Smith       }
174847c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
174947c6ae99SBarry Smith         x_t = x;
175047c6ae99SBarry Smith         /* y_t = ly[(n7/m)]; */
175147c6ae99SBarry Smith         s_t = bases[n7] + (i-1)*x_t;
175247c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1753ce00eea3SSatish Balay       } else if (Ye-ye > 0) {
1754ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
175547c6ae99SBarry Smith       }
175647c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
1757ce00eea3SSatish Balay         x_t = lx[n8 % m];
175847c6ae99SBarry Smith         /* y_t = ly[(n8/m)]; */
175947c6ae99SBarry Smith         s_t = bases[n8] + (i-1)*x_t;
176047c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1761ce00eea3SSatish Balay       } else if (Xe-xe > 0 && Ye-ye > 0) {
1762ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
176347c6ae99SBarry Smith       }
176447c6ae99SBarry Smith     }
176547c6ae99SBarry Smith   }
1766ce00eea3SSatish Balay   /*
1767ce00eea3SSatish Balay      Set the local to global ordering in the global vector, this allows use
1768ce00eea3SSatish Balay      of VecSetValuesLocal().
1769ce00eea3SSatish Balay   */
1770ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_OWN_POINTER,&ltogis);CHKERRQ(ierr);
1771ce00eea3SSatish Balay   ierr = PetscMalloc(nn*dof*sizeof(PetscInt),&idx_cpy);CHKERRQ(ierr);
1772db87c5ecSEthan Coon   ierr = PetscLogObjectMemory(da,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);
1773ce00eea3SSatish Balay   ierr = ISGetIndices(ltogis, &idx_full);
1774ce00eea3SSatish Balay   ierr = PetscMemcpy(idx_cpy,idx_full,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);
1775ce00eea3SSatish Balay   ierr = ISRestoreIndices(ltogis, &idx_full);
1776ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingCreateIS(ltogis,&da->ltogmap);CHKERRQ(ierr);
1777ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
1778fcfd50ebSBarry Smith   ierr = ISDestroy(&ltogis);CHKERRQ(ierr);
1779ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingBlock(da->ltogmap,dd->w,&da->ltogmapb);CHKERRQ(ierr);
1780ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
178147c6ae99SBarry Smith 
1782ce00eea3SSatish Balay   ierr = PetscFree2(bases,ldims);CHKERRQ(ierr);
178347c6ae99SBarry Smith   dd->m  = m;  dd->n  = n;
1784ce00eea3SSatish Balay   /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
1785ce00eea3SSatish Balay   dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1;
1786ce00eea3SSatish Balay   dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1;
178747c6ae99SBarry Smith 
1788fcfd50ebSBarry Smith   ierr = VecDestroy(&local);CHKERRQ(ierr);
1789fcfd50ebSBarry Smith   ierr = VecDestroy(&global);CHKERRQ(ierr);
179047c6ae99SBarry Smith 
179147c6ae99SBarry Smith   dd->gtol      = gtol;
179247c6ae99SBarry Smith   dd->ltog      = ltog;
1793ce00eea3SSatish Balay   dd->idx       = idx_cpy;
1794ce00eea3SSatish Balay   dd->Nl        = nn*dof;
179547c6ae99SBarry Smith   dd->base      = base;
17969a42bb27SBarry Smith   da->ops->view = DMView_DA_2d;
179747c6ae99SBarry Smith   dd->ltol = PETSC_NULL;
179847c6ae99SBarry Smith   dd->ao   = PETSC_NULL;
179947c6ae99SBarry Smith 
180047c6ae99SBarry Smith   PetscFunctionReturn(0);
180147c6ae99SBarry Smith }
180247c6ae99SBarry Smith 
180347c6ae99SBarry Smith #undef __FUNCT__
1804aa219208SBarry Smith #define __FUNCT__ "DMDACreate2d"
180547c6ae99SBarry Smith /*@C
1806aa219208SBarry Smith    DMDACreate2d -  Creates an object that will manage the communication of  two-dimensional
180747c6ae99SBarry Smith    regular array data that is distributed across some processors.
180847c6ae99SBarry Smith 
180947c6ae99SBarry Smith    Collective on MPI_Comm
181047c6ae99SBarry Smith 
181147c6ae99SBarry Smith    Input Parameters:
181247c6ae99SBarry Smith +  comm - MPI communicator
18131321219cSEthan Coon .  bx,by - type of ghost nodes the array have.
18141321219cSEthan Coon          Use one of DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_GHOSTED, DMDA_BOUNDARY_PERIODIC.
1815aa219208SBarry Smith .  stencil_type - stencil type.  Use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
181647c6ae99SBarry Smith .  M,N - global dimension in each direction of the array (use -M and or -N to indicate that it may be set to a different value
181747c6ae99SBarry Smith             from the command line with -da_grid_x <M> -da_grid_y <N>)
181847c6ae99SBarry Smith .  m,n - corresponding number of processors in each dimension
181947c6ae99SBarry Smith          (or PETSC_DECIDE to have calculated)
182047c6ae99SBarry Smith .  dof - number of degrees of freedom per node
182147c6ae99SBarry Smith .  s - stencil width
182247c6ae99SBarry Smith -  lx, ly - arrays containing the number of nodes in each cell along
182347c6ae99SBarry Smith            the x and y coordinates, or PETSC_NULL. If non-null, these
182447c6ae99SBarry Smith            must be of length as m and n, and the corresponding
182547c6ae99SBarry Smith            m and n cannot be PETSC_DECIDE. The sum of the lx[] entries
182647c6ae99SBarry Smith            must be M, and the sum of the ly[] entries must be N.
182747c6ae99SBarry Smith 
182847c6ae99SBarry Smith    Output Parameter:
182947c6ae99SBarry Smith .  da - the resulting distributed array object
183047c6ae99SBarry Smith 
183147c6ae99SBarry Smith    Options Database Key:
1832aa219208SBarry Smith +  -da_view - Calls DMView() at the conclusion of DMDACreate2d()
183347c6ae99SBarry Smith .  -da_grid_x <nx> - number of grid points in x direction, if M < 0
183447c6ae99SBarry Smith .  -da_grid_y <ny> - number of grid points in y direction, if N < 0
183547c6ae99SBarry Smith .  -da_processors_x <nx> - number of processors in x direction
183647c6ae99SBarry Smith .  -da_processors_y <ny> - number of processors in y direction
183747c6ae99SBarry Smith .  -da_refine_x - refinement ratio in x direction
183847c6ae99SBarry Smith -  -da_refine_y - refinement ratio in y direction
183947c6ae99SBarry Smith 
184047c6ae99SBarry Smith    Level: beginner
184147c6ae99SBarry Smith 
184247c6ae99SBarry Smith    Notes:
1843aa219208SBarry Smith    The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the
1844aa219208SBarry Smith    standard 5-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes
184547c6ae99SBarry Smith    the standard 9-pt stencil.
184647c6ae99SBarry Smith 
1847aa219208SBarry Smith    The array data itself is NOT stored in the DMDA, it is stored in Vec objects;
1848564755cdSBarry Smith    The appropriate vector objects can be obtained with calls to DMCreateGlobalVector()
1849564755cdSBarry Smith    and DMCreateLocalVector() and calls to VecDuplicate() if more are needed.
185047c6ae99SBarry Smith 
185147c6ae99SBarry Smith .keywords: distributed array, create, two-dimensional
185247c6ae99SBarry Smith 
1853aa219208SBarry Smith .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate3d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(),
1854aa219208SBarry Smith           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMDALocalToLocalBegin(), DMDALocalToLocalEnd(), DMDASetRefinementFactor(),
1855aa219208SBarry Smith           DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMDALoad(), DMDAGetOwnershipRanges()
185647c6ae99SBarry Smith 
185747c6ae99SBarry Smith @*/
18581321219cSEthan Coon PetscErrorCode  DMDACreate2d(MPI_Comm comm,DMDABoundaryType bx,DMDABoundaryType by,DMDAStencilType stencil_type,
18599a42bb27SBarry Smith                           PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da)
186047c6ae99SBarry Smith {
186147c6ae99SBarry Smith   PetscErrorCode ierr;
186247c6ae99SBarry Smith 
186347c6ae99SBarry Smith   PetscFunctionBegin;
1864aa219208SBarry Smith   ierr = DMDACreate(comm, da);CHKERRQ(ierr);
1865aa219208SBarry Smith   ierr = DMDASetDim(*da, 2);CHKERRQ(ierr);
1866aa219208SBarry Smith   ierr = DMDASetSizes(*da, M, N, 1);CHKERRQ(ierr);
1867aa219208SBarry Smith   ierr = DMDASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr);
1868755f258dSLisandro Dalcin   ierr = DMDASetBoundaryType(*da, bx, by, DMDA_BOUNDARY_NONE);CHKERRQ(ierr);
1869aa219208SBarry Smith   ierr = DMDASetDof(*da, dof);CHKERRQ(ierr);
1870aa219208SBarry Smith   ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr);
1871aa219208SBarry Smith   ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr);
1872aa219208SBarry Smith   ierr = DMDASetOwnershipRanges(*da, lx, ly, PETSC_NULL);CHKERRQ(ierr);
187347c6ae99SBarry Smith   /* This violates the behavior for other classes, but right now users expect negative dimensions to be handled this way */
18749a42bb27SBarry Smith   ierr = DMSetFromOptions(*da);CHKERRQ(ierr);
18759a42bb27SBarry Smith   ierr = DMSetUp(*da);CHKERRQ(ierr);
18767242296bSJed Brown   ierr = DMView_DA_Private(*da);CHKERRQ(ierr);
187747c6ae99SBarry Smith   PetscFunctionReturn(0);
187847c6ae99SBarry Smith }
1879