xref: /petsc/src/dm/impls/da/da2.c (revision 9a42bb27a39f0cdf3306a1e22d33cd9809484eaa)
1*9a42bb27SBarry Smith 
247c6ae99SBarry Smith #define PETSCDM_DLL
347c6ae99SBarry Smith 
447c6ae99SBarry Smith #include "private/daimpl.h"    /*I   "petscda.h"   I*/
547c6ae99SBarry Smith 
647c6ae99SBarry Smith #undef __FUNCT__
7*9a42bb27SBarry Smith #define __FUNCT__ "DMView_DA_2d"
8*9a42bb27SBarry Smith PetscErrorCode DMView_DA_2d(DM da,PetscViewer viewer)
947c6ae99SBarry Smith {
1047c6ae99SBarry Smith   PetscErrorCode ierr;
1147c6ae99SBarry Smith   PetscMPIInt    rank;
12*9a42bb27SBarry Smith   PetscBool      iascii,isdraw,isbinary;
1347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
14*9a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
15*9a42bb27SBarry Smith   PetscBool      ismatlab;
16*9a42bb27SBarry 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);
23*9a42bb27SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
24*9a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
25*9a42bb27SBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);CHKERRQ(ierr);
26*9a42bb27SBarry 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) {
3247c6ae99SBarry Smith       DALocalInfo info;
3347c6ae99SBarry Smith       ierr = DAGetLocalInfo(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);
3747c6ae99SBarry Smith     }
3847c6ae99SBarry Smith   } else if (isdraw) {
3947c6ae99SBarry Smith     PetscDraw       draw;
4047c6ae99SBarry Smith     double     ymin = -1*dd->s-1,ymax = dd->N+dd->s;
4147c6ae99SBarry Smith     double     xmin = -1*dd->s-1,xmax = dd->M+dd->s;
4247c6ae99SBarry Smith     double     x,y;
4347c6ae99SBarry Smith     PetscInt   base,*idx;
4447c6ae99SBarry Smith     char       node[10];
4547c6ae99SBarry Smith     PetscBool  isnull;
4647c6ae99SBarry Smith 
4747c6ae99SBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
4847c6ae99SBarry Smith     ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
4947c6ae99SBarry Smith     if (!dd->coordinates) {
5047c6ae99SBarry Smith       ierr = PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);CHKERRQ(ierr);
5147c6ae99SBarry Smith     }
5247c6ae99SBarry Smith     ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr);
5347c6ae99SBarry Smith 
5447c6ae99SBarry Smith     /* first processor draw all node lines */
5547c6ae99SBarry Smith     if (!rank) {
5647c6ae99SBarry Smith       ymin = 0.0; ymax = dd->N - 1;
5747c6ae99SBarry Smith       for (xmin=0; xmin<dd->M; xmin++) {
5847c6ae99SBarry Smith         ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_BLACK);CHKERRQ(ierr);
5947c6ae99SBarry Smith       }
6047c6ae99SBarry Smith       xmin = 0.0; xmax = dd->M - 1;
6147c6ae99SBarry Smith       for (ymin=0; ymin<dd->N; ymin++) {
6247c6ae99SBarry Smith         ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_BLACK);CHKERRQ(ierr);
6347c6ae99SBarry Smith       }
6447c6ae99SBarry Smith     }
6547c6ae99SBarry Smith     ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
6647c6ae99SBarry Smith     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
6747c6ae99SBarry Smith 
6847c6ae99SBarry Smith     /* draw my box */
6947c6ae99SBarry Smith     ymin = dd->ys; ymax = dd->ye - 1; xmin = dd->xs/dd->w;
7047c6ae99SBarry Smith     xmax =(dd->xe-1)/dd->w;
7147c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_RED);CHKERRQ(ierr);
7247c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
7347c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
7447c6ae99SBarry Smith     ierr = PetscDrawLine(draw,xmax,ymin,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
7547c6ae99SBarry Smith 
7647c6ae99SBarry Smith     /* put in numbers */
7747c6ae99SBarry Smith     base = (dd->base)/dd->w;
7847c6ae99SBarry Smith     for (y=ymin; y<=ymax; y++) {
7947c6ae99SBarry Smith       for (x=xmin; x<=xmax; x++) {
8047c6ae99SBarry Smith         sprintf(node,"%d",(int)base++);
8147c6ae99SBarry Smith         ierr = PetscDrawString(draw,x,y,PETSC_DRAW_BLACK,node);CHKERRQ(ierr);
8247c6ae99SBarry Smith       }
8347c6ae99SBarry Smith     }
8447c6ae99SBarry Smith 
8547c6ae99SBarry Smith     ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
8647c6ae99SBarry Smith     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
8747c6ae99SBarry Smith     /* overlay ghost numbers, useful for error checking */
8847c6ae99SBarry Smith     /* put in numbers */
8947c6ae99SBarry Smith 
9047c6ae99SBarry Smith     base = 0; idx = dd->idx;
9147c6ae99SBarry Smith     ymin = dd->Ys; ymax = dd->Ye; xmin = dd->Xs; xmax = dd->Xe;
9247c6ae99SBarry Smith     for (y=ymin; y<ymax; y++) {
9347c6ae99SBarry Smith       for (x=xmin; x<xmax; x++) {
9447c6ae99SBarry Smith         if ((base % dd->w) == 0) {
9547c6ae99SBarry Smith           sprintf(node,"%d",(int)(idx[base]/dd->w));
9647c6ae99SBarry Smith           ierr = PetscDrawString(draw,x/dd->w,y,PETSC_DRAW_BLUE,node);CHKERRQ(ierr);
9747c6ae99SBarry Smith         }
9847c6ae99SBarry Smith         base++;
9947c6ae99SBarry Smith       }
10047c6ae99SBarry Smith     }
10147c6ae99SBarry Smith     ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
10247c6ae99SBarry Smith     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
103*9a42bb27SBarry Smith   } else if (isbinary){
104*9a42bb27SBarry Smith     ierr = DMView_DA_Binary(da,viewer);CHKERRQ(ierr);
105*9a42bb27SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
106*9a42bb27SBarry Smith   } else if (ismatlab) {
107*9a42bb27SBarry Smith     ierr = DMView_DA_Matlab(da,viewer);CHKERRQ(ierr);
108*9a42bb27SBarry Smith #endif
109*9a42bb27SBarry Smith   } else SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for DA 1d",((PetscObject)viewer)->type_name);
11047c6ae99SBarry Smith   PetscFunctionReturn(0);
11147c6ae99SBarry Smith }
11247c6ae99SBarry Smith 
11347c6ae99SBarry Smith /*
11447c6ae99SBarry Smith       M is number of grid points
11547c6ae99SBarry Smith       m is number of processors
11647c6ae99SBarry Smith 
11747c6ae99SBarry Smith */
11847c6ae99SBarry Smith #undef __FUNCT__
11947c6ae99SBarry Smith #define __FUNCT__ "DASplitComm2d"
12047c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DASplitComm2d(MPI_Comm comm,PetscInt M,PetscInt N,PetscInt sw,MPI_Comm *outcomm)
12147c6ae99SBarry Smith {
12247c6ae99SBarry Smith   PetscErrorCode ierr;
12347c6ae99SBarry Smith   PetscInt       m,n = 0,x = 0,y = 0;
12447c6ae99SBarry Smith   PetscMPIInt    size,csize,rank;
12547c6ae99SBarry Smith 
12647c6ae99SBarry Smith   PetscFunctionBegin;
12747c6ae99SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
12847c6ae99SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
12947c6ae99SBarry Smith 
13047c6ae99SBarry Smith   csize = 4*size;
13147c6ae99SBarry Smith   do {
13247c6ae99SBarry 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);
13347c6ae99SBarry Smith     csize   = csize/4;
13447c6ae99SBarry Smith 
13547c6ae99SBarry Smith     m = (PetscInt)(0.5 + sqrt(((double)M)*((double)csize)/((double)N)));
13647c6ae99SBarry Smith     if (!m) m = 1;
13747c6ae99SBarry Smith     while (m > 0) {
13847c6ae99SBarry Smith       n = csize/m;
13947c6ae99SBarry Smith       if (m*n == csize) break;
14047c6ae99SBarry Smith       m--;
14147c6ae99SBarry Smith     }
14247c6ae99SBarry Smith     if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;}
14347c6ae99SBarry Smith 
14447c6ae99SBarry Smith     x = M/m + ((M % m) > ((csize-1) % m));
14547c6ae99SBarry Smith     y = (N + (csize-1)/m)/n;
14647c6ae99SBarry Smith   } while ((x < 4 || y < 4) && csize > 1);
14747c6ae99SBarry Smith   if (size != csize) {
14847c6ae99SBarry Smith     MPI_Group    entire_group,sub_group;
14947c6ae99SBarry Smith     PetscMPIInt  i,*groupies;
15047c6ae99SBarry Smith 
15147c6ae99SBarry Smith     ierr = MPI_Comm_group(comm,&entire_group);CHKERRQ(ierr);
15247c6ae99SBarry Smith     ierr = PetscMalloc(csize*sizeof(PetscInt),&groupies);CHKERRQ(ierr);
15347c6ae99SBarry Smith     for (i=0; i<csize; i++) {
15447c6ae99SBarry Smith       groupies[i] = (rank/csize)*csize + i;
15547c6ae99SBarry Smith     }
15647c6ae99SBarry Smith     ierr = MPI_Group_incl(entire_group,csize,groupies,&sub_group);CHKERRQ(ierr);
15747c6ae99SBarry Smith     ierr = PetscFree(groupies);CHKERRQ(ierr);
15847c6ae99SBarry Smith     ierr = MPI_Comm_create(comm,sub_group,outcomm);CHKERRQ(ierr);
15947c6ae99SBarry Smith     ierr = MPI_Group_free(&entire_group);CHKERRQ(ierr);
16047c6ae99SBarry Smith     ierr = MPI_Group_free(&sub_group);CHKERRQ(ierr);
16147c6ae99SBarry Smith     ierr = PetscInfo1(0,"DASplitComm2d:Creating redundant coarse problems of size %d\n",csize);CHKERRQ(ierr);
16247c6ae99SBarry Smith   } else {
16347c6ae99SBarry Smith     *outcomm = comm;
16447c6ae99SBarry Smith   }
16547c6ae99SBarry Smith   PetscFunctionReturn(0);
16647c6ae99SBarry Smith }
16747c6ae99SBarry Smith 
16847c6ae99SBarry Smith #undef __FUNCT__
1695dff015aSBarry Smith #define __FUNCT__ "DMGetElements_DA_2d_P1"
170*9a42bb27SBarry Smith PetscErrorCode DMGetElements_DA_2d_P1(DM da,PetscInt *n,const PetscInt *e[])
17147c6ae99SBarry Smith {
17247c6ae99SBarry Smith   PetscErrorCode ierr;
17347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
17447c6ae99SBarry Smith   PetscInt       i,j,cnt,xs,xe = dd->xe,ys,ye = dd->ye,Xs = dd->Xs, Xe = dd->Xe, Ys = dd->Ys;
17547c6ae99SBarry Smith 
17647c6ae99SBarry Smith   PetscFunctionBegin;
17747c6ae99SBarry Smith   if (!dd->e) {
17847c6ae99SBarry Smith     if (dd->xs == Xs) xs = dd->xs; else xs = dd->xs - 1;
17947c6ae99SBarry Smith     if (dd->ys == Ys) ys = dd->ys; else ys = dd->ys - 1;
18047c6ae99SBarry Smith     dd->ne = 2*(xe - xs - 1)*(ye - ys - 1);
18147c6ae99SBarry Smith     ierr   = PetscMalloc((1 + 3*dd->ne)*sizeof(PetscInt),&dd->e);CHKERRQ(ierr);
18247c6ae99SBarry Smith     cnt    = 0;
18347c6ae99SBarry Smith     for (j=ys; j<ye-1; j++) {
18447c6ae99SBarry Smith       for (i=xs; i<xe-1; i++) {
18547c6ae99SBarry Smith         dd->e[cnt]   = i - Xs + (j - Ys)*(Xe - Xs);
18647c6ae99SBarry Smith         dd->e[cnt+1] = i - Xs + 1 + (j - Ys)*(Xe - Xs);
18747c6ae99SBarry Smith         dd->e[cnt+2] = i - Xs + (j - Ys + 1)*(Xe - Xs);
18847c6ae99SBarry Smith 
18947c6ae99SBarry Smith         dd->e[cnt+3] = i - Xs + 1 + (j - Ys + 1)*(Xe - Xs);
19047c6ae99SBarry Smith         dd->e[cnt+4] = i - Xs + (j - Ys + 1)*(Xe - Xs);
19147c6ae99SBarry Smith         dd->e[cnt+5] = i - Xs + 1 + (j - Ys)*(Xe - Xs);
19247c6ae99SBarry Smith         cnt += 6;
19347c6ae99SBarry Smith       }
19447c6ae99SBarry Smith     }
19547c6ae99SBarry Smith   }
19647c6ae99SBarry Smith   *n = dd->ne;
19747c6ae99SBarry Smith   *e = dd->e;
19847c6ae99SBarry Smith   PetscFunctionReturn(0);
19947c6ae99SBarry Smith }
20047c6ae99SBarry Smith 
20147c6ae99SBarry Smith #undef __FUNCT__
20247c6ae99SBarry Smith #define __FUNCT__ "DASetLocalFunction"
20347c6ae99SBarry Smith /*@C
204*9a42bb27SBarry Smith        DASetLocalFunction - Caches in a DM a local function.
20547c6ae99SBarry Smith 
20647c6ae99SBarry Smith    Logically Collective on DA
20747c6ae99SBarry Smith 
20847c6ae99SBarry Smith    Input Parameter:
20947c6ae99SBarry Smith +  da - initial distributed array
21047c6ae99SBarry Smith -  lf - the local function
21147c6ae99SBarry Smith 
21247c6ae99SBarry Smith    Level: intermediate
21347c6ae99SBarry Smith 
21447c6ae99SBarry Smith    Notes: The routine SNESDAFormFunction() uses this the cached function to evaluate the user provided function.
21547c6ae99SBarry Smith 
21647c6ae99SBarry Smith .keywords:  distributed array, refine
21747c6ae99SBarry Smith 
218*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunctioni()
21947c6ae99SBarry Smith @*/
220*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DASetLocalFunction(DM da,DALocalFunction1 lf)
22147c6ae99SBarry Smith {
22247c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
22347c6ae99SBarry Smith   PetscFunctionBegin;
22447c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
22547c6ae99SBarry Smith   dd->lf    = lf;
22647c6ae99SBarry Smith   PetscFunctionReturn(0);
22747c6ae99SBarry Smith }
22847c6ae99SBarry Smith 
22947c6ae99SBarry Smith #undef __FUNCT__
23047c6ae99SBarry Smith #define __FUNCT__ "DASetLocalFunctioni"
23147c6ae99SBarry Smith /*@C
232*9a42bb27SBarry Smith        DASetLocalFunctioni - Caches in a DM a local function that evaluates a single component
23347c6ae99SBarry Smith 
23447c6ae99SBarry Smith    Logically Collective on DA
23547c6ae99SBarry Smith 
23647c6ae99SBarry Smith    Input Parameter:
23747c6ae99SBarry Smith +  da - initial distributed array
23847c6ae99SBarry Smith -  lfi - the local function
23947c6ae99SBarry Smith 
24047c6ae99SBarry Smith    Level: intermediate
24147c6ae99SBarry Smith 
24247c6ae99SBarry Smith .keywords:  distributed array, refine
24347c6ae99SBarry Smith 
244*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction()
24547c6ae99SBarry Smith @*/
246*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DASetLocalFunctioni(DM da,PetscErrorCode (*lfi)(DALocalInfo*,MatStencil*,void*,PetscScalar*,void*))
24747c6ae99SBarry Smith {
24847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
24947c6ae99SBarry Smith   PetscFunctionBegin;
25047c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
25147c6ae99SBarry Smith   dd->lfi = lfi;
25247c6ae99SBarry Smith   PetscFunctionReturn(0);
25347c6ae99SBarry Smith }
25447c6ae99SBarry Smith 
25547c6ae99SBarry Smith #undef __FUNCT__
25647c6ae99SBarry Smith #define __FUNCT__ "DASetLocalFunctionib"
25747c6ae99SBarry Smith /*@C
258*9a42bb27SBarry Smith        DASetLocalFunctionib - Caches in a DM a block local function that evaluates a single component
25947c6ae99SBarry Smith 
26047c6ae99SBarry Smith    Logically Collective on DA
26147c6ae99SBarry Smith 
26247c6ae99SBarry Smith    Input Parameter:
26347c6ae99SBarry Smith +  da - initial distributed array
26447c6ae99SBarry Smith -  lfi - the local function
26547c6ae99SBarry Smith 
26647c6ae99SBarry Smith    Level: intermediate
26747c6ae99SBarry Smith 
26847c6ae99SBarry Smith .keywords:  distributed array, refine
26947c6ae99SBarry Smith 
270*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction()
27147c6ae99SBarry Smith @*/
272*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DASetLocalFunctionib(DM da,PetscErrorCode (*lfi)(DALocalInfo*,MatStencil*,void*,PetscScalar*,void*))
27347c6ae99SBarry Smith {
27447c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
27547c6ae99SBarry Smith   PetscFunctionBegin;
27647c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
27747c6ae99SBarry Smith   dd->lfib = lfi;
27847c6ae99SBarry Smith   PetscFunctionReturn(0);
27947c6ae99SBarry Smith }
28047c6ae99SBarry Smith 
28147c6ae99SBarry Smith #undef __FUNCT__
28247c6ae99SBarry Smith #define __FUNCT__ "DASetLocalAdicFunction_Private"
283*9a42bb27SBarry Smith PetscErrorCode DASetLocalAdicFunction_Private(DM da,DALocalFunction1 ad_lf)
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_lf = ad_lf;
28947c6ae99SBarry Smith   PetscFunctionReturn(0);
29047c6ae99SBarry Smith }
29147c6ae99SBarry Smith 
29247c6ae99SBarry Smith /*MC
293*9a42bb27SBarry Smith        DASetLocalAdicFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR
29447c6ae99SBarry Smith 
29547c6ae99SBarry Smith    Synopsis:
296*9a42bb27SBarry Smith    PetscErrorCode DASetLocalAdicFunctioni(DM da,PetscInt (ad_lf*)(DALocalInfo*,MatStencil*,void*,void*,void*)
29747c6ae99SBarry Smith 
29847c6ae99SBarry Smith    Logically Collective on DA
29947c6ae99SBarry Smith 
30047c6ae99SBarry Smith    Input Parameter:
30147c6ae99SBarry Smith +  da - initial distributed array
30247c6ae99SBarry Smith -  ad_lfi - the local function as computed by ADIC/ADIFOR
30347c6ae99SBarry Smith 
30447c6ae99SBarry Smith    Level: intermediate
30547c6ae99SBarry Smith 
30647c6ae99SBarry Smith .keywords:  distributed array, refine
30747c6ae99SBarry Smith 
308*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction(),
30947c6ae99SBarry Smith           DASetLocalJacobian(), DASetLocalFunctioni()
31047c6ae99SBarry Smith M*/
31147c6ae99SBarry Smith 
31247c6ae99SBarry Smith #undef __FUNCT__
31347c6ae99SBarry Smith #define __FUNCT__ "DASetLocalAdicFunctioni_Private"
314*9a42bb27SBarry Smith PetscErrorCode DASetLocalAdicFunctioni_Private(DM da,PetscErrorCode (*ad_lfi)(DALocalInfo*,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->adic_lfi = ad_lfi;
32047c6ae99SBarry Smith   PetscFunctionReturn(0);
32147c6ae99SBarry Smith }
32247c6ae99SBarry Smith 
32347c6ae99SBarry Smith /*MC
324*9a42bb27SBarry Smith        DASetLocalAdicMFFunctioni - Caches in a DM a local functioni computed by ADIC/ADIFOR
32547c6ae99SBarry Smith 
32647c6ae99SBarry Smith    Synopsis:
327*9a42bb27SBarry Smith    PetscErrorCode  DASetLocalAdicFunctioni(DM da,int (ad_lf*)(DALocalInfo*,MatStencil*,void*,void*,void*)
32847c6ae99SBarry Smith 
32947c6ae99SBarry Smith    Logically Collective on DA
33047c6ae99SBarry Smith 
33147c6ae99SBarry Smith    Input Parameter:
33247c6ae99SBarry Smith +  da - initial distributed array
33347c6ae99SBarry Smith -  admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR
33447c6ae99SBarry Smith 
33547c6ae99SBarry Smith    Level: intermediate
33647c6ae99SBarry Smith 
33747c6ae99SBarry Smith .keywords:  distributed array, refine
33847c6ae99SBarry Smith 
339*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction(),
34047c6ae99SBarry Smith           DASetLocalJacobian(), DASetLocalFunctioni()
34147c6ae99SBarry Smith M*/
34247c6ae99SBarry Smith 
34347c6ae99SBarry Smith #undef __FUNCT__
34447c6ae99SBarry Smith #define __FUNCT__ "DASetLocalAdicMFFunctioni_Private"
345*9a42bb27SBarry Smith PetscErrorCode DASetLocalAdicMFFunctioni_Private(DM da,PetscErrorCode (*admf_lfi)(DALocalInfo*,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->adicmf_lfi = admf_lfi;
35147c6ae99SBarry Smith   PetscFunctionReturn(0);
35247c6ae99SBarry Smith }
35347c6ae99SBarry Smith 
35447c6ae99SBarry Smith /*MC
355*9a42bb27SBarry Smith        DASetLocalAdicFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR
35647c6ae99SBarry Smith 
35747c6ae99SBarry Smith    Synopsis:
358*9a42bb27SBarry Smith    PetscErrorCode DASetLocalAdicFunctionib(DM da,PetscInt (ad_lf*)(DALocalInfo*,MatStencil*,void*,void*,void*)
35947c6ae99SBarry Smith 
36047c6ae99SBarry Smith    Logically Collective on DA
36147c6ae99SBarry Smith 
36247c6ae99SBarry Smith    Input Parameter:
36347c6ae99SBarry Smith +  da - initial distributed array
36447c6ae99SBarry Smith -  ad_lfi - the local function as computed by ADIC/ADIFOR
36547c6ae99SBarry Smith 
36647c6ae99SBarry Smith    Level: intermediate
36747c6ae99SBarry Smith 
36847c6ae99SBarry Smith .keywords:  distributed array, refine
36947c6ae99SBarry Smith 
370*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction(),
37147c6ae99SBarry Smith           DASetLocalJacobian(), DASetLocalFunctionib()
37247c6ae99SBarry Smith M*/
37347c6ae99SBarry Smith 
37447c6ae99SBarry Smith #undef __FUNCT__
37547c6ae99SBarry Smith #define __FUNCT__ "DASetLocalAdicFunctionib_Private"
376*9a42bb27SBarry Smith PetscErrorCode DASetLocalAdicFunctionib_Private(DM da,PetscErrorCode (*ad_lfi)(DALocalInfo*,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->adic_lfib = ad_lfi;
38247c6ae99SBarry Smith   PetscFunctionReturn(0);
38347c6ae99SBarry Smith }
38447c6ae99SBarry Smith 
38547c6ae99SBarry Smith /*MC
386*9a42bb27SBarry Smith        DASetLocalAdicMFFunctionib - Caches in a DM a block local functioni computed by ADIC/ADIFOR
38747c6ae99SBarry Smith 
38847c6ae99SBarry Smith    Synopsis:
389*9a42bb27SBarry Smith    PetscErrorCode  DASetLocalAdicFunctionib(DM da,int (ad_lf*)(DALocalInfo*,MatStencil*,void*,void*,void*)
39047c6ae99SBarry Smith 
39147c6ae99SBarry Smith    Logically Collective on DA
39247c6ae99SBarry Smith 
39347c6ae99SBarry Smith    Input Parameter:
39447c6ae99SBarry Smith +  da - initial distributed array
39547c6ae99SBarry Smith -  admf_lfi - the local matrix-free function as computed by ADIC/ADIFOR
39647c6ae99SBarry Smith 
39747c6ae99SBarry Smith    Level: intermediate
39847c6ae99SBarry Smith 
39947c6ae99SBarry Smith .keywords:  distributed array, refine
40047c6ae99SBarry Smith 
401*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction(),
40247c6ae99SBarry Smith           DASetLocalJacobian(), DASetLocalFunctionib()
40347c6ae99SBarry Smith M*/
40447c6ae99SBarry Smith 
40547c6ae99SBarry Smith #undef __FUNCT__
40647c6ae99SBarry Smith #define __FUNCT__ "DASetLocalAdicMFFunctionib_Private"
407*9a42bb27SBarry Smith PetscErrorCode DASetLocalAdicMFFunctionib_Private(DM da,PetscErrorCode (*admf_lfi)(DALocalInfo*,MatStencil*,void*,void*,void*))
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_lfib = admf_lfi;
41347c6ae99SBarry Smith   PetscFunctionReturn(0);
41447c6ae99SBarry Smith }
41547c6ae99SBarry Smith 
41647c6ae99SBarry Smith /*MC
417*9a42bb27SBarry Smith        DASetLocalAdicMFFunction - Caches in a DM a local function computed by ADIC/ADIFOR
41847c6ae99SBarry Smith 
41947c6ae99SBarry Smith    Synopsis:
420*9a42bb27SBarry Smith    PetscErrorCode DASetLocalAdicMFFunction(DM da,DALocalFunction1 ad_lf)
42147c6ae99SBarry Smith 
42247c6ae99SBarry Smith    Logically Collective on DA
42347c6ae99SBarry Smith 
42447c6ae99SBarry Smith    Input Parameter:
42547c6ae99SBarry Smith +  da - initial distributed array
42647c6ae99SBarry Smith -  ad_lf - the local function as computed by ADIC/ADIFOR
42747c6ae99SBarry Smith 
42847c6ae99SBarry Smith    Level: intermediate
42947c6ae99SBarry Smith 
43047c6ae99SBarry Smith .keywords:  distributed array, refine
43147c6ae99SBarry Smith 
432*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction(),
43347c6ae99SBarry Smith           DASetLocalJacobian()
43447c6ae99SBarry Smith M*/
43547c6ae99SBarry Smith 
43647c6ae99SBarry Smith #undef __FUNCT__
43747c6ae99SBarry Smith #define __FUNCT__ "DASetLocalAdicMFFunction_Private"
438*9a42bb27SBarry Smith PetscErrorCode DASetLocalAdicMFFunction_Private(DM da,DALocalFunction1 ad_lf)
43947c6ae99SBarry Smith {
44047c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
44147c6ae99SBarry Smith   PetscFunctionBegin;
44247c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
44347c6ae99SBarry Smith   dd->adicmf_lf = ad_lf;
44447c6ae99SBarry Smith   PetscFunctionReturn(0);
44547c6ae99SBarry Smith }
44647c6ae99SBarry Smith 
44747c6ae99SBarry Smith /*@C
448*9a42bb27SBarry Smith        DASetLocalJacobian - Caches in a DM a local Jacobian computation function
44947c6ae99SBarry Smith 
45047c6ae99SBarry Smith    Logically Collective on DA
45147c6ae99SBarry Smith 
45247c6ae99SBarry Smith 
45347c6ae99SBarry Smith    Input Parameter:
45447c6ae99SBarry Smith +  da - initial distributed array
45547c6ae99SBarry Smith -  lj - the local Jacobian
45647c6ae99SBarry Smith 
45747c6ae99SBarry Smith    Level: intermediate
45847c6ae99SBarry Smith 
45947c6ae99SBarry Smith    Notes: The routine SNESDAFormFunction() uses this the cached function to evaluate the user provided function.
46047c6ae99SBarry Smith 
46147c6ae99SBarry Smith .keywords:  distributed array, refine
46247c6ae99SBarry Smith 
463*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalFunction()
46447c6ae99SBarry Smith @*/
46547c6ae99SBarry Smith #undef __FUNCT__
46647c6ae99SBarry Smith #define __FUNCT__ "DASetLocalJacobian"
467*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DASetLocalJacobian(DM da,DALocalFunction1 lj)
46847c6ae99SBarry Smith {
46947c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
47047c6ae99SBarry Smith   PetscFunctionBegin;
47147c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
47247c6ae99SBarry Smith   dd->lj    = lj;
47347c6ae99SBarry Smith   PetscFunctionReturn(0);
47447c6ae99SBarry Smith }
47547c6ae99SBarry Smith 
47647c6ae99SBarry Smith #undef __FUNCT__
47747c6ae99SBarry Smith #define __FUNCT__ "DAGetLocalFunction"
47847c6ae99SBarry Smith /*@C
479*9a42bb27SBarry Smith        DAGetLocalFunction - Gets from a DM a local function and its ADIC/ADIFOR Jacobian
48047c6ae99SBarry Smith 
48147c6ae99SBarry Smith    Note Collective
48247c6ae99SBarry Smith 
48347c6ae99SBarry Smith    Input Parameter:
48447c6ae99SBarry Smith .  da - initial distributed array
48547c6ae99SBarry Smith 
48647c6ae99SBarry Smith    Output Parameter:
48747c6ae99SBarry Smith .  lf - the local function
48847c6ae99SBarry Smith 
48947c6ae99SBarry Smith    Level: intermediate
49047c6ae99SBarry Smith 
49147c6ae99SBarry Smith .keywords:  distributed array, refine
49247c6ae99SBarry Smith 
493*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalJacobian(), DASetLocalFunction()
49447c6ae99SBarry Smith @*/
495*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAGetLocalFunction(DM da,DALocalFunction1 *lf)
49647c6ae99SBarry Smith {
49747c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
49847c6ae99SBarry Smith   PetscFunctionBegin;
49947c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
50047c6ae99SBarry Smith   if (lf)       *lf = dd->lf;
50147c6ae99SBarry Smith   PetscFunctionReturn(0);
50247c6ae99SBarry Smith }
50347c6ae99SBarry Smith 
50447c6ae99SBarry Smith #undef __FUNCT__
50547c6ae99SBarry Smith #define __FUNCT__ "DAGetLocalJacobian"
50647c6ae99SBarry Smith /*@C
507*9a42bb27SBarry Smith        DAGetLocalJacobian - Gets from a DM a local jacobian
50847c6ae99SBarry Smith 
50947c6ae99SBarry Smith    Not Collective
51047c6ae99SBarry Smith 
51147c6ae99SBarry Smith    Input Parameter:
51247c6ae99SBarry Smith .  da - initial distributed array
51347c6ae99SBarry Smith 
51447c6ae99SBarry Smith    Output Parameter:
51547c6ae99SBarry Smith .  lj - the local jacobian
51647c6ae99SBarry Smith 
51747c6ae99SBarry Smith    Level: intermediate
51847c6ae99SBarry Smith 
51947c6ae99SBarry Smith .keywords:  distributed array, refine
52047c6ae99SBarry Smith 
521*9a42bb27SBarry Smith .seealso: DACreate1d(), DACreate2d(), DACreate3d(), DMDestroy(), DAGetLocalFunction(), DASetLocalJacobian()
52247c6ae99SBarry Smith @*/
523*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAGetLocalJacobian(DM da,DALocalFunction1 *lj)
52447c6ae99SBarry Smith {
52547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
52647c6ae99SBarry Smith   PetscFunctionBegin;
52747c6ae99SBarry Smith   PetscValidHeaderSpecific(da,DM_CLASSID,1);
52847c6ae99SBarry Smith   if (lj) *lj = dd->lj;
52947c6ae99SBarry Smith   PetscFunctionReturn(0);
53047c6ae99SBarry Smith }
53147c6ae99SBarry Smith 
53247c6ae99SBarry Smith #undef __FUNCT__
53347c6ae99SBarry Smith #define __FUNCT__ "DAFormFunction"
53447c6ae99SBarry Smith /*@
53547c6ae99SBarry Smith     DAFormFunction - Evaluates a user provided function on each processor that
53647c6ae99SBarry Smith         share a DA
53747c6ae99SBarry Smith 
53847c6ae99SBarry Smith    Input Parameters:
539*9a42bb27SBarry Smith +    da - the DM that defines the grid
54047c6ae99SBarry Smith .    vu - input vector
54147c6ae99SBarry Smith .    vfu - output vector
54247c6ae99SBarry Smith -    w - any user data
54347c6ae99SBarry Smith 
54447c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
54547c6ae99SBarry Smith 
54647c6ae99SBarry Smith            This should eventually replace DAFormFunction1
54747c6ae99SBarry Smith 
54847c6ae99SBarry Smith     Level: advanced
54947c6ae99SBarry Smith 
55047c6ae99SBarry Smith .seealso: DAComputeJacobian1WithAdic()
55147c6ae99SBarry Smith 
55247c6ae99SBarry Smith @*/
553*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormFunction(DM da,PetscErrorCode (*lf)(void),Vec vu,Vec vfu,void *w)
55447c6ae99SBarry Smith {
55547c6ae99SBarry Smith   PetscErrorCode ierr;
55647c6ae99SBarry Smith   void           *u,*fu;
55747c6ae99SBarry Smith   DALocalInfo    info;
55847c6ae99SBarry Smith   PetscErrorCode (*f)(DALocalInfo*,void*,void*,void*) = (PetscErrorCode (*)(DALocalInfo*,void*,void*,void*))lf;
55947c6ae99SBarry Smith 
56047c6ae99SBarry Smith   PetscFunctionBegin;
56147c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
56247c6ae99SBarry Smith   ierr = DAVecGetArray(da,vu,&u);CHKERRQ(ierr);
56347c6ae99SBarry Smith   ierr = DAVecGetArray(da,vfu,&fu);CHKERRQ(ierr);
56447c6ae99SBarry Smith 
56547c6ae99SBarry Smith   ierr = (*f)(&info,u,fu,w);
56647c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
56747c6ae99SBarry Smith     PetscErrorCode pierr = DAVecRestoreArray(da,vu,&u);CHKERRQ(pierr);
56847c6ae99SBarry Smith     pierr = DAVecRestoreArray(da,vfu,&fu);CHKERRQ(pierr);
56947c6ae99SBarry Smith   }
57047c6ae99SBarry Smith  CHKERRQ(ierr);
57147c6ae99SBarry Smith 
57247c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
57347c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr);
57447c6ae99SBarry Smith   PetscFunctionReturn(0);
57547c6ae99SBarry Smith }
57647c6ae99SBarry Smith 
57747c6ae99SBarry Smith #undef __FUNCT__
57847c6ae99SBarry Smith #define __FUNCT__ "DAFormFunctionLocal"
57947c6ae99SBarry Smith /*@C
58047c6ae99SBarry Smith    DAFormFunctionLocal - This is a universal function evaluation routine for
581*9a42bb27SBarry Smith    a local DM function.
58247c6ae99SBarry Smith 
58347c6ae99SBarry Smith    Collective on DA
58447c6ae99SBarry Smith 
58547c6ae99SBarry Smith    Input Parameters:
586*9a42bb27SBarry Smith +  da - the DM context
58747c6ae99SBarry Smith .  func - The local function
58847c6ae99SBarry Smith .  X - input vector
58947c6ae99SBarry Smith .  F - function vector
59047c6ae99SBarry Smith -  ctx - A user context
59147c6ae99SBarry Smith 
59247c6ae99SBarry Smith    Level: intermediate
59347c6ae99SBarry Smith 
59447c6ae99SBarry Smith .seealso: DASetLocalFunction(), DASetLocalJacobian(), DASetLocalAdicFunction(), DASetLocalAdicMFFunction(),
59547c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
59647c6ae99SBarry Smith 
59747c6ae99SBarry Smith @*/
598*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormFunctionLocal(DM da, DALocalFunction1 func, Vec X, Vec F, void *ctx)
59947c6ae99SBarry Smith {
60047c6ae99SBarry Smith   Vec            localX;
60147c6ae99SBarry Smith   DALocalInfo    info;
60247c6ae99SBarry Smith   void          *u;
60347c6ae99SBarry Smith   void          *fu;
60447c6ae99SBarry Smith   PetscErrorCode ierr;
60547c6ae99SBarry Smith 
60647c6ae99SBarry Smith   PetscFunctionBegin;
607*9a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
60847c6ae99SBarry Smith   /*
60947c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
610*9a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
61147c6ae99SBarry Smith   */
612*9a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
613*9a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
61447c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
61547c6ae99SBarry Smith   ierr = DAVecGetArray(da,localX,&u);CHKERRQ(ierr);
61647c6ae99SBarry Smith   ierr = DAVecGetArray(da,F,&fu);CHKERRQ(ierr);
61747c6ae99SBarry Smith   ierr = (*func)(&info,u,fu,ctx);
61847c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
61947c6ae99SBarry Smith     PetscErrorCode pierr = DAVecRestoreArray(da,localX,&u);CHKERRQ(pierr);
62047c6ae99SBarry Smith     pierr = DAVecRestoreArray(da,F,&fu);CHKERRQ(pierr);
62147c6ae99SBarry Smith   }
62247c6ae99SBarry Smith  CHKERRQ(ierr);
62347c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
62447c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,F,&fu);CHKERRQ(ierr);
62547c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
626*9a42bb27SBarry Smith     PetscErrorCode pierr = DMRestoreLocalVector(da,&localX);CHKERRQ(pierr);
62747c6ae99SBarry Smith   }
62847c6ae99SBarry Smith  CHKERRQ(ierr);
629*9a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
63047c6ae99SBarry Smith   PetscFunctionReturn(0);
63147c6ae99SBarry Smith }
63247c6ae99SBarry Smith 
63347c6ae99SBarry Smith #undef __FUNCT__
63447c6ae99SBarry Smith #define __FUNCT__ "DAFormFunctionLocalGhost"
63547c6ae99SBarry Smith /*@C
63647c6ae99SBarry Smith    DAFormFunctionLocalGhost - This is a universal function evaluation routine for
637*9a42bb27SBarry Smith    a local DM function, but the ghost values of the output are communicated and added.
63847c6ae99SBarry Smith 
63947c6ae99SBarry Smith    Collective on DA
64047c6ae99SBarry Smith 
64147c6ae99SBarry Smith    Input Parameters:
642*9a42bb27SBarry Smith +  da - the DM context
64347c6ae99SBarry Smith .  func - The local function
64447c6ae99SBarry Smith .  X - input vector
64547c6ae99SBarry Smith .  F - function vector
64647c6ae99SBarry Smith -  ctx - A user context
64747c6ae99SBarry Smith 
64847c6ae99SBarry Smith    Level: intermediate
64947c6ae99SBarry Smith 
65047c6ae99SBarry Smith .seealso: DASetLocalFunction(), DASetLocalJacobian(), DASetLocalAdicFunction(), DASetLocalAdicMFFunction(),
65147c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
65247c6ae99SBarry Smith 
65347c6ae99SBarry Smith @*/
654*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormFunctionLocalGhost(DM da, DALocalFunction1 func, Vec X, Vec F, void *ctx)
65547c6ae99SBarry Smith {
65647c6ae99SBarry Smith   Vec            localX, localF;
65747c6ae99SBarry Smith   DALocalInfo    info;
65847c6ae99SBarry Smith   void          *u;
65947c6ae99SBarry Smith   void          *fu;
66047c6ae99SBarry Smith   PetscErrorCode ierr;
66147c6ae99SBarry Smith 
66247c6ae99SBarry Smith   PetscFunctionBegin;
663*9a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
664*9a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localF);CHKERRQ(ierr);
66547c6ae99SBarry Smith   /*
66647c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
667*9a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
66847c6ae99SBarry Smith   */
669*9a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
670*9a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
67147c6ae99SBarry Smith   ierr = VecSet(F, 0.0);CHKERRQ(ierr);
67247c6ae99SBarry Smith   ierr = VecSet(localF, 0.0);CHKERRQ(ierr);
67347c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
67447c6ae99SBarry Smith   ierr = DAVecGetArray(da,localX,&u);CHKERRQ(ierr);
67547c6ae99SBarry Smith   ierr = DAVecGetArray(da,localF,&fu);CHKERRQ(ierr);
67647c6ae99SBarry Smith   ierr = (*func)(&info,u,fu,ctx);
67747c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
67847c6ae99SBarry Smith     PetscErrorCode pierr = DAVecRestoreArray(da,localX,&u);CHKERRQ(pierr);
67947c6ae99SBarry Smith     pierr = DAVecRestoreArray(da,localF,&fu);CHKERRQ(pierr);
68047c6ae99SBarry Smith   }
68147c6ae99SBarry Smith   CHKERRQ(ierr);
682*9a42bb27SBarry Smith   ierr = DMLocalToGlobalBegin(da,localF,ADD_VALUES,F);CHKERRQ(ierr);
683*9a42bb27SBarry Smith   ierr = DMLocalToGlobalEnd(da,localF,ADD_VALUES,F);CHKERRQ(ierr);
68447c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
68547c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,localF,&fu);CHKERRQ(ierr);
68647c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
687*9a42bb27SBarry Smith     PetscErrorCode pierr = DMRestoreLocalVector(da,&localX);CHKERRQ(pierr);
688*9a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localF);CHKERRQ(ierr);
68947c6ae99SBarry Smith   }
69047c6ae99SBarry Smith   CHKERRQ(ierr);
691*9a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
692*9a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localF);CHKERRQ(ierr);
69347c6ae99SBarry Smith   PetscFunctionReturn(0);
69447c6ae99SBarry Smith }
69547c6ae99SBarry Smith 
69647c6ae99SBarry Smith #undef __FUNCT__
69747c6ae99SBarry Smith #define __FUNCT__ "DAFormFunction1"
69847c6ae99SBarry Smith /*@
69947c6ae99SBarry Smith     DAFormFunction1 - Evaluates a user provided function on each processor that
70047c6ae99SBarry Smith         share a DA
70147c6ae99SBarry Smith 
70247c6ae99SBarry Smith    Input Parameters:
703*9a42bb27SBarry Smith +    da - the DM that defines the grid
70447c6ae99SBarry Smith .    vu - input vector
70547c6ae99SBarry Smith .    vfu - output vector
70647c6ae99SBarry Smith -    w - any user data
70747c6ae99SBarry Smith 
70847c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
70947c6ae99SBarry Smith 
71047c6ae99SBarry Smith     Level: advanced
71147c6ae99SBarry Smith 
71247c6ae99SBarry Smith .seealso: DAComputeJacobian1WithAdic()
71347c6ae99SBarry Smith 
71447c6ae99SBarry Smith @*/
715*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormFunction1(DM da,Vec vu,Vec vfu,void *w)
71647c6ae99SBarry Smith {
71747c6ae99SBarry Smith   PetscErrorCode ierr;
71847c6ae99SBarry Smith   void           *u,*fu;
71947c6ae99SBarry Smith   DALocalInfo    info;
72047c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
72147c6ae99SBarry Smith 
72247c6ae99SBarry Smith   PetscFunctionBegin;
72347c6ae99SBarry Smith 
72447c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
72547c6ae99SBarry Smith   ierr = DAVecGetArray(da,vu,&u);CHKERRQ(ierr);
72647c6ae99SBarry Smith   ierr = DAVecGetArray(da,vfu,&fu);CHKERRQ(ierr);
72747c6ae99SBarry Smith 
72847c6ae99SBarry Smith   CHKMEMQ;
72947c6ae99SBarry Smith   ierr = (*dd->lf)(&info,u,fu,w);
73047c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
73147c6ae99SBarry Smith     PetscErrorCode pierr = DAVecRestoreArray(da,vu,&u);CHKERRQ(pierr);
73247c6ae99SBarry Smith     pierr = DAVecRestoreArray(da,vfu,&fu);CHKERRQ(pierr);
73347c6ae99SBarry Smith   }
73447c6ae99SBarry Smith   CHKERRQ(ierr);
73547c6ae99SBarry Smith   CHKMEMQ;
73647c6ae99SBarry Smith 
73747c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
73847c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,vfu,&fu);CHKERRQ(ierr);
73947c6ae99SBarry Smith   PetscFunctionReturn(0);
74047c6ae99SBarry Smith }
74147c6ae99SBarry Smith 
74247c6ae99SBarry Smith #undef __FUNCT__
74347c6ae99SBarry Smith #define __FUNCT__ "DAFormFunctioniTest1"
744*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormFunctioniTest1(DM da,void *w)
74547c6ae99SBarry Smith {
74647c6ae99SBarry Smith   Vec            vu,fu,fui;
74747c6ae99SBarry Smith   PetscErrorCode ierr;
74847c6ae99SBarry Smith   PetscInt       i,n;
74947c6ae99SBarry Smith   PetscScalar    *ui;
75047c6ae99SBarry Smith   PetscRandom    rnd;
75147c6ae99SBarry Smith   PetscReal      norm;
75247c6ae99SBarry Smith 
75347c6ae99SBarry Smith   PetscFunctionBegin;
754*9a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&vu);CHKERRQ(ierr);
75547c6ae99SBarry Smith   ierr = PetscRandomCreate(PETSC_COMM_SELF,&rnd);CHKERRQ(ierr);
75647c6ae99SBarry Smith   ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr);
75747c6ae99SBarry Smith   ierr = VecSetRandom(vu,rnd);CHKERRQ(ierr);
75847c6ae99SBarry Smith   ierr = PetscRandomDestroy(rnd);CHKERRQ(ierr);
75947c6ae99SBarry Smith 
760*9a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&fu);CHKERRQ(ierr);
761*9a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&fui);CHKERRQ(ierr);
76247c6ae99SBarry Smith 
76347c6ae99SBarry Smith   ierr = DAFormFunction1(da,vu,fu,w);CHKERRQ(ierr);
76447c6ae99SBarry Smith 
76547c6ae99SBarry Smith   ierr = VecGetArray(fui,&ui);CHKERRQ(ierr);
76647c6ae99SBarry Smith   ierr = VecGetLocalSize(fui,&n);CHKERRQ(ierr);
76747c6ae99SBarry Smith   for (i=0; i<n; i++) {
76847c6ae99SBarry Smith     ierr = DAFormFunctioni1(da,i,vu,ui+i,w);CHKERRQ(ierr);
76947c6ae99SBarry Smith   }
77047c6ae99SBarry Smith   ierr = VecRestoreArray(fui,&ui);CHKERRQ(ierr);
77147c6ae99SBarry Smith 
77247c6ae99SBarry Smith   ierr = VecAXPY(fui,-1.0,fu);CHKERRQ(ierr);
77347c6ae99SBarry Smith   ierr = VecNorm(fui,NORM_2,&norm);CHKERRQ(ierr);
77447c6ae99SBarry Smith   ierr = PetscPrintf(((PetscObject)da)->comm,"Norm of difference in vectors %G\n",norm);CHKERRQ(ierr);
77547c6ae99SBarry Smith   ierr = VecView(fu,0);CHKERRQ(ierr);
77647c6ae99SBarry Smith   ierr = VecView(fui,0);CHKERRQ(ierr);
77747c6ae99SBarry Smith 
778*9a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&vu);CHKERRQ(ierr);
779*9a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&fu);CHKERRQ(ierr);
780*9a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&fui);CHKERRQ(ierr);
78147c6ae99SBarry Smith   PetscFunctionReturn(0);
78247c6ae99SBarry Smith }
78347c6ae99SBarry Smith 
78447c6ae99SBarry Smith #undef __FUNCT__
78547c6ae99SBarry Smith #define __FUNCT__ "DAFormFunctioni1"
78647c6ae99SBarry Smith /*@
78747c6ae99SBarry Smith     DAFormFunctioni1 - Evaluates a user provided point-wise function
78847c6ae99SBarry Smith 
78947c6ae99SBarry Smith    Input Parameters:
790*9a42bb27SBarry Smith +    da - the DM that defines the grid
79147c6ae99SBarry Smith .    i - the component of the function we wish to compute (must be local)
79247c6ae99SBarry Smith .    vu - input vector
79347c6ae99SBarry Smith .    vfu - output value
79447c6ae99SBarry Smith -    w - any user data
79547c6ae99SBarry Smith 
79647c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
79747c6ae99SBarry Smith 
79847c6ae99SBarry Smith     Level: advanced
79947c6ae99SBarry Smith 
80047c6ae99SBarry Smith .seealso: DAComputeJacobian1WithAdic()
80147c6ae99SBarry Smith 
80247c6ae99SBarry Smith @*/
803*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormFunctioni1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w)
80447c6ae99SBarry Smith {
80547c6ae99SBarry Smith   PetscErrorCode ierr;
80647c6ae99SBarry Smith   void           *u;
80747c6ae99SBarry Smith   DALocalInfo    info;
80847c6ae99SBarry Smith   MatStencil     stencil;
80947c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
81047c6ae99SBarry Smith 
81147c6ae99SBarry Smith   PetscFunctionBegin;
81247c6ae99SBarry Smith 
81347c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
81447c6ae99SBarry Smith   ierr = DAVecGetArray(da,vu,&u);CHKERRQ(ierr);
81547c6ae99SBarry Smith 
81647c6ae99SBarry Smith   /* figure out stencil value from i */
81747c6ae99SBarry Smith   stencil.c = i % info.dof;
81847c6ae99SBarry Smith   stencil.i = (i % (info.xm*info.dof))/info.dof;
81947c6ae99SBarry Smith   stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof);
82047c6ae99SBarry Smith   stencil.k = i/(info.xm*info.ym*info.dof);
82147c6ae99SBarry Smith 
82247c6ae99SBarry Smith   ierr = (*dd->lfi)(&info,&stencil,u,vfu,w);CHKERRQ(ierr);
82347c6ae99SBarry Smith 
82447c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
82547c6ae99SBarry Smith   PetscFunctionReturn(0);
82647c6ae99SBarry Smith }
82747c6ae99SBarry Smith 
82847c6ae99SBarry Smith #undef __FUNCT__
82947c6ae99SBarry Smith #define __FUNCT__ "DAFormFunctionib1"
83047c6ae99SBarry Smith /*@
83147c6ae99SBarry Smith     DAFormFunctionib1 - Evaluates a user provided point-block function
83247c6ae99SBarry Smith 
83347c6ae99SBarry Smith    Input Parameters:
834*9a42bb27SBarry Smith +    da - the DM that defines the grid
83547c6ae99SBarry Smith .    i - the component of the function we wish to compute (must be local)
83647c6ae99SBarry Smith .    vu - input vector
83747c6ae99SBarry Smith .    vfu - output value
83847c6ae99SBarry Smith -    w - any user data
83947c6ae99SBarry Smith 
84047c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
84147c6ae99SBarry Smith 
84247c6ae99SBarry Smith     Level: advanced
84347c6ae99SBarry Smith 
84447c6ae99SBarry Smith .seealso: DAComputeJacobian1WithAdic()
84547c6ae99SBarry Smith 
84647c6ae99SBarry Smith @*/
847*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormFunctionib1(DM da,PetscInt i,Vec vu,PetscScalar *vfu,void *w)
84847c6ae99SBarry Smith {
84947c6ae99SBarry Smith   PetscErrorCode ierr;
85047c6ae99SBarry Smith   void           *u;
85147c6ae99SBarry Smith   DALocalInfo    info;
85247c6ae99SBarry Smith   MatStencil     stencil;
85347c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
85447c6ae99SBarry Smith 
85547c6ae99SBarry Smith   PetscFunctionBegin;
85647c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
85747c6ae99SBarry Smith   ierr = DAVecGetArray(da,vu,&u);CHKERRQ(ierr);
85847c6ae99SBarry Smith 
85947c6ae99SBarry Smith   /* figure out stencil value from i */
86047c6ae99SBarry Smith   stencil.c = i % info.dof;
86147c6ae99SBarry Smith   if (stencil.c) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONG,"Point-block functions can only be called for the entire block");
86247c6ae99SBarry Smith   stencil.i = (i % (info.xm*info.dof))/info.dof;
86347c6ae99SBarry Smith   stencil.j = (i % (info.xm*info.ym*info.dof))/(info.xm*info.dof);
86447c6ae99SBarry Smith   stencil.k = i/(info.xm*info.ym*info.dof);
86547c6ae99SBarry Smith 
86647c6ae99SBarry Smith   ierr = (*dd->lfib)(&info,&stencil,u,vfu,w);CHKERRQ(ierr);
86747c6ae99SBarry Smith 
86847c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
86947c6ae99SBarry Smith   PetscFunctionReturn(0);
87047c6ae99SBarry Smith }
87147c6ae99SBarry Smith 
87247c6ae99SBarry Smith #if defined(new)
87347c6ae99SBarry Smith #undef __FUNCT__
87447c6ae99SBarry Smith #define __FUNCT__ "DAGetDiagonal_MFFD"
87547c6ae99SBarry Smith /*
87647c6ae99SBarry Smith   DAGetDiagonal_MFFD - Gets the diagonal for a matrix free matrix where local
87747c6ae99SBarry Smith     function lives on a DA
87847c6ae99SBarry Smith 
87947c6ae99SBarry Smith         y ~= (F(u + ha) - F(u))/h,
88047c6ae99SBarry Smith   where F = nonlinear function, as set by SNESSetFunction()
88147c6ae99SBarry Smith         u = current iterate
88247c6ae99SBarry Smith         h = difference interval
88347c6ae99SBarry Smith */
884*9a42bb27SBarry Smith PetscErrorCode DAGetDiagonal_MFFD(DM da,Vec U,Vec a)
88547c6ae99SBarry Smith {
88647c6ae99SBarry Smith   PetscScalar    h,*aa,*ww,v;
88747c6ae99SBarry Smith   PetscReal      epsilon = PETSC_SQRT_MACHINE_EPSILON,umin = 100.0*PETSC_SQRT_MACHINE_EPSILON;
88847c6ae99SBarry Smith   PetscErrorCode ierr;
88947c6ae99SBarry Smith   PetscInt       gI,nI;
89047c6ae99SBarry Smith   MatStencil     stencil;
89147c6ae99SBarry Smith   DALocalInfo    info;
89247c6ae99SBarry Smith 
89347c6ae99SBarry Smith   PetscFunctionBegin;
89447c6ae99SBarry Smith   ierr = (*ctx->func)(0,U,a,ctx->funcctx);CHKERRQ(ierr);
89547c6ae99SBarry Smith   ierr = (*ctx->funcisetbase)(U,ctx->funcctx);CHKERRQ(ierr);
89647c6ae99SBarry Smith 
89747c6ae99SBarry Smith   ierr = VecGetArray(U,&ww);CHKERRQ(ierr);
89847c6ae99SBarry Smith   ierr = VecGetArray(a,&aa);CHKERRQ(ierr);
89947c6ae99SBarry Smith 
90047c6ae99SBarry Smith   nI = 0;
90147c6ae99SBarry Smith     h  = ww[gI];
90247c6ae99SBarry Smith     if (h == 0.0) h = 1.0;
90347c6ae99SBarry Smith #if !defined(PETSC_USE_COMPLEX)
90447c6ae99SBarry Smith     if (h < umin && h >= 0.0)      h = umin;
90547c6ae99SBarry Smith     else if (h < 0.0 && h > -umin) h = -umin;
90647c6ae99SBarry Smith #else
90747c6ae99SBarry Smith     if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0)     h = umin;
90847c6ae99SBarry Smith     else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin;
90947c6ae99SBarry Smith #endif
91047c6ae99SBarry Smith     h     *= epsilon;
91147c6ae99SBarry Smith 
91247c6ae99SBarry Smith     ww[gI] += h;
91347c6ae99SBarry Smith     ierr          = (*ctx->funci)(i,w,&v,ctx->funcctx);CHKERRQ(ierr);
91447c6ae99SBarry Smith     aa[nI]  = (v - aa[nI])/h;
91547c6ae99SBarry Smith     ww[gI] -= h;
91647c6ae99SBarry Smith     nI++;
91747c6ae99SBarry Smith   }
91847c6ae99SBarry Smith   ierr = VecRestoreArray(U,&ww);CHKERRQ(ierr);
91947c6ae99SBarry Smith   ierr = VecRestoreArray(a,&aa);CHKERRQ(ierr);
92047c6ae99SBarry Smith   PetscFunctionReturn(0);
92147c6ae99SBarry Smith }
92247c6ae99SBarry Smith #endif
92347c6ae99SBarry Smith 
92447c6ae99SBarry Smith #if defined(PETSC_HAVE_ADIC)
92547c6ae99SBarry Smith EXTERN_C_BEGIN
92647c6ae99SBarry Smith #include "adic/ad_utils.h"
92747c6ae99SBarry Smith EXTERN_C_END
92847c6ae99SBarry Smith 
92947c6ae99SBarry Smith #undef __FUNCT__
93047c6ae99SBarry Smith #define __FUNCT__ "DAComputeJacobian1WithAdic"
93147c6ae99SBarry Smith /*@C
93247c6ae99SBarry Smith     DAComputeJacobian1WithAdic - Evaluates a adiC provided Jacobian function on each processor that
93347c6ae99SBarry Smith         share a DA
93447c6ae99SBarry Smith 
93547c6ae99SBarry Smith    Input Parameters:
936*9a42bb27SBarry Smith +    da - the DM that defines the grid
93747c6ae99SBarry Smith .    vu - input vector (ghosted)
93847c6ae99SBarry Smith .    J - output matrix
93947c6ae99SBarry Smith -    w - any user data
94047c6ae99SBarry Smith 
94147c6ae99SBarry Smith    Level: advanced
94247c6ae99SBarry Smith 
94347c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
94447c6ae99SBarry Smith 
94547c6ae99SBarry Smith .seealso: DAFormFunction1()
94647c6ae99SBarry Smith 
94747c6ae99SBarry Smith @*/
948*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAComputeJacobian1WithAdic(DM da,Vec vu,Mat J,void *w)
94947c6ae99SBarry Smith {
95047c6ae99SBarry Smith   PetscErrorCode ierr;
95147c6ae99SBarry Smith   PetscInt       gtdof,tdof;
95247c6ae99SBarry Smith   PetscScalar    *ustart;
95347c6ae99SBarry Smith   DALocalInfo    info;
95447c6ae99SBarry Smith   void           *ad_u,*ad_f,*ad_ustart,*ad_fstart;
95547c6ae99SBarry Smith   ISColoring     iscoloring;
95647c6ae99SBarry Smith 
95747c6ae99SBarry Smith   PetscFunctionBegin;
95847c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
95947c6ae99SBarry Smith 
96047c6ae99SBarry Smith   PetscADResetIndep();
96147c6ae99SBarry Smith 
96247c6ae99SBarry Smith   /* get space for derivative objects.  */
96347c6ae99SBarry Smith   ierr = DAGetAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,&gtdof);CHKERRQ(ierr);
96447c6ae99SBarry Smith   ierr = DAGetAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
96547c6ae99SBarry Smith   ierr = VecGetArray(vu,&ustart);CHKERRQ(ierr);
96647c6ae99SBarry Smith   ierr = DAGetColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr);
96747c6ae99SBarry Smith 
96847c6ae99SBarry Smith   PetscADSetValueAndColor(ad_ustart,gtdof,iscoloring->colors,ustart);
96947c6ae99SBarry Smith 
97047c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&ustart);CHKERRQ(ierr);
97147c6ae99SBarry Smith   ierr = ISColoringDestroy(iscoloring);CHKERRQ(ierr);
97247c6ae99SBarry Smith   ierr = PetscADIncrementTotalGradSize(iscoloring->n);CHKERRQ(ierr);
97347c6ae99SBarry Smith   PetscADSetIndepDone();
97447c6ae99SBarry Smith 
97547c6ae99SBarry Smith   ierr = PetscLogEventBegin(DA_LocalADFunction,0,0,0,0);CHKERRQ(ierr);
97647c6ae99SBarry Smith   ierr = (*dd->adic_lf)(&info,ad_u,ad_f,w);CHKERRQ(ierr);
97747c6ae99SBarry Smith   ierr = PetscLogEventEnd(DA_LocalADFunction,0,0,0,0);CHKERRQ(ierr);
97847c6ae99SBarry Smith 
97947c6ae99SBarry Smith   /* stick the values into the matrix */
98047c6ae99SBarry Smith   ierr = MatSetValuesAdic(J,(PetscScalar**)ad_fstart);CHKERRQ(ierr);
98147c6ae99SBarry Smith 
98247c6ae99SBarry Smith   /* return space for derivative objects.  */
98347c6ae99SBarry Smith   ierr = DARestoreAdicArray(da,PETSC_TRUE,&ad_u,&ad_ustart,&gtdof);CHKERRQ(ierr);
98447c6ae99SBarry Smith   ierr = DARestoreAdicArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
98547c6ae99SBarry Smith   PetscFunctionReturn(0);
98647c6ae99SBarry Smith }
98747c6ae99SBarry Smith 
98847c6ae99SBarry Smith #undef __FUNCT__
98947c6ae99SBarry Smith #define __FUNCT__ "DAMultiplyByJacobian1WithAdic"
99047c6ae99SBarry Smith /*@C
99147c6ae99SBarry Smith     DAMultiplyByJacobian1WithAdic - Applies an ADIC-provided Jacobian function to a vector on
99247c6ae99SBarry Smith     each processor that shares a DA.
99347c6ae99SBarry Smith 
99447c6ae99SBarry Smith     Input Parameters:
995*9a42bb27SBarry Smith +   da - the DM that defines the grid
99647c6ae99SBarry Smith .   vu - Jacobian is computed at this point (ghosted)
99747c6ae99SBarry Smith .   v - product is done on this vector (ghosted)
99847c6ae99SBarry Smith .   fu - output vector = J(vu)*v (not ghosted)
99947c6ae99SBarry Smith -   w - any user data
100047c6ae99SBarry Smith 
100147c6ae99SBarry Smith     Notes:
100247c6ae99SBarry Smith     This routine does NOT do ghost updates on vu upon entry.
100347c6ae99SBarry Smith 
100447c6ae99SBarry Smith    Level: advanced
100547c6ae99SBarry Smith 
100647c6ae99SBarry Smith .seealso: DAFormFunction1()
100747c6ae99SBarry Smith 
100847c6ae99SBarry Smith @*/
1009*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAMultiplyByJacobian1WithAdic(DM da,Vec vu,Vec v,Vec f,void *w)
101047c6ae99SBarry Smith {
101147c6ae99SBarry Smith   PetscErrorCode ierr;
101247c6ae99SBarry Smith   PetscInt       i,gtdof,tdof;
101347c6ae99SBarry Smith   PetscScalar    *avu,*av,*af,*ad_vustart,*ad_fstart;
101447c6ae99SBarry Smith   DALocalInfo    info;
101547c6ae99SBarry Smith   void           *ad_vu,*ad_f;
101647c6ae99SBarry Smith 
101747c6ae99SBarry Smith   PetscFunctionBegin;
101847c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
101947c6ae99SBarry Smith 
102047c6ae99SBarry Smith   /* get space for derivative objects.  */
102147c6ae99SBarry Smith   ierr = DAGetAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,&gtdof);CHKERRQ(ierr);
102247c6ae99SBarry Smith   ierr = DAGetAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
102347c6ae99SBarry Smith 
102447c6ae99SBarry Smith   /* copy input vector into derivative object */
102547c6ae99SBarry Smith   ierr = VecGetArray(vu,&avu);CHKERRQ(ierr);
102647c6ae99SBarry Smith   ierr = VecGetArray(v,&av);CHKERRQ(ierr);
102747c6ae99SBarry Smith   for (i=0; i<gtdof; i++) {
102847c6ae99SBarry Smith     ad_vustart[2*i]   = avu[i];
102947c6ae99SBarry Smith     ad_vustart[2*i+1] = av[i];
103047c6ae99SBarry Smith   }
103147c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&avu);CHKERRQ(ierr);
103247c6ae99SBarry Smith   ierr = VecRestoreArray(v,&av);CHKERRQ(ierr);
103347c6ae99SBarry Smith 
103447c6ae99SBarry Smith   PetscADResetIndep();
103547c6ae99SBarry Smith   ierr = PetscADIncrementTotalGradSize(1);CHKERRQ(ierr);
103647c6ae99SBarry Smith   PetscADSetIndepDone();
103747c6ae99SBarry Smith 
103847c6ae99SBarry Smith   ierr = (*dd->adicmf_lf)(&info,ad_vu,ad_f,w);CHKERRQ(ierr);
103947c6ae99SBarry Smith 
104047c6ae99SBarry Smith   /* stick the values into the vector */
104147c6ae99SBarry Smith   ierr = VecGetArray(f,&af);CHKERRQ(ierr);
104247c6ae99SBarry Smith   for (i=0; i<tdof; i++) {
104347c6ae99SBarry Smith     af[i] = ad_fstart[2*i+1];
104447c6ae99SBarry Smith   }
104547c6ae99SBarry Smith   ierr = VecRestoreArray(f,&af);CHKERRQ(ierr);
104647c6ae99SBarry Smith 
104747c6ae99SBarry Smith   /* return space for derivative objects.  */
104847c6ae99SBarry Smith   ierr = DARestoreAdicMFArray(da,PETSC_TRUE,&ad_vu,&ad_vustart,&gtdof);CHKERRQ(ierr);
104947c6ae99SBarry Smith   ierr = DARestoreAdicMFArray(da,PETSC_FALSE,&ad_f,&ad_fstart,&tdof);CHKERRQ(ierr);
105047c6ae99SBarry Smith   PetscFunctionReturn(0);
105147c6ae99SBarry Smith }
105247c6ae99SBarry Smith #endif
105347c6ae99SBarry Smith 
105447c6ae99SBarry Smith #undef __FUNCT__
105547c6ae99SBarry Smith #define __FUNCT__ "DAComputeJacobian1"
105647c6ae99SBarry Smith /*@
105747c6ae99SBarry Smith     DAComputeJacobian1 - Evaluates a local Jacobian function on each processor that
105847c6ae99SBarry Smith         share a DA
105947c6ae99SBarry Smith 
106047c6ae99SBarry Smith    Input Parameters:
1061*9a42bb27SBarry Smith +    da - the DM that defines the grid
106247c6ae99SBarry Smith .    vu - input vector (ghosted)
106347c6ae99SBarry Smith .    J - output matrix
106447c6ae99SBarry Smith -    w - any user data
106547c6ae99SBarry Smith 
106647c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
106747c6ae99SBarry Smith 
106847c6ae99SBarry Smith     Level: advanced
106947c6ae99SBarry Smith 
107047c6ae99SBarry Smith .seealso: DAFormFunction1()
107147c6ae99SBarry Smith 
107247c6ae99SBarry Smith @*/
1073*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAComputeJacobian1(DM da,Vec vu,Mat J,void *w)
107447c6ae99SBarry Smith {
107547c6ae99SBarry Smith   PetscErrorCode ierr;
107647c6ae99SBarry Smith   void           *u;
107747c6ae99SBarry Smith   DALocalInfo    info;
107847c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
107947c6ae99SBarry Smith 
108047c6ae99SBarry Smith   PetscFunctionBegin;
108147c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
108247c6ae99SBarry Smith   ierr = DAVecGetArray(da,vu,&u);CHKERRQ(ierr);
108347c6ae99SBarry Smith   ierr = (*dd->lj)(&info,u,J,w);CHKERRQ(ierr);
108447c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,vu,&u);CHKERRQ(ierr);
108547c6ae99SBarry Smith   PetscFunctionReturn(0);
108647c6ae99SBarry Smith }
108747c6ae99SBarry Smith 
108847c6ae99SBarry Smith 
108947c6ae99SBarry Smith #undef __FUNCT__
109047c6ae99SBarry Smith #define __FUNCT__ "DAComputeJacobian1WithAdifor"
109147c6ae99SBarry Smith /*
109247c6ae99SBarry Smith     DAComputeJacobian1WithAdifor - Evaluates a ADIFOR provided Jacobian local function on each processor that
109347c6ae99SBarry Smith         share a DA
109447c6ae99SBarry Smith 
109547c6ae99SBarry Smith    Input Parameters:
1096*9a42bb27SBarry Smith +    da - the DM that defines the grid
109747c6ae99SBarry Smith .    vu - input vector (ghosted)
109847c6ae99SBarry Smith .    J - output matrix
109947c6ae99SBarry Smith -    w - any user data
110047c6ae99SBarry Smith 
110147c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu upon entry
110247c6ae99SBarry Smith 
110347c6ae99SBarry Smith .seealso: DAFormFunction1()
110447c6ae99SBarry Smith 
110547c6ae99SBarry Smith */
1106*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAComputeJacobian1WithAdifor(DM da,Vec vu,Mat J,void *w)
110747c6ae99SBarry Smith {
110847c6ae99SBarry Smith   PetscErrorCode  ierr;
110947c6ae99SBarry Smith   PetscInt        i,Nc,N;
111047c6ae99SBarry Smith   ISColoringValue *color;
111147c6ae99SBarry Smith   DALocalInfo     info;
111247c6ae99SBarry Smith   PetscScalar     *u,*g_u,*g_f,*f = 0,*p_u;
111347c6ae99SBarry Smith   ISColoring      iscoloring;
111447c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
111547c6ae99SBarry Smith   void            (*lf)(PetscInt*,DALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*) =
111647c6ae99SBarry Smith                   (void (*)(PetscInt*,DALocalInfo*,PetscScalar*,PetscScalar*,PetscInt*,PetscScalar*,PetscScalar*,PetscInt*,void*,PetscErrorCode*))*dd->adifor_lf;
111747c6ae99SBarry Smith 
111847c6ae99SBarry Smith   PetscFunctionBegin;
111947c6ae99SBarry Smith   ierr = DAGetColoring(da,IS_COLORING_GHOSTED,MATAIJ,&iscoloring);CHKERRQ(ierr);
112047c6ae99SBarry Smith   Nc   = iscoloring->n;
112147c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
112247c6ae99SBarry Smith   N    = info.gxm*info.gym*info.gzm*info.dof;
112347c6ae99SBarry Smith 
112447c6ae99SBarry Smith   /* get space for derivative objects.  */
112547c6ae99SBarry Smith   ierr  = PetscMalloc(Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar),&g_u);CHKERRQ(ierr);
112647c6ae99SBarry Smith   ierr  = PetscMemzero(g_u,Nc*info.gxm*info.gym*info.gzm*info.dof*sizeof(PetscScalar));CHKERRQ(ierr);
112747c6ae99SBarry Smith   p_u   = g_u;
112847c6ae99SBarry Smith   color = iscoloring->colors;
112947c6ae99SBarry Smith   for (i=0; i<N; i++) {
113047c6ae99SBarry Smith     p_u[*color++] = 1.0;
113147c6ae99SBarry Smith     p_u          += Nc;
113247c6ae99SBarry Smith   }
113347c6ae99SBarry Smith   ierr = ISColoringDestroy(iscoloring);CHKERRQ(ierr);
113447c6ae99SBarry 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);
113547c6ae99SBarry Smith 
113647c6ae99SBarry Smith   /* Seed the input array g_u with coloring information */
113747c6ae99SBarry Smith 
113847c6ae99SBarry Smith   ierr = VecGetArray(vu,&u);CHKERRQ(ierr);
113947c6ae99SBarry Smith   (lf)(&Nc,&info,u,g_u,&Nc,f,g_f,&Nc,w,&ierr);CHKERRQ(ierr);
114047c6ae99SBarry Smith   ierr = VecRestoreArray(vu,&u);CHKERRQ(ierr);
114147c6ae99SBarry Smith 
114247c6ae99SBarry Smith   /* stick the values into the matrix */
114347c6ae99SBarry Smith   /* PetscScalarView(Nc*info.xm*info.ym,g_f,0); */
114447c6ae99SBarry Smith   ierr = MatSetValuesAdifor(J,Nc,g_f);CHKERRQ(ierr);
114547c6ae99SBarry Smith 
114647c6ae99SBarry Smith   /* return space for derivative objects.  */
114747c6ae99SBarry Smith   ierr = PetscFree(g_u);CHKERRQ(ierr);
114847c6ae99SBarry Smith   ierr = PetscFree2(g_f,f);CHKERRQ(ierr);
114947c6ae99SBarry Smith   PetscFunctionReturn(0);
115047c6ae99SBarry Smith }
115147c6ae99SBarry Smith 
115247c6ae99SBarry Smith #undef __FUNCT__
115347c6ae99SBarry Smith #define __FUNCT__ "DAFormJacobianLocal"
115447c6ae99SBarry Smith /*@C
115547c6ae99SBarry Smith    DAFormjacobianLocal - This is a universal Jacobian evaluation routine for
1156*9a42bb27SBarry Smith    a local DM function.
115747c6ae99SBarry Smith 
115847c6ae99SBarry Smith    Collective on DA
115947c6ae99SBarry Smith 
116047c6ae99SBarry Smith    Input Parameters:
1161*9a42bb27SBarry Smith +  da - the DM context
116247c6ae99SBarry Smith .  func - The local function
116347c6ae99SBarry Smith .  X - input vector
116447c6ae99SBarry Smith .  J - Jacobian matrix
116547c6ae99SBarry Smith -  ctx - A user context
116647c6ae99SBarry Smith 
116747c6ae99SBarry Smith    Level: intermediate
116847c6ae99SBarry Smith 
116947c6ae99SBarry Smith .seealso: DASetLocalFunction(), DASetLocalJacobian(), DASetLocalAdicFunction(), DASetLocalAdicMFFunction(),
117047c6ae99SBarry Smith           SNESSetFunction(), SNESSetJacobian()
117147c6ae99SBarry Smith 
117247c6ae99SBarry Smith @*/
1173*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAFormJacobianLocal(DM da, DALocalFunction1 func, Vec X, Mat J, void *ctx)
117447c6ae99SBarry Smith {
117547c6ae99SBarry Smith   Vec            localX;
117647c6ae99SBarry Smith   DALocalInfo    info;
117747c6ae99SBarry Smith   void          *u;
117847c6ae99SBarry Smith   PetscErrorCode ierr;
117947c6ae99SBarry Smith 
118047c6ae99SBarry Smith   PetscFunctionBegin;
1181*9a42bb27SBarry Smith   ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr);
118247c6ae99SBarry Smith   /*
118347c6ae99SBarry Smith      Scatter ghost points to local vector, using the 2-step process
1184*9a42bb27SBarry Smith         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
118547c6ae99SBarry Smith   */
1186*9a42bb27SBarry Smith   ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
1187*9a42bb27SBarry Smith   ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
118847c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
118947c6ae99SBarry Smith   ierr = DAVecGetArray(da,localX,&u);CHKERRQ(ierr);
119047c6ae99SBarry Smith   ierr = (*func)(&info,u,J,ctx);
119147c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
119247c6ae99SBarry Smith     PetscErrorCode pierr = DAVecRestoreArray(da,localX,&u);CHKERRQ(pierr);
119347c6ae99SBarry Smith   }
119447c6ae99SBarry Smith   CHKERRQ(ierr);
119547c6ae99SBarry Smith   ierr = DAVecRestoreArray(da,localX,&u);CHKERRQ(ierr);
119647c6ae99SBarry Smith   if (PetscExceptionValue(ierr)) {
1197*9a42bb27SBarry Smith     PetscErrorCode pierr = DMRestoreLocalVector(da,&localX);CHKERRQ(pierr);
119847c6ae99SBarry Smith   }
119947c6ae99SBarry Smith   CHKERRQ(ierr);
1200*9a42bb27SBarry Smith   ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr);
120147c6ae99SBarry Smith   PetscFunctionReturn(0);
120247c6ae99SBarry Smith }
120347c6ae99SBarry Smith 
120447c6ae99SBarry Smith #undef __FUNCT__
120547c6ae99SBarry Smith #define __FUNCT__ "DAMultiplyByJacobian1WithAD"
120647c6ae99SBarry Smith /*@C
120747c6ae99SBarry Smith     DAMultiplyByJacobian1WithAD - Applies a Jacobian function supplied by ADIFOR or ADIC
120847c6ae99SBarry Smith     to a vector on each processor that shares a DA.
120947c6ae99SBarry Smith 
121047c6ae99SBarry Smith    Input Parameters:
1211*9a42bb27SBarry Smith +    da - the DM that defines the grid
121247c6ae99SBarry Smith .    vu - Jacobian is computed at this point (ghosted)
121347c6ae99SBarry Smith .    v - product is done on this vector (ghosted)
121447c6ae99SBarry Smith .    fu - output vector = J(vu)*v (not ghosted)
121547c6ae99SBarry Smith -    w - any user data
121647c6ae99SBarry Smith 
121747c6ae99SBarry Smith     Notes:
121847c6ae99SBarry Smith     This routine does NOT do ghost updates on vu and v upon entry.
121947c6ae99SBarry Smith 
122047c6ae99SBarry Smith     Automatically calls DAMultiplyByJacobian1WithAdifor() or DAMultiplyByJacobian1WithAdic()
122147c6ae99SBarry Smith     depending on whether DASetLocalAdicMFFunction() or DASetLocalAdiforMFFunction() was called.
122247c6ae99SBarry Smith 
122347c6ae99SBarry Smith    Level: advanced
122447c6ae99SBarry Smith 
122547c6ae99SBarry Smith .seealso: DAFormFunction1(), DAMultiplyByJacobian1WithAdifor(), DAMultiplyByJacobian1WithAdic()
122647c6ae99SBarry Smith 
122747c6ae99SBarry Smith @*/
1228*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAMultiplyByJacobian1WithAD(DM da,Vec u,Vec v,Vec f,void *w)
122947c6ae99SBarry Smith {
123047c6ae99SBarry Smith   PetscErrorCode ierr;
123147c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
123247c6ae99SBarry Smith 
123347c6ae99SBarry Smith   PetscFunctionBegin;
123447c6ae99SBarry Smith   if (dd->adicmf_lf) {
123547c6ae99SBarry Smith #if defined(PETSC_HAVE_ADIC)
123647c6ae99SBarry Smith     ierr = DAMultiplyByJacobian1WithAdic(da,u,v,f,w);CHKERRQ(ierr);
123747c6ae99SBarry Smith #else
123847c6ae99SBarry Smith     SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP_SYS,"Requires ADIC to be installed and cannot use complex numbers");
123947c6ae99SBarry Smith #endif
124047c6ae99SBarry Smith   } else if (dd->adiformf_lf) {
124147c6ae99SBarry Smith     ierr = DAMultiplyByJacobian1WithAdifor(da,u,v,f,w);CHKERRQ(ierr);
124247c6ae99SBarry Smith   } else {
124347c6ae99SBarry Smith     SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ORDER,"Must call DASetLocalAdiforMFFunction() or DASetLocalAdicMFFunction() before using");
124447c6ae99SBarry Smith   }
124547c6ae99SBarry Smith   PetscFunctionReturn(0);
124647c6ae99SBarry Smith }
124747c6ae99SBarry Smith 
124847c6ae99SBarry Smith 
124947c6ae99SBarry Smith #undef __FUNCT__
125047c6ae99SBarry Smith #define __FUNCT__ "DAMultiplyByJacobian1WithAdifor"
125147c6ae99SBarry Smith /*@C
125247c6ae99SBarry Smith     DAMultiplyByJacobian1WithAdifor - Applies a ADIFOR provided Jacobian function on each processor that
1253*9a42bb27SBarry Smith         share a DM to a vector
125447c6ae99SBarry Smith 
125547c6ae99SBarry Smith    Input Parameters:
1256*9a42bb27SBarry Smith +    da - the DM that defines the grid
125747c6ae99SBarry Smith .    vu - Jacobian is computed at this point (ghosted)
125847c6ae99SBarry Smith .    v - product is done on this vector (ghosted)
125947c6ae99SBarry Smith .    fu - output vector = J(vu)*v (not ghosted)
126047c6ae99SBarry Smith -    w - any user data
126147c6ae99SBarry Smith 
126247c6ae99SBarry Smith     Notes: Does NOT do ghost updates on vu and v upon entry
126347c6ae99SBarry Smith 
126447c6ae99SBarry Smith    Level: advanced
126547c6ae99SBarry Smith 
126647c6ae99SBarry Smith .seealso: DAFormFunction1()
126747c6ae99SBarry Smith 
126847c6ae99SBarry Smith @*/
1269*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DAMultiplyByJacobian1WithAdifor(DM da,Vec u,Vec v,Vec f,void *w)
127047c6ae99SBarry Smith {
127147c6ae99SBarry Smith   PetscErrorCode ierr;
127247c6ae99SBarry Smith   PetscScalar    *au,*av,*af,*awork;
127347c6ae99SBarry Smith   Vec            work;
127447c6ae99SBarry Smith   DALocalInfo    info;
127547c6ae99SBarry Smith   DM_DA          *dd = (DM_DA*)da->data;
127647c6ae99SBarry Smith   void           (*lf)(DALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*) =
127747c6ae99SBarry Smith                  (void (*)(DALocalInfo*,PetscScalar*,PetscScalar*,PetscScalar*,PetscScalar*,void*,PetscErrorCode*))*dd->adiformf_lf;
127847c6ae99SBarry Smith 
127947c6ae99SBarry Smith   PetscFunctionBegin;
128047c6ae99SBarry Smith   ierr = DAGetLocalInfo(da,&info);CHKERRQ(ierr);
128147c6ae99SBarry Smith 
1282*9a42bb27SBarry Smith   ierr = DMGetGlobalVector(da,&work);CHKERRQ(ierr);
128347c6ae99SBarry Smith   ierr = VecGetArray(u,&au);CHKERRQ(ierr);
128447c6ae99SBarry Smith   ierr = VecGetArray(v,&av);CHKERRQ(ierr);
128547c6ae99SBarry Smith   ierr = VecGetArray(f,&af);CHKERRQ(ierr);
128647c6ae99SBarry Smith   ierr = VecGetArray(work,&awork);CHKERRQ(ierr);
128747c6ae99SBarry Smith   (lf)(&info,au,av,awork,af,w,&ierr);CHKERRQ(ierr);
128847c6ae99SBarry Smith   ierr = VecRestoreArray(u,&au);CHKERRQ(ierr);
128947c6ae99SBarry Smith   ierr = VecRestoreArray(v,&av);CHKERRQ(ierr);
129047c6ae99SBarry Smith   ierr = VecRestoreArray(f,&af);CHKERRQ(ierr);
129147c6ae99SBarry Smith   ierr = VecRestoreArray(work,&awork);CHKERRQ(ierr);
1292*9a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(da,&work);CHKERRQ(ierr);
129347c6ae99SBarry Smith 
129447c6ae99SBarry Smith   PetscFunctionReturn(0);
129547c6ae99SBarry Smith }
129647c6ae99SBarry Smith 
129747c6ae99SBarry Smith EXTERN_C_BEGIN
129847c6ae99SBarry Smith #undef __FUNCT__
1299*9a42bb27SBarry Smith #define __FUNCT__ "DMSetUp_DA_2D"
1300*9a42bb27SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DMSetUp_DA_2D(DM da)
130147c6ae99SBarry Smith {
130247c6ae99SBarry Smith   DM_DA               *dd = (DM_DA*)da->data;
130347c6ae99SBarry Smith   const PetscInt       M            = dd->M;
130447c6ae99SBarry Smith   const PetscInt       N            = dd->N;
130547c6ae99SBarry Smith   PetscInt             m            = dd->m;
130647c6ae99SBarry Smith   PetscInt             n            = dd->n;
130747c6ae99SBarry Smith   const PetscInt       dof          = dd->w;
130847c6ae99SBarry Smith   const PetscInt       s            = dd->s;
130947c6ae99SBarry Smith   const DAPeriodicType wrap         = dd->wrap;
131047c6ae99SBarry Smith   const DAStencilType  stencil_type = dd->stencil_type;
131147c6ae99SBarry Smith   PetscInt            *lx           = dd->lx;
131247c6ae99SBarry Smith   PetscInt            *ly           = dd->ly;
131347c6ae99SBarry Smith   MPI_Comm             comm;
131447c6ae99SBarry Smith   PetscMPIInt          rank,size;
131547c6ae99SBarry Smith   PetscInt             xs,xe,ys,ye,x,y,Xs,Xe,Ys,Ye,start,end;
131647c6ae99SBarry Smith   PetscInt             up,down,left,i,n0,n1,n2,n3,n5,n6,n7,n8,*idx,nn;
131747c6ae99SBarry Smith   PetscInt             xbase,*bases,*ldims,j,x_t,y_t,s_t,base,count;
131847c6ae99SBarry Smith   PetscInt             s_x,s_y; /* s proportionalized to w */
131947c6ae99SBarry Smith   PetscInt             sn0 = 0,sn2 = 0,sn6 = 0,sn8 = 0;
132047c6ae99SBarry Smith   Vec                  local,global;
132147c6ae99SBarry Smith   VecScatter           ltog,gtol;
132247c6ae99SBarry Smith   IS                   to,from;
132347c6ae99SBarry Smith   PetscErrorCode       ierr;
132447c6ae99SBarry Smith 
132547c6ae99SBarry Smith   PetscFunctionBegin;
132647c6ae99SBarry Smith   ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr);
132747c6ae99SBarry Smith 
132847c6ae99SBarry Smith   if (dof < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof);
132947c6ae99SBarry Smith   if (s < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s);
133047c6ae99SBarry Smith 
133147c6ae99SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
133247c6ae99SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
133347c6ae99SBarry Smith 
1334264ace61SBarry Smith   da->ops->getelements = DMGetElements_DA_2d_P1;
133547c6ae99SBarry Smith 
133647c6ae99SBarry Smith   dd->dim         = 2;
133747c6ae99SBarry Smith   dd->elementtype = DA_ELEMENT_P1;
133847c6ae99SBarry Smith   ierr = PetscMalloc(dof*sizeof(char*),&dd->fieldname);CHKERRQ(ierr);
133947c6ae99SBarry Smith   ierr = PetscMemzero(dd->fieldname,dof*sizeof(char*));CHKERRQ(ierr);
134047c6ae99SBarry Smith 
134147c6ae99SBarry Smith   if (m != PETSC_DECIDE) {
134247c6ae99SBarry Smith     if (m < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in X direction: %D",m);
134347c6ae99SBarry Smith     else if (m > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in X direction: %D %d",m,size);
134447c6ae99SBarry Smith   }
134547c6ae99SBarry Smith   if (n != PETSC_DECIDE) {
134647c6ae99SBarry Smith     if (n < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Y direction: %D",n);
134747c6ae99SBarry Smith     else if (n > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Y direction: %D %d",n,size);
134847c6ae99SBarry Smith   }
134947c6ae99SBarry Smith 
135047c6ae99SBarry Smith   if (m == PETSC_DECIDE || n == PETSC_DECIDE) {
135147c6ae99SBarry Smith     if (n != PETSC_DECIDE) {
135247c6ae99SBarry Smith       m = size/n;
135347c6ae99SBarry Smith     } else if (m != PETSC_DECIDE) {
135447c6ae99SBarry Smith       n = size/m;
135547c6ae99SBarry Smith     } else {
135647c6ae99SBarry Smith       /* try for squarish distribution */
135747c6ae99SBarry Smith       m = (PetscInt)(0.5 + sqrt(((double)M)*((double)size)/((double)N)));
135847c6ae99SBarry Smith       if (!m) m = 1;
135947c6ae99SBarry Smith       while (m > 0) {
136047c6ae99SBarry Smith 	n = size/m;
136147c6ae99SBarry Smith 	if (m*n == size) break;
136247c6ae99SBarry Smith 	m--;
136347c6ae99SBarry Smith       }
136447c6ae99SBarry Smith       if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;}
136547c6ae99SBarry Smith     }
136647c6ae99SBarry 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 ");
136747c6ae99SBarry Smith   } else if (m*n != size) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Given Bad partition");
136847c6ae99SBarry Smith 
136947c6ae99SBarry Smith   if (M < m) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in x direction is too fine! %D %D",M,m);
137047c6ae99SBarry Smith   if (N < n) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in y direction is too fine! %D %D",N,n);
137147c6ae99SBarry Smith 
137247c6ae99SBarry Smith   /*
137347c6ae99SBarry Smith      Determine locally owned region
137447c6ae99SBarry Smith      xs is the first local node number, x is the number of local nodes
137547c6ae99SBarry Smith   */
137647c6ae99SBarry Smith   if (!lx) {
137747c6ae99SBarry Smith     ierr = PetscMalloc(m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr);
137847c6ae99SBarry Smith     lx = dd->lx;
137947c6ae99SBarry Smith     for (i=0; i<m; i++) {
138047c6ae99SBarry Smith       lx[i] = M/m + ((M % m) > i);
138147c6ae99SBarry Smith     }
138247c6ae99SBarry Smith   }
138347c6ae99SBarry Smith   x  = lx[rank % m];
138447c6ae99SBarry Smith   xs = 0;
138547c6ae99SBarry Smith   for (i=0; i<(rank % m); i++) {
138647c6ae99SBarry Smith     xs += lx[i];
138747c6ae99SBarry Smith   }
138847c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
138947c6ae99SBarry Smith   left = xs;
139047c6ae99SBarry Smith   for (i=(rank % m); i<m; i++) {
139147c6ae99SBarry Smith     left += lx[i];
139247c6ae99SBarry Smith   }
139347c6ae99SBarry 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);
139447c6ae99SBarry Smith #endif
139547c6ae99SBarry Smith 
139647c6ae99SBarry Smith   /*
139747c6ae99SBarry Smith      Determine locally owned region
139847c6ae99SBarry Smith      ys is the first local node number, y is the number of local nodes
139947c6ae99SBarry Smith   */
140047c6ae99SBarry Smith   if (!ly) {
140147c6ae99SBarry Smith     ierr = PetscMalloc(n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr);
140247c6ae99SBarry Smith     ly = dd->ly;
140347c6ae99SBarry Smith     for (i=0; i<n; i++) {
140447c6ae99SBarry Smith       ly[i] = N/n + ((N % n) > i);
140547c6ae99SBarry Smith     }
140647c6ae99SBarry Smith   }
140747c6ae99SBarry Smith   y  = ly[rank/m];
140847c6ae99SBarry Smith   ys = 0;
140947c6ae99SBarry Smith   for (i=0; i<(rank/m); i++) {
141047c6ae99SBarry Smith     ys += ly[i];
141147c6ae99SBarry Smith   }
141247c6ae99SBarry Smith #if defined(PETSC_USE_DEBUG)
141347c6ae99SBarry Smith   left = ys;
141447c6ae99SBarry Smith   for (i=(rank/m); i<n; i++) {
141547c6ae99SBarry Smith     left += ly[i];
141647c6ae99SBarry Smith   }
141747c6ae99SBarry 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);
141847c6ae99SBarry Smith #endif
141947c6ae99SBarry Smith 
142047c6ae99SBarry 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);
142147c6ae99SBarry 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);
142247c6ae99SBarry Smith   xe = xs + x;
142347c6ae99SBarry Smith   ye = ys + y;
142447c6ae99SBarry Smith 
142547c6ae99SBarry Smith   /* determine ghost region */
142647c6ae99SBarry Smith   /* Assume No Periodicity */
142747c6ae99SBarry Smith   if (xs-s > 0) Xs = xs - s; else Xs = 0;
142847c6ae99SBarry Smith   if (ys-s > 0) Ys = ys - s; else Ys = 0;
142947c6ae99SBarry Smith   if (xe+s <= M) Xe = xe + s; else Xe = M;
143047c6ae99SBarry Smith   if (ye+s <= N) Ye = ye + s; else Ye = N;
143147c6ae99SBarry Smith 
143247c6ae99SBarry Smith   /* X Periodic */
143347c6ae99SBarry Smith   if (DAXPeriodic(wrap)){
143447c6ae99SBarry Smith     Xs = xs - s;
143547c6ae99SBarry Smith     Xe = xe + s;
143647c6ae99SBarry Smith   }
143747c6ae99SBarry Smith 
143847c6ae99SBarry Smith   /* Y Periodic */
143947c6ae99SBarry Smith   if (DAYPeriodic(wrap)){
144047c6ae99SBarry Smith     Ys = ys - s;
144147c6ae99SBarry Smith     Ye = ye + s;
144247c6ae99SBarry Smith   }
144347c6ae99SBarry Smith 
144447c6ae99SBarry Smith   /* Resize all X parameters to reflect w */
144547c6ae99SBarry Smith   x   *= dof;
144647c6ae99SBarry Smith   xs  *= dof;
144747c6ae99SBarry Smith   xe  *= dof;
144847c6ae99SBarry Smith   Xs  *= dof;
144947c6ae99SBarry Smith   Xe  *= dof;
145047c6ae99SBarry Smith   s_x = s*dof;
145147c6ae99SBarry Smith   s_y = s;
145247c6ae99SBarry Smith 
145347c6ae99SBarry Smith   /* determine starting point of each processor */
145447c6ae99SBarry Smith   nn    = x*y;
145547c6ae99SBarry Smith   ierr  = PetscMalloc2(size+1,PetscInt,&bases,size,PetscInt,&ldims);CHKERRQ(ierr);
145647c6ae99SBarry Smith   ierr  = MPI_Allgather(&nn,1,MPIU_INT,ldims,1,MPIU_INT,comm);CHKERRQ(ierr);
145747c6ae99SBarry Smith   bases[0] = 0;
145847c6ae99SBarry Smith   for (i=1; i<=size; i++) {
145947c6ae99SBarry Smith     bases[i] = ldims[i-1];
146047c6ae99SBarry Smith   }
146147c6ae99SBarry Smith   for (i=1; i<=size; i++) {
146247c6ae99SBarry Smith     bases[i] += bases[i-1];
146347c6ae99SBarry Smith   }
146447c6ae99SBarry Smith 
146547c6ae99SBarry Smith   /* allocate the base parallel and sequential vectors */
146647c6ae99SBarry Smith   dd->Nlocal = x*y;
146747c6ae99SBarry Smith   ierr = VecCreateMPIWithArray(comm,dd->Nlocal,PETSC_DECIDE,0,&global);CHKERRQ(ierr);
146847c6ae99SBarry Smith   ierr = VecSetBlockSize(global,dof);CHKERRQ(ierr);
146947c6ae99SBarry Smith   dd->nlocal = (Xe-Xs)*(Ye-Ys);
147047c6ae99SBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dd->nlocal,0,&local);CHKERRQ(ierr);
147147c6ae99SBarry Smith   ierr = VecSetBlockSize(local,dof);CHKERRQ(ierr);
147247c6ae99SBarry Smith 
147347c6ae99SBarry Smith 
147447c6ae99SBarry Smith   /* generate appropriate vector scatters */
147547c6ae99SBarry Smith   /* local to global inserts non-ghost point region into global */
147647c6ae99SBarry Smith   ierr = VecGetOwnershipRange(global,&start,&end);CHKERRQ(ierr);
147747c6ae99SBarry Smith   ierr = ISCreateStride(comm,x*y,start,1,&to);CHKERRQ(ierr);
147847c6ae99SBarry Smith 
147947c6ae99SBarry Smith   left  = xs - Xs; down  = ys - Ys; up    = down + y;
148047c6ae99SBarry Smith   ierr = PetscMalloc(x*(up - down)*sizeof(PetscInt),&idx);CHKERRQ(ierr);
148147c6ae99SBarry Smith   count = 0;
148247c6ae99SBarry Smith   for (i=down; i<up; i++) {
148347c6ae99SBarry Smith     for (j=0; j<x/dof; j++) {
148447c6ae99SBarry Smith       idx[count++] = (left + i*(Xe-Xs) + j*dof)/dof;
148547c6ae99SBarry Smith     }
148647c6ae99SBarry Smith   }
148747c6ae99SBarry Smith   ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr);
148847c6ae99SBarry Smith 
148947c6ae99SBarry Smith   ierr = VecScatterCreate(local,from,global,to,&ltog);CHKERRQ(ierr);
149047c6ae99SBarry Smith   ierr = PetscLogObjectParent(dd,ltog);CHKERRQ(ierr);
149147c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
149247c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
149347c6ae99SBarry Smith 
149447c6ae99SBarry Smith   /* global to local must include ghost points */
149547c6ae99SBarry Smith   if (stencil_type == DA_STENCIL_BOX) {
149647c6ae99SBarry Smith     ierr = ISCreateStride(comm,(Xe-Xs)*(Ye-Ys),0,1,&to);CHKERRQ(ierr);
149747c6ae99SBarry Smith   } else {
149847c6ae99SBarry Smith     /* must drop into cross shape region */
149947c6ae99SBarry Smith     /*       ---------|
150047c6ae99SBarry Smith             |  top    |
150147c6ae99SBarry Smith          |---         ---|
150247c6ae99SBarry Smith          |   middle      |
150347c6ae99SBarry Smith          |               |
150447c6ae99SBarry Smith          ----         ----
150547c6ae99SBarry Smith             | bottom  |
150647c6ae99SBarry Smith             -----------
150747c6ae99SBarry Smith         Xs xs        xe  Xe */
150847c6ae99SBarry Smith     /* bottom */
150947c6ae99SBarry Smith     left  = xs - Xs; down = ys - Ys; up    = down + y;
151047c6ae99SBarry Smith     count = down*(xe-xs) + (up-down)*(Xe-Xs) + (Ye-Ys-up)*(xe-xs);
151147c6ae99SBarry Smith     ierr  = PetscMalloc(count*sizeof(PetscInt)/dof,&idx);CHKERRQ(ierr);
151247c6ae99SBarry Smith     count = 0;
151347c6ae99SBarry Smith     for (i=0; i<down; i++) {
151447c6ae99SBarry Smith       for (j=0; j<xe-xs; j += dof) {
151547c6ae99SBarry Smith         idx[count++] = left + i*(Xe-Xs) + j;
151647c6ae99SBarry Smith       }
151747c6ae99SBarry Smith     }
151847c6ae99SBarry Smith     /* middle */
151947c6ae99SBarry Smith     for (i=down; i<up; i++) {
152047c6ae99SBarry Smith       for (j=0; j<Xe-Xs; j += dof) {
152147c6ae99SBarry Smith         idx[count++] = i*(Xe-Xs) + j;
152247c6ae99SBarry Smith       }
152347c6ae99SBarry Smith     }
152447c6ae99SBarry Smith     /* top */
152547c6ae99SBarry Smith     for (i=up; i<Ye-Ys; i++) {
152647c6ae99SBarry Smith       for (j=0; j<xe-xs; j += dof) {
152747c6ae99SBarry Smith         idx[count++] = (left + i*(Xe-Xs) + j);
152847c6ae99SBarry Smith       }
152947c6ae99SBarry Smith     }
153047c6ae99SBarry Smith     for (i=0; i<count; i++) idx[i] = idx[i]/dof;
153147c6ae99SBarry Smith     ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
153247c6ae99SBarry Smith   }
153347c6ae99SBarry Smith 
153447c6ae99SBarry Smith 
153547c6ae99SBarry Smith   /* determine who lies on each side of us stored in    n6 n7 n8
153647c6ae99SBarry Smith                                                         n3    n5
153747c6ae99SBarry Smith                                                         n0 n1 n2
153847c6ae99SBarry Smith   */
153947c6ae99SBarry Smith 
154047c6ae99SBarry Smith   /* Assume the Non-Periodic Case */
154147c6ae99SBarry Smith   n1 = rank - m;
154247c6ae99SBarry Smith   if (rank % m) {
154347c6ae99SBarry Smith     n0 = n1 - 1;
154447c6ae99SBarry Smith   } else {
154547c6ae99SBarry Smith     n0 = -1;
154647c6ae99SBarry Smith   }
154747c6ae99SBarry Smith   if ((rank+1) % m) {
154847c6ae99SBarry Smith     n2 = n1 + 1;
154947c6ae99SBarry Smith     n5 = rank + 1;
155047c6ae99SBarry Smith     n8 = rank + m + 1; if (n8 >= m*n) n8 = -1;
155147c6ae99SBarry Smith   } else {
155247c6ae99SBarry Smith     n2 = -1; n5 = -1; n8 = -1;
155347c6ae99SBarry Smith   }
155447c6ae99SBarry Smith   if (rank % m) {
155547c6ae99SBarry Smith     n3 = rank - 1;
155647c6ae99SBarry Smith     n6 = n3 + m; if (n6 >= m*n) n6 = -1;
155747c6ae99SBarry Smith   } else {
155847c6ae99SBarry Smith     n3 = -1; n6 = -1;
155947c6ae99SBarry Smith   }
156047c6ae99SBarry Smith   n7 = rank + m; if (n7 >= m*n) n7 = -1;
156147c6ae99SBarry Smith 
156247c6ae99SBarry Smith 
156347c6ae99SBarry Smith   /* Modify for Periodic Cases */
156447c6ae99SBarry Smith   if (wrap == DA_YPERIODIC) {  /* Handle Top and Bottom Sides */
156547c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n-1);
156647c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n-1);
156747c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
156847c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
156947c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
157047c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
157147c6ae99SBarry Smith   } else if (wrap == DA_XPERIODIC) { /* Handle Left and Right Sides */
157247c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m-1);
157347c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m-1);
157447c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
157547c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
157647c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
157747c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
157847c6ae99SBarry Smith   } else if (wrap == DA_XYPERIODIC) {
157947c6ae99SBarry Smith 
158047c6ae99SBarry Smith     /* Handle all four corners */
158147c6ae99SBarry Smith     if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m-1;
158247c6ae99SBarry Smith     if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0;
158347c6ae99SBarry Smith     if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size-m;
158447c6ae99SBarry Smith     if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size-1;
158547c6ae99SBarry Smith 
158647c6ae99SBarry Smith     /* Handle Top and Bottom Sides */
158747c6ae99SBarry Smith     if (n1 < 0) n1 = rank + m * (n-1);
158847c6ae99SBarry Smith     if (n7 < 0) n7 = rank - m * (n-1);
158947c6ae99SBarry Smith     if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1;
159047c6ae99SBarry Smith     if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1;
159147c6ae99SBarry Smith     if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1;
159247c6ae99SBarry Smith     if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1;
159347c6ae99SBarry Smith 
159447c6ae99SBarry Smith     /* Handle Left and Right Sides */
159547c6ae99SBarry Smith     if (n3 < 0) n3 = rank + (m-1);
159647c6ae99SBarry Smith     if (n5 < 0) n5 = rank - (m-1);
159747c6ae99SBarry Smith     if ((n1 >= 0) && (n0 < 0)) n0 = rank-1;
159847c6ae99SBarry Smith     if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1;
159947c6ae99SBarry Smith     if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1;
160047c6ae99SBarry Smith     if ((n7 >= 0) && (n8 < 0)) n8 = rank+1;
160147c6ae99SBarry Smith   }
160247c6ae99SBarry Smith   ierr = PetscMalloc(9*sizeof(PetscInt),&dd->neighbors);CHKERRQ(ierr);
160347c6ae99SBarry Smith   dd->neighbors[0] = n0;
160447c6ae99SBarry Smith   dd->neighbors[1] = n1;
160547c6ae99SBarry Smith   dd->neighbors[2] = n2;
160647c6ae99SBarry Smith   dd->neighbors[3] = n3;
160747c6ae99SBarry Smith   dd->neighbors[4] = rank;
160847c6ae99SBarry Smith   dd->neighbors[5] = n5;
160947c6ae99SBarry Smith   dd->neighbors[6] = n6;
161047c6ae99SBarry Smith   dd->neighbors[7] = n7;
161147c6ae99SBarry Smith   dd->neighbors[8] = n8;
161247c6ae99SBarry Smith 
161347c6ae99SBarry Smith   if (stencil_type == DA_STENCIL_STAR) {
161447c6ae99SBarry Smith     /* save corner processor numbers */
161547c6ae99SBarry Smith     sn0 = n0; sn2 = n2; sn6 = n6; sn8 = n8;
161647c6ae99SBarry Smith     n0 = n2 = n6 = n8 = -1;
161747c6ae99SBarry Smith   }
161847c6ae99SBarry Smith 
161947c6ae99SBarry Smith   ierr = PetscMalloc((x+2*s_x)*(y+2*s_y)*sizeof(PetscInt),&idx);CHKERRQ(ierr);
162047c6ae99SBarry Smith   ierr = PetscLogObjectMemory(da,(x+2*s_x)*(y+2*s_y)*sizeof(PetscInt));CHKERRQ(ierr);
162147c6ae99SBarry Smith   nn = 0;
162247c6ae99SBarry Smith 
162347c6ae99SBarry Smith   xbase = bases[rank];
162447c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
162547c6ae99SBarry Smith     if (n0 >= 0) { /* left below */
162647c6ae99SBarry Smith       x_t = lx[n0 % m]*dof;
162747c6ae99SBarry Smith       y_t = ly[(n0/m)];
162847c6ae99SBarry Smith       s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
162947c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
163047c6ae99SBarry Smith     }
163147c6ae99SBarry Smith     if (n1 >= 0) { /* directly below */
163247c6ae99SBarry Smith       x_t = x;
163347c6ae99SBarry Smith       y_t = ly[(n1/m)];
163447c6ae99SBarry Smith       s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
163547c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
163647c6ae99SBarry Smith     }
163747c6ae99SBarry Smith     if (n2 >= 0) { /* right below */
163847c6ae99SBarry Smith       x_t = lx[n2 % m]*dof;
163947c6ae99SBarry Smith       y_t = ly[(n2/m)];
164047c6ae99SBarry Smith       s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
164147c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
164247c6ae99SBarry Smith     }
164347c6ae99SBarry Smith   }
164447c6ae99SBarry Smith 
164547c6ae99SBarry Smith   for (i=0; i<y; i++) {
164647c6ae99SBarry Smith     if (n3 >= 0) { /* directly left */
164747c6ae99SBarry Smith       x_t = lx[n3 % m]*dof;
164847c6ae99SBarry Smith       /* y_t = y; */
164947c6ae99SBarry Smith       s_t = bases[n3] + (i+1)*x_t - s_x;
165047c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
165147c6ae99SBarry Smith     }
165247c6ae99SBarry Smith 
165347c6ae99SBarry Smith     for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
165447c6ae99SBarry Smith 
165547c6ae99SBarry Smith     if (n5 >= 0) { /* directly right */
165647c6ae99SBarry Smith       x_t = lx[n5 % m]*dof;
165747c6ae99SBarry Smith       /* y_t = y; */
165847c6ae99SBarry Smith       s_t = bases[n5] + (i)*x_t;
165947c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
166047c6ae99SBarry Smith     }
166147c6ae99SBarry Smith   }
166247c6ae99SBarry Smith 
166347c6ae99SBarry Smith   for (i=1; i<=s_y; i++) {
166447c6ae99SBarry Smith     if (n6 >= 0) { /* left above */
166547c6ae99SBarry Smith       x_t = lx[n6 % m]*dof;
166647c6ae99SBarry Smith       /* y_t = ly[(n6/m)]; */
166747c6ae99SBarry Smith       s_t = bases[n6] + (i)*x_t - s_x;
166847c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
166947c6ae99SBarry Smith     }
167047c6ae99SBarry Smith     if (n7 >= 0) { /* directly above */
167147c6ae99SBarry Smith       x_t = x;
167247c6ae99SBarry Smith       /* y_t = ly[(n7/m)]; */
167347c6ae99SBarry Smith       s_t = bases[n7] + (i-1)*x_t;
167447c6ae99SBarry Smith       for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
167547c6ae99SBarry Smith     }
167647c6ae99SBarry Smith     if (n8 >= 0) { /* right above */
167747c6ae99SBarry Smith       x_t = lx[n8 % m]*dof;
167847c6ae99SBarry Smith       /* y_t = ly[(n8/m)]; */
167947c6ae99SBarry Smith       s_t = bases[n8] + (i-1)*x_t;
168047c6ae99SBarry Smith       for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
168147c6ae99SBarry Smith     }
168247c6ae99SBarry Smith   }
168347c6ae99SBarry Smith 
168447c6ae99SBarry Smith   base = bases[rank];
168547c6ae99SBarry Smith   {
168647c6ae99SBarry Smith     PetscInt nnn = nn/dof,*iidx;
168747c6ae99SBarry Smith     ierr = PetscMalloc(nnn*sizeof(PetscInt),&iidx);CHKERRQ(ierr);
168847c6ae99SBarry Smith     for (i=0; i<nnn; i++) {
168947c6ae99SBarry Smith       iidx[i] = idx[dof*i]/dof;
169047c6ae99SBarry Smith     }
169147c6ae99SBarry Smith     ierr = ISCreateBlock(comm,dof,nnn,iidx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr);
169247c6ae99SBarry Smith   }
169347c6ae99SBarry Smith   ierr = VecScatterCreate(global,from,local,to,&gtol);CHKERRQ(ierr);
169447c6ae99SBarry Smith   ierr = PetscLogObjectParent(da,gtol);CHKERRQ(ierr);
169547c6ae99SBarry Smith   ierr = ISDestroy(to);CHKERRQ(ierr);
169647c6ae99SBarry Smith   ierr = ISDestroy(from);CHKERRQ(ierr);
169747c6ae99SBarry Smith 
169847c6ae99SBarry Smith   if (stencil_type == DA_STENCIL_STAR) {
169947c6ae99SBarry Smith     /*
170047c6ae99SBarry Smith         Recompute the local to global mappings, this time keeping the
170147c6ae99SBarry Smith       information about the cross corner processor numbers.
170247c6ae99SBarry Smith     */
170347c6ae99SBarry Smith     n0 = sn0; n2 = sn2; n6 = sn6; n8 = sn8;
170447c6ae99SBarry Smith     nn = 0;
170547c6ae99SBarry Smith     xbase = bases[rank];
170647c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
170747c6ae99SBarry Smith       if (n0 >= 0) { /* left below */
170847c6ae99SBarry Smith         x_t = lx[n0 % m]*dof;
170947c6ae99SBarry Smith         y_t = ly[(n0/m)];
171047c6ae99SBarry Smith         s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x;
171147c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
171247c6ae99SBarry Smith       }
171347c6ae99SBarry Smith       if (n1 >= 0) { /* directly below */
171447c6ae99SBarry Smith         x_t = x;
171547c6ae99SBarry Smith         y_t = ly[(n1/m)];
171647c6ae99SBarry Smith         s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t;
171747c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
171847c6ae99SBarry Smith       }
171947c6ae99SBarry Smith       if (n2 >= 0) { /* right below */
172047c6ae99SBarry Smith         x_t = lx[n2 % m]*dof;
172147c6ae99SBarry Smith         y_t = ly[(n2/m)];
172247c6ae99SBarry Smith         s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t;
172347c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
172447c6ae99SBarry Smith       }
172547c6ae99SBarry Smith     }
172647c6ae99SBarry Smith 
172747c6ae99SBarry Smith     for (i=0; i<y; i++) {
172847c6ae99SBarry Smith       if (n3 >= 0) { /* directly left */
172947c6ae99SBarry Smith         x_t = lx[n3 % m]*dof;
173047c6ae99SBarry Smith         /* y_t = y; */
173147c6ae99SBarry Smith         s_t = bases[n3] + (i+1)*x_t - s_x;
173247c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
173347c6ae99SBarry Smith       }
173447c6ae99SBarry Smith 
173547c6ae99SBarry Smith       for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */
173647c6ae99SBarry Smith 
173747c6ae99SBarry Smith       if (n5 >= 0) { /* directly right */
173847c6ae99SBarry Smith         x_t = lx[n5 % m]*dof;
173947c6ae99SBarry Smith         /* y_t = y; */
174047c6ae99SBarry Smith         s_t = bases[n5] + (i)*x_t;
174147c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
174247c6ae99SBarry Smith       }
174347c6ae99SBarry Smith     }
174447c6ae99SBarry Smith 
174547c6ae99SBarry Smith     for (i=1; i<=s_y; i++) {
174647c6ae99SBarry Smith       if (n6 >= 0) { /* left above */
174747c6ae99SBarry Smith         x_t = lx[n6 % m]*dof;
174847c6ae99SBarry Smith         /* y_t = ly[(n6/m)]; */
174947c6ae99SBarry Smith         s_t = bases[n6] + (i)*x_t - s_x;
175047c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
175147c6ae99SBarry Smith       }
175247c6ae99SBarry Smith       if (n7 >= 0) { /* directly above */
175347c6ae99SBarry Smith         x_t = x;
175447c6ae99SBarry Smith         /* y_t = ly[(n7/m)]; */
175547c6ae99SBarry Smith         s_t = bases[n7] + (i-1)*x_t;
175647c6ae99SBarry Smith         for (j=0; j<x_t; j++) { idx[nn++] = s_t++;}
175747c6ae99SBarry Smith       }
175847c6ae99SBarry Smith       if (n8 >= 0) { /* right above */
175947c6ae99SBarry Smith         x_t = lx[n8 % m]*dof;
176047c6ae99SBarry Smith         /* y_t = ly[(n8/m)]; */
176147c6ae99SBarry Smith         s_t = bases[n8] + (i-1)*x_t;
176247c6ae99SBarry Smith         for (j=0; j<s_x; j++) { idx[nn++] = s_t++;}
176347c6ae99SBarry Smith       }
176447c6ae99SBarry Smith     }
176547c6ae99SBarry Smith   }
176647c6ae99SBarry Smith   ierr = PetscFree2(bases,ldims);CHKERRQ(ierr);
176747c6ae99SBarry Smith 
176847c6ae99SBarry Smith   dd->m  = m;  dd->n  = n;
176947c6ae99SBarry Smith   dd->xs = xs; dd->xe = xe; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1;
177047c6ae99SBarry Smith   dd->Xs = Xs; dd->Xe = Xe; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1;
177147c6ae99SBarry Smith 
177247c6ae99SBarry Smith   ierr = VecDestroy(local);CHKERRQ(ierr);
177347c6ae99SBarry Smith   ierr = VecDestroy(global);CHKERRQ(ierr);
177447c6ae99SBarry Smith 
177547c6ae99SBarry Smith   dd->gtol      = gtol;
177647c6ae99SBarry Smith   dd->ltog      = ltog;
177747c6ae99SBarry Smith   dd->idx       = idx;
177847c6ae99SBarry Smith   dd->Nl        = nn;
177947c6ae99SBarry Smith   dd->base      = base;
1780*9a42bb27SBarry Smith   da->ops->view = DMView_DA_2d;
178147c6ae99SBarry Smith 
178247c6ae99SBarry Smith   /*
178347c6ae99SBarry Smith      Set the local to global ordering in the global vector, this allows use
178447c6ae99SBarry Smith      of VecSetValuesLocal().
178547c6ae99SBarry Smith   */
178647c6ae99SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,nn,idx,PETSC_OWN_POINTER,&dd->ltogmap);CHKERRQ(ierr);
178747c6ae99SBarry Smith   ierr = ISLocalToGlobalMappingBlock(dd->ltogmap,dd->w,&dd->ltogmapb);CHKERRQ(ierr);
178847c6ae99SBarry Smith   ierr = PetscLogObjectParent(da,dd->ltogmap);CHKERRQ(ierr);
178947c6ae99SBarry Smith 
179047c6ae99SBarry Smith   dd->ltol = PETSC_NULL;
179147c6ae99SBarry Smith   dd->ao   = PETSC_NULL;
179247c6ae99SBarry Smith 
179347c6ae99SBarry Smith   PetscFunctionReturn(0);
179447c6ae99SBarry Smith }
179547c6ae99SBarry Smith EXTERN_C_END
179647c6ae99SBarry Smith 
179747c6ae99SBarry Smith #undef __FUNCT__
179847c6ae99SBarry Smith #define __FUNCT__ "DACreate2d"
179947c6ae99SBarry Smith /*@C
180047c6ae99SBarry Smith    DACreate2d -  Creates an object that will manage the communication of  two-dimensional
180147c6ae99SBarry Smith    regular array data that is distributed across some processors.
180247c6ae99SBarry Smith 
180347c6ae99SBarry Smith    Collective on MPI_Comm
180447c6ae99SBarry Smith 
180547c6ae99SBarry Smith    Input Parameters:
180647c6ae99SBarry Smith +  comm - MPI communicator
180747c6ae99SBarry Smith .  wrap - type of periodicity should the array have.
180847c6ae99SBarry Smith          Use one of DA_NONPERIODIC, DA_XPERIODIC, DA_YPERIODIC, or DA_XYPERIODIC.
180947c6ae99SBarry Smith .  stencil_type - stencil type.  Use either DA_STENCIL_BOX or DA_STENCIL_STAR.
181047c6ae99SBarry 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
181147c6ae99SBarry Smith             from the command line with -da_grid_x <M> -da_grid_y <N>)
181247c6ae99SBarry Smith .  m,n - corresponding number of processors in each dimension
181347c6ae99SBarry Smith          (or PETSC_DECIDE to have calculated)
181447c6ae99SBarry Smith .  dof - number of degrees of freedom per node
181547c6ae99SBarry Smith .  s - stencil width
181647c6ae99SBarry Smith -  lx, ly - arrays containing the number of nodes in each cell along
181747c6ae99SBarry Smith            the x and y coordinates, or PETSC_NULL. If non-null, these
181847c6ae99SBarry Smith            must be of length as m and n, and the corresponding
181947c6ae99SBarry Smith            m and n cannot be PETSC_DECIDE. The sum of the lx[] entries
182047c6ae99SBarry Smith            must be M, and the sum of the ly[] entries must be N.
182147c6ae99SBarry Smith 
182247c6ae99SBarry Smith    Output Parameter:
182347c6ae99SBarry Smith .  da - the resulting distributed array object
182447c6ae99SBarry Smith 
182547c6ae99SBarry Smith    Options Database Key:
1826*9a42bb27SBarry Smith +  -da_view - Calls DMView() at the conclusion of DACreate2d()
182747c6ae99SBarry Smith .  -da_grid_x <nx> - number of grid points in x direction, if M < 0
182847c6ae99SBarry Smith .  -da_grid_y <ny> - number of grid points in y direction, if N < 0
182947c6ae99SBarry Smith .  -da_processors_x <nx> - number of processors in x direction
183047c6ae99SBarry Smith .  -da_processors_y <ny> - number of processors in y direction
183147c6ae99SBarry Smith .  -da_refine_x - refinement ratio in x direction
183247c6ae99SBarry Smith -  -da_refine_y - refinement ratio in y direction
183347c6ae99SBarry Smith 
183447c6ae99SBarry Smith    Level: beginner
183547c6ae99SBarry Smith 
183647c6ae99SBarry Smith    Notes:
183747c6ae99SBarry Smith    The stencil type DA_STENCIL_STAR with width 1 corresponds to the
183847c6ae99SBarry Smith    standard 5-pt stencil, while DA_STENCIL_BOX with width 1 denotes
183947c6ae99SBarry Smith    the standard 9-pt stencil.
184047c6ae99SBarry Smith 
184147c6ae99SBarry Smith    The array data itself is NOT stored in the DA, it is stored in Vec objects;
184247c6ae99SBarry Smith    The appropriate vector objects can be obtained with calls to DACreateGlobalVector()
184347c6ae99SBarry Smith    and DACreateLocalVector() and calls to VecDuplicate() if more are needed.
184447c6ae99SBarry Smith 
184547c6ae99SBarry Smith .keywords: distributed array, create, two-dimensional
184647c6ae99SBarry Smith 
1847*9a42bb27SBarry Smith .seealso: DMDestroy(), DMView(), DACreate1d(), DACreate3d(), DMGlobalToLocalBegin(), DAGetRefinementFactor(),
1848*9a42bb27SBarry Smith           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DALocalToLocalBegin(), DALocalToLocalEnd(), DASetRefinementFactor(),
1849*9a42bb27SBarry Smith           DAGetInfo(), DACreateGlobalVector(), DACreateLocalVector(), DACreateNaturalVector(), DALoad(), DAGetOwnershipRanges()
185047c6ae99SBarry Smith 
185147c6ae99SBarry Smith @*/
185247c6ae99SBarry Smith PetscErrorCode PETSCDM_DLLEXPORT DACreate2d(MPI_Comm comm,DAPeriodicType wrap,DAStencilType stencil_type,
1853*9a42bb27SBarry Smith                           PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da)
185447c6ae99SBarry Smith {
185547c6ae99SBarry Smith   PetscErrorCode ierr;
185647c6ae99SBarry Smith 
185747c6ae99SBarry Smith   PetscFunctionBegin;
185847c6ae99SBarry Smith   ierr = DACreate(comm, da);CHKERRQ(ierr);
185947c6ae99SBarry Smith   ierr = DASetDim(*da, 2);CHKERRQ(ierr);
186047c6ae99SBarry Smith   ierr = DASetSizes(*da, M, N, 1);CHKERRQ(ierr);
186147c6ae99SBarry Smith   ierr = DASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr);
186247c6ae99SBarry Smith   ierr = DASetPeriodicity(*da, wrap);CHKERRQ(ierr);
186347c6ae99SBarry Smith   ierr = DASetDof(*da, dof);CHKERRQ(ierr);
186447c6ae99SBarry Smith   ierr = DASetStencilType(*da, stencil_type);CHKERRQ(ierr);
186547c6ae99SBarry Smith   ierr = DASetStencilWidth(*da, s);CHKERRQ(ierr);
186647c6ae99SBarry Smith   ierr = DASetOwnershipRanges(*da, lx, ly, PETSC_NULL);CHKERRQ(ierr);
186747c6ae99SBarry Smith   /* This violates the behavior for other classes, but right now users expect negative dimensions to be handled this way */
1868*9a42bb27SBarry Smith   ierr = DMSetFromOptions(*da);CHKERRQ(ierr);
1869*9a42bb27SBarry Smith   ierr = DMSetUp(*da);CHKERRQ(ierr);
187047c6ae99SBarry Smith   PetscFunctionReturn(0);
187147c6ae99SBarry Smith }
1872