xref: /petsc/src/dm/impls/da/da2.c (revision ce00eea3264a0806f1119e205005401f21164aea)
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;
1239aa219208SBarry Smith   const DMDAPeriodicType 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;
1245*ce00eea3SSatish Balay   PetscInt               xs,xe,ys,ye,x,y,Xs,Xe,Ys,Ye,start,end,IXs,IXe,IYs,IYe;
1246*ce00eea3SSatish Balay   PetscInt               up,down,left,right,i,n0,n1,n2,n3,n5,n6,n7,n8,*idx,nn,*idx_cpy;
1247*ce00eea3SSatish Balay   const PetscInt         *idx_full;
1248*ce00eea3SSatish Balay   PetscInt               xbase,*bases,*ldims,j,x_t,y_t,s_t,base,count,count_dbg;
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;
1253*ce00eea3SSatish 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 
1353*ce00eea3SSatish Balay   /* determine ghost region (Xs) and region scattered into (IXs)  */
135447c6ae99SBarry Smith   /* Assume No Periodicity */
1355*ce00eea3SSatish Balay   if (xs-s > 0) { Xs = xs - s; IXs = xs - s; } else { Xs = 0; IXs = 0; }
1356*ce00eea3SSatish Balay   if (xe+s <= M) { Xe = xe + s; IXe = xe + s; } else { Xe = M; IXe = M; }
1357*ce00eea3SSatish Balay   if (ys-s > 0) { Ys = ys - s; IYs = ys - s; } else { Ys = 0; IYs = 0; }
1358*ce00eea3SSatish Balay   if (ye+s <= N) { Ye = ye + s; IYe = ye + s; } else { Ye = N; IYe = N; }
135947c6ae99SBarry Smith 
1360*ce00eea3SSatish Balay   /* fix for periodicity/ghosted */
1361*ce00eea3SSatish Balay   if (DMDAXGhosted(wrap)) { Xs = xs - s; Xe = xe + s; }
1362*ce00eea3SSatish Balay   if (DMDAXPeriodic(wrap)) { IXs = xs - s; IXe = xe + s; }
1363*ce00eea3SSatish Balay   if (DMDAYGhosted(wrap)) { Ys = ys - s; Ye = ye + s; }
1364*ce00eea3SSatish Balay   if (DMDAYPeriodic(wrap)) { IYs = ys - s; IYe = ye + s; }
136547c6ae99SBarry Smith 
136647c6ae99SBarry Smith   /* Resize all X parameters to reflect w */
1367*ce00eea3SSatish 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   }
1381*ce00eea3SSatish Balay   base = bases[rank]*dof;
138247c6ae99SBarry Smith 
138347c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
1384*ce00eea3SSatish 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);
1387*ce00eea3SSatish 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);
1394*ce00eea3SSatish Balay   ierr = ISCreateStride(comm,x*y*dof,start,1,&to);CHKERRQ(ierr);
139547c6ae99SBarry Smith 
1396*ce00eea3SSatish Balay   count_dbg = x*y;
1397*ce00eea3SSatish Balay   ierr = PetscMalloc(x*y*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1398*ce00eea3SSatish Balay   left = xs - Xs; right = left + x;
1399*ce00eea3SSatish Balay   down = ys - Ys; up = down + y;
140047c6ae99SBarry Smith   count = 0;
140147c6ae99SBarry Smith   for (i=down; i<up; i++) {
1402*ce00eea3SSatish Balay     for (j=left; j<right; j++) {
1403*ce00eea3SSatish Balay       idx[count++] = i*(Xe-Xs) + j;
140447c6ae99SBarry Smith     }
140547c6ae99SBarry Smith   }
1406*ce00eea3SSatish Balay   if (count != count_dbg) {
1407*ce00eea3SSatish Balay     SETERRQ(((PetscObject)da)->comm, PETSC_ERR_SUP,"count != count_dbg");
1408*ce00eea3SSatish Balay     PetscFunctionReturn(1);
1409*ce00eea3SSatish Balay   }
141047c6ae99SBarry Smith 
1411*ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr);
141247c6ae99SBarry Smith   ierr = VecScatterCreate(local,from,global,to,&ltog);CHKERRQ(ierr);
141347c6ae99SBarry Smith   ierr = PetscLogObjectParent(dd,ltog);CHKERRQ(ierr);
141447c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
141547c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
141647c6ae99SBarry Smith 
1417*ce00eea3SSatish Balay   /* global to local must include ghost points within the domain,
1418*ce00eea3SSatish Balay      but not ghost points outside the domain that aren't periodic */
1419aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_BOX) {
1420*ce00eea3SSatish Balay     count_dbg = (IXe-IXs)*(IYe-IYs);
1421*ce00eea3SSatish Balay     ierr  = PetscMalloc(count_dbg*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1422*ce00eea3SSatish Balay 
1423*ce00eea3SSatish Balay     left = IXs - Xs; right = left + (IXe-IXs);
1424*ce00eea3SSatish Balay     down = IYs - Ys; up = down + (IYe-IYs);
1425*ce00eea3SSatish Balay     count = 0;
1426*ce00eea3SSatish Balay     for (i=down; i<up; i++) {
1427*ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1428*ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
1429*ce00eea3SSatish Balay       }
1430*ce00eea3SSatish Balay     }
1431*ce00eea3SSatish Balay     if (count != count_dbg) {
1432*ce00eea3SSatish Balay       SETERRQ(((PetscObject)da)->comm, PETSC_ERR_SUP,"count != count_dbg");
1433*ce00eea3SSatish Balay       PetscFunctionReturn(1);
1434*ce00eea3SSatish Balay     }
1435*ce00eea3SSatish Balay     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
1436*ce00eea3SSatish Balay 
143747c6ae99SBarry Smith   } else {
143847c6ae99SBarry Smith     /* must drop into cross shape region */
143947c6ae99SBarry Smith     /*       ---------|
144047c6ae99SBarry Smith             |  top    |
1441*ce00eea3SSatish Balay          |---         ---| up
144247c6ae99SBarry Smith          |   middle      |
144347c6ae99SBarry Smith          |               |
1444*ce00eea3SSatish Balay          ----         ---- down
144547c6ae99SBarry Smith             | bottom  |
144647c6ae99SBarry Smith             -----------
144747c6ae99SBarry Smith          Xs xs        xe Xe */
1448*ce00eea3SSatish Balay     count_dbg = (ys-IYs)*x + y*(IXe-IXs) + (IYe-ye)*x;
1449*ce00eea3SSatish Balay     ierr  = PetscMalloc(count_dbg*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1450*ce00eea3SSatish Balay 
1451*ce00eea3SSatish Balay     left = xs - Xs; right = left + x;
1452*ce00eea3SSatish Balay     down = ys - Ys; up = down + y;
145347c6ae99SBarry Smith     count = 0;
1454*ce00eea3SSatish Balay     /* bottom */
1455*ce00eea3SSatish Balay     for (i=(IYs-Ys); i<down; i++) {
1456*ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1457*ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
145847c6ae99SBarry Smith       }
145947c6ae99SBarry Smith     }
146047c6ae99SBarry Smith     /* middle */
146147c6ae99SBarry Smith     for (i=down; i<up; i++) {
1462*ce00eea3SSatish Balay       for (j=(IXs-Xs); j<(IXe-Xs); j++) {
1463*ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
146447c6ae99SBarry Smith       }
146547c6ae99SBarry Smith     }
146647c6ae99SBarry Smith     /* top */
1467*ce00eea3SSatish Balay     for (i=up; i<up+IYe-ye; i++) {
1468*ce00eea3SSatish Balay       for (j=left; j<right; j++) {
1469*ce00eea3SSatish Balay         idx[count++] = j + i*(Xe-Xs);
147047c6ae99SBarry Smith       }
147147c6ae99SBarry Smith     }
1472*ce00eea3SSatish Balay     if (count != count_dbg) {
1473*ce00eea3SSatish Balay       SETERRQ(((PetscObject)da)->comm, PETSC_ERR_SUP,"count != count_dbg");
1474*ce00eea3SSatish Balay       PetscFunctionReturn(1);
1475*ce00eea3SSatish Balay     }
147647c6ae99SBarry Smith     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
147747c6ae99SBarry Smith   }
147847c6ae99SBarry Smith 
147947c6ae99SBarry Smith 
148047c6ae99SBarry Smith   /* determine who lies on each side of us stored in    n6 n7 n8
148147c6ae99SBarry Smith                                                         n3    n5
148247c6ae99SBarry Smith                                                         n0 n1 n2
148347c6ae99SBarry Smith   */
148447c6ae99SBarry Smith 
148547c6ae99SBarry Smith   /* Assume the Non-Periodic Case */
148647c6ae99SBarry Smith   n1 = rank - m;
148747c6ae99SBarry Smith   if (rank % m) {
148847c6ae99SBarry Smith     n0 = n1 - 1;
148947c6ae99SBarry Smith   } else {
149047c6ae99SBarry Smith     n0 = -1;
149147c6ae99SBarry Smith   }
149247c6ae99SBarry Smith   if ((rank+1) % m) {
149347c6ae99SBarry Smith     n2 = n1 + 1;
149447c6ae99SBarry Smith     n5 = rank + 1;
149547c6ae99SBarry Smith     n8 = rank + m + 1; if (n8 >= m*n) n8 = -1;
149647c6ae99SBarry Smith   } else {
149747c6ae99SBarry Smith     n2 = -1; n5 = -1; n8 = -1;
149847c6ae99SBarry Smith   }
149947c6ae99SBarry Smith   if (rank % m) {
150047c6ae99SBarry Smith     n3 = rank - 1;
150147c6ae99SBarry Smith     n6 = n3 + m; if (n6 >= m*n) n6 = -1;
150247c6ae99SBarry Smith   } else {
150347c6ae99SBarry Smith     n3 = -1; n6 = -1;
150447c6ae99SBarry Smith   }
150547c6ae99SBarry Smith   n7 = rank + m; if (n7 >= m*n) n7 = -1;
150647c6ae99SBarry Smith 
1507*ce00eea3SSatish Balay   if (DMDAXPeriodic(wrap) && DMDAYPeriodic(wrap)) {
150847c6ae99SBarry Smith   /* Modify for Periodic Cases */
150947c6ae99SBarry Smith     /* Handle all four corners */
151047c6ae99SBarry Smith     if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m-1;
151147c6ae99SBarry Smith     if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0;
151247c6ae99SBarry Smith     if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size-m;
151347c6ae99SBarry Smith     if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size-1;
151447c6ae99SBarry Smith 
151547c6ae99SBarry Smith     /* Handle Top and Bottom Sides */
151647c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n-1);
151747c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n-1);
151847c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
151947c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
152047c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
152147c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
152247c6ae99SBarry Smith 
152347c6ae99SBarry Smith     /* Handle Left and Right Sides */
152447c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m-1);
152547c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m-1);
152647c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
152747c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
152847c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
152947c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
1530*ce00eea3SSatish Balay   } else if (DMDAYPeriodic(wrap)) {  /* Handle Top and Bottom Sides */
1531*ce00eea3SSatish Balay     if (n1 < 0) n1 = rank + m * (n-1);
1532*ce00eea3SSatish Balay     if (n7 < 0) n7 = rank - m * (n-1);
1533*ce00eea3SSatish Balay     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
1534*ce00eea3SSatish Balay     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
1535*ce00eea3SSatish Balay     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
1536*ce00eea3SSatish Balay     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
1537*ce00eea3SSatish Balay   } else if (DMDAXPeriodic(wrap)) { /* Handle Left and Right Sides */
1538*ce00eea3SSatish Balay     if (n3 < 0) n3 = rank + (m-1);
1539*ce00eea3SSatish Balay     if (n5 < 0) n5 = rank - (m-1);
1540*ce00eea3SSatish Balay     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
1541*ce00eea3SSatish Balay     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
1542*ce00eea3SSatish Balay     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
1543*ce00eea3SSatish Balay     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
154447c6ae99SBarry Smith   }
1545*ce00eea3SSatish Balay 
154647c6ae99SBarry Smith   ierr = PetscMalloc(9*sizeof(PetscInt),&dd->neighbors);CHKERRQ(ierr);
154747c6ae99SBarry Smith   dd->neighbors[0] = n0;
154847c6ae99SBarry Smith   dd->neighbors[1] = n1;
154947c6ae99SBarry Smith   dd->neighbors[2] = n2;
155047c6ae99SBarry Smith   dd->neighbors[3] = n3;
155147c6ae99SBarry Smith   dd->neighbors[4] = rank;
155247c6ae99SBarry Smith   dd->neighbors[5] = n5;
155347c6ae99SBarry Smith   dd->neighbors[6] = n6;
155447c6ae99SBarry Smith   dd->neighbors[7] = n7;
155547c6ae99SBarry Smith   dd->neighbors[8] = n8;
155647c6ae99SBarry Smith 
1557aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
155847c6ae99SBarry Smith     /* save corner processor numbers */
155947c6ae99SBarry Smith     sn0 = n0; sn2 = n2; sn6 = n6; sn8 = n8;
156047c6ae99SBarry Smith     n0 = n2 = n6 = n8 = -1;
156147c6ae99SBarry Smith   }
156247c6ae99SBarry Smith 
1563*ce00eea3SSatish Balay   ierr = PetscMalloc((Xe-Xs)*(Ye-Ys)*sizeof(PetscInt),&idx);CHKERRQ(ierr);
1564*ce00eea3SSatish Balay   ierr = PetscLogObjectMemory(da,(Xe-Xs)*(Ye-Ys)*sizeof(PetscInt));CHKERRQ(ierr);
156547c6ae99SBarry Smith 
1566*ce00eea3SSatish Balay   nn = 0;
156747c6ae99SBarry Smith   xbase = bases[rank];
156847c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
156947c6ae99SBarry Smith     if (n0 >= 0) { /* left below */
1570*ce00eea3SSatish Balay       x_t = lx[n0 % m];
157147c6ae99SBarry Smith       y_t = ly[(n0/m)];
157247c6ae99SBarry Smith       s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
157347c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
157447c6ae99SBarry Smith     }
157547c6ae99SBarry Smith     if (n1 >= 0) { /* directly below */
157647c6ae99SBarry Smith       x_t = x;
157747c6ae99SBarry Smith       y_t = ly[(n1/m)];
157847c6ae99SBarry Smith       s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
157947c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
158047c6ae99SBarry Smith     }
158147c6ae99SBarry Smith     if (n2 >= 0) { /* right below */
1582*ce00eea3SSatish Balay       x_t = lx[n2 % m];
158347c6ae99SBarry Smith       y_t = ly[(n2/m)];
158447c6ae99SBarry Smith       s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
158547c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
158647c6ae99SBarry Smith     }
158747c6ae99SBarry Smith   }
158847c6ae99SBarry Smith 
158947c6ae99SBarry Smith   for (i=0; i<y; i++) {
159047c6ae99SBarry Smith     if (n3 >= 0) { /* directly left */
1591*ce00eea3SSatish Balay       x_t = lx[n3 % m];
159247c6ae99SBarry Smith       /* y_t = y; */
159347c6ae99SBarry Smith       s_t = bases[n3] + (i+1)*x_t - s_x;
159447c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
159547c6ae99SBarry Smith     }
159647c6ae99SBarry Smith 
159747c6ae99SBarry Smith     for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
159847c6ae99SBarry Smith 
159947c6ae99SBarry Smith     if (n5 >= 0) { /* directly right */
1600*ce00eea3SSatish Balay       x_t = lx[n5 % m];
160147c6ae99SBarry Smith       /* y_t = y; */
160247c6ae99SBarry Smith       s_t = bases[n5] + (i)*x_t;
160347c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
160447c6ae99SBarry Smith     }
160547c6ae99SBarry Smith   }
160647c6ae99SBarry Smith 
160747c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
160847c6ae99SBarry Smith     if (n6 >= 0) { /* left above */
1609*ce00eea3SSatish Balay       x_t = lx[n6 % m];
161047c6ae99SBarry Smith       /* y_t = ly[(n6/m)]; */
161147c6ae99SBarry Smith       s_t = bases[n6] + (i)*x_t - s_x;
161247c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
161347c6ae99SBarry Smith     }
161447c6ae99SBarry Smith     if (n7 >= 0) { /* directly above */
161547c6ae99SBarry Smith       x_t = x;
161647c6ae99SBarry Smith       /* y_t = ly[(n7/m)]; */
161747c6ae99SBarry Smith       s_t = bases[n7] + (i-1)*x_t;
161847c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
161947c6ae99SBarry Smith     }
162047c6ae99SBarry Smith     if (n8 >= 0) { /* right above */
1621*ce00eea3SSatish Balay       x_t = lx[n8 % m];
162247c6ae99SBarry Smith       /* y_t = ly[(n8/m)]; */
162347c6ae99SBarry Smith       s_t = bases[n8] + (i-1)*x_t;
162447c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
162547c6ae99SBarry Smith     }
162647c6ae99SBarry Smith   }
162747c6ae99SBarry Smith 
1628*ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
162947c6ae99SBarry Smith   ierr = VecScatterCreate(global,from,local,to,&gtol);CHKERRQ(ierr);
163047c6ae99SBarry Smith   ierr = PetscLogObjectParent(da,gtol);CHKERRQ(ierr);
163147c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
163247c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
163347c6ae99SBarry Smith 
1634aa219208SBarry Smith   if (stencil_type == DMDA_STENCIL_STAR) {
1635*ce00eea3SSatish Balay     n0 = sn0; n2 = sn2; n6 = sn6; n8 = sn8;
1636*ce00eea3SSatish Balay   }
1637*ce00eea3SSatish Balay 
1638*ce00eea3SSatish Balay   if ((stencil_type == DMDA_STENCIL_STAR) ||
1639*ce00eea3SSatish Balay       (!DMDAXPeriodic(wrap) && DMDAXGhosted(wrap)) ||
1640*ce00eea3SSatish Balay       (!DMDAYPeriodic(wrap) && DMDAYGhosted(wrap))) {
164147c6ae99SBarry Smith     /*
164247c6ae99SBarry Smith         Recompute the local to global mappings, this time keeping the
1643*ce00eea3SSatish Balay       information about the cross corner processor numbers and any ghosted
1644*ce00eea3SSatish Balay       but not periodic indices.
164547c6ae99SBarry Smith     */
164647c6ae99SBarry Smith     nn = 0;
164747c6ae99SBarry Smith     xbase = bases[rank];
164847c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
164947c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
1650*ce00eea3SSatish Balay         x_t = lx[n0 % m];
165147c6ae99SBarry Smith         y_t = ly[(n0/m)];
165247c6ae99SBarry Smith         s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
165347c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1654*ce00eea3SSatish Balay       } else if (xs-Xs > 0 && ys-Ys > 0) {
1655*ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
165647c6ae99SBarry Smith       }
165747c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
165847c6ae99SBarry Smith         x_t = x;
165947c6ae99SBarry Smith         y_t = ly[(n1/m)];
166047c6ae99SBarry Smith         s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
166147c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1662*ce00eea3SSatish Balay       } else if (ys-Ys > 0) {
1663*ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
166447c6ae99SBarry Smith       }
166547c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
1666*ce00eea3SSatish Balay         x_t = lx[n2 % m];
166747c6ae99SBarry Smith         y_t = ly[(n2/m)];
166847c6ae99SBarry Smith         s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
166947c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1670*ce00eea3SSatish Balay       } else if (Xe-xe> 0 && ys-Ys > 0) {
1671*ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
167247c6ae99SBarry Smith       }
167347c6ae99SBarry Smith     }
167447c6ae99SBarry Smith 
167547c6ae99SBarry Smith     for (i=0; i<y; i++) {
167647c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
1677*ce00eea3SSatish Balay         x_t = lx[n3 % m];
167847c6ae99SBarry Smith         /* y_t = y; */
167947c6ae99SBarry Smith         s_t = bases[n3] + (i+1)*x_t - s_x;
168047c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1681*ce00eea3SSatish Balay       } else if (xs-Xs > 0) {
1682*ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
168347c6ae99SBarry Smith       }
168447c6ae99SBarry Smith 
168547c6ae99SBarry Smith       for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
168647c6ae99SBarry Smith 
168747c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
1688*ce00eea3SSatish Balay         x_t = lx[n5 % m];
168947c6ae99SBarry Smith         /* y_t = y; */
169047c6ae99SBarry Smith         s_t = bases[n5] + (i)*x_t;
169147c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1692*ce00eea3SSatish Balay       } else if (Xe-xe > 0) {
1693*ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
169447c6ae99SBarry Smith       }
169547c6ae99SBarry Smith     }
169647c6ae99SBarry Smith 
169747c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
169847c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
1699*ce00eea3SSatish Balay         x_t = lx[n6 % m];
170047c6ae99SBarry Smith         /* y_t = ly[(n6/m)]; */
170147c6ae99SBarry Smith         s_t = bases[n6] + (i)*x_t - s_x;
170247c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1703*ce00eea3SSatish Balay       } else if (xs-Xs > 0 && Ye-ye > 0) {
1704*ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
170547c6ae99SBarry Smith       }
170647c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
170747c6ae99SBarry Smith         x_t = x;
170847c6ae99SBarry Smith         /* y_t = ly[(n7/m)]; */
170947c6ae99SBarry Smith         s_t = bases[n7] + (i-1)*x_t;
171047c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
1711*ce00eea3SSatish Balay       } else if (Ye-ye > 0) {
1712*ce00eea3SSatish Balay         for (j=0; j<x; j++) { idx[nn++] = -1;}
171347c6ae99SBarry Smith       }
171447c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
1715*ce00eea3SSatish Balay         x_t = lx[n8 % m];
171647c6ae99SBarry Smith         /* y_t = ly[(n8/m)]; */
171747c6ae99SBarry Smith         s_t = bases[n8] + (i-1)*x_t;
171847c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
1719*ce00eea3SSatish Balay       } else if (Xe-xe > 0 && Ye-ye > 0) {
1720*ce00eea3SSatish Balay         for (j=0; j<s_x; j++) { idx[nn++] = -1;}
172147c6ae99SBarry Smith       }
172247c6ae99SBarry Smith     }
172347c6ae99SBarry Smith   }
1724*ce00eea3SSatish Balay   /*
1725*ce00eea3SSatish Balay      Set the local to global ordering in the global vector, this allows use
1726*ce00eea3SSatish Balay      of VecSetValuesLocal().
1727*ce00eea3SSatish Balay   */
1728*ce00eea3SSatish Balay   if (nn != (Xe-Xs)*(Ye-Ys)) {
1729*ce00eea3SSatish Balay     SETERRQ(((PetscObject)da)->comm, PETSC_ERR_SUP,"nn != count_dbg");
1730*ce00eea3SSatish Balay     PetscFunctionReturn(1);
1731*ce00eea3SSatish Balay   }
1732*ce00eea3SSatish Balay   ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_OWN_POINTER,&ltogis);CHKERRQ(ierr);
1733*ce00eea3SSatish Balay   ierr = PetscMalloc(nn*dof*sizeof(PetscInt),&idx_cpy);CHKERRQ(ierr);
1734*ce00eea3SSatish Balay   /*  ierr = PetscLogObjectMemory(da,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);*/
1735*ce00eea3SSatish Balay   ierr = ISGetIndices(ltogis, &idx_full);
1736*ce00eea3SSatish Balay   ierr = PetscMemcpy(idx_cpy,idx_full,nn*dof*sizeof(PetscInt));CHKERRQ(ierr);
1737*ce00eea3SSatish Balay   CHKMEMQ;
1738*ce00eea3SSatish Balay   ierr = ISRestoreIndices(ltogis, &idx_full);
1739*ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingCreateIS(ltogis,&da->ltogmap);CHKERRQ(ierr);
1740*ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
1741*ce00eea3SSatish Balay   ierr = ISDestroy(ltogis);CHKERRQ(ierr);
1742*ce00eea3SSatish Balay   ierr = ISLocalToGlobalMappingBlock(da->ltogmap,dd->w,&da->ltogmapb);CHKERRQ(ierr);
1743*ce00eea3SSatish Balay   ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr);
174447c6ae99SBarry Smith 
1745*ce00eea3SSatish Balay   ierr = PetscFree2(bases,ldims);CHKERRQ(ierr);
174647c6ae99SBarry Smith   dd->m  = m;  dd->n  = n;
1747*ce00eea3SSatish Balay   /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */
1748*ce00eea3SSatish Balay   dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1;
1749*ce00eea3SSatish Balay   dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1;
175047c6ae99SBarry Smith 
175147c6ae99SBarry Smith   ierr = VecDestroy(local);CHKERRQ(ierr);
175247c6ae99SBarry Smith   ierr = VecDestroy(global);CHKERRQ(ierr);
175347c6ae99SBarry Smith 
175447c6ae99SBarry Smith   dd->gtol      = gtol;
175547c6ae99SBarry Smith   dd->ltog      = ltog;
1756*ce00eea3SSatish Balay   dd->idx       = idx_cpy;
1757*ce00eea3SSatish Balay   dd->Nl        = nn*dof;
175847c6ae99SBarry Smith   dd->base      = base;
17599a42bb27SBarry Smith   da->ops->view = DMView_DA_2d;
176047c6ae99SBarry Smith   dd->ltol = PETSC_NULL;
176147c6ae99SBarry Smith   dd->ao   = PETSC_NULL;
176247c6ae99SBarry Smith 
176347c6ae99SBarry Smith   PetscFunctionReturn(0);
176447c6ae99SBarry Smith }
176547c6ae99SBarry Smith 
176647c6ae99SBarry Smith #undef __FUNCT__
1767aa219208SBarry Smith #define __FUNCT__ "DMDACreate2d"
176847c6ae99SBarry Smith /*@C
1769aa219208SBarry Smith    DMDACreate2d -  Creates an object that will manage the communication of  two-dimensional
177047c6ae99SBarry Smith    regular array data that is distributed across some processors.
177147c6ae99SBarry Smith 
177247c6ae99SBarry Smith    Collective on MPI_Comm
177347c6ae99SBarry Smith 
177447c6ae99SBarry Smith    Input Parameters:
177547c6ae99SBarry Smith +  comm - MPI communicator
177647c6ae99SBarry Smith .  wrap - type of periodicity should the array have.
1777aa219208SBarry Smith          Use one of DMDA_NONPERIODIC, DMDA_XPERIODIC, DMDA_YPERIODIC, or DMDA_XYPERIODIC.
1778aa219208SBarry Smith .  stencil_type - stencil type.  Use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR.
177947c6ae99SBarry 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
178047c6ae99SBarry Smith             from the command line with -da_grid_x <M> -da_grid_y <N>)
178147c6ae99SBarry Smith .  m,n - corresponding number of processors in each dimension
178247c6ae99SBarry Smith          (or PETSC_DECIDE to have calculated)
178347c6ae99SBarry Smith .  dof - number of degrees of freedom per node
178447c6ae99SBarry Smith .  s - stencil width
178547c6ae99SBarry Smith -  lx, ly - arrays containing the number of nodes in each cell along
178647c6ae99SBarry Smith            the x and y coordinates, or PETSC_NULL. If non-null, these
178747c6ae99SBarry Smith            must be of length as m and n, and the corresponding
178847c6ae99SBarry Smith            m and n cannot be PETSC_DECIDE. The sum of the lx[] entries
178947c6ae99SBarry Smith            must be M, and the sum of the ly[] entries must be N.
179047c6ae99SBarry Smith 
179147c6ae99SBarry Smith    Output Parameter:
179247c6ae99SBarry Smith .  da - the resulting distributed array object
179347c6ae99SBarry Smith 
179447c6ae99SBarry Smith    Options Database Key:
1795aa219208SBarry Smith +  -da_view - Calls DMView() at the conclusion of DMDACreate2d()
179647c6ae99SBarry Smith .  -da_grid_x <nx> - number of grid points in x direction, if M < 0
179747c6ae99SBarry Smith .  -da_grid_y <ny> - number of grid points in y direction, if N < 0
179847c6ae99SBarry Smith .  -da_processors_x <nx> - number of processors in x direction
179947c6ae99SBarry Smith .  -da_processors_y <ny> - number of processors in y direction
180047c6ae99SBarry Smith .  -da_refine_x - refinement ratio in x direction
180147c6ae99SBarry Smith -  -da_refine_y - refinement ratio in y direction
180247c6ae99SBarry Smith 
180347c6ae99SBarry Smith    Level: beginner
180447c6ae99SBarry Smith 
180547c6ae99SBarry Smith    Notes:
1806aa219208SBarry Smith    The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the
1807aa219208SBarry Smith    standard 5-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes
180847c6ae99SBarry Smith    the standard 9-pt stencil.
180947c6ae99SBarry Smith 
1810aa219208SBarry Smith    The array data itself is NOT stored in the DMDA, it is stored in Vec objects;
1811564755cdSBarry Smith    The appropriate vector objects can be obtained with calls to DMCreateGlobalVector()
1812564755cdSBarry Smith    and DMCreateLocalVector() and calls to VecDuplicate() if more are needed.
181347c6ae99SBarry Smith 
181447c6ae99SBarry Smith .keywords: distributed array, create, two-dimensional
181547c6ae99SBarry Smith 
1816aa219208SBarry Smith .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate3d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(),
1817aa219208SBarry Smith           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMDALocalToLocalBegin(), DMDALocalToLocalEnd(), DMDASetRefinementFactor(),
1818aa219208SBarry Smith           DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMDALoad(), DMDAGetOwnershipRanges()
181947c6ae99SBarry Smith 
182047c6ae99SBarry Smith @*/
18217087cfbeSBarry Smith PetscErrorCode  DMDACreate2d(MPI_Comm comm,DMDAPeriodicType wrap,DMDAStencilType stencil_type,
18229a42bb27SBarry Smith                           PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da)
182347c6ae99SBarry Smith {
182447c6ae99SBarry Smith   PetscErrorCode ierr;
182547c6ae99SBarry Smith 
182647c6ae99SBarry Smith   PetscFunctionBegin;
1827aa219208SBarry Smith   ierr = DMDACreate(comm, da);CHKERRQ(ierr);
1828aa219208SBarry Smith   ierr = DMDASetDim(*da, 2);CHKERRQ(ierr);
1829aa219208SBarry Smith   ierr = DMDASetSizes(*da, M, N, 1);CHKERRQ(ierr);
1830aa219208SBarry Smith   ierr = DMDASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr);
1831aa219208SBarry Smith   ierr = DMDASetPeriodicity(*da, wrap);CHKERRQ(ierr);
1832aa219208SBarry Smith   ierr = DMDASetDof(*da, dof);CHKERRQ(ierr);
1833aa219208SBarry Smith   ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr);
1834aa219208SBarry Smith   ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr);
1835aa219208SBarry Smith   ierr = DMDASetOwnershipRanges(*da, lx, ly, PETSC_NULL);CHKERRQ(ierr);
183647c6ae99SBarry Smith   /* This violates the behavior for other classes, but right now users expect negative dimensions to be handled this way */
18379a42bb27SBarry Smith   ierr = DMSetFromOptions(*da);CHKERRQ(ierr);
18389a42bb27SBarry Smith   ierr = DMSetUp(*da);CHKERRQ(ierr);
18397242296bSJed Brown   ierr = DMView_DA_Private(*da);CHKERRQ(ierr);
184047c6ae99SBarry Smith   PetscFunctionReturn(0);
184147c6ae99SBarry Smith }
1842