xref: /petsc/src/dm/impls/da/da2.c (revision 7b23a99a4cafc5f74ba930d377af92d6b7c0a4c1)
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);
32*7b23a99aSBarry 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);
36*7b23a99aSBarry 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__
171aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalFunction"
17247c6ae99SBarry Smith /*@C
173aa219208SBarry Smith        DMDASetLocalFunction - Caches in a DM a local function.
17447c6ae99SBarry Smith 
175aa219208SBarry Smith    Logically Collective on DMDA
17647c6ae99SBarry Smith 
17747c6ae99SBarry Smith    Input Parameter:
17847c6ae99SBarry Smith +  da - initial distributed array
17947c6ae99SBarry Smith -  lf - the local function
18047c6ae99SBarry Smith 
18147c6ae99SBarry Smith    Level: intermediate
18247c6ae99SBarry Smith 
18347c6ae99SBarry Smith    Notes: The routine SNESDAFormFunction() uses this the cached function to evaluate the user provided function.
18447c6ae99SBarry Smith 
18547c6ae99SBarry Smith .keywords:  distributed array, refine
18647c6ae99SBarry Smith 
187aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunctioni()
18847c6ae99SBarry Smith @*/
1897087cfbeSBarry Smith PetscErrorCode  DMDASetLocalFunction(DM da,DMDALocalFunction1 lf)
19047c6ae99SBarry Smith {
19147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
19247c6ae99SBarry Smith   PetscFunctionBegin;
19347c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
19447c6ae99SBarry Smith   dd->lf    = lf;
19547c6ae99SBarry Smith   PetscFunctionReturn(0);
19647c6ae99SBarry Smith }
19747c6ae99SBarry Smith 
19847c6ae99SBarry Smith #undef __FUNCT__
199aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalFunctioni"
20047c6ae99SBarry Smith /*@C
201aa219208SBarry Smith        DMDASetLocalFunctioni - Caches in a DM a local function that evaluates a single component
20247c6ae99SBarry Smith 
203aa219208SBarry Smith    Logically Collective on DMDA
20447c6ae99SBarry Smith 
20547c6ae99SBarry Smith    Input Parameter:
20647c6ae99SBarry Smith +  da - initial distributed array
20747c6ae99SBarry Smith -  lfi - the local function
20847c6ae99SBarry Smith 
20947c6ae99SBarry Smith    Level: intermediate
21047c6ae99SBarry Smith 
21147c6ae99SBarry Smith .keywords:  distributed array, refine
21247c6ae99SBarry Smith 
213aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction()
21447c6ae99SBarry Smith @*/
2157087cfbeSBarry Smith PetscErrorCode  DMDASetLocalFunctioni(DM da,PetscErrorCode (*lfi)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*))
21647c6ae99SBarry Smith {
21747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
21847c6ae99SBarry Smith   PetscFunctionBegin;
21947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
22047c6ae99SBarry Smith   dd->lfi = lfi;
22147c6ae99SBarry Smith   PetscFunctionReturn(0);
22247c6ae99SBarry Smith }
22347c6ae99SBarry Smith 
22447c6ae99SBarry Smith #undef __FUNCT__
225aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalFunctionib"
22647c6ae99SBarry Smith /*@C
227aa219208SBarry Smith        DMDASetLocalFunctionib - Caches in a DM a block local function that evaluates a single component
22847c6ae99SBarry Smith 
229aa219208SBarry Smith    Logically Collective on DMDA
23047c6ae99SBarry Smith 
23147c6ae99SBarry Smith    Input Parameter:
23247c6ae99SBarry Smith +  da - initial distributed array
23347c6ae99SBarry Smith -  lfi - the local function
23447c6ae99SBarry Smith 
23547c6ae99SBarry Smith    Level: intermediate
23647c6ae99SBarry Smith 
23747c6ae99SBarry Smith .keywords:  distributed array, refine
23847c6ae99SBarry Smith 
239aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction()
24047c6ae99SBarry Smith @*/
2417087cfbeSBarry Smith PetscErrorCode  DMDASetLocalFunctionib(DM da,PetscErrorCode (*lfi)(DMDALocalInfo*,MatStencil*,void*,PetscScalar*,void*))
24247c6ae99SBarry Smith {
24347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
24447c6ae99SBarry Smith   PetscFunctionBegin;
24547c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
24647c6ae99SBarry Smith   dd->lfib = lfi;
24747c6ae99SBarry Smith   PetscFunctionReturn(0);
24847c6ae99SBarry Smith }
24947c6ae99SBarry Smith 
25047c6ae99SBarry Smith #undef __FUNCT__
251aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicFunction_Private"
252aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicFunction_Private(DM da,DMDALocalFunction1 ad_lf)
25347c6ae99SBarry Smith {
25447c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
25547c6ae99SBarry Smith   PetscFunctionBegin;
25647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
25747c6ae99SBarry Smith   dd->adic_lf = ad_lf;
25847c6ae99SBarry Smith   PetscFunctionReturn(0);
25947c6ae99SBarry Smith }
26047c6ae99SBarry Smith 
26147c6ae99SBarry Smith /*MC
262aa219208SBarry Smith        DMDASetLocalAdicFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR
26347c6ae99SBarry Smith 
26447c6ae99SBarry Smith    Synopsis:
265aa219208SBarry Smith    PetscErrorCode DMDASetLocalAdicFunctioni(DM da,PetscInt (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
26647c6ae99SBarry Smith 
267aa219208SBarry Smith    Logically Collective on DMDA
26847c6ae99SBarry Smith 
26947c6ae99SBarry Smith    Input Parameter:
27047c6ae99SBarry Smith +  da - initial distributed array
27147c6ae99SBarry Smith -  ad_lfi - the local function as computed by ADIC/ADIFOR
27247c6ae99SBarry Smith 
27347c6ae99SBarry Smith    Level: intermediate
27447c6ae99SBarry Smith 
27547c6ae99SBarry Smith .keywords:  distributed array, refine
27647c6ae99SBarry Smith 
277aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
278aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctioni()
27947c6ae99SBarry Smith M*/
28047c6ae99SBarry Smith 
28147c6ae99SBarry Smith #undef __FUNCT__
282aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicFunctioni_Private"
283aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicFunctioni_Private(DM da,PetscErrorCode (*ad_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
28447c6ae99SBarry Smith {
28547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
28647c6ae99SBarry Smith   PetscFunctionBegin;
28747c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
28847c6ae99SBarry Smith   dd->adic_lfi = ad_lfi;
28947c6ae99SBarry Smith   PetscFunctionReturn(0);
29047c6ae99SBarry Smith }
29147c6ae99SBarry Smith 
29247c6ae99SBarry Smith /*MC
293aa219208SBarry Smith        DMDASetLocalAdicMFFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR
29447c6ae99SBarry Smith 
29547c6ae99SBarry Smith    Synopsis:
296aa219208SBarry Smith    PetscErrorCode  DMDASetLocalAdicFunctioni(DM da,int (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
29747c6ae99SBarry Smith 
298aa219208SBarry Smith    Logically Collective on DMDA
29947c6ae99SBarry Smith 
30047c6ae99SBarry Smith    Input Parameter:
30147c6ae99SBarry Smith +  da - initial distributed array
30247c6ae99SBarry Smith -  admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR
30347c6ae99SBarry Smith 
30447c6ae99SBarry Smith    Level: intermediate
30547c6ae99SBarry Smith 
30647c6ae99SBarry Smith .keywords:  distributed array, refine
30747c6ae99SBarry Smith 
308aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
309aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctioni()
31047c6ae99SBarry Smith M*/
31147c6ae99SBarry Smith 
31247c6ae99SBarry Smith #undef __FUNCT__
313aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicMFFunctioni_Private"
314aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicMFFunctioni_Private(DM da,PetscErrorCode (*admf_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
31547c6ae99SBarry Smith {
31647c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
31747c6ae99SBarry Smith   PetscFunctionBegin;
31847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
31947c6ae99SBarry Smith   dd->adicmf_lfi = admf_lfi;
32047c6ae99SBarry Smith   PetscFunctionReturn(0);
32147c6ae99SBarry Smith }
32247c6ae99SBarry Smith 
32347c6ae99SBarry Smith /*MC
324aa219208SBarry Smith        DMDASetLocalAdicFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR
32547c6ae99SBarry Smith 
32647c6ae99SBarry Smith    Synopsis:
327aa219208SBarry Smith    PetscErrorCode DMDASetLocalAdicFunctionib(DM da,PetscInt (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
32847c6ae99SBarry Smith 
329aa219208SBarry Smith    Logically Collective on DMDA
33047c6ae99SBarry Smith 
33147c6ae99SBarry Smith    Input Parameter:
33247c6ae99SBarry Smith +  da - initial distributed array
33347c6ae99SBarry Smith -  ad_lfi - the local function as computed by ADIC/ADIFOR
33447c6ae99SBarry Smith 
33547c6ae99SBarry Smith    Level: intermediate
33647c6ae99SBarry Smith 
33747c6ae99SBarry Smith .keywords:  distributed array, refine
33847c6ae99SBarry Smith 
339aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
340aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctionib()
34147c6ae99SBarry Smith M*/
34247c6ae99SBarry Smith 
34347c6ae99SBarry Smith #undef __FUNCT__
344aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicFunctionib_Private"
345aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicFunctionib_Private(DM da,PetscErrorCode (*ad_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
34647c6ae99SBarry Smith {
34747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
34847c6ae99SBarry Smith   PetscFunctionBegin;
34947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
35047c6ae99SBarry Smith   dd->adic_lfib = ad_lfi;
35147c6ae99SBarry Smith   PetscFunctionReturn(0);
35247c6ae99SBarry Smith }
35347c6ae99SBarry Smith 
35447c6ae99SBarry Smith /*MC
355aa219208SBarry Smith        DMDASetLocalAdicMFFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR
35647c6ae99SBarry Smith 
35747c6ae99SBarry Smith    Synopsis:
358aa219208SBarry Smith    PetscErrorCode  DMDASetLocalAdicFunctionib(DM da,int (ad_lf*)(DMDALocalInfo*,MatStencil*,void*,void*,void*)
35947c6ae99SBarry Smith 
360aa219208SBarry Smith    Logically Collective on DMDA
36147c6ae99SBarry Smith 
36247c6ae99SBarry Smith    Input Parameter:
36347c6ae99SBarry Smith +  da - initial distributed array
36447c6ae99SBarry Smith -  admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR
36547c6ae99SBarry Smith 
36647c6ae99SBarry Smith    Level: intermediate
36747c6ae99SBarry Smith 
36847c6ae99SBarry Smith .keywords:  distributed array, refine
36947c6ae99SBarry Smith 
370aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
371aa219208SBarry Smith           DMDASetLocalJacobian(), DMDASetLocalFunctionib()
37247c6ae99SBarry Smith M*/
37347c6ae99SBarry Smith 
37447c6ae99SBarry Smith #undef __FUNCT__
375aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicMFFunctionib_Private"
376aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicMFFunctionib_Private(DM da,PetscErrorCode (*admf_lfi)(DMDALocalInfo*,MatStencil*,void*,void*,void*))
37747c6ae99SBarry Smith {
37847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
37947c6ae99SBarry Smith   PetscFunctionBegin;
38047c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
38147c6ae99SBarry Smith   dd->adicmf_lfib = admf_lfi;
38247c6ae99SBarry Smith   PetscFunctionReturn(0);
38347c6ae99SBarry Smith }
38447c6ae99SBarry Smith 
38547c6ae99SBarry Smith /*MC
386aa219208SBarry Smith        DMDASetLocalAdicMFFunction - Caches in a DM a local function computed by ADIC/ADIFOR
38747c6ae99SBarry Smith 
38847c6ae99SBarry Smith    Synopsis:
389aa219208SBarry Smith    PetscErrorCode DMDASetLocalAdicMFFunction(DM da,DMDALocalFunction1 ad_lf)
39047c6ae99SBarry Smith 
391aa219208SBarry Smith    Logically Collective on DMDA
39247c6ae99SBarry Smith 
39347c6ae99SBarry Smith    Input Parameter:
39447c6ae99SBarry Smith +  da - initial distributed array
39547c6ae99SBarry Smith -  ad_lf - the local function as computed by ADIC/ADIFOR
39647c6ae99SBarry Smith 
39747c6ae99SBarry Smith    Level: intermediate
39847c6ae99SBarry Smith 
39947c6ae99SBarry Smith .keywords:  distributed array, refine
40047c6ae99SBarry Smith 
401aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction(),
402aa219208SBarry Smith           DMDASetLocalJacobian()
40347c6ae99SBarry Smith M*/
40447c6ae99SBarry Smith 
40547c6ae99SBarry Smith #undef __FUNCT__
406aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalAdicMFFunction_Private"
407aa219208SBarry Smith PetscErrorCode DMDASetLocalAdicMFFunction_Private(DM da,DMDALocalFunction1 ad_lf)
40847c6ae99SBarry Smith {
40947c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
41047c6ae99SBarry Smith   PetscFunctionBegin;
41147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
41247c6ae99SBarry Smith   dd->adicmf_lf = ad_lf;
41347c6ae99SBarry Smith   PetscFunctionReturn(0);
41447c6ae99SBarry Smith }
41547c6ae99SBarry Smith 
41647c6ae99SBarry Smith /*@C
417aa219208SBarry Smith        DMDASetLocalJacobian - Caches in a DM a local Jacobian computation function
41847c6ae99SBarry Smith 
419aa219208SBarry Smith    Logically Collective on DMDA
42047c6ae99SBarry Smith 
42147c6ae99SBarry Smith 
42247c6ae99SBarry Smith    Input Parameter:
42347c6ae99SBarry Smith +  da - initial distributed array
42447c6ae99SBarry Smith -  lj - the local Jacobian
42547c6ae99SBarry Smith 
42647c6ae99SBarry Smith    Level: intermediate
42747c6ae99SBarry Smith 
42847c6ae99SBarry Smith    Notes: The routine SNESDAFormFunction() uses this the cached function to evaluate the user provided function.
42947c6ae99SBarry Smith 
43047c6ae99SBarry Smith .keywords:  distributed array, refine
43147c6ae99SBarry Smith 
432aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalFunction()
43347c6ae99SBarry Smith @*/
43447c6ae99SBarry Smith #undef __FUNCT__
435aa219208SBarry Smith #define __FUNCT__ "DMDASetLocalJacobian"
4367087cfbeSBarry Smith PetscErrorCode  DMDASetLocalJacobian(DM da,DMDALocalFunction1 lj)
43747c6ae99SBarry Smith {
43847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
43947c6ae99SBarry Smith   PetscFunctionBegin;
44047c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
44147c6ae99SBarry Smith   dd->lj    = lj;
44247c6ae99SBarry Smith   PetscFunctionReturn(0);
44347c6ae99SBarry Smith }
44447c6ae99SBarry Smith 
44547c6ae99SBarry Smith #undef __FUNCT__
446aa219208SBarry Smith #define __FUNCT__ "DMDAGetLocalFunction"
44747c6ae99SBarry Smith /*@C
448aa219208SBarry Smith        DMDAGetLocalFunction - Gets from a DM a local function and its ADIC/ADIFOR Jacobian
44947c6ae99SBarry Smith 
45047c6ae99SBarry Smith    Note Collective
45147c6ae99SBarry Smith 
45247c6ae99SBarry Smith    Input Parameter:
45347c6ae99SBarry Smith .  da - initial distributed array
45447c6ae99SBarry Smith 
45547c6ae99SBarry Smith    Output Parameter:
45647c6ae99SBarry Smith .  lf - the local function
45747c6ae99SBarry Smith 
45847c6ae99SBarry Smith    Level: intermediate
45947c6ae99SBarry Smith 
46047c6ae99SBarry Smith .keywords:  distributed array, refine
46147c6ae99SBarry Smith 
462aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalJacobian(), DMDASetLocalFunction()
46347c6ae99SBarry Smith @*/
4647087cfbeSBarry Smith PetscErrorCode  DMDAGetLocalFunction(DM da,DMDALocalFunction1 *lf)
46547c6ae99SBarry Smith {
46647c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
46747c6ae99SBarry Smith   PetscFunctionBegin;
46847c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
46947c6ae99SBarry Smith   if (lf) *lf = dd->lf;
47047c6ae99SBarry Smith   PetscFunctionReturn(0);
47147c6ae99SBarry Smith }
47247c6ae99SBarry Smith 
47347c6ae99SBarry Smith #undef __FUNCT__
474aa219208SBarry Smith #define __FUNCT__ "DMDAGetLocalJacobian"
47547c6ae99SBarry Smith /*@C
476aa219208SBarry Smith        DMDAGetLocalJacobian - Gets from a DM a local jacobian
47747c6ae99SBarry Smith 
47847c6ae99SBarry Smith    Not Collective
47947c6ae99SBarry Smith 
48047c6ae99SBarry Smith    Input Parameter:
48147c6ae99SBarry Smith .  da - initial distributed array
48247c6ae99SBarry Smith 
48347c6ae99SBarry Smith    Output Parameter:
48447c6ae99SBarry Smith .  lj - the local jacobian
48547c6ae99SBarry Smith 
48647c6ae99SBarry Smith    Level: intermediate
48747c6ae99SBarry Smith 
48847c6ae99SBarry Smith .keywords:  distributed array, refine
48947c6ae99SBarry Smith 
490aa219208SBarry Smith .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDAGetLocalFunction(), DMDASetLocalJacobian()
49147c6ae99SBarry Smith @*/
4927087cfbeSBarry Smith PetscErrorCode  DMDAGetLocalJacobian(DM da,DMDALocalFunction1 *lj)
49347c6ae99SBarry Smith {
49447c6ae99SBarry Smith   DM_DA *dd = (DM_DA*)da->data;
49547c6ae99SBarry Smith   PetscFunctionBegin;
49647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
49747c6ae99SBarry Smith   if (lj) *lj = dd->lj;
49847c6ae99SBarry Smith   PetscFunctionReturn(0);
49947c6ae99SBarry Smith }
50047c6ae99SBarry Smith 
50147c6ae99SBarry Smith #undef __FUNCT__
502aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunction"
50347c6ae99SBarry Smith /*@
504aa219208SBarry Smith     DMDAFormFunction - Evaluates a user provided function on each processor that
505aa219208SBarry Smith         share a DMDA
50647c6ae99SBarry Smith 
50747c6ae99SBarry Smith    Input Parameters:
5089a42bb27SBarry Smith +    da - the DM that defines the grid
50947c6ae99SBarry Smith .    vu - input vector
51047c6ae99SBarry Smith .    vfu - output vector
51147c6ae99SBarry Smith -    w - any user data
51247c6ae99SBarry Smith 
51347c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
51447c6ae99SBarry Smith 
515aa219208SBarry Smith            This should eventually replace DMDAFormFunction1
51647c6ae99SBarry Smith 
51747c6ae99SBarry Smith     Level: advanced
51847c6ae99SBarry Smith 
519aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
52047c6ae99SBarry Smith 
52147c6ae99SBarry Smith @*/
5227087cfbeSBarry Smith PetscErrorCode  DMDAFormFunction(DM da,PetscErrorCode (*lf)(void),Vec vu,Vec vfu,void *w)
52347c6ae99SBarry Smith {
52447c6ae99SBarry Smith   PetscErrorCode ierr;
52547c6ae99SBarry Smith   void           *u,*fu;
526aa219208SBarry Smith   DMDALocalInfo  info;
527aa219208SBarry Smith   PetscErrorCode (*f)(DMDALocalInfo*,void*,void*,void*) = (PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))lf;
52847c6ae99SBarry Smith 
52947c6ae99SBarry Smith   PetscFunctionBegin;
530aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
531aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
532aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vfu,&fu);CHKERRQ(ierr);
53347c6ae99SBarry Smith 
53439d508bbSBarry Smith   ierr = (*f)(&info,u,fu,w);CHKERRQ(ierr);
53547c6ae99SBarry Smith 
536aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
537aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr);
53847c6ae99SBarry Smith   PetscFunctionReturn(0);
53947c6ae99SBarry Smith }
54047c6ae99SBarry Smith 
54147c6ae99SBarry Smith #undef __FUNCT__
542aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctionLocal"
54347c6ae99SBarry Smith /*@C
544aa219208SBarry Smith    DMDAFormFunctionLocal - This is a universal function evaluation routine for
5459a42bb27SBarry Smith    a local DM function.
54647c6ae99SBarry Smith 
547aa219208SBarry Smith    Collective on DMDA
54847c6ae99SBarry Smith 
54947c6ae99SBarry Smith    Input Parameters:
5509a42bb27SBarry Smith +  da - the DM context
55147c6ae99SBarry Smith .  func - The local function
55247c6ae99SBarry Smith .  X - input vector
55347c6ae99SBarry Smith .  F - function vector
55447c6ae99SBarry Smith -  ctx - A user context
55547c6ae99SBarry Smith 
55647c6ae99SBarry Smith    Level: intermediate
55747c6ae99SBarry Smith 
558aa219208SBarry Smith .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(),
55947c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
56047c6ae99SBarry Smith 
56147c6ae99SBarry Smith @*/
5627087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctionLocal(DM da, DMDALocalFunction1 func, Vec X, Vec F, void *ctx)
56347c6ae99SBarry Smith {
56447c6ae99SBarry Smith   Vec            localX;
565aa219208SBarry Smith   DMDALocalInfo  info;
56647c6ae99SBarry Smith   void           *u;
56747c6ae99SBarry Smith   void           *fu;
56847c6ae99SBarry Smith   PetscErrorCode ierr;
56947c6ae99SBarry Smith 
57047c6ae99SBarry Smith   PetscFunctionBegin;
5719a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
57247c6ae99SBarry Smith   /*
57347c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
5749a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
57547c6ae99SBarry Smith   */
5769a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
5779a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
578aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
579aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr);
580aa219208SBarry Smith   ierr = DMDAVecGetArray(da,F,&fu);CHKERRQ(ierr);
58139d508bbSBarry Smith   ierr = (*func)(&info,u,fu,ctx);CHKERRQ(ierr);
582aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
583aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,F,&fu);CHKERRQ(ierr);
5849a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
58547c6ae99SBarry Smith   PetscFunctionReturn(0);
58647c6ae99SBarry Smith }
58747c6ae99SBarry Smith 
58847c6ae99SBarry Smith #undef __FUNCT__
589aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctionLocalGhost"
59047c6ae99SBarry Smith /*@C
591aa219208SBarry Smith    DMDAFormFunctionLocalGhost - This is a universal function evaluation routine for
5929a42bb27SBarry Smith    a local DM function, but the ghost values of the output are communicated and added.
59347c6ae99SBarry Smith 
594aa219208SBarry Smith    Collective on DMDA
59547c6ae99SBarry Smith 
59647c6ae99SBarry Smith    Input Parameters:
5979a42bb27SBarry Smith +  da - the DM context
59847c6ae99SBarry Smith .  func - The local function
59947c6ae99SBarry Smith .  X - input vector
60047c6ae99SBarry Smith .  F - function vector
60147c6ae99SBarry Smith -  ctx - A user context
60247c6ae99SBarry Smith 
60347c6ae99SBarry Smith    Level: intermediate
60447c6ae99SBarry Smith 
605aa219208SBarry Smith .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(),
60647c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
60747c6ae99SBarry Smith 
60847c6ae99SBarry Smith @*/
6097087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctionLocalGhost(DM da, DMDALocalFunction1 func, Vec X, Vec F, void *ctx)
61047c6ae99SBarry Smith {
61147c6ae99SBarry Smith   Vec            localX, localF;
612aa219208SBarry Smith   DMDALocalInfo  info;
61347c6ae99SBarry Smith   void           *u;
61447c6ae99SBarry Smith   void           *fu;
61547c6ae99SBarry Smith   PetscErrorCode ierr;
61647c6ae99SBarry Smith 
61747c6ae99SBarry Smith   PetscFunctionBegin;
6189a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
6199a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localF);CHKERRQ(ierr);
62047c6ae99SBarry Smith   /*
62147c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
6229a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
62347c6ae99SBarry Smith   */
6249a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
6259a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
62647c6ae99SBarry Smith   ierr = VecSet(F, 0.0);CHKERRQ(ierr);
62747c6ae99SBarry Smith   ierr = VecSet(localF, 0.0);CHKERRQ(ierr);
628aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
629aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr);
630aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localF,&fu);CHKERRQ(ierr);
63139d508bbSBarry Smith   ierr = (*func)(&info,u,fu,ctx);CHKERRQ(ierr);
6329a42bb27SBarry Smith   ierr = DMLocalToGlobalBegin(da,localF,ADD_VALUES,F);CHKERRQ(ierr);
6339a42bb27SBarry Smith   ierr = DMLocalToGlobalEnd(da,localF,ADD_VALUES,F);CHKERRQ(ierr);
634aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
635aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localF,&fu);CHKERRQ(ierr);
6369a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
6379a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localF);CHKERRQ(ierr);
63847c6ae99SBarry Smith   PetscFunctionReturn(0);
63947c6ae99SBarry Smith }
64047c6ae99SBarry Smith 
64147c6ae99SBarry Smith #undef __FUNCT__
642aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunction1"
64347c6ae99SBarry Smith /*@
644aa219208SBarry Smith     DMDAFormFunction1 - Evaluates a user provided function on each processor that
645aa219208SBarry Smith         share a DMDA
64647c6ae99SBarry Smith 
64747c6ae99SBarry Smith    Input Parameters:
6489a42bb27SBarry Smith +    da - the DM that defines the grid
64947c6ae99SBarry Smith .    vu - input vector
65047c6ae99SBarry Smith .    vfu - output vector
65147c6ae99SBarry Smith -    w - any user data
65247c6ae99SBarry Smith 
65347c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
65447c6ae99SBarry Smith 
65547c6ae99SBarry Smith     Level: advanced
65647c6ae99SBarry Smith 
657aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
65847c6ae99SBarry Smith 
65947c6ae99SBarry Smith @*/
6607087cfbeSBarry Smith PetscErrorCode  DMDAFormFunction1(DM da,Vec vu,Vec vfu,void *w)
66147c6ae99SBarry Smith {
66247c6ae99SBarry Smith   PetscErrorCode ierr;
66347c6ae99SBarry Smith   void           *u,*fu;
664aa219208SBarry Smith   DMDALocalInfo  info;
66547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
66647c6ae99SBarry Smith 
66747c6ae99SBarry Smith   PetscFunctionBegin;
668aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
669aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
670aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vfu,&fu);CHKERRQ(ierr);
67147c6ae99SBarry Smith 
67247c6ae99SBarry Smith   CHKMEMQ;
67339d508bbSBarry Smith   ierr = (*dd->lf)(&info,u,fu,w);CHKERRQ(ierr);
67447c6ae99SBarry Smith   CHKMEMQ;
67547c6ae99SBarry Smith 
676aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
677aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr);
67847c6ae99SBarry Smith   PetscFunctionReturn(0);
67947c6ae99SBarry Smith }
68047c6ae99SBarry Smith 
68147c6ae99SBarry Smith #undef __FUNCT__
682aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctioniTest1"
6837087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctioniTest1(DM da,void *w)
68447c6ae99SBarry Smith {
68547c6ae99SBarry Smith   Vec            vu,fu,fui;
68647c6ae99SBarry Smith   PetscErrorCode ierr;
68747c6ae99SBarry Smith   PetscInt       i,n;
68847c6ae99SBarry Smith   PetscScalar    *ui;
68947c6ae99SBarry Smith   PetscRandom    rnd;
69047c6ae99SBarry Smith   PetscReal      norm;
69147c6ae99SBarry Smith 
69247c6ae99SBarry Smith   PetscFunctionBegin;
6939a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&vu);CHKERRQ(ierr);
69447c6ae99SBarry Smith   ierr = PetscRandomCreate(PETSC_COMM_SELF,&rnd);CHKERRQ(ierr);
69547c6ae99SBarry Smith   ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr);
69647c6ae99SBarry Smith   ierr = VecSetRandom(vu,rnd);CHKERRQ(ierr);
69747c6ae99SBarry Smith   ierr = PetscRandomDestroy(rnd);CHKERRQ(ierr);
69847c6ae99SBarry Smith 
6999a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&fu);CHKERRQ(ierr);
7009a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&fui);CHKERRQ(ierr);
70147c6ae99SBarry Smith 
702aa219208SBarry Smith   ierr = DMDAFormFunction1(da,vu,fu,w);CHKERRQ(ierr);
70347c6ae99SBarry Smith 
70447c6ae99SBarry Smith   ierr = VecGetArray(fui,&ui);CHKERRQ(ierr);
70547c6ae99SBarry Smith   ierr = VecGetLocalSize(fui,&n);CHKERRQ(ierr);
70647c6ae99SBarry Smith   for (i=0; i<n; i++) {
707aa219208SBarry Smith     ierr = DMDAFormFunctioni1(da,i,vu,ui+i,w);CHKERRQ(ierr);
70847c6ae99SBarry Smith   }
70947c6ae99SBarry Smith   ierr = VecRestoreArray(fui,&ui);CHKERRQ(ierr);
71047c6ae99SBarry Smith 
71147c6ae99SBarry Smith   ierr = VecAXPY(fui,-1.0,fu);CHKERRQ(ierr);
71247c6ae99SBarry Smith   ierr = VecNorm(fui,NORM_2,&norm);CHKERRQ(ierr);
71347c6ae99SBarry Smith   ierr = PetscPrintf(((PetscObject)da)->comm,"Norm of difference in vectors %G\n",norm);CHKERRQ(ierr);
71447c6ae99SBarry Smith   ierr = VecView(fu,0);CHKERRQ(ierr);
71547c6ae99SBarry Smith   ierr = VecView(fui,0);CHKERRQ(ierr);
71647c6ae99SBarry Smith 
7179a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&vu);CHKERRQ(ierr);
7189a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&fu);CHKERRQ(ierr);
7199a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&fui);CHKERRQ(ierr);
72047c6ae99SBarry Smith   PetscFunctionReturn(0);
72147c6ae99SBarry Smith }
72247c6ae99SBarry Smith 
72347c6ae99SBarry Smith #undef __FUNCT__
724aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctioni1"
72547c6ae99SBarry Smith /*@
726aa219208SBarry Smith     DMDAFormFunctioni1 - Evaluates a user provided point-wise function
72747c6ae99SBarry Smith 
72847c6ae99SBarry Smith    Input Parameters:
7299a42bb27SBarry Smith +    da - the DM that defines the grid
73047c6ae99SBarry Smith .    i - the component of the function we wish to compute (must be local)
73147c6ae99SBarry Smith .    vu - input vector
73247c6ae99SBarry Smith .    vfu - output value
73347c6ae99SBarry Smith -    w - any user data
73447c6ae99SBarry Smith 
73547c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
73647c6ae99SBarry Smith 
73747c6ae99SBarry Smith     Level: advanced
73847c6ae99SBarry Smith 
739aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
74047c6ae99SBarry Smith 
74147c6ae99SBarry Smith @*/
7427087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctioni1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w)
74347c6ae99SBarry Smith {
74447c6ae99SBarry Smith   PetscErrorCode ierr;
74547c6ae99SBarry Smith   void           *u;
746aa219208SBarry Smith   DMDALocalInfo  info;
74747c6ae99SBarry Smith   MatStencil     stencil;
74847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
74947c6ae99SBarry Smith 
75047c6ae99SBarry Smith   PetscFunctionBegin;
75147c6ae99SBarry Smith 
752aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
753aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
75447c6ae99SBarry Smith 
75547c6ae99SBarry Smith   /* figure out stencil value from i */
75647c6ae99SBarry Smith   stencil.c = i % info.dof;
75747c6ae99SBarry Smith   stencil.i = (i % (info.xm*info.dof))/info.dof;
75847c6ae99SBarry Smith   stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof);
75947c6ae99SBarry Smith   stencil.k = i/(info.xm*info.ym*info.dof);
76047c6ae99SBarry Smith 
76147c6ae99SBarry Smith   ierr = (*dd->lfi)(&info,&stencil,u,vfu,w);CHKERRQ(ierr);
76247c6ae99SBarry Smith 
763aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
76447c6ae99SBarry Smith   PetscFunctionReturn(0);
76547c6ae99SBarry Smith }
76647c6ae99SBarry Smith 
76747c6ae99SBarry Smith #undef __FUNCT__
768aa219208SBarry Smith #define __FUNCT__ "DMDAFormFunctionib1"
76947c6ae99SBarry Smith /*@
770aa219208SBarry Smith     DMDAFormFunctionib1 - Evaluates a user provided point-block function
77147c6ae99SBarry Smith 
77247c6ae99SBarry Smith    Input Parameters:
7739a42bb27SBarry Smith +    da - the DM that defines the grid
77447c6ae99SBarry Smith .    i - the component of the function we wish to compute (must be local)
77547c6ae99SBarry Smith .    vu - input vector
77647c6ae99SBarry Smith .    vfu - output value
77747c6ae99SBarry Smith -    w - any user data
77847c6ae99SBarry Smith 
77947c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
78047c6ae99SBarry Smith 
78147c6ae99SBarry Smith     Level: advanced
78247c6ae99SBarry Smith 
783aa219208SBarry Smith .seealso: DMDAComputeJacobian1WithAdic()
78447c6ae99SBarry Smith 
78547c6ae99SBarry Smith @*/
7867087cfbeSBarry Smith PetscErrorCode  DMDAFormFunctionib1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w)
78747c6ae99SBarry Smith {
78847c6ae99SBarry Smith   PetscErrorCode ierr;
78947c6ae99SBarry Smith   void           *u;
790aa219208SBarry Smith   DMDALocalInfo  info;
79147c6ae99SBarry Smith   MatStencil     stencil;
79247c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
79347c6ae99SBarry Smith 
79447c6ae99SBarry Smith   PetscFunctionBegin;
795aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
796aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
79747c6ae99SBarry Smith 
79847c6ae99SBarry Smith   /* figure out stencil value from i */
79947c6ae99SBarry Smith   stencil.c = i % info.dof;
80047c6ae99SBarry Smith   if (stencil.c) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONG,"Point-block functions can only be called for the entire block");
80147c6ae99SBarry Smith   stencil.i = (i % (info.xm*info.dof))/info.dof;
80247c6ae99SBarry Smith   stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof);
80347c6ae99SBarry Smith   stencil.k = i/(info.xm*info.ym*info.dof);
80447c6ae99SBarry Smith 
80547c6ae99SBarry Smith   ierr = (*dd->lfib)(&info,&stencil,u,vfu,w);CHKERRQ(ierr);
80647c6ae99SBarry Smith 
807aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
80847c6ae99SBarry Smith   PetscFunctionReturn(0);
80947c6ae99SBarry Smith }
81047c6ae99SBarry Smith 
81147c6ae99SBarry Smith #if defined(new)
81247c6ae99SBarry Smith #undef __FUNCT__
813aa219208SBarry Smith #define __FUNCT__ "DMDAGetDiagonal_MFFD"
81447c6ae99SBarry Smith /*
815aa219208SBarry Smith   DMDAGetDiagonal_MFFD - Gets the diagonal for a matrix free matrix where local
816aa219208SBarry Smith     function lives on a DMDA
81747c6ae99SBarry Smith 
81847c6ae99SBarry Smith         y ~= (F(u + ha) - F(u))/h,
81947c6ae99SBarry Smith   where F = nonlinear function, as set by SNESSetFunction()
82047c6ae99SBarry Smith         u = current iterate
82147c6ae99SBarry Smith         h = difference interval
82247c6ae99SBarry Smith */
823aa219208SBarry Smith PetscErrorCode DMDAGetDiagonal_MFFD(DM da,Vec U,Vec a)
82447c6ae99SBarry Smith {
82547c6ae99SBarry Smith   PetscScalar    h,*aa,*ww,v;
82647c6ae99SBarry Smith   PetscReal      epsilon = PETSC_SQRT_MACHINE_EPSILON,umin = 100.0*PETSC_SQRT_MACHINE_EPSILON;
82747c6ae99SBarry Smith   PetscErrorCode ierr;
82847c6ae99SBarry Smith   PetscInt       gI,nI;
82947c6ae99SBarry Smith   MatStencil     stencil;
830aa219208SBarry Smith   DMDALocalInfo  info;
83147c6ae99SBarry Smith 
83247c6ae99SBarry Smith   PetscFunctionBegin;
83347c6ae99SBarry Smith   ierr = (*ctx->func)(0,U,a,ctx->funcctx);CHKERRQ(ierr);
83447c6ae99SBarry Smith   ierr = (*ctx->funcisetbase)(U,ctx->funcctx);CHKERRQ(ierr);
83547c6ae99SBarry Smith 
83647c6ae99SBarry Smith   ierr = VecGetArray(U,&ww);CHKERRQ(ierr);
83747c6ae99SBarry Smith   ierr = VecGetArray(a,&aa);CHKERRQ(ierr);
83847c6ae99SBarry Smith 
83947c6ae99SBarry Smith   nI = 0;
84047c6ae99SBarry Smith     h  = ww[gI];
84147c6ae99SBarry Smith     if (h == 0.0) h = 1.0;
84247c6ae99SBarry Smith #if !defined(PETSC_USE_COMPLEX)
84347c6ae99SBarry Smith     if (h < umin && h >= 0.0)      h = umin;
84447c6ae99SBarry Smith     else if (h < 0.0 && h > -umin) h = -umin;
84547c6ae99SBarry Smith #else
84647c6ae99SBarry Smith     if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0)     h = umin;
84747c6ae99SBarry Smith     else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin;
84847c6ae99SBarry Smith #endif
84947c6ae99SBarry Smith     h     *= epsilon;
85047c6ae99SBarry Smith 
85147c6ae99SBarry Smith     ww[gI] += h;
85247c6ae99SBarry Smith     ierr          = (*ctx->funci)(i,w,&v,ctx->funcctx);CHKERRQ(ierr);
85347c6ae99SBarry Smith     aa[nI]  = (v - aa[nI])/h;
85447c6ae99SBarry Smith     ww[gI] -= h;
85547c6ae99SBarry Smith     nI++;
85647c6ae99SBarry Smith   }
85747c6ae99SBarry Smith   ierr = VecRestoreArray(U,&ww);CHKERRQ(ierr);
85847c6ae99SBarry Smith   ierr = VecRestoreArray(a,&aa);CHKERRQ(ierr);
85947c6ae99SBarry Smith   PetscFunctionReturn(0);
86047c6ae99SBarry Smith }
86147c6ae99SBarry Smith #endif
86247c6ae99SBarry Smith 
86347c6ae99SBarry Smith #if defined(PETSC_HAVE_ADIC)
86447c6ae99SBarry Smith EXTERN_C_BEGIN
865c6db04a5SJed Brown #include <adic/ad_utils.h>
86647c6ae99SBarry Smith EXTERN_C_END
86747c6ae99SBarry Smith 
86847c6ae99SBarry Smith #undef __FUNCT__
869aa219208SBarry Smith #define __FUNCT__ "DMDAComputeJacobian1WithAdic"
87047c6ae99SBarry Smith /*@C
871aa219208SBarry Smith     DMDAComputeJacobian1WithAdic - Evaluates a adiC provided Jacobian function on each processor that
872aa219208SBarry Smith         share a DMDA
87347c6ae99SBarry Smith 
87447c6ae99SBarry Smith    Input Parameters:
8759a42bb27SBarry Smith +    da - the DM that defines the grid
87647c6ae99SBarry Smith .    vu - input vector (ghosted)
87747c6ae99SBarry Smith .    J - output matrix
87847c6ae99SBarry Smith -    w - any user data
87947c6ae99SBarry Smith 
88047c6ae99SBarry Smith    Level: advanced
88147c6ae99SBarry Smith 
88247c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
88347c6ae99SBarry Smith 
884aa219208SBarry Smith .seealso: DMDAFormFunction1()
88547c6ae99SBarry Smith 
88647c6ae99SBarry Smith @*/
8877087cfbeSBarry Smith PetscErrorCode  DMDAComputeJacobian1WithAdic(DM da,Vec vu,Mat J,void *w)
88847c6ae99SBarry Smith {
88947c6ae99SBarry Smith   PetscErrorCode ierr;
89047c6ae99SBarry Smith   PetscInt       gtdof,tdof;
89147c6ae99SBarry Smith   PetscScalar    *ustart;
892aa219208SBarry Smith   DMDALocalInfo  info;
89347c6ae99SBarry Smith   void           *ad_u,*ad_f,*ad_ustart,*ad_fstart;
89447c6ae99SBarry Smith   ISColoring     iscoloring;
89547c6ae99SBarry Smith 
89647c6ae99SBarry Smith   PetscFunctionBegin;
897aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
89847c6ae99SBarry Smith 
89947c6ae99SBarry Smith   PetscADResetIndep();
90047c6ae99SBarry Smith 
90147c6ae99SBarry Smith   /* get space for derivative objects.  */
902aa219208SBarry Smith   ierr = DMDAGetAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,&gtdof);CHKERRQ(ierr);
903aa219208SBarry Smith   ierr = DMDAGetAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
90447c6ae99SBarry Smith   ierr = VecGetArray(vu,&ustart);CHKERRQ(ierr);
90594013140SBarry Smith   ierr = DMGetColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr);
90647c6ae99SBarry Smith 
90747c6ae99SBarry Smith   PetscADSetValueAndColor(ad_ustart,gtdof,iscoloring->colors,ustart);
90847c6ae99SBarry Smith 
90947c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&ustart);CHKERRQ(ierr);
91047c6ae99SBarry Smith   ierr = ISColoringDestroy(iscoloring);CHKERRQ(ierr);
91147c6ae99SBarry Smith   ierr = PetscADIncrementTotalGradSize(iscoloring->n);CHKERRQ(ierr);
91247c6ae99SBarry Smith   PetscADSetIndepDone();
91347c6ae99SBarry Smith 
914aa219208SBarry Smith   ierr = PetscLogEventBegin(DMDA_LocalADFunction,0,0,0,0);CHKERRQ(ierr);
91547c6ae99SBarry Smith   ierr = (*dd->adic_lf)(&info,ad_u,ad_f,w);CHKERRQ(ierr);
916aa219208SBarry Smith   ierr = PetscLogEventEnd(DMDA_LocalADFunction,0,0,0,0);CHKERRQ(ierr);
91747c6ae99SBarry Smith 
91847c6ae99SBarry Smith   /* stick the values into the matrix */
91947c6ae99SBarry Smith   ierr = MatSetValuesAdic(J,(PetscScalar**)ad_fstart);CHKERRQ(ierr);
92047c6ae99SBarry Smith 
92147c6ae99SBarry Smith   /* return space for derivative objects.  */
922aa219208SBarry Smith   ierr = DMDARestoreAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,&gtdof);CHKERRQ(ierr);
923aa219208SBarry Smith   ierr = DMDARestoreAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
92447c6ae99SBarry Smith   PetscFunctionReturn(0);
92547c6ae99SBarry Smith }
92647c6ae99SBarry Smith 
92747c6ae99SBarry Smith #undef __FUNCT__
928aa219208SBarry Smith #define __FUNCT__ "DMDAMultiplyByJacobian1WithAdic"
92947c6ae99SBarry Smith /*@C
930aa219208SBarry Smith     DMDAMultiplyByJacobian1WithAdic - Applies an ADIC-provided Jacobian function to a vector on
931aa219208SBarry Smith     each processor that shares a DMDA.
93247c6ae99SBarry Smith 
93347c6ae99SBarry Smith     Input Parameters:
9349a42bb27SBarry Smith +   da - the DM that defines the grid
93547c6ae99SBarry Smith .   vu - Jacobian is computed at this point (ghosted)
93647c6ae99SBarry Smith .   v - product is done on this vector (ghosted)
93747c6ae99SBarry Smith .   fu - output vector = J(vu)*v (not ghosted)
93847c6ae99SBarry Smith -   w - any user data
93947c6ae99SBarry Smith 
94047c6ae99SBarry Smith     Notes:
94147c6ae99SBarry Smith     This routine does NOT do ghost updates on vu upon entry.
94247c6ae99SBarry Smith 
94347c6ae99SBarry Smith    Level: advanced
94447c6ae99SBarry Smith 
945aa219208SBarry Smith .seealso: DMDAFormFunction1()
94647c6ae99SBarry Smith 
94747c6ae99SBarry Smith @*/
9487087cfbeSBarry Smith PetscErrorCode  DMDAMultiplyByJacobian1WithAdic(DM da,Vec vu,Vec v,Vec f,void *w)
94947c6ae99SBarry Smith {
95047c6ae99SBarry Smith   PetscErrorCode ierr;
95147c6ae99SBarry Smith   PetscInt       i,gtdof,tdof;
95247c6ae99SBarry Smith   PetscScalar    *avu,*av,*af,*ad_vustart,*ad_fstart;
953aa219208SBarry Smith   DMDALocalInfo  info;
95447c6ae99SBarry Smith   void           *ad_vu,*ad_f;
95547c6ae99SBarry Smith 
95647c6ae99SBarry Smith   PetscFunctionBegin;
957aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
95847c6ae99SBarry Smith 
95947c6ae99SBarry Smith   /* get space for derivative objects.  */
960aa219208SBarry Smith   ierr = DMDAGetAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,&gtdof);CHKERRQ(ierr);
961aa219208SBarry Smith   ierr = DMDAGetAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
96247c6ae99SBarry Smith 
96347c6ae99SBarry Smith   /* copy input vector into derivative object */
96447c6ae99SBarry Smith   ierr = VecGetArray(vu,&avu);CHKERRQ(ierr);
96547c6ae99SBarry Smith   ierr = VecGetArray(v,&av);CHKERRQ(ierr);
96647c6ae99SBarry Smith   for (i=0; i<gtdof; i++) {
96747c6ae99SBarry Smith     ad_vustart[2*i]   = avu[i];
96847c6ae99SBarry Smith     ad_vustart[2*i+1] = av[i];
96947c6ae99SBarry Smith   }
97047c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&avu);CHKERRQ(ierr);
97147c6ae99SBarry Smith   ierr = VecRestoreArray(v,&av);CHKERRQ(ierr);
97247c6ae99SBarry Smith 
97347c6ae99SBarry Smith   PetscADResetIndep();
97447c6ae99SBarry Smith   ierr = PetscADIncrementTotalGradSize(1);CHKERRQ(ierr);
97547c6ae99SBarry Smith   PetscADSetIndepDone();
97647c6ae99SBarry Smith 
97747c6ae99SBarry Smith   ierr = (*dd->adicmf_lf)(&info,ad_vu,ad_f,w);CHKERRQ(ierr);
97847c6ae99SBarry Smith 
97947c6ae99SBarry Smith   /* stick the values into the vector */
98047c6ae99SBarry Smith   ierr = VecGetArray(f,&af);CHKERRQ(ierr);
98147c6ae99SBarry Smith   for (i=0; i<tdof; i++) {
98247c6ae99SBarry Smith     af[i] = ad_fstart[2*i+1];
98347c6ae99SBarry Smith   }
98447c6ae99SBarry Smith   ierr = VecRestoreArray(f,&af);CHKERRQ(ierr);
98547c6ae99SBarry Smith 
98647c6ae99SBarry Smith   /* return space for derivative objects.  */
987aa219208SBarry Smith   ierr = DMDARestoreAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,&gtdof);CHKERRQ(ierr);
988aa219208SBarry Smith   ierr = DMDARestoreAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
98947c6ae99SBarry Smith   PetscFunctionReturn(0);
99047c6ae99SBarry Smith }
99147c6ae99SBarry Smith #endif
99247c6ae99SBarry Smith 
99347c6ae99SBarry Smith #undef __FUNCT__
994aa219208SBarry Smith #define __FUNCT__ "DMDAComputeJacobian1"
99547c6ae99SBarry Smith /*@
996aa219208SBarry Smith     DMDAComputeJacobian1 - Evaluates a local Jacobian function on each processor that
997aa219208SBarry Smith         share a DMDA
99847c6ae99SBarry Smith 
99947c6ae99SBarry Smith    Input Parameters:
10009a42bb27SBarry Smith +    da - the DM that defines the grid
100147c6ae99SBarry Smith .    vu - input vector (ghosted)
100247c6ae99SBarry Smith .    J - output matrix
100347c6ae99SBarry Smith -    w - any user data
100447c6ae99SBarry Smith 
100547c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
100647c6ae99SBarry Smith 
100747c6ae99SBarry Smith     Level: advanced
100847c6ae99SBarry Smith 
1009aa219208SBarry Smith .seealso: DMDAFormFunction1()
101047c6ae99SBarry Smith 
101147c6ae99SBarry Smith @*/
10127087cfbeSBarry Smith PetscErrorCode  DMDAComputeJacobian1(DM da,Vec vu,Mat J,void *w)
101347c6ae99SBarry Smith {
101447c6ae99SBarry Smith   PetscErrorCode ierr;
101547c6ae99SBarry Smith   void           *u;
1016aa219208SBarry Smith   DMDALocalInfo  info;
101747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
101847c6ae99SBarry Smith 
101947c6ae99SBarry Smith   PetscFunctionBegin;
1020aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
1021aa219208SBarry Smith   ierr = DMDAVecGetArray(da,vu,&u);CHKERRQ(ierr);
102247c6ae99SBarry Smith   ierr = (*dd->lj)(&info,u,J,w);CHKERRQ(ierr);
1023aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
102447c6ae99SBarry Smith   PetscFunctionReturn(0);
102547c6ae99SBarry Smith }
102647c6ae99SBarry Smith 
102747c6ae99SBarry Smith 
102847c6ae99SBarry Smith #undef __FUNCT__
1029aa219208SBarry Smith #define __FUNCT__ "DMDAComputeJacobian1WithAdifor"
103047c6ae99SBarry Smith /*
1031aa219208SBarry Smith     DMDAComputeJacobian1WithAdifor - Evaluates a ADIFOR provided Jacobian local function on each processor that
1032aa219208SBarry Smith         share a DMDA
103347c6ae99SBarry Smith 
103447c6ae99SBarry Smith    Input Parameters:
10359a42bb27SBarry Smith +    da - the DM that defines the grid
103647c6ae99SBarry Smith .    vu - input vector (ghosted)
103747c6ae99SBarry Smith .    J - output matrix
103847c6ae99SBarry Smith -    w - any user data
103947c6ae99SBarry Smith 
104047c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
104147c6ae99SBarry Smith 
1042aa219208SBarry Smith .seealso: DMDAFormFunction1()
104347c6ae99SBarry Smith 
104447c6ae99SBarry Smith */
10457087cfbeSBarry Smith PetscErrorCode  DMDAComputeJacobian1WithAdifor(DM da,Vec vu,Mat J,void *w)
104647c6ae99SBarry Smith {
104747c6ae99SBarry Smith   PetscErrorCode  ierr;
104847c6ae99SBarry Smith   PetscInt        i,Nc,N;
104947c6ae99SBarry Smith   ISColoringValue *color;
1050aa219208SBarry Smith   DMDALocalInfo   info;
105147c6ae99SBarry Smith   PetscScalar     *u,*g_u,*g_f,*f = 0,*p_u;
105247c6ae99SBarry Smith   ISColoring      iscoloring;
105347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
1054aa219208SBarry Smith   void            (*lf)(PetscInt*,DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*) =
1055aa219208SBarry Smith                   (void (*)(PetscInt*,DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*))*dd->adifor_lf;
105647c6ae99SBarry Smith 
105747c6ae99SBarry Smith   PetscFunctionBegin;
105894013140SBarry Smith   ierr = DMGetColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr);
105947c6ae99SBarry Smith   Nc   = iscoloring->n;
1060aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
106147c6ae99SBarry Smith   N    = info.gxm*info.gym*info.gzm*info.dof;
106247c6ae99SBarry Smith 
106347c6ae99SBarry Smith   /* get space for derivative objects.  */
106447c6ae99SBarry Smith   ierr  = PetscMalloc(Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar),&g_u);CHKERRQ(ierr);
106547c6ae99SBarry Smith   ierr  = PetscMemzero(g_u,Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar));CHKERRQ(ierr);
106647c6ae99SBarry Smith   p_u   = g_u;
106747c6ae99SBarry Smith   color = iscoloring->colors;
106847c6ae99SBarry Smith   for (i=0; i<N; i++) {
106947c6ae99SBarry Smith     p_u[*color++] = 1.0;
107047c6ae99SBarry Smith     p_u          += Nc;
107147c6ae99SBarry Smith   }
107247c6ae99SBarry Smith   ierr = ISColoringDestroy(iscoloring);CHKERRQ(ierr);
107347c6ae99SBarry 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);
107447c6ae99SBarry Smith 
107547c6ae99SBarry Smith   /* Seed the input array g_u with coloring information */
107647c6ae99SBarry Smith 
107747c6ae99SBarry Smith   ierr = VecGetArray(vu,&u);CHKERRQ(ierr);
107847c6ae99SBarry Smith   (lf)(&Nc,&info,u,g_u,&Nc,f,g_f,&Nc,w,&ierr);CHKERRQ(ierr);
107947c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&u);CHKERRQ(ierr);
108047c6ae99SBarry Smith 
108147c6ae99SBarry Smith   /* stick the values into the matrix */
108247c6ae99SBarry Smith   /* PetscScalarView(Nc*info.xm*info.ym,g_f,0); */
108347c6ae99SBarry Smith   ierr = MatSetValuesAdifor(J,Nc,g_f);CHKERRQ(ierr);
108447c6ae99SBarry Smith 
108547c6ae99SBarry Smith   /* return space for derivative objects.  */
108647c6ae99SBarry Smith   ierr = PetscFree(g_u);CHKERRQ(ierr);
108747c6ae99SBarry Smith   ierr = PetscFree2(g_f,f);CHKERRQ(ierr);
108847c6ae99SBarry Smith   PetscFunctionReturn(0);
108947c6ae99SBarry Smith }
109047c6ae99SBarry Smith 
109147c6ae99SBarry Smith #undef __FUNCT__
1092aa219208SBarry Smith #define __FUNCT__ "DMDAFormJacobianLocal"
109347c6ae99SBarry Smith /*@C
1094aa219208SBarry Smith    DMDAFormjacobianLocal - This is a universal Jacobian evaluation routine for
10959a42bb27SBarry Smith    a local DM function.
109647c6ae99SBarry Smith 
1097aa219208SBarry Smith    Collective on DMDA
109847c6ae99SBarry Smith 
109947c6ae99SBarry Smith    Input Parameters:
11009a42bb27SBarry Smith +  da - the DM context
110147c6ae99SBarry Smith .  func - The local function
110247c6ae99SBarry Smith .  X - input vector
110347c6ae99SBarry Smith .  J - Jacobian matrix
110447c6ae99SBarry Smith -  ctx - A user context
110547c6ae99SBarry Smith 
110647c6ae99SBarry Smith    Level: intermediate
110747c6ae99SBarry Smith 
1108aa219208SBarry Smith .seealso: DMDASetLocalFunction(), DMDASetLocalJacobian(), DMDASetLocalAdicFunction(), DMDASetLocalAdicMFFunction(),
110947c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
111047c6ae99SBarry Smith 
111147c6ae99SBarry Smith @*/
11127087cfbeSBarry Smith PetscErrorCode  DMDAFormJacobianLocal(DM da, DMDALocalFunction1 func, Vec X, Mat J, void *ctx)
111347c6ae99SBarry Smith {
111447c6ae99SBarry Smith   Vec            localX;
1115aa219208SBarry Smith   DMDALocalInfo  info;
111647c6ae99SBarry Smith   void           *u;
111747c6ae99SBarry Smith   PetscErrorCode ierr;
111847c6ae99SBarry Smith 
111947c6ae99SBarry Smith   PetscFunctionBegin;
11209a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
112147c6ae99SBarry Smith   /*
112247c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
11239a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
112447c6ae99SBarry Smith   */
11259a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
11269a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
1127aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
1128aa219208SBarry Smith   ierr = DMDAVecGetArray(da,localX,&u);CHKERRQ(ierr);
112939d508bbSBarry Smith   ierr = (*func)(&info,u,J,ctx);CHKERRQ(ierr);
1130aa219208SBarry Smith   ierr = DMDAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
11319a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
113247c6ae99SBarry Smith   PetscFunctionReturn(0);
113347c6ae99SBarry Smith }
113447c6ae99SBarry Smith 
113547c6ae99SBarry Smith #undef __FUNCT__
1136aa219208SBarry Smith #define __FUNCT__ "DMDAMultiplyByJacobian1WithAD"
113747c6ae99SBarry Smith /*@C
1138aa219208SBarry Smith     DMDAMultiplyByJacobian1WithAD - Applies a Jacobian function supplied by ADIFOR or ADIC
1139aa219208SBarry Smith     to a vector on each processor that shares a DMDA.
114047c6ae99SBarry Smith 
114147c6ae99SBarry Smith    Input Parameters:
11429a42bb27SBarry Smith +    da - the DM that defines the grid
114347c6ae99SBarry Smith .    vu - Jacobian is computed at this point (ghosted)
114447c6ae99SBarry Smith .    v - product is done on this vector (ghosted)
114547c6ae99SBarry Smith .    fu - output vector = J(vu)*v (not ghosted)
114647c6ae99SBarry Smith -    w - any user data
114747c6ae99SBarry Smith 
114847c6ae99SBarry Smith     Notes:
114947c6ae99SBarry Smith     This routine does NOT do ghost updates on vu and v upon entry.
115047c6ae99SBarry Smith 
1151aa219208SBarry Smith     Automatically calls DMDAMultiplyByJacobian1WithAdifor() or DMDAMultiplyByJacobian1WithAdic()
1152aa219208SBarry Smith     depending on whether DMDASetLocalAdicMFFunction() or DMDASetLocalAdiforMFFunction() was called.
115347c6ae99SBarry Smith 
115447c6ae99SBarry Smith    Level: advanced
115547c6ae99SBarry Smith 
1156aa219208SBarry Smith .seealso: DMDAFormFunction1(), DMDAMultiplyByJacobian1WithAdifor(), DMDAMultiplyByJacobian1WithAdic()
115747c6ae99SBarry Smith 
115847c6ae99SBarry Smith @*/
11597087cfbeSBarry Smith PetscErrorCode  DMDAMultiplyByJacobian1WithAD(DM da,Vec u,Vec v,Vec f,void *w)
116047c6ae99SBarry Smith {
116147c6ae99SBarry Smith   PetscErrorCode ierr;
116247c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
116347c6ae99SBarry Smith 
116447c6ae99SBarry Smith   PetscFunctionBegin;
116547c6ae99SBarry Smith   if (dd->adicmf_lf) {
116647c6ae99SBarry Smith #if defined(PETSC_HAVE_ADIC)
1167aa219208SBarry Smith     ierr = DMDAMultiplyByJacobian1WithAdic(da,u,v,f,w);CHKERRQ(ierr);
116847c6ae99SBarry Smith #else
116947c6ae99SBarry Smith     SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP_SYS,"Requires ADIC to be installed and cannot use complex numbers");
117047c6ae99SBarry Smith #endif
117147c6ae99SBarry Smith   } else if (dd->adiformf_lf) {
1172aa219208SBarry Smith     ierr = DMDAMultiplyByJacobian1WithAdifor(da,u,v,f,w);CHKERRQ(ierr);
117347c6ae99SBarry Smith   } else {
1174aa219208SBarry Smith     SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ORDER,"Must call DMDASetLocalAdiforMFFunction() or DMDASetLocalAdicMFFunction() before using");
117547c6ae99SBarry Smith   }
117647c6ae99SBarry Smith   PetscFunctionReturn(0);
117747c6ae99SBarry Smith }
117847c6ae99SBarry Smith 
117947c6ae99SBarry Smith 
118047c6ae99SBarry Smith #undef __FUNCT__
1181aa219208SBarry Smith #define __FUNCT__ "DMDAMultiplyByJacobian1WithAdifor"
118247c6ae99SBarry Smith /*@C
1183aa219208SBarry Smith     DMDAMultiplyByJacobian1WithAdifor - Applies a ADIFOR provided Jacobian function on each processor that
11849a42bb27SBarry Smith         share a DM to a vector
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: Does NOT do ghost updates on vu and v upon entry
119447c6ae99SBarry Smith 
119547c6ae99SBarry Smith    Level: advanced
119647c6ae99SBarry Smith 
1197aa219208SBarry Smith .seealso: DMDAFormFunction1()
119847c6ae99SBarry Smith 
119947c6ae99SBarry Smith @*/
12007087cfbeSBarry Smith PetscErrorCode  DMDAMultiplyByJacobian1WithAdifor(DM da,Vec u,Vec v,Vec f,void *w)
120147c6ae99SBarry Smith {
120247c6ae99SBarry Smith   PetscErrorCode ierr;
120347c6ae99SBarry Smith   PetscScalar    *au,*av,*af,*awork;
120447c6ae99SBarry Smith   Vec            work;
1205aa219208SBarry Smith   DMDALocalInfo  info;
120647c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
1207aa219208SBarry Smith   void           (*lf)(DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*) =
1208aa219208SBarry Smith                  (void (*)(DMDALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*))*dd->adiformf_lf;
120947c6ae99SBarry Smith 
121047c6ae99SBarry Smith   PetscFunctionBegin;
1211aa219208SBarry Smith   ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
121247c6ae99SBarry Smith 
12139a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&work);CHKERRQ(ierr);
121447c6ae99SBarry Smith   ierr = VecGetArray(u,&au);CHKERRQ(ierr);
121547c6ae99SBarry Smith   ierr = VecGetArray(v,&av);CHKERRQ(ierr);
121647c6ae99SBarry Smith   ierr = VecGetArray(f,&af);CHKERRQ(ierr);
121747c6ae99SBarry Smith   ierr = VecGetArray(work,&awork);CHKERRQ(ierr);
121847c6ae99SBarry Smith   (lf)(&info,au,av,awork,af,w,&ierr);CHKERRQ(ierr);
121947c6ae99SBarry Smith   ierr = VecRestoreArray(u,&au);CHKERRQ(ierr);
122047c6ae99SBarry Smith   ierr = VecRestoreArray(v,&av);CHKERRQ(ierr);
122147c6ae99SBarry Smith   ierr = VecRestoreArray(f,&af);CHKERRQ(ierr);
122247c6ae99SBarry Smith   ierr = VecRestoreArray(work,&awork);CHKERRQ(ierr);
12239a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&work);CHKERRQ(ierr);
122447c6ae99SBarry Smith 
122547c6ae99SBarry Smith   PetscFunctionReturn(0);
122647c6ae99SBarry Smith }
122747c6ae99SBarry Smith 
122847c6ae99SBarry Smith #undef __FUNCT__
12299a42bb27SBarry Smith #define __FUNCT__ "DMSetUp_DA_2D"
12307087cfbeSBarry Smith PetscErrorCode  DMSetUp_DA_2D(DM da)
123147c6ae99SBarry Smith {
123247c6ae99SBarry Smith   DM_DA                  *dd = (DM_DA*)da->data;
123347c6ae99SBarry Smith   const PetscInt         M            = dd->M;
123447c6ae99SBarry Smith   const PetscInt         N            = dd->N;
123547c6ae99SBarry Smith   PetscInt               m            = dd->m;
123647c6ae99SBarry Smith   PetscInt               n            = dd->n;
123747c6ae99SBarry Smith   const PetscInt         dof          = dd->w;
123847c6ae99SBarry Smith   const PetscInt         s            = dd->s;
12391321219cSEthan Coon   const DMDABoundaryType bx         = dd->bx;
12401321219cSEthan Coon   const DMDABoundaryType by         = dd->by;
1241aa219208SBarry Smith   const DMDAStencilType  stencil_type = dd->stencil_type;
124247c6ae99SBarry Smith   PetscInt               *lx           = dd->lx;
124347c6ae99SBarry Smith   PetscInt               *ly           = dd->ly;
124447c6ae99SBarry Smith   MPI_Comm               comm;
124547c6ae99SBarry Smith   PetscMPIInt            rank,size;
1246ce00eea3SSatish Balay   PetscInt               xs,xe,ys,ye,x,y,Xs,Xe,Ys,Ye,start,end,IXs,IXe,IYs,IYe;
1247ce00eea3SSatish Balay   PetscInt               up,down,left,right,i,n0,n1,n2,n3,n5,n6,n7,n8,*idx,nn,*idx_cpy;
1248ce00eea3SSatish Balay   const PetscInt         *idx_full;
1249db87c5ecSEthan Coon   PetscInt               xbase,*bases,*ldims,j,x_t,y_t,s_t,base,count;
125047c6ae99SBarry Smith   PetscInt               s_x,s_y; /* s proportionalized to w */
125147c6ae99SBarry Smith   PetscInt               sn0 = 0,sn2 = 0,sn6 = 0,sn8 = 0;
125247c6ae99SBarry Smith   Vec                    local,global;
125347c6ae99SBarry Smith   VecScatter             ltog,gtol;
1254ce00eea3SSatish Balay   IS                     to,from,ltogis;
125547c6ae99SBarry Smith   PetscErrorCode         ierr;
125647c6ae99SBarry Smith 
125747c6ae99SBarry Smith   PetscFunctionBegin;
125847c6ae99SBarry Smith   ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr);
125947c6ae99SBarry Smith 
126047c6ae99SBarry Smith   if (dof < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof);
126147c6ae99SBarry Smith   if (s < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s);
126247c6ae99SBarry Smith 
126347c6ae99SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
126447c6ae99SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
126547c6ae99SBarry Smith 
126647c6ae99SBarry Smith   dd->dim         = 2;
126747c6ae99SBarry Smith   ierr = PetscMalloc(dof*sizeof(char*),&dd->fieldname);CHKERRQ(ierr);
126847c6ae99SBarry Smith   ierr = PetscMemzero(dd->fieldname,dof*sizeof(char*));CHKERRQ(ierr);
126947c6ae99SBarry Smith 
127047c6ae99SBarry Smith   if (m != PETSC_DECIDE) {
127147c6ae99SBarry Smith     if (m < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in X direction: %D",m);
127247c6ae99SBarry Smith     else if (m > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in X direction: %D %d",m,size);
127347c6ae99SBarry Smith   }
127447c6ae99SBarry Smith   if (n != PETSC_DECIDE) {
127547c6ae99SBarry Smith     if (n < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Y direction: %D",n);
127647c6ae99SBarry Smith     else if (n > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Y direction: %D %d",n,size);
127747c6ae99SBarry Smith   }
127847c6ae99SBarry Smith 
127947c6ae99SBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
128047c6ae99SBarry Smith     if (n != PETSC_DECIDE) {
128147c6ae99SBarry Smith       m = size/n;
128247c6ae99SBarry Smith     } else if (m != PETSC_DECIDE) {
128347c6ae99SBarry Smith       n = size/m;
128447c6ae99SBarry Smith     } else {
128547c6ae99SBarry Smith       /* try for squarish distribution */
128647c6ae99SBarry Smith       m = (PetscInt)(0.5 + sqrt(((double)M)*((double)size)/((double)N)));
128747c6ae99SBarry Smith       if (!m) m = 1;
128847c6ae99SBarry Smith       while (m > 0) {
128947c6ae99SBarry Smith 	n = size/m;
129047c6ae99SBarry Smith 	if (m*n == size) break;
129147c6ae99SBarry Smith 	m--;
129247c6ae99SBarry Smith       }
129347c6ae99SBarry Smith       if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;}
129447c6ae99SBarry Smith     }
129547c6ae99SBarry 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 ");
129647c6ae99SBarry Smith   } else if (m*n != size) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Given Bad partition");
129747c6ae99SBarry Smith 
129847c6ae99SBarry Smith   if (M < m) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in x direction is too fine! %D %D",M,m);
129947c6ae99SBarry Smith   if (N < n) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in y direction is too fine! %D %D",N,n);
130047c6ae99SBarry Smith 
130147c6ae99SBarry Smith   /*
130247c6ae99SBarry Smith      Determine locally owned region
130347c6ae99SBarry Smith      xs is the first local node number, x is the number of local nodes
130447c6ae99SBarry Smith   */
130547c6ae99SBarry Smith   if (!lx) {
130647c6ae99SBarry Smith     ierr = PetscMalloc(m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr);
130747c6ae99SBarry Smith     lx = dd->lx;
130847c6ae99SBarry Smith     for (i=0; i<m; i++) {
130947c6ae99SBarry Smith       lx[i] = M/m + ((M % m) > i);
131047c6ae99SBarry Smith     }
131147c6ae99SBarry Smith   }
131247c6ae99SBarry Smith   x  = lx[rank % m];
131347c6ae99SBarry Smith   xs = 0;
131447c6ae99SBarry Smith   for (i=0; i<(rank % m); i++) {
131547c6ae99SBarry Smith     xs += lx[i];
131647c6ae99SBarry Smith   }
131747c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
131847c6ae99SBarry Smith   left = xs;
131947c6ae99SBarry Smith   for (i=(rank % m); i<m; i++) {
132047c6ae99SBarry Smith     left += lx[i];
132147c6ae99SBarry Smith   }
132247c6ae99SBarry 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);
132347c6ae99SBarry Smith #endif
132447c6ae99SBarry Smith 
132547c6ae99SBarry Smith   /*
132647c6ae99SBarry Smith      Determine locally owned region
132747c6ae99SBarry Smith      ys is the first local node number, y is the number of local nodes
132847c6ae99SBarry Smith   */
132947c6ae99SBarry Smith   if (!ly) {
133047c6ae99SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr);
133147c6ae99SBarry Smith     ly = dd->ly;
133247c6ae99SBarry Smith     for (i=0; i<n; i++) {
133347c6ae99SBarry Smith       ly[i] = N/n + ((N % n) > i);
133447c6ae99SBarry Smith     }
133547c6ae99SBarry Smith   }
133647c6ae99SBarry Smith   y  = ly[rank/m];
133747c6ae99SBarry Smith   ys = 0;
133847c6ae99SBarry Smith   for (i=0; i<(rank/m); i++) {
133947c6ae99SBarry Smith     ys += ly[i];
134047c6ae99SBarry Smith   }
134147c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
134247c6ae99SBarry Smith   left = ys;
134347c6ae99SBarry Smith   for (i=(rank/m); i<n; i++) {
134447c6ae99SBarry Smith     left += ly[i];
134547c6ae99SBarry Smith   }
134647c6ae99SBarry 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);
134747c6ae99SBarry Smith #endif
134847c6ae99SBarry Smith 
134947c6ae99SBarry Smith   if (x < s) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local x-width of domain x %D is smaller than stencil width s %D",x,s);
135047c6ae99SBarry Smith   if (y < s) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local y-width of domain y %D is smaller than stencil width s %D",y,s);
135147c6ae99SBarry Smith   xe = xs + x;
135247c6ae99SBarry Smith   ye = ys + y;
135347c6ae99SBarry Smith 
1354ce00eea3SSatish Balay   /* determine ghost region (Xs) and region scattered into (IXs)  */
135547c6ae99SBarry Smith   /* Assume No Periodicity */
1356ce00eea3SSatish Balay   if (xs-s > 0) { Xs = xs - s; IXs = xs - s; } else { Xs = 0; IXs = 0; }
1357ce00eea3SSatish Balay   if (xe+s <= M) { Xe = xe + s; IXe = xe + s; } else { Xe = M; IXe = M; }
1358ce00eea3SSatish Balay   if (ys-s > 0) { Ys = ys - s; IYs = ys - s; } else { Ys = 0; IYs = 0; }
1359ce00eea3SSatish Balay   if (ye+s <= N) { Ye = ye + s; IYe = ye + s; } else { Ye = N; IYe = N; }
136047c6ae99SBarry Smith 
1361ce00eea3SSatish Balay   /* fix for periodicity/ghosted */
13621321219cSEthan Coon   if (bx) { Xs = xs - s; Xe = xe + s; }
13631321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) { IXs = xs - s; IXe = xe + s; }
13641321219cSEthan Coon   if (by) { Ys = ys - s; Ye = ye + s; }
13651321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) { IYs = ys - s; IYe = ye + s; }
136647c6ae99SBarry Smith 
136747c6ae99SBarry Smith   /* Resize all X parameters to reflect w */
1368ce00eea3SSatish Balay   s_x = s;
136947c6ae99SBarry Smith   s_y = s;
137047c6ae99SBarry Smith 
137147c6ae99SBarry Smith   /* determine starting point of each processor */
137247c6ae99SBarry Smith   nn    = x*y;
137347c6ae99SBarry Smith   ierr  = PetscMalloc2(size+1,PetscInt,&bases,size,PetscInt,&ldims);CHKERRQ(ierr);
137447c6ae99SBarry Smith   ierr  = MPI_Allgather(&nn,1,MPIU_INT,ldims,1,MPIU_INT,comm);CHKERRQ(ierr);
137547c6ae99SBarry Smith   bases[0] = 0;
137647c6ae99SBarry Smith   for (i=1; i<=size; i++) {
137747c6ae99SBarry Smith     bases[i] = ldims[i-1];
137847c6ae99SBarry Smith   }
137947c6ae99SBarry Smith   for (i=1; i<=size; i++) {
138047c6ae99SBarry Smith     bases[i] += bases[i-1];
138147c6ae99SBarry Smith   }
1382ce00eea3SSatish Balay   base = bases[rank]*dof;
138347c6ae99SBarry Smith 
138447c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
1385ce00eea3SSatish Balay   dd->Nlocal = x*y*dof;
138647c6ae99SBarry Smith   ierr = VecCreateMPIWithArray(comm,dd->Nlocal,PETSC_DECIDE,0,&global);CHKERRQ(ierr);
138747c6ae99SBarry Smith   ierr = VecSetBlockSize(global,dof);CHKERRQ(ierr);
1388ce00eea3SSatish Balay   dd->nlocal = (Xe-Xs)*(Ye-Ys)*dof;
138947c6ae99SBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dd->nlocal,0,&local);CHKERRQ(ierr);
139047c6ae99SBarry Smith   ierr = VecSetBlockSize(local,dof);CHKERRQ(ierr);
139147c6ae99SBarry Smith 
139247c6ae99SBarry Smith   /* generate appropriate vector scatters */
139347c6ae99SBarry Smith   /* local to global inserts non-ghost point region into global */
139447c6ae99SBarry Smith   ierr = VecGetOwnershipRange(global,&start,&end);CHKERRQ(ierr);
1395ce00eea3SSatish Balay   ierr = ISCreateStride(comm,x*y*dof,start,1,&to);CHKERRQ(ierr);
139647c6ae99SBarry Smith 
1397db87c5ecSEthan Coon   count = x*y;
1398ce00eea3SSatish Balay   ierr = PetscMalloc(x*y*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1399ce00eea3SSatish Balay   left = xs - Xs; right = left + x;
1400ce00eea3SSatish Balay   down = ys - Ys; up = down + y;
140147c6ae99SBarry Smith   count = 0;
140247c6ae99SBarry Smith   for (i=down; i<up; i++) {
1403ce00eea3SSatish Balay     for (j=left; j<right; j++) {
1404ce00eea3SSatish Balay       idx[count++] = i*(Xe-Xs) + j;
140547c6ae99SBarry Smith     }
140647c6ae99SBarry Smith   }
140747c6ae99SBarry Smith 
1408ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr);
140947c6ae99SBarry Smith   ierr = VecScatterCreate(local,from,global,to,&ltog);CHKERRQ(ierr);
141047c6ae99SBarry Smith   ierr = PetscLogObjectParent(dd,ltog);CHKERRQ(ierr);
141147c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
141247c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
141347c6ae99SBarry Smith 
1414ce00eea3SSatish Balay   /* global to local must include ghost points within the domain,
1415ce00eea3SSatish Balay      but not ghost points outside the domain that aren't periodic */
1416aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_BOX) {
1417db87c5ecSEthan Coon     count = (IXe-IXs)*(IYe-IYs);
1418db87c5ecSEthan Coon     ierr  = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1419ce00eea3SSatish Balay 
1420ce00eea3SSatish Balay     left = IXs - Xs; right = left + (IXe-IXs);
1421ce00eea3SSatish Balay     down = IYs - Ys; up = down + (IYe-IYs);
1422ce00eea3SSatish Balay     count = 0;
1423ce00eea3SSatish Balay     for (i=down; i<up; i++) {
1424ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1425ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
1426ce00eea3SSatish Balay       }
1427ce00eea3SSatish Balay     }
1428ce00eea3SSatish Balay     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
1429ce00eea3SSatish Balay 
143047c6ae99SBarry Smith   } else {
143147c6ae99SBarry Smith     /* must drop into cross shape region */
143247c6ae99SBarry Smith     /*       ---------|
143347c6ae99SBarry Smith             |  top    |
1434ce00eea3SSatish Balay          |---         ---| up
143547c6ae99SBarry Smith          |   middle      |
143647c6ae99SBarry Smith          |               |
1437ce00eea3SSatish Balay          ----         ---- down
143847c6ae99SBarry Smith             | bottom  |
143947c6ae99SBarry Smith             -----------
144047c6ae99SBarry Smith          Xs xs        xe Xe */
1441db87c5ecSEthan Coon     count = (ys-IYs)*x + y*(IXe-IXs) + (IYe-ye)*x;
1442db87c5ecSEthan Coon     ierr  = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1443ce00eea3SSatish Balay 
1444ce00eea3SSatish Balay     left = xs - Xs; right = left + x;
1445ce00eea3SSatish Balay     down = ys - Ys; up = down + y;
144647c6ae99SBarry Smith     count = 0;
1447ce00eea3SSatish Balay     /* bottom */
1448ce00eea3SSatish Balay     for (i=(IYs-Ys); i<down; i++) {
1449ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1450ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
145147c6ae99SBarry Smith       }
145247c6ae99SBarry Smith     }
145347c6ae99SBarry Smith     /* middle */
145447c6ae99SBarry Smith     for (i=down; i<up; i++) {
1455ce00eea3SSatish Balay       for (j=(IXs-Xs); j<(IXe-Xs); j++) {
1456ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
145747c6ae99SBarry Smith       }
145847c6ae99SBarry Smith     }
145947c6ae99SBarry Smith     /* top */
1460ce00eea3SSatish Balay     for (i=up; i<up+IYe-ye; i++) {
1461ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1462ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
146347c6ae99SBarry Smith       }
146447c6ae99SBarry Smith     }
146547c6ae99SBarry Smith     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
146647c6ae99SBarry Smith   }
146747c6ae99SBarry Smith 
146847c6ae99SBarry Smith 
146947c6ae99SBarry Smith   /* determine who lies on each side of us stored in    n6 n7 n8
147047c6ae99SBarry Smith                                                         n3    n5
147147c6ae99SBarry Smith                                                         n0 n1 n2
147247c6ae99SBarry Smith   */
147347c6ae99SBarry Smith 
147447c6ae99SBarry Smith   /* Assume the Non-Periodic Case */
147547c6ae99SBarry Smith   n1 = rank - m;
147647c6ae99SBarry Smith   if (rank % m) {
147747c6ae99SBarry Smith     n0 = n1 - 1;
147847c6ae99SBarry Smith   } else {
147947c6ae99SBarry Smith     n0 = -1;
148047c6ae99SBarry Smith   }
148147c6ae99SBarry Smith   if ((rank+1) % m) {
148247c6ae99SBarry Smith     n2 = n1 + 1;
148347c6ae99SBarry Smith     n5 = rank + 1;
148447c6ae99SBarry Smith     n8 = rank + m + 1; if (n8 >= m*n) n8 = -1;
148547c6ae99SBarry Smith   } else {
148647c6ae99SBarry Smith     n2 = -1; n5 = -1; n8 = -1;
148747c6ae99SBarry Smith   }
148847c6ae99SBarry Smith   if (rank % m) {
148947c6ae99SBarry Smith     n3 = rank - 1;
149047c6ae99SBarry Smith     n6 = n3 + m; if (n6 >= m*n) n6 = -1;
149147c6ae99SBarry Smith   } else {
149247c6ae99SBarry Smith     n3 = -1; n6 = -1;
149347c6ae99SBarry Smith   }
149447c6ae99SBarry Smith   n7 = rank + m; if (n7 >= m*n) n7 = -1;
149547c6ae99SBarry Smith 
14961321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC && by == DMDA_BOUNDARY_PERIODIC) {
149747c6ae99SBarry Smith   /* Modify for Periodic Cases */
149847c6ae99SBarry Smith     /* Handle all four corners */
149947c6ae99SBarry Smith     if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m-1;
150047c6ae99SBarry Smith     if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0;
150147c6ae99SBarry Smith     if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size-m;
150247c6ae99SBarry Smith     if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size-1;
150347c6ae99SBarry Smith 
150447c6ae99SBarry Smith     /* Handle Top and Bottom Sides */
150547c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n-1);
150647c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n-1);
150747c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
150847c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
150947c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
151047c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
151147c6ae99SBarry Smith 
151247c6ae99SBarry Smith     /* Handle Left and Right Sides */
151347c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m-1);
151447c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m-1);
151547c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
151647c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
151747c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
151847c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
15191321219cSEthan Coon   } else if (by == DMDA_BOUNDARY_PERIODIC) {  /* Handle Top and Bottom Sides */
1520ce00eea3SSatish Balay     if (n1 < 0) n1 = rank + m * (n-1);
1521ce00eea3SSatish Balay     if (n7 < 0) n7 = rank - m * (n-1);
1522ce00eea3SSatish Balay     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
1523ce00eea3SSatish Balay     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
1524ce00eea3SSatish Balay     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
1525ce00eea3SSatish Balay     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
15261321219cSEthan Coon   } else if (bx == DMDA_BOUNDARY_PERIODIC) { /* Handle Left and Right Sides */
1527ce00eea3SSatish Balay     if (n3 < 0) n3 = rank + (m-1);
1528ce00eea3SSatish Balay     if (n5 < 0) n5 = rank - (m-1);
1529ce00eea3SSatish Balay     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
1530ce00eea3SSatish Balay     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
1531ce00eea3SSatish Balay     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
1532ce00eea3SSatish Balay     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
153347c6ae99SBarry Smith   }
1534ce00eea3SSatish Balay 
153547c6ae99SBarry Smith   ierr = PetscMalloc(9*sizeof(PetscInt),&dd->neighbors);CHKERRQ(ierr);
153647c6ae99SBarry Smith   dd->neighbors[0] = n0;
153747c6ae99SBarry Smith   dd->neighbors[1] = n1;
153847c6ae99SBarry Smith   dd->neighbors[2] = n2;
153947c6ae99SBarry Smith   dd->neighbors[3] = n3;
154047c6ae99SBarry Smith   dd->neighbors[4] = rank;
154147c6ae99SBarry Smith   dd->neighbors[5] = n5;
154247c6ae99SBarry Smith   dd->neighbors[6] = n6;
154347c6ae99SBarry Smith   dd->neighbors[7] = n7;
154447c6ae99SBarry Smith   dd->neighbors[8] = n8;
154547c6ae99SBarry Smith 
1546aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
154747c6ae99SBarry Smith     /* save corner processor numbers */
154847c6ae99SBarry Smith     sn0 = n0; sn2 = n2; sn6 = n6; sn8 = n8;
154947c6ae99SBarry Smith     n0 = n2 = n6 = n8 = -1;
155047c6ae99SBarry Smith   }
155147c6ae99SBarry Smith 
1552ce00eea3SSatish Balay   ierr = PetscMalloc((Xe-Xs)*(Ye-Ys)*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1553ce00eea3SSatish Balay   ierr = PetscLogObjectMemory(da,(Xe-Xs)*(Ye-Ys)*sizeof(PetscInt));CHKERRQ(ierr);
155447c6ae99SBarry Smith 
1555ce00eea3SSatish Balay   nn = 0;
155647c6ae99SBarry Smith   xbase = bases[rank];
155747c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
155847c6ae99SBarry Smith     if (n0 >= 0) { /* left below */
1559ce00eea3SSatish Balay       x_t = lx[n0 % m];
156047c6ae99SBarry Smith       y_t = ly[(n0/m)];
156147c6ae99SBarry Smith       s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
156247c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
156347c6ae99SBarry Smith     }
156447c6ae99SBarry Smith     if (n1 >= 0) { /* directly below */
156547c6ae99SBarry Smith       x_t = x;
156647c6ae99SBarry Smith       y_t = ly[(n1/m)];
156747c6ae99SBarry Smith       s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
156847c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
156947c6ae99SBarry Smith     }
157047c6ae99SBarry Smith     if (n2 >= 0) { /* right below */
1571ce00eea3SSatish Balay       x_t = lx[n2 % m];
157247c6ae99SBarry Smith       y_t = ly[(n2/m)];
157347c6ae99SBarry Smith       s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
157447c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
157547c6ae99SBarry Smith     }
157647c6ae99SBarry Smith   }
157747c6ae99SBarry Smith 
157847c6ae99SBarry Smith   for (i=0; i<y; i++) {
157947c6ae99SBarry Smith     if (n3 >= 0) { /* directly left */
1580ce00eea3SSatish Balay       x_t = lx[n3 % m];
158147c6ae99SBarry Smith       /* y_t = y; */
158247c6ae99SBarry Smith       s_t = bases[n3] + (i+1)*x_t - s_x;
158347c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
158447c6ae99SBarry Smith     }
158547c6ae99SBarry Smith 
158647c6ae99SBarry Smith     for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
158747c6ae99SBarry Smith 
158847c6ae99SBarry Smith     if (n5 >= 0) { /* directly right */
1589ce00eea3SSatish Balay       x_t = lx[n5 % m];
159047c6ae99SBarry Smith       /* y_t = y; */
159147c6ae99SBarry Smith       s_t = bases[n5] + (i)*x_t;
159247c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
159347c6ae99SBarry Smith     }
159447c6ae99SBarry Smith   }
159547c6ae99SBarry Smith 
159647c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
159747c6ae99SBarry Smith     if (n6 >= 0) { /* left above */
1598ce00eea3SSatish Balay       x_t = lx[n6 % m];
159947c6ae99SBarry Smith       /* y_t = ly[(n6/m)]; */
160047c6ae99SBarry Smith       s_t = bases[n6] + (i)*x_t - s_x;
160147c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
160247c6ae99SBarry Smith     }
160347c6ae99SBarry Smith     if (n7 >= 0) { /* directly above */
160447c6ae99SBarry Smith       x_t = x;
160547c6ae99SBarry Smith       /* y_t = ly[(n7/m)]; */
160647c6ae99SBarry Smith       s_t = bases[n7] + (i-1)*x_t;
160747c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
160847c6ae99SBarry Smith     }
160947c6ae99SBarry Smith     if (n8 >= 0) { /* right above */
1610ce00eea3SSatish Balay       x_t = lx[n8 % m];
161147c6ae99SBarry Smith       /* y_t = ly[(n8/m)]; */
161247c6ae99SBarry Smith       s_t = bases[n8] + (i-1)*x_t;
161347c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
161447c6ae99SBarry Smith     }
161547c6ae99SBarry Smith   }
161647c6ae99SBarry Smith 
1617ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
161847c6ae99SBarry Smith   ierr = VecScatterCreate(global,from,local,to,&gtol);CHKERRQ(ierr);
161947c6ae99SBarry Smith   ierr = PetscLogObjectParent(da,gtol);CHKERRQ(ierr);
162047c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
162147c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
162247c6ae99SBarry Smith 
1623aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
1624ce00eea3SSatish Balay     n0 = sn0; n2 = sn2; n6 = sn6; n8 = sn8;
1625ce00eea3SSatish Balay   }
1626ce00eea3SSatish Balay 
1627ce00eea3SSatish Balay   if ((stencil_type == DMDA_STENCIL_STAR) ||
16281321219cSEthan Coon       (bx && bx != DMDA_BOUNDARY_PERIODIC) ||
16291321219cSEthan Coon       (by && by != DMDA_BOUNDARY_PERIODIC)) {
163047c6ae99SBarry Smith     /*
163147c6ae99SBarry Smith         Recompute the local to global mappings, this time keeping the
1632ce00eea3SSatish Balay       information about the cross corner processor numbers and any ghosted
1633ce00eea3SSatish Balay       but not periodic indices.
163447c6ae99SBarry Smith     */
163547c6ae99SBarry Smith     nn = 0;
163647c6ae99SBarry Smith     xbase = bases[rank];
163747c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
163847c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
1639ce00eea3SSatish Balay         x_t = lx[n0 % m];
164047c6ae99SBarry Smith         y_t = ly[(n0/m)];
164147c6ae99SBarry Smith         s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
164247c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1643ce00eea3SSatish Balay       } else if (xs-Xs > 0 && ys-Ys > 0) {
1644ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
164547c6ae99SBarry Smith       }
164647c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
164747c6ae99SBarry Smith         x_t = x;
164847c6ae99SBarry Smith         y_t = ly[(n1/m)];
164947c6ae99SBarry Smith         s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
165047c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1651ce00eea3SSatish Balay       } else if (ys-Ys > 0) {
1652ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
165347c6ae99SBarry Smith       }
165447c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
1655ce00eea3SSatish Balay         x_t = lx[n2 % m];
165647c6ae99SBarry Smith         y_t = ly[(n2/m)];
165747c6ae99SBarry Smith         s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
165847c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1659ce00eea3SSatish Balay       } else if (Xe-xe> 0 && ys-Ys > 0) {
1660ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
166147c6ae99SBarry Smith       }
166247c6ae99SBarry Smith     }
166347c6ae99SBarry Smith 
166447c6ae99SBarry Smith     for (i=0; i<y; i++) {
166547c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
1666ce00eea3SSatish Balay         x_t = lx[n3 % m];
166747c6ae99SBarry Smith         /* y_t = y; */
166847c6ae99SBarry Smith         s_t = bases[n3] + (i+1)*x_t - s_x;
166947c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1670ce00eea3SSatish Balay       } else if (xs-Xs > 0) {
1671ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
167247c6ae99SBarry Smith       }
167347c6ae99SBarry Smith 
167447c6ae99SBarry Smith       for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
167547c6ae99SBarry Smith 
167647c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
1677ce00eea3SSatish Balay         x_t = lx[n5 % m];
167847c6ae99SBarry Smith         /* y_t = y; */
167947c6ae99SBarry Smith         s_t = bases[n5] + (i)*x_t;
168047c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1681ce00eea3SSatish Balay       } else if (Xe-xe > 0) {
1682ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
168347c6ae99SBarry Smith       }
168447c6ae99SBarry Smith     }
168547c6ae99SBarry Smith 
168647c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
168747c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
1688ce00eea3SSatish Balay         x_t = lx[n6 % m];
168947c6ae99SBarry Smith         /* y_t = ly[(n6/m)]; */
169047c6ae99SBarry Smith         s_t = bases[n6] + (i)*x_t - s_x;
169147c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1692ce00eea3SSatish Balay       } else if (xs-Xs > 0 && Ye-ye > 0) {
1693ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
169447c6ae99SBarry Smith       }
169547c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
169647c6ae99SBarry Smith         x_t = x;
169747c6ae99SBarry Smith         /* y_t = ly[(n7/m)]; */
169847c6ae99SBarry Smith         s_t = bases[n7] + (i-1)*x_t;
169947c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1700ce00eea3SSatish Balay       } else if (Ye-ye > 0) {
1701ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
170247c6ae99SBarry Smith       }
170347c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
1704ce00eea3SSatish Balay         x_t = lx[n8 % m];
170547c6ae99SBarry Smith         /* y_t = ly[(n8/m)]; */
170647c6ae99SBarry Smith         s_t = bases[n8] + (i-1)*x_t;
170747c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1708ce00eea3SSatish Balay       } else if (Xe-xe > 0 && Ye-ye > 0) {
1709ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
171047c6ae99SBarry Smith       }
171147c6ae99SBarry Smith     }
171247c6ae99SBarry Smith   }
1713ce00eea3SSatish Balay   /*
1714ce00eea3SSatish Balay      Set the local to global ordering in the global vector, this allows use
1715ce00eea3SSatish Balay      of VecSetValuesLocal().
1716ce00eea3SSatish Balay   */
1717ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_OWN_POINTER,&ltogis);CHKERRQ(ierr);
1718ce00eea3SSatish Balay   ierr = PetscMalloc(nn*dof*sizeof(PetscInt),&idx_cpy);CHKERRQ(ierr);
1719db87c5ecSEthan Coon   ierr = PetscLogObjectMemory(da,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);
1720ce00eea3SSatish Balay   ierr = ISGetIndices(ltogis, &idx_full);
1721ce00eea3SSatish Balay   ierr = PetscMemcpy(idx_cpy,idx_full,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);
1722ce00eea3SSatish Balay   ierr = ISRestoreIndices(ltogis, &idx_full);
1723ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingCreateIS(ltogis,&da->ltogmap);CHKERRQ(ierr);
1724ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
1725ce00eea3SSatish Balay   ierr = ISDestroy(ltogis);CHKERRQ(ierr);
1726ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingBlock(da->ltogmap,dd->w,&da->ltogmapb);CHKERRQ(ierr);
1727ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
172847c6ae99SBarry Smith 
1729ce00eea3SSatish Balay   ierr = PetscFree2(bases,ldims);CHKERRQ(ierr);
173047c6ae99SBarry Smith   dd->m  = m;  dd->n  = n;
1731ce00eea3SSatish Balay   /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
1732ce00eea3SSatish Balay   dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1;
1733ce00eea3SSatish Balay   dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1;
173447c6ae99SBarry Smith 
173547c6ae99SBarry Smith   ierr = VecDestroy(local);CHKERRQ(ierr);
173647c6ae99SBarry Smith   ierr = VecDestroy(global);CHKERRQ(ierr);
173747c6ae99SBarry Smith 
173847c6ae99SBarry Smith   dd->gtol      = gtol;
173947c6ae99SBarry Smith   dd->ltog      = ltog;
1740ce00eea3SSatish Balay   dd->idx       = idx_cpy;
1741ce00eea3SSatish Balay   dd->Nl        = nn*dof;
174247c6ae99SBarry Smith   dd->base      = base;
17439a42bb27SBarry Smith   da->ops->view = DMView_DA_2d;
174447c6ae99SBarry Smith   dd->ltol = PETSC_NULL;
174547c6ae99SBarry Smith   dd->ao   = PETSC_NULL;
174647c6ae99SBarry Smith 
174747c6ae99SBarry Smith   PetscFunctionReturn(0);
174847c6ae99SBarry Smith }
174947c6ae99SBarry Smith 
175047c6ae99SBarry Smith #undef __FUNCT__
1751aa219208SBarry Smith #define __FUNCT__ "DMDACreate2d"
175247c6ae99SBarry Smith /*@C
1753aa219208SBarry Smith    DMDACreate2d -  Creates an object that will manage the communication of  two-dimensional
175447c6ae99SBarry Smith    regular array data that is distributed across some processors.
175547c6ae99SBarry Smith 
175647c6ae99SBarry Smith    Collective on MPI_Comm
175747c6ae99SBarry Smith 
175847c6ae99SBarry Smith    Input Parameters:
175947c6ae99SBarry Smith +  comm - MPI communicator
17601321219cSEthan Coon .  bx,by - type of ghost nodes the array have.
17611321219cSEthan Coon          Use one of DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_GHOSTED, DMDA_BOUNDARY_PERIODIC.
1762aa219208SBarry Smith .  stencil_type - stencil type.  Use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
176347c6ae99SBarry 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
176447c6ae99SBarry Smith             from the command line with -da_grid_x <M> -da_grid_y <N>)
176547c6ae99SBarry Smith .  m,n - corresponding number of processors in each dimension
176647c6ae99SBarry Smith          (or PETSC_DECIDE to have calculated)
176747c6ae99SBarry Smith .  dof - number of degrees of freedom per node
176847c6ae99SBarry Smith .  s - stencil width
176947c6ae99SBarry Smith -  lx, ly - arrays containing the number of nodes in each cell along
177047c6ae99SBarry Smith            the x and y coordinates, or PETSC_NULL. If non-null, these
177147c6ae99SBarry Smith            must be of length as m and n, and the corresponding
177247c6ae99SBarry Smith            m and n cannot be PETSC_DECIDE. The sum of the lx[] entries
177347c6ae99SBarry Smith            must be M, and the sum of the ly[] entries must be N.
177447c6ae99SBarry Smith 
177547c6ae99SBarry Smith    Output Parameter:
177647c6ae99SBarry Smith .  da - the resulting distributed array object
177747c6ae99SBarry Smith 
177847c6ae99SBarry Smith    Options Database Key:
1779aa219208SBarry Smith +  -da_view - Calls DMView() at the conclusion of DMDACreate2d()
178047c6ae99SBarry Smith .  -da_grid_x <nx> - number of grid points in x direction, if M < 0
178147c6ae99SBarry Smith .  -da_grid_y <ny> - number of grid points in y direction, if N < 0
178247c6ae99SBarry Smith .  -da_processors_x <nx> - number of processors in x direction
178347c6ae99SBarry Smith .  -da_processors_y <ny> - number of processors in y direction
178447c6ae99SBarry Smith .  -da_refine_x - refinement ratio in x direction
178547c6ae99SBarry Smith -  -da_refine_y - refinement ratio in y direction
178647c6ae99SBarry Smith 
178747c6ae99SBarry Smith    Level: beginner
178847c6ae99SBarry Smith 
178947c6ae99SBarry Smith    Notes:
1790aa219208SBarry Smith    The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the
1791aa219208SBarry Smith    standard 5-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes
179247c6ae99SBarry Smith    the standard 9-pt stencil.
179347c6ae99SBarry Smith 
1794aa219208SBarry Smith    The array data itself is NOT stored in the DMDA, it is stored in Vec objects;
1795564755cdSBarry Smith    The appropriate vector objects can be obtained with calls to DMCreateGlobalVector()
1796564755cdSBarry Smith    and DMCreateLocalVector() and calls to VecDuplicate() if more are needed.
179747c6ae99SBarry Smith 
179847c6ae99SBarry Smith .keywords: distributed array, create, two-dimensional
179947c6ae99SBarry Smith 
1800aa219208SBarry Smith .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate3d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(),
1801aa219208SBarry Smith           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMDALocalToLocalBegin(), DMDALocalToLocalEnd(), DMDASetRefinementFactor(),
1802aa219208SBarry Smith           DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMDALoad(), DMDAGetOwnershipRanges()
180347c6ae99SBarry Smith 
180447c6ae99SBarry Smith @*/
18051321219cSEthan Coon PetscErrorCode  DMDACreate2d(MPI_Comm comm,DMDABoundaryType bx,DMDABoundaryType by,DMDAStencilType stencil_type,
18069a42bb27SBarry Smith                           PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da)
180747c6ae99SBarry Smith {
180847c6ae99SBarry Smith   PetscErrorCode ierr;
180947c6ae99SBarry Smith 
181047c6ae99SBarry Smith   PetscFunctionBegin;
1811aa219208SBarry Smith   ierr = DMDACreate(comm, da);CHKERRQ(ierr);
1812aa219208SBarry Smith   ierr = DMDASetDim(*da, 2);CHKERRQ(ierr);
1813aa219208SBarry Smith   ierr = DMDASetSizes(*da, M, N, 1);CHKERRQ(ierr);
1814aa219208SBarry Smith   ierr = DMDASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr);
1815755f258dSLisandro Dalcin   ierr = DMDASetBoundaryType(*da, bx, by, DMDA_BOUNDARY_NONE);CHKERRQ(ierr);
1816aa219208SBarry Smith   ierr = DMDASetDof(*da, dof);CHKERRQ(ierr);
1817aa219208SBarry Smith   ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr);
1818aa219208SBarry Smith   ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr);
1819aa219208SBarry Smith   ierr = DMDASetOwnershipRanges(*da, lx, ly, PETSC_NULL);CHKERRQ(ierr);
182047c6ae99SBarry Smith   /* This violates the behavior for other classes, but right now users expect negative dimensions to be handled this way */
18219a42bb27SBarry Smith   ierr = DMSetFromOptions(*da);CHKERRQ(ierr);
18229a42bb27SBarry Smith   ierr = DMSetUp(*da);CHKERRQ(ierr);
18237242296bSJed Brown   ierr = DMView_DA_Private(*da);CHKERRQ(ierr);
182447c6ae99SBarry Smith   PetscFunctionReturn(0);
182547c6ae99SBarry Smith }
1826