xref: /petsc/src/dm/impls/da/da2.c (revision db87c5ece1d3413ffbda6893d8b5051cee4eef53)
19a42bb27SBarry Smith 
247c6ae99SBarry Smith #define PETSCDM_DLL
347c6ae99SBarry Smith 
4e1589f56SBarry Smith #include "private/daimpl.h"    /*I   "petscdm.h"   I*/
547c6ae99SBarry Smith 
647c6ae99SBarry Smith #undef __FUNCT__
79a42bb27SBarry Smith #define __FUNCT__ "DMView_DA_2d"
89a42bb27SBarry Smith PetscErrorCode DMView_DA_2d(DM da,PetscViewer viewer)
947c6ae99SBarry Smith {
1047c6ae99SBarry Smith   PetscErrorCode ierr;
1147c6ae99SBarry Smith   PetscMPIInt    rank;
129a42bb27SBarry Smith   PetscBool      iascii,isdraw,isbinary;
1347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
149a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
159a42bb27SBarry Smith   PetscBool      ismatlab;
169a42bb27SBarry Smith #endif
1747c6ae99SBarry Smith 
1847c6ae99SBarry Smith   PetscFunctionBegin;
1947c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)da)->comm,&rank);CHKERRQ(ierr);
2047c6ae99SBarry Smith 
2147c6ae99SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2247c6ae99SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
239a42bb27SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
249a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
259a42bb27SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);CHKERRQ(ierr);
269a42bb27SBarry Smith #endif
2747c6ae99SBarry Smith   if (iascii) {
2847c6ae99SBarry Smith     PetscViewerFormat format;
2947c6ae99SBarry Smith 
3047c6ae99SBarry Smith     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
3147c6ae99SBarry Smith     if (format != PETSC_VIEWER_ASCII_VTK && format != PETSC_VIEWER_ASCII_VTK_CELL) {
32aa219208SBarry Smith       DMDALocalInfo info;
33aa219208SBarry Smith       ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
3447c6ae99SBarry 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);
3547c6ae99SBarry 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);
3647c6ae99SBarry Smith       ierr = PetscViewerFlush(viewer);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
86547c6ae99SBarry Smith #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;
1239*db87c5ecSEthan Coon   const DMDABoundaryType wrap         = dd->wrap;
1240aa219208SBarry Smith   const DMDAStencilType  stencil_type = dd->stencil_type;
124147c6ae99SBarry Smith   PetscInt               *lx           = dd->lx;
124247c6ae99SBarry Smith   PetscInt               *ly           = dd->ly;
124347c6ae99SBarry Smith   MPI_Comm               comm;
124447c6ae99SBarry Smith   PetscMPIInt            rank,size;
1245ce00eea3SSatish Balay   PetscInt               xs,xe,ys,ye,x,y,Xs,Xe,Ys,Ye,start,end,IXs,IXe,IYs,IYe;
1246ce00eea3SSatish Balay   PetscInt               up,down,left,right,i,n0,n1,n2,n3,n5,n6,n7,n8,*idx,nn,*idx_cpy;
1247ce00eea3SSatish Balay   const PetscInt         *idx_full;
1248*db87c5ecSEthan Coon   PetscInt               xbase,*bases,*ldims,j,x_t,y_t,s_t,base,count;
124947c6ae99SBarry Smith   PetscInt               s_x,s_y; /* s proportionalized to w */
125047c6ae99SBarry Smith   PetscInt               sn0 = 0,sn2 = 0,sn6 = 0,sn8 = 0;
125147c6ae99SBarry Smith   Vec                    local,global;
125247c6ae99SBarry Smith   VecScatter             ltog,gtol;
1253ce00eea3SSatish Balay   IS                     to,from,ltogis;
125447c6ae99SBarry Smith   PetscErrorCode         ierr;
125547c6ae99SBarry Smith 
125647c6ae99SBarry Smith   PetscFunctionBegin;
125747c6ae99SBarry Smith   ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr);
125847c6ae99SBarry Smith 
125947c6ae99SBarry Smith   if (dof < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof);
126047c6ae99SBarry Smith   if (s < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s);
126147c6ae99SBarry Smith 
126247c6ae99SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
126347c6ae99SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
126447c6ae99SBarry Smith 
126547c6ae99SBarry Smith   dd->dim         = 2;
126647c6ae99SBarry Smith   ierr = PetscMalloc(dof*sizeof(char*),&dd->fieldname);CHKERRQ(ierr);
126747c6ae99SBarry Smith   ierr = PetscMemzero(dd->fieldname,dof*sizeof(char*));CHKERRQ(ierr);
126847c6ae99SBarry Smith 
126947c6ae99SBarry Smith   if (m != PETSC_DECIDE) {
127047c6ae99SBarry Smith     if (m < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in X direction: %D",m);
127147c6ae99SBarry Smith     else if (m > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in X direction: %D %d",m,size);
127247c6ae99SBarry Smith   }
127347c6ae99SBarry Smith   if (n != PETSC_DECIDE) {
127447c6ae99SBarry Smith     if (n < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Y direction: %D",n);
127547c6ae99SBarry Smith     else if (n > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Y direction: %D %d",n,size);
127647c6ae99SBarry Smith   }
127747c6ae99SBarry Smith 
127847c6ae99SBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
127947c6ae99SBarry Smith     if (n != PETSC_DECIDE) {
128047c6ae99SBarry Smith       m = size/n;
128147c6ae99SBarry Smith     } else if (m != PETSC_DECIDE) {
128247c6ae99SBarry Smith       n = size/m;
128347c6ae99SBarry Smith     } else {
128447c6ae99SBarry Smith       /* try for squarish distribution */
128547c6ae99SBarry Smith       m = (PetscInt)(0.5 + sqrt(((double)M)*((double)size)/((double)N)));
128647c6ae99SBarry Smith       if (!m) m = 1;
128747c6ae99SBarry Smith       while (m > 0) {
128847c6ae99SBarry Smith 	n = size/m;
128947c6ae99SBarry Smith 	if (m*n == size) break;
129047c6ae99SBarry Smith 	m--;
129147c6ae99SBarry Smith       }
129247c6ae99SBarry Smith       if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;}
129347c6ae99SBarry Smith     }
129447c6ae99SBarry 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 ");
129547c6ae99SBarry Smith   } else if (m*n != size) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Given Bad partition");
129647c6ae99SBarry Smith 
129747c6ae99SBarry Smith   if (M < m) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in x direction is too fine! %D %D",M,m);
129847c6ae99SBarry Smith   if (N < n) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in y direction is too fine! %D %D",N,n);
129947c6ae99SBarry Smith 
130047c6ae99SBarry Smith   /*
130147c6ae99SBarry Smith      Determine locally owned region
130247c6ae99SBarry Smith      xs is the first local node number, x is the number of local nodes
130347c6ae99SBarry Smith   */
130447c6ae99SBarry Smith   if (!lx) {
130547c6ae99SBarry Smith     ierr = PetscMalloc(m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr);
130647c6ae99SBarry Smith     lx = dd->lx;
130747c6ae99SBarry Smith     for (i=0; i<m; i++) {
130847c6ae99SBarry Smith       lx[i] = M/m + ((M % m) > i);
130947c6ae99SBarry Smith     }
131047c6ae99SBarry Smith   }
131147c6ae99SBarry Smith   x  = lx[rank % m];
131247c6ae99SBarry Smith   xs = 0;
131347c6ae99SBarry Smith   for (i=0; i<(rank % m); i++) {
131447c6ae99SBarry Smith     xs += lx[i];
131547c6ae99SBarry Smith   }
131647c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
131747c6ae99SBarry Smith   left = xs;
131847c6ae99SBarry Smith   for (i=(rank % m); i<m; i++) {
131947c6ae99SBarry Smith     left += lx[i];
132047c6ae99SBarry Smith   }
132147c6ae99SBarry 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);
132247c6ae99SBarry Smith #endif
132347c6ae99SBarry Smith 
132447c6ae99SBarry Smith   /*
132547c6ae99SBarry Smith      Determine locally owned region
132647c6ae99SBarry Smith      ys is the first local node number, y is the number of local nodes
132747c6ae99SBarry Smith   */
132847c6ae99SBarry Smith   if (!ly) {
132947c6ae99SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr);
133047c6ae99SBarry Smith     ly = dd->ly;
133147c6ae99SBarry Smith     for (i=0; i<n; i++) {
133247c6ae99SBarry Smith       ly[i] = N/n + ((N % n) > i);
133347c6ae99SBarry Smith     }
133447c6ae99SBarry Smith   }
133547c6ae99SBarry Smith   y  = ly[rank/m];
133647c6ae99SBarry Smith   ys = 0;
133747c6ae99SBarry Smith   for (i=0; i<(rank/m); i++) {
133847c6ae99SBarry Smith     ys += ly[i];
133947c6ae99SBarry Smith   }
134047c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
134147c6ae99SBarry Smith   left = ys;
134247c6ae99SBarry Smith   for (i=(rank/m); i<n; i++) {
134347c6ae99SBarry Smith     left += ly[i];
134447c6ae99SBarry Smith   }
134547c6ae99SBarry 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);
134647c6ae99SBarry Smith #endif
134747c6ae99SBarry Smith 
134847c6ae99SBarry 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);
134947c6ae99SBarry 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);
135047c6ae99SBarry Smith   xe = xs + x;
135147c6ae99SBarry Smith   ye = ys + y;
135247c6ae99SBarry Smith 
1353ce00eea3SSatish Balay   /* determine ghost region (Xs) and region scattered into (IXs)  */
135447c6ae99SBarry Smith   /* Assume No Periodicity */
1355ce00eea3SSatish Balay   if (xs-s > 0) { Xs = xs - s; IXs = xs - s; } else { Xs = 0; IXs = 0; }
1356ce00eea3SSatish Balay   if (xe+s <= M) { Xe = xe + s; IXe = xe + s; } else { Xe = M; IXe = M; }
1357ce00eea3SSatish Balay   if (ys-s > 0) { Ys = ys - s; IYs = ys - s; } else { Ys = 0; IYs = 0; }
1358ce00eea3SSatish Balay   if (ye+s <= N) { Ye = ye + s; IYe = ye + s; } else { Ye = N; IYe = N; }
135947c6ae99SBarry Smith 
1360ce00eea3SSatish Balay   /* fix for periodicity/ghosted */
1361ce00eea3SSatish Balay   if (DMDAXGhosted(wrap)) { Xs = xs - s; Xe = xe + s; }
1362ce00eea3SSatish Balay   if (DMDAXPeriodic(wrap)) { IXs = xs - s; IXe = xe + s; }
1363ce00eea3SSatish Balay   if (DMDAYGhosted(wrap)) { Ys = ys - s; Ye = ye + s; }
1364ce00eea3SSatish Balay   if (DMDAYPeriodic(wrap)) { IYs = ys - s; IYe = ye + s; }
136547c6ae99SBarry Smith 
136647c6ae99SBarry Smith   /* Resize all X parameters to reflect w */
1367ce00eea3SSatish Balay   s_x = s;
136847c6ae99SBarry Smith   s_y = s;
136947c6ae99SBarry Smith 
137047c6ae99SBarry Smith   /* determine starting point of each processor */
137147c6ae99SBarry Smith   nn    = x*y;
137247c6ae99SBarry Smith   ierr  = PetscMalloc2(size+1,PetscInt,&bases,size,PetscInt,&ldims);CHKERRQ(ierr);
137347c6ae99SBarry Smith   ierr  = MPI_Allgather(&nn,1,MPIU_INT,ldims,1,MPIU_INT,comm);CHKERRQ(ierr);
137447c6ae99SBarry Smith   bases[0] = 0;
137547c6ae99SBarry Smith   for (i=1; i<=size; i++) {
137647c6ae99SBarry Smith     bases[i] = ldims[i-1];
137747c6ae99SBarry Smith   }
137847c6ae99SBarry Smith   for (i=1; i<=size; i++) {
137947c6ae99SBarry Smith     bases[i] += bases[i-1];
138047c6ae99SBarry Smith   }
1381ce00eea3SSatish Balay   base = bases[rank]*dof;
138247c6ae99SBarry Smith 
138347c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
1384ce00eea3SSatish Balay   dd->Nlocal = x*y*dof;
138547c6ae99SBarry Smith   ierr = VecCreateMPIWithArray(comm,dd->Nlocal,PETSC_DECIDE,0,&global);CHKERRQ(ierr);
138647c6ae99SBarry Smith   ierr = VecSetBlockSize(global,dof);CHKERRQ(ierr);
1387ce00eea3SSatish Balay   dd->nlocal = (Xe-Xs)*(Ye-Ys)*dof;
138847c6ae99SBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dd->nlocal,0,&local);CHKERRQ(ierr);
138947c6ae99SBarry Smith   ierr = VecSetBlockSize(local,dof);CHKERRQ(ierr);
139047c6ae99SBarry Smith 
139147c6ae99SBarry Smith   /* generate appropriate vector scatters */
139247c6ae99SBarry Smith   /* local to global inserts non-ghost point region into global */
139347c6ae99SBarry Smith   ierr = VecGetOwnershipRange(global,&start,&end);CHKERRQ(ierr);
1394ce00eea3SSatish Balay   ierr = ISCreateStride(comm,x*y*dof,start,1,&to);CHKERRQ(ierr);
139547c6ae99SBarry Smith 
1396*db87c5ecSEthan Coon   count = x*y;
1397ce00eea3SSatish Balay   ierr = PetscMalloc(x*y*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1398ce00eea3SSatish Balay   left = xs - Xs; right = left + x;
1399ce00eea3SSatish Balay   down = ys - Ys; up = down + y;
140047c6ae99SBarry Smith   count = 0;
140147c6ae99SBarry Smith   for (i=down; i<up; i++) {
1402ce00eea3SSatish Balay     for (j=left; j<right; j++) {
1403ce00eea3SSatish Balay       idx[count++] = i*(Xe-Xs) + j;
140447c6ae99SBarry Smith     }
140547c6ae99SBarry Smith   }
140647c6ae99SBarry Smith 
1407ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr);
140847c6ae99SBarry Smith   ierr = VecScatterCreate(local,from,global,to,&ltog);CHKERRQ(ierr);
140947c6ae99SBarry Smith   ierr = PetscLogObjectParent(dd,ltog);CHKERRQ(ierr);
141047c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
141147c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
141247c6ae99SBarry Smith 
1413ce00eea3SSatish Balay   /* global to local must include ghost points within the domain,
1414ce00eea3SSatish Balay      but not ghost points outside the domain that aren't periodic */
1415aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_BOX) {
1416*db87c5ecSEthan Coon     count = (IXe-IXs)*(IYe-IYs);
1417*db87c5ecSEthan Coon     ierr  = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1418ce00eea3SSatish Balay 
1419ce00eea3SSatish Balay     left = IXs - Xs; right = left + (IXe-IXs);
1420ce00eea3SSatish Balay     down = IYs - Ys; up = down + (IYe-IYs);
1421ce00eea3SSatish Balay     count = 0;
1422ce00eea3SSatish Balay     for (i=down; i<up; i++) {
1423ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1424ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
1425ce00eea3SSatish Balay       }
1426ce00eea3SSatish Balay     }
1427ce00eea3SSatish Balay     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
1428ce00eea3SSatish Balay 
142947c6ae99SBarry Smith   } else {
143047c6ae99SBarry Smith     /* must drop into cross shape region */
143147c6ae99SBarry Smith     /*       ---------|
143247c6ae99SBarry Smith             |  top    |
1433ce00eea3SSatish Balay          |---         ---| up
143447c6ae99SBarry Smith          |   middle      |
143547c6ae99SBarry Smith          |               |
1436ce00eea3SSatish Balay          ----         ---- down
143747c6ae99SBarry Smith             | bottom  |
143847c6ae99SBarry Smith             -----------
143947c6ae99SBarry Smith          Xs xs        xe Xe */
1440*db87c5ecSEthan Coon     count = (ys-IYs)*x + y*(IXe-IXs) + (IYe-ye)*x;
1441*db87c5ecSEthan Coon     ierr  = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1442ce00eea3SSatish Balay 
1443ce00eea3SSatish Balay     left = xs - Xs; right = left + x;
1444ce00eea3SSatish Balay     down = ys - Ys; up = down + y;
144547c6ae99SBarry Smith     count = 0;
1446ce00eea3SSatish Balay     /* bottom */
1447ce00eea3SSatish Balay     for (i=(IYs-Ys); i<down; i++) {
1448ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1449ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
145047c6ae99SBarry Smith       }
145147c6ae99SBarry Smith     }
145247c6ae99SBarry Smith     /* middle */
145347c6ae99SBarry Smith     for (i=down; i<up; i++) {
1454ce00eea3SSatish Balay       for (j=(IXs-Xs); j<(IXe-Xs); j++) {
1455ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
145647c6ae99SBarry Smith       }
145747c6ae99SBarry Smith     }
145847c6ae99SBarry Smith     /* top */
1459ce00eea3SSatish Balay     for (i=up; i<up+IYe-ye; i++) {
1460ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1461ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
146247c6ae99SBarry Smith       }
146347c6ae99SBarry Smith     }
146447c6ae99SBarry Smith     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
146547c6ae99SBarry Smith   }
146647c6ae99SBarry Smith 
146747c6ae99SBarry Smith 
146847c6ae99SBarry Smith   /* determine who lies on each side of us stored in    n6 n7 n8
146947c6ae99SBarry Smith                                                         n3    n5
147047c6ae99SBarry Smith                                                         n0 n1 n2
147147c6ae99SBarry Smith   */
147247c6ae99SBarry Smith 
147347c6ae99SBarry Smith   /* Assume the Non-Periodic Case */
147447c6ae99SBarry Smith   n1 = rank - m;
147547c6ae99SBarry Smith   if (rank % m) {
147647c6ae99SBarry Smith     n0 = n1 - 1;
147747c6ae99SBarry Smith   } else {
147847c6ae99SBarry Smith     n0 = -1;
147947c6ae99SBarry Smith   }
148047c6ae99SBarry Smith   if ((rank+1) % m) {
148147c6ae99SBarry Smith     n2 = n1 + 1;
148247c6ae99SBarry Smith     n5 = rank + 1;
148347c6ae99SBarry Smith     n8 = rank + m + 1; if (n8 >= m*n) n8 = -1;
148447c6ae99SBarry Smith   } else {
148547c6ae99SBarry Smith     n2 = -1; n5 = -1; n8 = -1;
148647c6ae99SBarry Smith   }
148747c6ae99SBarry Smith   if (rank % m) {
148847c6ae99SBarry Smith     n3 = rank - 1;
148947c6ae99SBarry Smith     n6 = n3 + m; if (n6 >= m*n) n6 = -1;
149047c6ae99SBarry Smith   } else {
149147c6ae99SBarry Smith     n3 = -1; n6 = -1;
149247c6ae99SBarry Smith   }
149347c6ae99SBarry Smith   n7 = rank + m; if (n7 >= m*n) n7 = -1;
149447c6ae99SBarry Smith 
1495ce00eea3SSatish Balay   if (DMDAXPeriodic(wrap) && DMDAYPeriodic(wrap)) {
149647c6ae99SBarry Smith   /* Modify for Periodic Cases */
149747c6ae99SBarry Smith     /* Handle all four corners */
149847c6ae99SBarry Smith     if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m-1;
149947c6ae99SBarry Smith     if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0;
150047c6ae99SBarry Smith     if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size-m;
150147c6ae99SBarry Smith     if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size-1;
150247c6ae99SBarry Smith 
150347c6ae99SBarry Smith     /* Handle Top and Bottom Sides */
150447c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n-1);
150547c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n-1);
150647c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
150747c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
150847c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
150947c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
151047c6ae99SBarry Smith 
151147c6ae99SBarry Smith     /* Handle Left and Right Sides */
151247c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m-1);
151347c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m-1);
151447c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
151547c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
151647c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
151747c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
1518ce00eea3SSatish Balay   } else if (DMDAYPeriodic(wrap)) {  /* Handle Top and Bottom Sides */
1519ce00eea3SSatish Balay     if (n1 < 0) n1 = rank + m * (n-1);
1520ce00eea3SSatish Balay     if (n7 < 0) n7 = rank - m * (n-1);
1521ce00eea3SSatish Balay     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
1522ce00eea3SSatish Balay     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
1523ce00eea3SSatish Balay     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
1524ce00eea3SSatish Balay     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
1525ce00eea3SSatish Balay   } else if (DMDAXPeriodic(wrap)) { /* Handle Left and Right Sides */
1526ce00eea3SSatish Balay     if (n3 < 0) n3 = rank + (m-1);
1527ce00eea3SSatish Balay     if (n5 < 0) n5 = rank - (m-1);
1528ce00eea3SSatish Balay     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
1529ce00eea3SSatish Balay     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
1530ce00eea3SSatish Balay     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
1531ce00eea3SSatish Balay     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
153247c6ae99SBarry Smith   }
1533ce00eea3SSatish Balay 
153447c6ae99SBarry Smith   ierr = PetscMalloc(9*sizeof(PetscInt),&dd->neighbors);CHKERRQ(ierr);
153547c6ae99SBarry Smith   dd->neighbors[0] = n0;
153647c6ae99SBarry Smith   dd->neighbors[1] = n1;
153747c6ae99SBarry Smith   dd->neighbors[2] = n2;
153847c6ae99SBarry Smith   dd->neighbors[3] = n3;
153947c6ae99SBarry Smith   dd->neighbors[4] = rank;
154047c6ae99SBarry Smith   dd->neighbors[5] = n5;
154147c6ae99SBarry Smith   dd->neighbors[6] = n6;
154247c6ae99SBarry Smith   dd->neighbors[7] = n7;
154347c6ae99SBarry Smith   dd->neighbors[8] = n8;
154447c6ae99SBarry Smith 
1545aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
154647c6ae99SBarry Smith     /* save corner processor numbers */
154747c6ae99SBarry Smith     sn0 = n0; sn2 = n2; sn6 = n6; sn8 = n8;
154847c6ae99SBarry Smith     n0 = n2 = n6 = n8 = -1;
154947c6ae99SBarry Smith   }
155047c6ae99SBarry Smith 
1551ce00eea3SSatish Balay   ierr = PetscMalloc((Xe-Xs)*(Ye-Ys)*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1552ce00eea3SSatish Balay   ierr = PetscLogObjectMemory(da,(Xe-Xs)*(Ye-Ys)*sizeof(PetscInt));CHKERRQ(ierr);
155347c6ae99SBarry Smith 
1554ce00eea3SSatish Balay   nn = 0;
155547c6ae99SBarry Smith   xbase = bases[rank];
155647c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
155747c6ae99SBarry Smith     if (n0 >= 0) { /* left below */
1558ce00eea3SSatish Balay       x_t = lx[n0 % m];
155947c6ae99SBarry Smith       y_t = ly[(n0/m)];
156047c6ae99SBarry Smith       s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
156147c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
156247c6ae99SBarry Smith     }
156347c6ae99SBarry Smith     if (n1 >= 0) { /* directly below */
156447c6ae99SBarry Smith       x_t = x;
156547c6ae99SBarry Smith       y_t = ly[(n1/m)];
156647c6ae99SBarry Smith       s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
156747c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
156847c6ae99SBarry Smith     }
156947c6ae99SBarry Smith     if (n2 >= 0) { /* right below */
1570ce00eea3SSatish Balay       x_t = lx[n2 % m];
157147c6ae99SBarry Smith       y_t = ly[(n2/m)];
157247c6ae99SBarry Smith       s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
157347c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
157447c6ae99SBarry Smith     }
157547c6ae99SBarry Smith   }
157647c6ae99SBarry Smith 
157747c6ae99SBarry Smith   for (i=0; i<y; i++) {
157847c6ae99SBarry Smith     if (n3 >= 0) { /* directly left */
1579ce00eea3SSatish Balay       x_t = lx[n3 % m];
158047c6ae99SBarry Smith       /* y_t = y; */
158147c6ae99SBarry Smith       s_t = bases[n3] + (i+1)*x_t - s_x;
158247c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
158347c6ae99SBarry Smith     }
158447c6ae99SBarry Smith 
158547c6ae99SBarry Smith     for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
158647c6ae99SBarry Smith 
158747c6ae99SBarry Smith     if (n5 >= 0) { /* directly right */
1588ce00eea3SSatish Balay       x_t = lx[n5 % m];
158947c6ae99SBarry Smith       /* y_t = y; */
159047c6ae99SBarry Smith       s_t = bases[n5] + (i)*x_t;
159147c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
159247c6ae99SBarry Smith     }
159347c6ae99SBarry Smith   }
159447c6ae99SBarry Smith 
159547c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
159647c6ae99SBarry Smith     if (n6 >= 0) { /* left above */
1597ce00eea3SSatish Balay       x_t = lx[n6 % m];
159847c6ae99SBarry Smith       /* y_t = ly[(n6/m)]; */
159947c6ae99SBarry Smith       s_t = bases[n6] + (i)*x_t - s_x;
160047c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
160147c6ae99SBarry Smith     }
160247c6ae99SBarry Smith     if (n7 >= 0) { /* directly above */
160347c6ae99SBarry Smith       x_t = x;
160447c6ae99SBarry Smith       /* y_t = ly[(n7/m)]; */
160547c6ae99SBarry Smith       s_t = bases[n7] + (i-1)*x_t;
160647c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
160747c6ae99SBarry Smith     }
160847c6ae99SBarry Smith     if (n8 >= 0) { /* right above */
1609ce00eea3SSatish Balay       x_t = lx[n8 % m];
161047c6ae99SBarry Smith       /* y_t = ly[(n8/m)]; */
161147c6ae99SBarry Smith       s_t = bases[n8] + (i-1)*x_t;
161247c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
161347c6ae99SBarry Smith     }
161447c6ae99SBarry Smith   }
161547c6ae99SBarry Smith 
1616ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
161747c6ae99SBarry Smith   ierr = VecScatterCreate(global,from,local,to,&gtol);CHKERRQ(ierr);
161847c6ae99SBarry Smith   ierr = PetscLogObjectParent(da,gtol);CHKERRQ(ierr);
161947c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
162047c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
162147c6ae99SBarry Smith 
1622aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
1623ce00eea3SSatish Balay     n0 = sn0; n2 = sn2; n6 = sn6; n8 = sn8;
1624ce00eea3SSatish Balay   }
1625ce00eea3SSatish Balay 
1626ce00eea3SSatish Balay   if ((stencil_type == DMDA_STENCIL_STAR) ||
1627ce00eea3SSatish Balay       (!DMDAXPeriodic(wrap) && DMDAXGhosted(wrap)) ||
1628ce00eea3SSatish Balay       (!DMDAYPeriodic(wrap) && DMDAYGhosted(wrap))) {
162947c6ae99SBarry Smith     /*
163047c6ae99SBarry Smith         Recompute the local to global mappings, this time keeping the
1631ce00eea3SSatish Balay       information about the cross corner processor numbers and any ghosted
1632ce00eea3SSatish Balay       but not periodic indices.
163347c6ae99SBarry Smith     */
163447c6ae99SBarry Smith     nn = 0;
163547c6ae99SBarry Smith     xbase = bases[rank];
163647c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
163747c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
1638ce00eea3SSatish Balay         x_t = lx[n0 % m];
163947c6ae99SBarry Smith         y_t = ly[(n0/m)];
164047c6ae99SBarry Smith         s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
164147c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1642ce00eea3SSatish Balay       } else if (xs-Xs > 0 && ys-Ys > 0) {
1643ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
164447c6ae99SBarry Smith       }
164547c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
164647c6ae99SBarry Smith         x_t = x;
164747c6ae99SBarry Smith         y_t = ly[(n1/m)];
164847c6ae99SBarry Smith         s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
164947c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1650ce00eea3SSatish Balay       } else if (ys-Ys > 0) {
1651ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
165247c6ae99SBarry Smith       }
165347c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
1654ce00eea3SSatish Balay         x_t = lx[n2 % m];
165547c6ae99SBarry Smith         y_t = ly[(n2/m)];
165647c6ae99SBarry Smith         s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
165747c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1658ce00eea3SSatish Balay       } else if (Xe-xe> 0 && ys-Ys > 0) {
1659ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
166047c6ae99SBarry Smith       }
166147c6ae99SBarry Smith     }
166247c6ae99SBarry Smith 
166347c6ae99SBarry Smith     for (i=0; i<y; i++) {
166447c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
1665ce00eea3SSatish Balay         x_t = lx[n3 % m];
166647c6ae99SBarry Smith         /* y_t = y; */
166747c6ae99SBarry Smith         s_t = bases[n3] + (i+1)*x_t - s_x;
166847c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1669ce00eea3SSatish Balay       } else if (xs-Xs > 0) {
1670ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
167147c6ae99SBarry Smith       }
167247c6ae99SBarry Smith 
167347c6ae99SBarry Smith       for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
167447c6ae99SBarry Smith 
167547c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
1676ce00eea3SSatish Balay         x_t = lx[n5 % m];
167747c6ae99SBarry Smith         /* y_t = y; */
167847c6ae99SBarry Smith         s_t = bases[n5] + (i)*x_t;
167947c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1680ce00eea3SSatish Balay       } else if (Xe-xe > 0) {
1681ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
168247c6ae99SBarry Smith       }
168347c6ae99SBarry Smith     }
168447c6ae99SBarry Smith 
168547c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
168647c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
1687ce00eea3SSatish Balay         x_t = lx[n6 % m];
168847c6ae99SBarry Smith         /* y_t = ly[(n6/m)]; */
168947c6ae99SBarry Smith         s_t = bases[n6] + (i)*x_t - s_x;
169047c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1691ce00eea3SSatish Balay       } else if (xs-Xs > 0 && Ye-ye > 0) {
1692ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
169347c6ae99SBarry Smith       }
169447c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
169547c6ae99SBarry Smith         x_t = x;
169647c6ae99SBarry Smith         /* y_t = ly[(n7/m)]; */
169747c6ae99SBarry Smith         s_t = bases[n7] + (i-1)*x_t;
169847c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1699ce00eea3SSatish Balay       } else if (Ye-ye > 0) {
1700ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
170147c6ae99SBarry Smith       }
170247c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
1703ce00eea3SSatish Balay         x_t = lx[n8 % m];
170447c6ae99SBarry Smith         /* y_t = ly[(n8/m)]; */
170547c6ae99SBarry Smith         s_t = bases[n8] + (i-1)*x_t;
170647c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1707ce00eea3SSatish Balay       } else if (Xe-xe > 0 && Ye-ye > 0) {
1708ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
170947c6ae99SBarry Smith       }
171047c6ae99SBarry Smith     }
171147c6ae99SBarry Smith   }
1712ce00eea3SSatish Balay   /*
1713ce00eea3SSatish Balay      Set the local to global ordering in the global vector, this allows use
1714ce00eea3SSatish Balay      of VecSetValuesLocal().
1715ce00eea3SSatish Balay   */
1716ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_OWN_POINTER,&ltogis);CHKERRQ(ierr);
1717ce00eea3SSatish Balay   ierr = PetscMalloc(nn*dof*sizeof(PetscInt),&idx_cpy);CHKERRQ(ierr);
1718*db87c5ecSEthan Coon   ierr = PetscLogObjectMemory(da,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);
1719ce00eea3SSatish Balay   ierr = ISGetIndices(ltogis, &idx_full);
1720ce00eea3SSatish Balay   ierr = PetscMemcpy(idx_cpy,idx_full,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);
1721ce00eea3SSatish Balay   ierr = ISRestoreIndices(ltogis, &idx_full);
1722ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingCreateIS(ltogis,&da->ltogmap);CHKERRQ(ierr);
1723ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
1724ce00eea3SSatish Balay   ierr = ISDestroy(ltogis);CHKERRQ(ierr);
1725ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingBlock(da->ltogmap,dd->w,&da->ltogmapb);CHKERRQ(ierr);
1726ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
172747c6ae99SBarry Smith 
1728ce00eea3SSatish Balay   ierr = PetscFree2(bases,ldims);CHKERRQ(ierr);
172947c6ae99SBarry Smith   dd->m  = m;  dd->n  = n;
1730ce00eea3SSatish Balay   /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
1731ce00eea3SSatish Balay   dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1;
1732ce00eea3SSatish Balay   dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1;
173347c6ae99SBarry Smith 
173447c6ae99SBarry Smith   ierr = VecDestroy(local);CHKERRQ(ierr);
173547c6ae99SBarry Smith   ierr = VecDestroy(global);CHKERRQ(ierr);
173647c6ae99SBarry Smith 
173747c6ae99SBarry Smith   dd->gtol      = gtol;
173847c6ae99SBarry Smith   dd->ltog      = ltog;
1739ce00eea3SSatish Balay   dd->idx       = idx_cpy;
1740ce00eea3SSatish Balay   dd->Nl        = nn*dof;
174147c6ae99SBarry Smith   dd->base      = base;
17429a42bb27SBarry Smith   da->ops->view = DMView_DA_2d;
174347c6ae99SBarry Smith   dd->ltol = PETSC_NULL;
174447c6ae99SBarry Smith   dd->ao   = PETSC_NULL;
174547c6ae99SBarry Smith 
174647c6ae99SBarry Smith   PetscFunctionReturn(0);
174747c6ae99SBarry Smith }
174847c6ae99SBarry Smith 
174947c6ae99SBarry Smith #undef __FUNCT__
1750aa219208SBarry Smith #define __FUNCT__ "DMDACreate2d"
175147c6ae99SBarry Smith /*@C
1752aa219208SBarry Smith    DMDACreate2d -  Creates an object that will manage the communication of  two-dimensional
175347c6ae99SBarry Smith    regular array data that is distributed across some processors.
175447c6ae99SBarry Smith 
175547c6ae99SBarry Smith    Collective on MPI_Comm
175647c6ae99SBarry Smith 
175747c6ae99SBarry Smith    Input Parameters:
175847c6ae99SBarry Smith +  comm - MPI communicator
175947c6ae99SBarry Smith .  wrap - type of periodicity should the array have.
1760aa219208SBarry Smith          Use one of DMDA_NONPERIODIC, DMDA_XPERIODIC, DMDA_YPERIODIC, or DMDA_XYPERIODIC.
1761aa219208SBarry Smith .  stencil_type - stencil type.  Use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
176247c6ae99SBarry 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
176347c6ae99SBarry Smith             from the command line with -da_grid_x <M> -da_grid_y <N>)
176447c6ae99SBarry Smith .  m,n - corresponding number of processors in each dimension
176547c6ae99SBarry Smith          (or PETSC_DECIDE to have calculated)
176647c6ae99SBarry Smith .  dof - number of degrees of freedom per node
176747c6ae99SBarry Smith .  s - stencil width
176847c6ae99SBarry Smith -  lx, ly - arrays containing the number of nodes in each cell along
176947c6ae99SBarry Smith            the x and y coordinates, or PETSC_NULL. If non-null, these
177047c6ae99SBarry Smith            must be of length as m and n, and the corresponding
177147c6ae99SBarry Smith            m and n cannot be PETSC_DECIDE. The sum of the lx[] entries
177247c6ae99SBarry Smith            must be M, and the sum of the ly[] entries must be N.
177347c6ae99SBarry Smith 
177447c6ae99SBarry Smith    Output Parameter:
177547c6ae99SBarry Smith .  da - the resulting distributed array object
177647c6ae99SBarry Smith 
177747c6ae99SBarry Smith    Options Database Key:
1778aa219208SBarry Smith +  -da_view - Calls DMView() at the conclusion of DMDACreate2d()
177947c6ae99SBarry Smith .  -da_grid_x <nx> - number of grid points in x direction, if M < 0
178047c6ae99SBarry Smith .  -da_grid_y <ny> - number of grid points in y direction, if N < 0
178147c6ae99SBarry Smith .  -da_processors_x <nx> - number of processors in x direction
178247c6ae99SBarry Smith .  -da_processors_y <ny> - number of processors in y direction
178347c6ae99SBarry Smith .  -da_refine_x - refinement ratio in x direction
178447c6ae99SBarry Smith -  -da_refine_y - refinement ratio in y direction
178547c6ae99SBarry Smith 
178647c6ae99SBarry Smith    Level: beginner
178747c6ae99SBarry Smith 
178847c6ae99SBarry Smith    Notes:
1789aa219208SBarry Smith    The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the
1790aa219208SBarry Smith    standard 5-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes
179147c6ae99SBarry Smith    the standard 9-pt stencil.
179247c6ae99SBarry Smith 
1793aa219208SBarry Smith    The array data itself is NOT stored in the DMDA, it is stored in Vec objects;
1794564755cdSBarry Smith    The appropriate vector objects can be obtained with calls to DMCreateGlobalVector()
1795564755cdSBarry Smith    and DMCreateLocalVector() and calls to VecDuplicate() if more are needed.
179647c6ae99SBarry Smith 
179747c6ae99SBarry Smith .keywords: distributed array, create, two-dimensional
179847c6ae99SBarry Smith 
1799aa219208SBarry Smith .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate3d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(),
1800aa219208SBarry Smith           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMDALocalToLocalBegin(), DMDALocalToLocalEnd(), DMDASetRefinementFactor(),
1801aa219208SBarry Smith           DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMDALoad(), DMDAGetOwnershipRanges()
180247c6ae99SBarry Smith 
180347c6ae99SBarry Smith @*/
1804*db87c5ecSEthan Coon PetscErrorCode  DMDACreate2d(MPI_Comm comm,DMDABoundaryType wrap,DMDAStencilType stencil_type,
18059a42bb27SBarry Smith                           PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da)
180647c6ae99SBarry Smith {
180747c6ae99SBarry Smith   PetscErrorCode ierr;
180847c6ae99SBarry Smith 
180947c6ae99SBarry Smith   PetscFunctionBegin;
1810aa219208SBarry Smith   ierr = DMDACreate(comm, da);CHKERRQ(ierr);
1811aa219208SBarry Smith   ierr = DMDASetDim(*da, 2);CHKERRQ(ierr);
1812aa219208SBarry Smith   ierr = DMDASetSizes(*da, M, N, 1);CHKERRQ(ierr);
1813aa219208SBarry Smith   ierr = DMDASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr);
1814aa219208SBarry Smith   ierr = DMDASetPeriodicity(*da, wrap);CHKERRQ(ierr);
1815aa219208SBarry Smith   ierr = DMDASetDof(*da, dof);CHKERRQ(ierr);
1816aa219208SBarry Smith   ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr);
1817aa219208SBarry Smith   ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr);
1818aa219208SBarry Smith   ierr = DMDASetOwnershipRanges(*da, lx, ly, PETSC_NULL);CHKERRQ(ierr);
181947c6ae99SBarry Smith   /* This violates the behavior for other classes, but right now users expect negative dimensions to be handled this way */
18209a42bb27SBarry Smith   ierr = DMSetFromOptions(*da);CHKERRQ(ierr);
18219a42bb27SBarry Smith   ierr = DMSetUp(*da);CHKERRQ(ierr);
18227242296bSJed Brown   ierr = DMView_DA_Private(*da);CHKERRQ(ierr);
182347c6ae99SBarry Smith   PetscFunctionReturn(0);
182447c6ae99SBarry Smith }
1825