xref: /petsc/src/dm/impls/da/dainterp.c (revision b7f7bd4055c8cae5018adf2e30bbec8c80acb6a5)
147c6ae99SBarry Smith 
247c6ae99SBarry Smith /*
3aa219208SBarry Smith   Code for interpolating between grids represented by DMDAs
447c6ae99SBarry Smith */
547c6ae99SBarry Smith 
6d52bd9f3SBarry Smith /*
7d52bd9f3SBarry Smith       For linear elements there are two branches of code to compute the interpolation. They should compute the same results but may not. The "new version" does
8d52bd9f3SBarry Smith    not work for periodic domains, the old does. Change NEWVERSION to 1 to compile in the new version. Eventually when we are sure the two produce identical results
92adb9dcfSBarry Smith    we will remove/merge the new version. Based on current tests, these both produce the same results. We are leaving NEWVERSION for now in the code since some
102adb9dcfSBarry Smith    consider it cleaner, but old version is turned on since it handles periodic case.
11d52bd9f3SBarry Smith */
129314d695SBarry Smith #define NEWVERSION 0
1385afcc9aSBarry Smith 
14c6db04a5SJed Brown #include <private/daimpl.h>    /*I   "petscdmda.h"   I*/
1547c6ae99SBarry Smith 
1647c6ae99SBarry Smith #undef __FUNCT__
17e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolationScale"
1847c6ae99SBarry Smith /*@
19e727c939SJed Brown     DMCreateInterpolationScale - Forms L = R*1/diag(R*1) - L.*v is like a coarse grid average of the
2047c6ae99SBarry Smith       nearby fine grid points.
2147c6ae99SBarry Smith 
2247c6ae99SBarry Smith   Input Parameters:
2347c6ae99SBarry Smith +      dac - DM that defines a coarse mesh
2447c6ae99SBarry Smith .      daf - DM that defines a fine mesh
2547c6ae99SBarry Smith -      mat - the restriction (or interpolation operator) from fine to coarse
2647c6ae99SBarry Smith 
2747c6ae99SBarry Smith   Output Parameter:
2847c6ae99SBarry Smith .    scale - the scaled vector
2947c6ae99SBarry Smith 
3047c6ae99SBarry Smith   Level: developer
3147c6ae99SBarry Smith 
32e727c939SJed Brown .seealso: DMCreateInterpolation()
3347c6ae99SBarry Smith 
3447c6ae99SBarry Smith @*/
35e727c939SJed Brown PetscErrorCode  DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale)
3647c6ae99SBarry Smith {
3747c6ae99SBarry Smith   PetscErrorCode ierr;
3847c6ae99SBarry Smith   Vec            fine;
3947c6ae99SBarry Smith   PetscScalar    one = 1.0;
4047c6ae99SBarry Smith 
4147c6ae99SBarry Smith   PetscFunctionBegin;
4247c6ae99SBarry Smith   ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr);
4347c6ae99SBarry Smith   ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr);
4447c6ae99SBarry Smith   ierr = VecSet(fine,one);CHKERRQ(ierr);
4547c6ae99SBarry Smith   ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr);
46fcfd50ebSBarry Smith   ierr = VecDestroy(&fine);CHKERRQ(ierr);
4747c6ae99SBarry Smith   ierr = VecReciprocal(*scale);CHKERRQ(ierr);
4847c6ae99SBarry Smith   PetscFunctionReturn(0);
4947c6ae99SBarry Smith }
5047c6ae99SBarry Smith 
5147c6ae99SBarry Smith #undef __FUNCT__
52e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_1D_Q1"
53e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A)
5447c6ae99SBarry Smith {
5547c6ae99SBarry Smith   PetscErrorCode   ierr;
5647c6ae99SBarry Smith   PetscInt         i,i_start,m_f,Mx,*idx_f;
5747c6ae99SBarry Smith   PetscInt         m_ghost,*idx_c,m_ghost_c;
5847c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,mx,m_c,nc,ratio;
5947c6ae99SBarry Smith   PetscInt         i_c,i_start_c,i_start_ghost_c,cols[2],dof;
6085afcc9aSBarry Smith   PetscScalar      v[2],x;
6147c6ae99SBarry Smith   Mat              mat;
621321219cSEthan Coon   DMDABoundaryType bx;
6347c6ae99SBarry Smith 
6447c6ae99SBarry Smith   PetscFunctionBegin;
651321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
661321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
671321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
6847c6ae99SBarry Smith     ratio = mx/Mx;
6947c6ae99SBarry Smith     if (ratio*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx  must be integer: mx %D Mx %D",mx,Mx);
7047c6ae99SBarry Smith   } else {
7147c6ae99SBarry Smith     ratio = (mx-1)/(Mx-1);
7247c6ae99SBarry Smith     if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx);
7347c6ae99SBarry Smith   }
7447c6ae99SBarry Smith 
75aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
76aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
77aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
7847c6ae99SBarry Smith 
79aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
80aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
81aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
8247c6ae99SBarry Smith 
8347c6ae99SBarry Smith   /* create interpolation matrix */
8447c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr);
8547c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr);
8647c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
8747c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr);
88*b7f7bd40SJed Brown   ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,1,PETSC_NULL);CHKERRQ(ierr);
8947c6ae99SBarry Smith 
9047c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
9185afcc9aSBarry Smith   if (!NEWVERSION) {
92b3bd94feSDave May 
9347c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
9447c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
9547c6ae99SBarry Smith       row    = idx_f[dof*(i-i_start_ghost)]/dof;
9647c6ae99SBarry Smith 
9747c6ae99SBarry Smith       i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
98aa219208SBarry Smith       if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
9947c6ae99SBarry Smith                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
10047c6ae99SBarry Smith 
10147c6ae99SBarry Smith       /*
10247c6ae99SBarry Smith        Only include those interpolation points that are truly
10347c6ae99SBarry Smith        nonzero. Note this is very important for final grid lines
10447c6ae99SBarry Smith        in x direction; since they have no right neighbor
10547c6ae99SBarry Smith        */
10647c6ae99SBarry Smith       x  = ((double)(i - i_c*ratio))/((double)ratio);
10747c6ae99SBarry Smith       nc = 0;
10847c6ae99SBarry Smith       /* one left and below; or we are right on it */
10947c6ae99SBarry Smith       col      = dof*(i_c-i_start_ghost_c);
11047c6ae99SBarry Smith       cols[nc] = idx_c[col]/dof;
11147c6ae99SBarry Smith       v[nc++]  = - x + 1.0;
11247c6ae99SBarry Smith       /* one right? */
11347c6ae99SBarry Smith       if (i_c*ratio != i) {
11447c6ae99SBarry Smith         cols[nc] = idx_c[col+dof]/dof;
11547c6ae99SBarry Smith         v[nc++]  = x;
11647c6ae99SBarry Smith       }
11747c6ae99SBarry Smith       ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
11847c6ae99SBarry Smith     }
119b3bd94feSDave May 
120b3bd94feSDave May   } else {
121b3bd94feSDave May     PetscScalar    *xi;
122b3bd94feSDave May     PetscInt       li,nxi,n;
123b3bd94feSDave May     PetscScalar    Ni[2];
124b3bd94feSDave May 
125b3bd94feSDave May     /* compute local coordinate arrays */
126b3bd94feSDave May     nxi   = ratio + 1;
127b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
128b3bd94feSDave May     for (li=0; li<nxi; li++) {
12952218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
130b3bd94feSDave May     }
131b3bd94feSDave May 
132b3bd94feSDave May     for (i=i_start; i<i_start+m_f; i++) {
133b3bd94feSDave May       /* convert to local "natural" numbering and then to PETSc global numbering */
134b3bd94feSDave May       row    = idx_f[dof*(i-i_start_ghost)]/dof;
135b3bd94feSDave May 
136b3bd94feSDave May       i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
137b3bd94feSDave May       if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
138b3bd94feSDave May                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
139b3bd94feSDave May 
140b3bd94feSDave May       /* remainders */
141b3bd94feSDave May       li = i - ratio * (i/ratio);
142b3bd94feSDave May       if (i==mx-1){ li = nxi-1; }
143b3bd94feSDave May 
144b3bd94feSDave May       /* corners */
145b3bd94feSDave May       col     = dof*(i_c-i_start_ghost_c);
146b3bd94feSDave May       cols[0] = idx_c[col]/dof;
147b3bd94feSDave May       Ni[0]   = 1.0;
148b3bd94feSDave May       if ( (li==0) || (li==nxi-1) ) {
149b3bd94feSDave May         ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
150b3bd94feSDave May         continue;
151b3bd94feSDave May       }
152b3bd94feSDave May 
153b3bd94feSDave May       /* edges + interior */
154b3bd94feSDave May       /* remainders */
155b3bd94feSDave May       if (i==mx-1){ i_c--; }
156b3bd94feSDave May 
157b3bd94feSDave May       col     = dof*(i_c-i_start_ghost_c);
158b3bd94feSDave May       cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */
159b3bd94feSDave May       cols[1] = idx_c[col+dof]/dof;
160b3bd94feSDave May 
161b3bd94feSDave May       Ni[0] = 0.5*(1.0-xi[li]);
162b3bd94feSDave May       Ni[1] = 0.5*(1.0+xi[li]);
163b3bd94feSDave May       for (n=0; n<2; n++) {
164b3bd94feSDave May         if( PetscAbsScalar(Ni[n])<1.0e-32) { cols[n]=-1; }
165b3bd94feSDave May       }
166b3bd94feSDave May       ierr = MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
167b3bd94feSDave May     }
168b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
169b3bd94feSDave May   }
17047c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17147c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17247c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
173fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
17447c6ae99SBarry Smith   PetscFunctionReturn(0);
17547c6ae99SBarry Smith }
17647c6ae99SBarry Smith 
17747c6ae99SBarry Smith #undef __FUNCT__
178e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_1D_Q0"
179e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A)
18047c6ae99SBarry Smith {
18147c6ae99SBarry Smith   PetscErrorCode   ierr;
18247c6ae99SBarry Smith   PetscInt         i,i_start,m_f,Mx,*idx_f;
18347c6ae99SBarry Smith   PetscInt         m_ghost,*idx_c,m_ghost_c;
18447c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,mx,m_c,nc,ratio;
18547c6ae99SBarry Smith   PetscInt         i_c,i_start_c,i_start_ghost_c,cols[2],dof;
18647c6ae99SBarry Smith   PetscScalar      v[2],x;
18747c6ae99SBarry Smith   Mat              mat;
1881321219cSEthan Coon   DMDABoundaryType bx;
18947c6ae99SBarry Smith 
19047c6ae99SBarry Smith   PetscFunctionBegin;
1911321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
1921321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
1931321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
19447c6ae99SBarry Smith     ratio = mx/Mx;
19547c6ae99SBarry Smith     if (ratio*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx  must be integer: mx %D Mx %D",mx,Mx);
19647c6ae99SBarry Smith   } else {
19747c6ae99SBarry Smith     ratio = (mx-1)/(Mx-1);
19847c6ae99SBarry Smith     if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx);
19947c6ae99SBarry Smith   }
20047c6ae99SBarry Smith 
201aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
202aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
203aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
20447c6ae99SBarry Smith 
205aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
206aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
207aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
20847c6ae99SBarry Smith 
20947c6ae99SBarry Smith   /* create interpolation matrix */
21047c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr);
21147c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr);
21247c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
21347c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr);
21447c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
21547c6ae99SBarry Smith 
21647c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
21747c6ae99SBarry Smith   for (i=i_start; i<i_start+m_f; i++) {
21847c6ae99SBarry Smith     /* convert to local "natural" numbering and then to PETSc global numbering */
21947c6ae99SBarry Smith     row    = idx_f[dof*(i-i_start_ghost)]/dof;
22047c6ae99SBarry Smith 
22147c6ae99SBarry Smith     i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
22247c6ae99SBarry Smith 
22347c6ae99SBarry Smith     /*
22447c6ae99SBarry Smith          Only include those interpolation points that are truly
22547c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
22647c6ae99SBarry Smith          in x direction; since they have no right neighbor
22747c6ae99SBarry Smith     */
22847c6ae99SBarry Smith     x  = ((double)(i - i_c*ratio))/((double)ratio);
22947c6ae99SBarry Smith     nc = 0;
23047c6ae99SBarry Smith       /* one left and below; or we are right on it */
23147c6ae99SBarry Smith     col      = dof*(i_c-i_start_ghost_c);
23247c6ae99SBarry Smith     cols[nc] = idx_c[col]/dof;
23347c6ae99SBarry Smith     v[nc++]  = - x + 1.0;
23447c6ae99SBarry Smith     /* one right? */
23547c6ae99SBarry Smith     if (i_c*ratio != i) {
23647c6ae99SBarry Smith       cols[nc] = idx_c[col+dof]/dof;
23747c6ae99SBarry Smith       v[nc++]  = x;
23847c6ae99SBarry Smith     }
23947c6ae99SBarry Smith     ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
24047c6ae99SBarry Smith   }
24147c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24247c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24347c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
244fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
24547c6ae99SBarry Smith   ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr);
24647c6ae99SBarry Smith   PetscFunctionReturn(0);
24747c6ae99SBarry Smith }
24847c6ae99SBarry Smith 
24947c6ae99SBarry Smith #undef __FUNCT__
250e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_2D_Q1"
251e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A)
25247c6ae99SBarry Smith {
25347c6ae99SBarry Smith   PetscErrorCode   ierr;
25447c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof;
25547c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz;
25647c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj;
25747c6ae99SBarry Smith   PetscInt         i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c,col_shift,col_scale;
25847c6ae99SBarry Smith   PetscMPIInt      size_c,size_f,rank_f;
25947c6ae99SBarry Smith   PetscScalar      v[4],x,y;
26047c6ae99SBarry Smith   Mat              mat;
2611321219cSEthan Coon   DMDABoundaryType bx,by;
26247c6ae99SBarry Smith 
26347c6ae99SBarry Smith   PetscFunctionBegin;
2641321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
2651321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
2661321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
26747c6ae99SBarry Smith     ratioi = mx/Mx;
26847c6ae99SBarry Smith     if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx  must be integer: mx %D Mx %D",mx,Mx);
26947c6ae99SBarry Smith   } else {
27047c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
27147c6ae99SBarry Smith     if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx);
27247c6ae99SBarry Smith   }
2731321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC){
27447c6ae99SBarry Smith     ratioj = my/My;
27547c6ae99SBarry Smith     if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My  must be integer: my %D My %D",my,My);
27647c6ae99SBarry Smith   } else {
27747c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
27847c6ae99SBarry Smith     if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My);
27947c6ae99SBarry Smith   }
28047c6ae99SBarry Smith 
28147c6ae99SBarry Smith 
282aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
283aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
284aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
28547c6ae99SBarry Smith 
286aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
287aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
288aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
28947c6ae99SBarry Smith 
29047c6ae99SBarry Smith   /*
291aa219208SBarry Smith    Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
29247c6ae99SBarry Smith    The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
29347c6ae99SBarry Smith    processors). It's effective length is hence 4 times its normal length, this is
29447c6ae99SBarry Smith    why the col_scale is multiplied by the interpolation matrix column sizes.
29547c6ae99SBarry Smith    sol_shift allows each set of 1/4 processors do its own interpolation using ITS
29647c6ae99SBarry Smith    copy of the coarse vector. A bit of a hack but you do better.
29747c6ae99SBarry Smith 
29847c6ae99SBarry Smith    In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
29947c6ae99SBarry Smith    */
30047c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr);
30147c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr);
30247c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr);
30347c6ae99SBarry Smith   col_scale = size_f/size_c;
30447c6ae99SBarry Smith   col_shift = Mx*My*(rank_f/size_c);
30547c6ae99SBarry Smith 
30647c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr);
30747c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
30847c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
30947c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
31047c6ae99SBarry Smith       row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
31147c6ae99SBarry Smith 
31247c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
31347c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
31447c6ae99SBarry Smith 
315aa219208SBarry Smith       if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
31647c6ae99SBarry Smith                                           j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
317aa219208SBarry Smith       if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
31847c6ae99SBarry Smith                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
31947c6ae99SBarry Smith 
32047c6ae99SBarry Smith       /*
32147c6ae99SBarry Smith        Only include those interpolation points that are truly
32247c6ae99SBarry Smith        nonzero. Note this is very important for final grid lines
32347c6ae99SBarry Smith        in x and y directions; since they have no right/top neighbors
32447c6ae99SBarry Smith        */
32547c6ae99SBarry Smith       nc = 0;
32647c6ae99SBarry Smith       /* one left and below; or we are right on it */
32747c6ae99SBarry Smith       col        = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
32847c6ae99SBarry Smith       cols[nc++] = col_shift + idx_c[col]/dof;
32947c6ae99SBarry Smith       /* one right and below */
33047c6ae99SBarry Smith       if (i_c*ratioi != i) {
33147c6ae99SBarry Smith         cols[nc++] = col_shift + idx_c[col+dof]/dof;
33247c6ae99SBarry Smith       }
33347c6ae99SBarry Smith       /* one left and above */
33447c6ae99SBarry Smith       if (j_c*ratioj != j) {
33547c6ae99SBarry Smith         cols[nc++] = col_shift + idx_c[col+m_ghost_c*dof]/dof;
33647c6ae99SBarry Smith       }
33747c6ae99SBarry Smith       /* one right and above */
3380c82216cSJed Brown       if (i_c*ratioi != i && j_c*ratioj != j) {
33947c6ae99SBarry Smith         cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof;
34047c6ae99SBarry Smith       }
34147c6ae99SBarry Smith       ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
34247c6ae99SBarry Smith     }
34347c6ae99SBarry Smith   }
34447c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr);
34547c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr);
34647c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
34747c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
34847c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
34947c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
35047c6ae99SBarry Smith 
35147c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
35285afcc9aSBarry Smith   if (!NEWVERSION) {
353b3bd94feSDave May 
35447c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
35547c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
35647c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
35747c6ae99SBarry Smith         row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
35847c6ae99SBarry Smith 
35947c6ae99SBarry Smith         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
36047c6ae99SBarry Smith         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
36147c6ae99SBarry Smith 
36247c6ae99SBarry Smith         /*
36347c6ae99SBarry Smith          Only include those interpolation points that are truly
36447c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
36547c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
36647c6ae99SBarry Smith          */
36747c6ae99SBarry Smith         x  = ((double)(i - i_c*ratioi))/((double)ratioi);
36847c6ae99SBarry Smith         y  = ((double)(j - j_c*ratioj))/((double)ratioj);
369b3bd94feSDave May 
37047c6ae99SBarry Smith         nc = 0;
37147c6ae99SBarry Smith         /* one left and below; or we are right on it */
37247c6ae99SBarry Smith         col      = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
37347c6ae99SBarry Smith         cols[nc] = col_shift + idx_c[col]/dof;
37447c6ae99SBarry Smith         v[nc++]  = x*y - x - y + 1.0;
37547c6ae99SBarry Smith         /* one right and below */
37647c6ae99SBarry Smith         if (i_c*ratioi != i) {
37747c6ae99SBarry Smith           cols[nc] = col_shift + idx_c[col+dof]/dof;
37847c6ae99SBarry Smith           v[nc++]  = -x*y + x;
37947c6ae99SBarry Smith         }
38047c6ae99SBarry Smith         /* one left and above */
38147c6ae99SBarry Smith         if (j_c*ratioj != j) {
38247c6ae99SBarry Smith           cols[nc] = col_shift + idx_c[col+m_ghost_c*dof]/dof;
38347c6ae99SBarry Smith           v[nc++]  = -x*y + y;
38447c6ae99SBarry Smith         }
38547c6ae99SBarry Smith         /* one right and above */
38647c6ae99SBarry Smith         if (j_c*ratioj != j && i_c*ratioi != i) {
38747c6ae99SBarry Smith           cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof;
38847c6ae99SBarry Smith           v[nc++]  = x*y;
38947c6ae99SBarry Smith         }
39047c6ae99SBarry Smith         ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
39147c6ae99SBarry Smith       }
39247c6ae99SBarry Smith     }
393b3bd94feSDave May 
394b3bd94feSDave May   } else {
395b3bd94feSDave May     PetscScalar    Ni[4];
396b3bd94feSDave May     PetscScalar    *xi,*eta;
397b3bd94feSDave May     PetscInt       li,nxi,lj,neta;
398b3bd94feSDave May 
399b3bd94feSDave May     /* compute local coordinate arrays */
400b3bd94feSDave May     nxi  = ratioi + 1;
401b3bd94feSDave May     neta = ratioj + 1;
402b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
403b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr);
404b3bd94feSDave May     for (li=0; li<nxi; li++) {
40552218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
406b3bd94feSDave May     }
407b3bd94feSDave May     for (lj=0; lj<neta; lj++) {
40852218ef2SJed Brown       eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1));
409b3bd94feSDave May     }
410b3bd94feSDave May 
411b3bd94feSDave May     /* loop over local fine grid nodes setting interpolation for those*/
412b3bd94feSDave May     for (j=j_start; j<j_start+n_f; j++) {
413b3bd94feSDave May       for (i=i_start; i<i_start+m_f; i++) {
414b3bd94feSDave May         /* convert to local "natural" numbering and then to PETSc global numbering */
415b3bd94feSDave May         row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
416b3bd94feSDave May 
417b3bd94feSDave May         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
418b3bd94feSDave May         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
419b3bd94feSDave May 
420b3bd94feSDave May         /* remainders */
421b3bd94feSDave May         li = i - ratioi * (i/ratioi);
422b3bd94feSDave May         if (i==mx-1){ li = nxi-1; }
423b3bd94feSDave May         lj = j - ratioj * (j/ratioj);
424b3bd94feSDave May         if (j==my-1){ lj = neta-1; }
425b3bd94feSDave May 
426b3bd94feSDave May         /* corners */
427b3bd94feSDave May         col     = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
428b3bd94feSDave May         cols[0] = col_shift + idx_c[col]/dof; /* left, below */
429b3bd94feSDave May         Ni[0]   = 1.0;
430b3bd94feSDave May         if ( (li==0) || (li==nxi-1) ) {
431b3bd94feSDave May           if ( (lj==0) || (lj==neta-1) ) {
432b3bd94feSDave May             ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
433b3bd94feSDave May             continue;
434b3bd94feSDave May           }
435b3bd94feSDave May         }
436b3bd94feSDave May 
437b3bd94feSDave May         /* edges + interior */
438b3bd94feSDave May         /* remainders */
439b3bd94feSDave May         if (i==mx-1){ i_c--; }
440b3bd94feSDave May         if (j==my-1){ j_c--; }
441b3bd94feSDave May 
442b3bd94feSDave May         col     = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
443b3bd94feSDave May         cols[0] = col_shift + idx_c[col]/dof; /* left, below */
444b3bd94feSDave May         cols[1] = col_shift + idx_c[col+dof]/dof; /* right, below */
445b3bd94feSDave May         cols[2] = col_shift + idx_c[col+m_ghost_c*dof]/dof; /* left, above */
446b3bd94feSDave May         cols[3] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; /* right, above */
447b3bd94feSDave May 
448b3bd94feSDave May         Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]);
449b3bd94feSDave May         Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]);
450b3bd94feSDave May         Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]);
451b3bd94feSDave May         Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]);
452b3bd94feSDave May 
453b3bd94feSDave May         nc = 0;
454b3bd94feSDave May         if( PetscAbsScalar(Ni[0])<1.0e-32) { cols[0]=-1; }
455b3bd94feSDave May         if( PetscAbsScalar(Ni[1])<1.0e-32) { cols[1]=-1; }
456b3bd94feSDave May         if( PetscAbsScalar(Ni[2])<1.0e-32) { cols[2]=-1; }
457b3bd94feSDave May         if( PetscAbsScalar(Ni[3])<1.0e-32) { cols[3]=-1; }
458b3bd94feSDave May 
459b3bd94feSDave May         ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
460b3bd94feSDave May       }
461b3bd94feSDave May     }
462b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
463b3bd94feSDave May     ierr = PetscFree(eta);CHKERRQ(ierr);
464b3bd94feSDave May   }
46547c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46647c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46747c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
468fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
46947c6ae99SBarry Smith   PetscFunctionReturn(0);
47047c6ae99SBarry Smith }
47147c6ae99SBarry Smith 
47247c6ae99SBarry Smith /*
47347c6ae99SBarry Smith        Contributed by Andrei Draganescu <aidraga@sandia.gov>
47447c6ae99SBarry Smith */
47547c6ae99SBarry Smith #undef __FUNCT__
476e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_2D_Q0"
477e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A)
47847c6ae99SBarry Smith {
47947c6ae99SBarry Smith   PetscErrorCode   ierr;
48047c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof;
48147c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz;
48247c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj;
48347c6ae99SBarry Smith   PetscInt         i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c,col_shift,col_scale;
48447c6ae99SBarry Smith   PetscMPIInt      size_c,size_f,rank_f;
48547c6ae99SBarry Smith   PetscScalar      v[4];
48647c6ae99SBarry Smith   Mat              mat;
4871321219cSEthan Coon   DMDABoundaryType bx,by;
48847c6ae99SBarry Smith 
48947c6ae99SBarry Smith   PetscFunctionBegin;
4901321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
4911321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
4921321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x");
4931321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y");
49447c6ae99SBarry Smith   ratioi = mx/Mx;
49547c6ae99SBarry Smith   ratioj = my/My;
49647c6ae99SBarry Smith   if (ratioi*Mx != mx) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x");
49747c6ae99SBarry Smith   if (ratioj*My != my) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y");
49847c6ae99SBarry Smith   if (ratioi != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2");
49947c6ae99SBarry Smith   if (ratioj != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2");
50047c6ae99SBarry Smith 
501aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
502aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
503aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
50447c6ae99SBarry Smith 
505aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
506aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
507aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
50847c6ae99SBarry Smith 
50947c6ae99SBarry Smith   /*
510aa219208SBarry Smith      Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
51147c6ae99SBarry Smith      The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
51247c6ae99SBarry Smith      processors). It's effective length is hence 4 times its normal length, this is
51347c6ae99SBarry Smith      why the col_scale is multiplied by the interpolation matrix column sizes.
51447c6ae99SBarry Smith      sol_shift allows each set of 1/4 processors do its own interpolation using ITS
51547c6ae99SBarry Smith      copy of the coarse vector. A bit of a hack but you do better.
51647c6ae99SBarry Smith 
51747c6ae99SBarry Smith      In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
51847c6ae99SBarry Smith   */
51947c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr);
52047c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr);
52147c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr);
52247c6ae99SBarry Smith   col_scale = size_f/size_c;
52347c6ae99SBarry Smith   col_shift = Mx*My*(rank_f/size_c);
52447c6ae99SBarry Smith 
52547c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr);
52647c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
52747c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
52847c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
52947c6ae99SBarry Smith       row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
53047c6ae99SBarry Smith 
53147c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
53247c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
53347c6ae99SBarry Smith 
534aa219208SBarry Smith       if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
53547c6ae99SBarry Smith     j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
536aa219208SBarry Smith       if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
53747c6ae99SBarry Smith     i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
53847c6ae99SBarry Smith 
53947c6ae99SBarry Smith       /*
54047c6ae99SBarry Smith          Only include those interpolation points that are truly
54147c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
54247c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
54347c6ae99SBarry Smith       */
54447c6ae99SBarry Smith       nc = 0;
54547c6ae99SBarry Smith       /* one left and below; or we are right on it */
54647c6ae99SBarry Smith       col        = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
54747c6ae99SBarry Smith       cols[nc++] = col_shift + idx_c[col]/dof;
54847c6ae99SBarry Smith       ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
54947c6ae99SBarry Smith     }
55047c6ae99SBarry Smith   }
55147c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr);
55247c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr);
55347c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
55447c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
55547c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
55647c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
55747c6ae99SBarry Smith 
55847c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
55947c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
56047c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
56147c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
56247c6ae99SBarry Smith       row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
56347c6ae99SBarry Smith 
56447c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
56547c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
56647c6ae99SBarry Smith       nc = 0;
56747c6ae99SBarry Smith       /* one left and below; or we are right on it */
56847c6ae99SBarry Smith       col      = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
56947c6ae99SBarry Smith       cols[nc] = col_shift + idx_c[col]/dof;
57047c6ae99SBarry Smith       v[nc++]  = 1.0;
57147c6ae99SBarry Smith 
57247c6ae99SBarry Smith       ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
57347c6ae99SBarry Smith     }
57447c6ae99SBarry Smith   }
57547c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57647c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57747c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
578fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
57947c6ae99SBarry Smith   ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr);
58047c6ae99SBarry Smith   PetscFunctionReturn(0);
58147c6ae99SBarry Smith }
58247c6ae99SBarry Smith 
58347c6ae99SBarry Smith /*
58447c6ae99SBarry Smith        Contributed by Jianming Yang <jianming-yang@uiowa.edu>
58547c6ae99SBarry Smith */
58647c6ae99SBarry Smith #undef __FUNCT__
587e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_3D_Q0"
588e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A)
58947c6ae99SBarry Smith {
59047c6ae99SBarry Smith   PetscErrorCode   ierr;
59147c6ae99SBarry Smith   PetscInt         i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,*idx_f,dof;
59247c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,p_ghost,*idx_c,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz;
59347c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,j_start_ghost,l_start_ghost,cols[8],mx,m_c,my,n_c,mz,p_c,ratioi,ratioj,ratiol;
59447c6ae99SBarry Smith   PetscInt         i_c,j_c,l_c,i_start_c,j_start_c,l_start_c,i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,col_shift,col_scale;
59547c6ae99SBarry Smith   PetscMPIInt      size_c,size_f,rank_f;
59647c6ae99SBarry Smith   PetscScalar      v[8];
59747c6ae99SBarry Smith   Mat              mat;
5981321219cSEthan Coon   DMDABoundaryType bx,by,bz;
59947c6ae99SBarry Smith 
60047c6ae99SBarry Smith   PetscFunctionBegin;
6011321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
6021321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
6031321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x");
6041321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y");
6051321219cSEthan Coon   if (bz == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in z");
60647c6ae99SBarry Smith   ratioi = mx/Mx;
60747c6ae99SBarry Smith   ratioj = my/My;
60847c6ae99SBarry Smith   ratiol = mz/Mz;
60947c6ae99SBarry Smith   if (ratioi*Mx != mx) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x");
61047c6ae99SBarry Smith   if (ratioj*My != my) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y");
61147c6ae99SBarry Smith   if (ratiol*Mz != mz) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z");
61247c6ae99SBarry Smith   if (ratioi != 2 && ratioi != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2");
61347c6ae99SBarry Smith   if (ratioj != 2 && ratioj != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2");
61447c6ae99SBarry Smith   if (ratiol != 2 && ratiol != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2");
61547c6ae99SBarry Smith 
616aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
617aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
618aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
61947c6ae99SBarry Smith 
620aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
621aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr);
622aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
62347c6ae99SBarry Smith   /*
624aa219208SBarry Smith      Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
62547c6ae99SBarry Smith      The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
62647c6ae99SBarry Smith      processors). It's effective length is hence 4 times its normal length, this is
62747c6ae99SBarry Smith      why the col_scale is multiplied by the interpolation matrix column sizes.
62847c6ae99SBarry Smith      sol_shift allows each set of 1/4 processors do its own interpolation using ITS
62947c6ae99SBarry Smith      copy of the coarse vector. A bit of a hack but you do better.
63047c6ae99SBarry Smith 
63147c6ae99SBarry Smith      In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
63247c6ae99SBarry Smith   */
63347c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr);
63447c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr);
63547c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr);
63647c6ae99SBarry Smith   col_scale = size_f/size_c;
63747c6ae99SBarry Smith   col_shift = Mx*My*Mz*(rank_f/size_c);
63847c6ae99SBarry Smith 
63947c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr);
64047c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
64147c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
64247c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
64347c6ae99SBarry Smith 	/* convert to local "natural" numbering and then to PETSc global numbering */
64447c6ae99SBarry Smith 	row    = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
64547c6ae99SBarry Smith 
64647c6ae99SBarry Smith 	i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
64747c6ae99SBarry Smith 	j_c = (j/ratioj);    /* coarse grid node below fine grid node */
64847c6ae99SBarry Smith 	l_c = (l/ratiol);
64947c6ae99SBarry Smith 
650aa219208SBarry Smith 	if (l_c < l_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
65147c6ae99SBarry Smith     l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c);
652aa219208SBarry Smith 	if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
65347c6ae99SBarry Smith     j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
654aa219208SBarry Smith 	if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
65547c6ae99SBarry Smith     i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
65647c6ae99SBarry Smith 
65747c6ae99SBarry Smith 	/*
65847c6ae99SBarry Smith 	   Only include those interpolation points that are truly
65947c6ae99SBarry Smith 	   nonzero. Note this is very important for final grid lines
66047c6ae99SBarry Smith 	   in x and y directions; since they have no right/top neighbors
66147c6ae99SBarry Smith 	*/
66247c6ae99SBarry Smith 	nc = 0;
66347c6ae99SBarry Smith 	/* one left and below; or we are right on it */
66447c6ae99SBarry Smith 	col        = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
66547c6ae99SBarry Smith 	cols[nc++] = col_shift + idx_c[col]/dof;
66647c6ae99SBarry Smith 	ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
66747c6ae99SBarry Smith       }
66847c6ae99SBarry Smith     }
66947c6ae99SBarry Smith   }
67047c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr);
67147c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f*p_f,col_scale*m_c*n_c*p_c,mx*my*mz,col_scale*Mx*My*Mz);CHKERRQ(ierr);
67247c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
67347c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
67447c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
67547c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
67647c6ae99SBarry Smith 
67747c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
67847c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
67947c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
68047c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
68147c6ae99SBarry Smith 	/* convert to local "natural" numbering and then to PETSc global numbering */
68247c6ae99SBarry Smith 	row    = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
68347c6ae99SBarry Smith 
68447c6ae99SBarry Smith 	i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
68547c6ae99SBarry Smith 	j_c = (j/ratioj);    /* coarse grid node below fine grid node */
68647c6ae99SBarry Smith 	l_c = (l/ratiol);
68747c6ae99SBarry Smith 	nc = 0;
68847c6ae99SBarry Smith 	/* one left and below; or we are right on it */
68947c6ae99SBarry Smith 	col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
69047c6ae99SBarry Smith 	cols[nc] = col_shift + idx_c[col]/dof;
69147c6ae99SBarry Smith 	v[nc++]  = 1.0;
69247c6ae99SBarry Smith 
69347c6ae99SBarry Smith 	ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
69447c6ae99SBarry Smith       }
69547c6ae99SBarry Smith     }
69647c6ae99SBarry Smith   }
69747c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
69847c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
69947c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
700fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
70147c6ae99SBarry Smith   ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr);
70247c6ae99SBarry Smith   PetscFunctionReturn(0);
70347c6ae99SBarry Smith }
70447c6ae99SBarry Smith 
70547c6ae99SBarry Smith #undef __FUNCT__
706e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_3D_Q1"
707e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A)
70847c6ae99SBarry Smith {
70947c6ae99SBarry Smith   PetscErrorCode   ierr;
71047c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof,l;
71147c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,Mz,mz;
71247c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok;
71347c6ae99SBarry Smith   PetscInt         i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c;
71447c6ae99SBarry Smith   PetscInt         l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c;
71547c6ae99SBarry Smith   PetscInt         l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz;
71647c6ae99SBarry Smith   PetscScalar      v[8],x,y,z;
71747c6ae99SBarry Smith   Mat              mat;
7181321219cSEthan Coon   DMDABoundaryType bx,by,bz;
71947c6ae99SBarry Smith 
72047c6ae99SBarry Smith   PetscFunctionBegin;
7211321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
7221321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
72347c6ae99SBarry Smith   if (mx == Mx) {
72447c6ae99SBarry Smith     ratioi = 1;
7251321219cSEthan Coon   } else if (bx == DMDA_BOUNDARY_PERIODIC) {
72647c6ae99SBarry Smith     ratioi = mx/Mx;
72747c6ae99SBarry Smith     if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx  must be integer: mx %D Mx %D",mx,Mx);
72847c6ae99SBarry Smith   } else {
72947c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
73047c6ae99SBarry Smith     if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx);
73147c6ae99SBarry Smith   }
73247c6ae99SBarry Smith   if (my == My) {
73347c6ae99SBarry Smith     ratioj = 1;
7341321219cSEthan Coon   } else if (by == DMDA_BOUNDARY_PERIODIC) {
73547c6ae99SBarry Smith     ratioj = my/My;
73647c6ae99SBarry Smith     if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My  must be integer: my %D My %D",my,My);
73747c6ae99SBarry Smith   } else {
73847c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
73947c6ae99SBarry Smith     if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My);
74047c6ae99SBarry Smith   }
74147c6ae99SBarry Smith   if (mz == Mz) {
74247c6ae99SBarry Smith     ratiok = 1;
7431321219cSEthan Coon   } else if (bz == DMDA_BOUNDARY_PERIODIC) {
74447c6ae99SBarry Smith     ratiok = mz/Mz;
74547c6ae99SBarry Smith     if (ratiok*Mz != mz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz  must be integer: mz %D Mz %D",mz,Mz);
74647c6ae99SBarry Smith   } else {
74747c6ae99SBarry Smith     ratiok = (mz-1)/(Mz-1);
74847c6ae99SBarry Smith     if (ratiok*(Mz-1) != mz-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz);
74947c6ae99SBarry Smith   }
75047c6ae99SBarry Smith 
751aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
752aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
753aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
75447c6ae99SBarry Smith 
755aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
756aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr);
757aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
75847c6ae99SBarry Smith 
75947c6ae99SBarry Smith   /* create interpolation matrix, determining exact preallocation */
76047c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)dac)->comm,m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr);
76147c6ae99SBarry Smith   /* loop over local fine grid nodes counting interpolating points */
76247c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
76347c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
76447c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
76547c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
76647c6ae99SBarry Smith         row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
76747c6ae99SBarry Smith         i_c = (i/ratioi);
76847c6ae99SBarry Smith         j_c = (j/ratioj);
76947c6ae99SBarry Smith         l_c = (l/ratiok);
770aa219208SBarry Smith         if (l_c < l_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
77147c6ae99SBarry Smith                                             l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c);
772aa219208SBarry Smith         if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
77347c6ae99SBarry Smith                                             j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
774aa219208SBarry Smith         if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
77547c6ae99SBarry Smith                                             i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
77647c6ae99SBarry Smith 
77747c6ae99SBarry Smith         /*
77847c6ae99SBarry Smith          Only include those interpolation points that are truly
77947c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
78047c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
78147c6ae99SBarry Smith          */
78247c6ae99SBarry Smith         nc       = 0;
78347c6ae99SBarry Smith         col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
78447c6ae99SBarry Smith         cols[nc++] = idx_c[col]/dof;
78547c6ae99SBarry Smith         if (i_c*ratioi != i) {
78647c6ae99SBarry Smith           cols[nc++] = idx_c[col+dof]/dof;
78747c6ae99SBarry Smith         }
78847c6ae99SBarry Smith         if (j_c*ratioj != j) {
78947c6ae99SBarry Smith           cols[nc++] = idx_c[col+m_ghost_c*dof]/dof;
79047c6ae99SBarry Smith         }
79147c6ae99SBarry Smith         if (l_c*ratiok != l) {
79247c6ae99SBarry Smith           cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof;
79347c6ae99SBarry Smith         }
79447c6ae99SBarry Smith         if (j_c*ratioj != j && i_c*ratioi != i) {
79547c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c+1)*dof]/dof;
79647c6ae99SBarry Smith         }
79747c6ae99SBarry Smith         if (j_c*ratioj != j && l_c*ratiok != l) {
79847c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;
79947c6ae99SBarry Smith         }
80047c6ae99SBarry Smith         if (i_c*ratioi != i && l_c*ratiok != l) {
80147c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof;
80247c6ae99SBarry Smith         }
80347c6ae99SBarry Smith         if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) {
80447c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof;
80547c6ae99SBarry Smith         }
80647c6ae99SBarry Smith         ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
80747c6ae99SBarry Smith       }
80847c6ae99SBarry Smith     }
80947c6ae99SBarry Smith   }
81047c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr);
81147c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr);
81247c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
81347c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
81447c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
81547c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
81647c6ae99SBarry Smith 
81747c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
8182adb9dcfSBarry Smith   if (!NEWVERSION) {
819b3bd94feSDave May 
82047c6ae99SBarry Smith     for (l=l_start; l<l_start+p_f; l++) {
82147c6ae99SBarry Smith       for (j=j_start; j<j_start+n_f; j++) {
82247c6ae99SBarry Smith         for (i=i_start; i<i_start+m_f; i++) {
82347c6ae99SBarry Smith           /* convert to local "natural" numbering and then to PETSc global numbering */
82447c6ae99SBarry Smith           row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
82547c6ae99SBarry Smith 
82647c6ae99SBarry Smith           i_c = (i/ratioi);
82747c6ae99SBarry Smith           j_c = (j/ratioj);
82847c6ae99SBarry Smith           l_c = (l/ratiok);
82947c6ae99SBarry Smith 
83047c6ae99SBarry Smith         /*
83147c6ae99SBarry Smith          Only include those interpolation points that are truly
83247c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
83347c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
83447c6ae99SBarry Smith          */
83547c6ae99SBarry Smith           x  = ((double)(i - i_c*ratioi))/((double)ratioi);
83647c6ae99SBarry Smith           y  = ((double)(j - j_c*ratioj))/((double)ratioj);
83747c6ae99SBarry Smith           z  = ((double)(l - l_c*ratiok))/((double)ratiok);
838b3bd94feSDave May 
83947c6ae99SBarry Smith           nc = 0;
84047c6ae99SBarry Smith           /* one left and below; or we are right on it */
84147c6ae99SBarry Smith           col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c)+m_ghost_c*(j_c-j_start_ghost_c)+(i_c-i_start_ghost_c));
84247c6ae99SBarry Smith 
84347c6ae99SBarry Smith           cols[nc] = idx_c[col]/dof;
84447c6ae99SBarry Smith           v[nc++]  = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.));
84547c6ae99SBarry Smith 
84647c6ae99SBarry Smith           if (i_c*ratioi != i) {
84747c6ae99SBarry Smith             cols[nc] = idx_c[col+dof]/dof;
84847c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.));
84947c6ae99SBarry Smith           }
85047c6ae99SBarry Smith 
85147c6ae99SBarry Smith           if (j_c*ratioj != j) {
85247c6ae99SBarry Smith             cols[nc] = idx_c[col+m_ghost_c*dof]/dof;
85347c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.));
85447c6ae99SBarry Smith           }
85547c6ae99SBarry Smith 
85647c6ae99SBarry Smith           if (l_c*ratiok != l) {
85747c6ae99SBarry Smith             cols[nc] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof;
85847c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.));
85947c6ae99SBarry Smith           }
86047c6ae99SBarry Smith 
86147c6ae99SBarry Smith           if (j_c*ratioj != j && i_c*ratioi != i) {
86247c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c+1)*dof]/dof;
86347c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.));
86447c6ae99SBarry Smith           }
86547c6ae99SBarry Smith 
86647c6ae99SBarry Smith           if (j_c*ratioj != j && l_c*ratiok != l) {
86747c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;
86847c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.));
86947c6ae99SBarry Smith           }
87047c6ae99SBarry Smith 
87147c6ae99SBarry Smith           if (i_c*ratioi != i && l_c*ratiok != l) {
87247c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof;
87347c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.));
87447c6ae99SBarry Smith           }
87547c6ae99SBarry Smith 
87647c6ae99SBarry Smith           if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) {
87747c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof;
87847c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.));
87947c6ae99SBarry Smith           }
88047c6ae99SBarry Smith           ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
88147c6ae99SBarry Smith         }
88247c6ae99SBarry Smith       }
88347c6ae99SBarry Smith     }
884b3bd94feSDave May 
885b3bd94feSDave May   } else {
886b3bd94feSDave May     PetscScalar    *xi,*eta,*zeta;
887b3bd94feSDave May     PetscInt       li,nxi,lj,neta,lk,nzeta,n;
888b3bd94feSDave May     PetscScalar    Ni[8];
889b3bd94feSDave May 
890b3bd94feSDave May     /* compute local coordinate arrays */
891b3bd94feSDave May     nxi   = ratioi + 1;
892b3bd94feSDave May     neta  = ratioj + 1;
893b3bd94feSDave May     nzeta = ratiok + 1;
894b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
895b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr);
896b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nzeta,&zeta);CHKERRQ(ierr);
897b3bd94feSDave May     for (li=0; li<nxi; li++) {
89852218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
899b3bd94feSDave May     }
900b3bd94feSDave May     for (lj=0; lj<neta; lj++) {
90152218ef2SJed Brown       eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1));
902b3bd94feSDave May     }
903b3bd94feSDave May     for (lk=0; lk<nzeta; lk++) {
90452218ef2SJed Brown       zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1));
905b3bd94feSDave May     }
906b3bd94feSDave May 
907b3bd94feSDave May     for (l=l_start; l<l_start+p_f; l++) {
908b3bd94feSDave May       for (j=j_start; j<j_start+n_f; j++) {
909b3bd94feSDave May         for (i=i_start; i<i_start+m_f; i++) {
910b3bd94feSDave May           /* convert to local "natural" numbering and then to PETSc global numbering */
911b3bd94feSDave May           row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
912b3bd94feSDave May 
913b3bd94feSDave May           i_c = (i/ratioi);
914b3bd94feSDave May           j_c = (j/ratioj);
915b3bd94feSDave May           l_c = (l/ratiok);
916b3bd94feSDave May 
917b3bd94feSDave May           /* remainders */
918b3bd94feSDave May           li = i - ratioi * (i/ratioi);
919b3bd94feSDave May           if (i==mx-1){ li = nxi-1; }
920b3bd94feSDave May           lj = j - ratioj * (j/ratioj);
921b3bd94feSDave May           if (j==my-1){ lj = neta-1; }
922b3bd94feSDave May           lk = l - ratiok * (l/ratiok);
923b3bd94feSDave May           if (l==mz-1){ lk = nzeta-1; }
924b3bd94feSDave May 
925b3bd94feSDave May           /* corners */
926b3bd94feSDave May           col     = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c)+m_ghost_c*(j_c-j_start_ghost_c)+(i_c-i_start_ghost_c));
927b3bd94feSDave May           cols[0] = idx_c[col]/dof;
928b3bd94feSDave May           Ni[0]   = 1.0;
929b3bd94feSDave May           if ( (li==0) || (li==nxi-1) ) {
930b3bd94feSDave May             if ( (lj==0) || (lj==neta-1) ) {
931b3bd94feSDave May               if ( (lk==0) || (lk==nzeta-1) ) {
932b3bd94feSDave May                 ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
933b3bd94feSDave May                 continue;
934b3bd94feSDave May               }
935b3bd94feSDave May             }
936b3bd94feSDave May           }
937b3bd94feSDave May 
938b3bd94feSDave May           /* edges + interior */
939b3bd94feSDave May           /* remainders */
940b3bd94feSDave May           if (i==mx-1){ i_c--; }
941b3bd94feSDave May           if (j==my-1){ j_c--; }
942b3bd94feSDave May           if (l==mz-1){ l_c--; }
943b3bd94feSDave May 
944b3bd94feSDave May           col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
945b3bd94feSDave May           cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */
946b3bd94feSDave May           cols[1] = idx_c[col+dof]/dof; /* one right and below */
947b3bd94feSDave May           cols[2] = idx_c[col+m_ghost_c*dof]/dof;  /* one left and above */
948b3bd94feSDave May           cols[3] = idx_c[col+(m_ghost_c+1)*dof]/dof; /* one right and above */
949b3bd94feSDave May 
950b3bd94feSDave May           cols[4] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof; /* one left and below and front; or we are right on it */
951b3bd94feSDave May           cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; /* one right and below, and front */
952b3bd94feSDave May           cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;/* one left and above and front*/
953b3bd94feSDave May           cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; /* one right and above and front */
954b3bd94feSDave May 
955b3bd94feSDave May           Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]);
956b3bd94feSDave May           Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]);
957b3bd94feSDave May           Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]);
958b3bd94feSDave May           Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]);
959b3bd94feSDave May 
960b3bd94feSDave May           Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]);
961b3bd94feSDave May           Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]);
962b3bd94feSDave May           Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]);
963b3bd94feSDave May           Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]);
964b3bd94feSDave May 
965b3bd94feSDave May           for (n=0; n<8; n++) {
966b3bd94feSDave May             if( PetscAbsScalar(Ni[n])<1.0e-32) { cols[n]=-1; }
967b3bd94feSDave May           }
968b3bd94feSDave May           ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
969b3bd94feSDave May 
970b3bd94feSDave May         }
971b3bd94feSDave May       }
972b3bd94feSDave May     }
973b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
974b3bd94feSDave May     ierr = PetscFree(eta);CHKERRQ(ierr);
975b3bd94feSDave May     ierr = PetscFree(zeta);CHKERRQ(ierr);
976b3bd94feSDave May   }
977b3bd94feSDave May 
97847c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
97947c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
98047c6ae99SBarry Smith 
98147c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
982fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
98347c6ae99SBarry Smith   PetscFunctionReturn(0);
98447c6ae99SBarry Smith }
98547c6ae99SBarry Smith 
98647c6ae99SBarry Smith #undef __FUNCT__
987e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA"
988e727c939SJed Brown PetscErrorCode  DMCreateInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale)
98947c6ae99SBarry Smith {
99047c6ae99SBarry Smith   PetscErrorCode   ierr;
99147c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
9921321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
993aa219208SBarry Smith   DMDAStencilType  stc,stf;
99447c6ae99SBarry Smith   DM_DA            *ddc = (DM_DA*)dac->data;
99547c6ae99SBarry Smith 
99647c6ae99SBarry Smith   PetscFunctionBegin;
99747c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
99847c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
99947c6ae99SBarry Smith   PetscValidPointer(A,3);
100047c6ae99SBarry Smith   if (scale) PetscValidPointer(scale,4);
100147c6ae99SBarry Smith 
10021321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
10031321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1004aa219208SBarry Smith   if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1005aa219208SBarry Smith   if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1006aa219208SBarry Smith   if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
10071321219cSEthan Coon   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1008aa219208SBarry Smith   if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
100947c6ae99SBarry Smith   if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction");
101047c6ae99SBarry Smith   if (dimc > 1 && Nc < 2 && Nf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction");
101147c6ae99SBarry Smith   if (dimc > 2 && Pc < 2 && Pf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction");
101247c6ae99SBarry Smith 
1013aa219208SBarry Smith   if (ddc->interptype == DMDA_Q1){
101447c6ae99SBarry Smith     if (dimc == 1){
1015e727c939SJed Brown       ierr = DMCreateInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr);
101647c6ae99SBarry Smith     } else if (dimc == 2){
1017e727c939SJed Brown       ierr = DMCreateInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr);
101847c6ae99SBarry Smith     } else if (dimc == 3){
1019e727c939SJed Brown       ierr = DMCreateInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr);
102085afcc9aSBarry Smith     } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype);
1021aa219208SBarry Smith   } else if (ddc->interptype == DMDA_Q0){
102247c6ae99SBarry Smith     if (dimc == 1){
1023e727c939SJed Brown       ierr = DMCreateInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr);
102447c6ae99SBarry Smith     } else if (dimc == 2){
1025e727c939SJed Brown        ierr = DMCreateInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr);
102647c6ae99SBarry Smith     } else if (dimc == 3){
1027e727c939SJed Brown        ierr = DMCreateInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr);
102885afcc9aSBarry Smith     } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype);
102947c6ae99SBarry Smith   }
103047c6ae99SBarry Smith   if (scale) {
1031e727c939SJed Brown     ierr = DMCreateInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr);
103247c6ae99SBarry Smith   }
103347c6ae99SBarry Smith   PetscFunctionReturn(0);
103447c6ae99SBarry Smith }
103547c6ae99SBarry Smith 
103647c6ae99SBarry Smith #undef __FUNCT__
1037e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_1D"
1038e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_1D(DM dac,DM daf,VecScatter *inject)
10390bb2b966SJungho Lee {
10400bb2b966SJungho Lee     PetscErrorCode   ierr;
10410bb2b966SJungho Lee     PetscInt         i,i_start,m_f,Mx,*idx_f,dof;
10420bb2b966SJungho Lee     PetscInt         m_ghost,*idx_c,m_ghost_c;
10430bb2b966SJungho Lee     PetscInt         row,i_start_ghost,mx,m_c,nc,ratioi;
10440bb2b966SJungho Lee     PetscInt         i_start_c,i_start_ghost_c;
10450bb2b966SJungho Lee     PetscInt         *cols;
10460bb2b966SJungho Lee     DMDABoundaryType bx;
10470bb2b966SJungho Lee     Vec              vecf,vecc;
10480bb2b966SJungho Lee     IS               isf;
10490bb2b966SJungho Lee 
10500bb2b966SJungho Lee     PetscFunctionBegin;
10510bb2b966SJungho Lee     ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
10520bb2b966SJungho Lee     ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
10530bb2b966SJungho Lee     if (bx == DMDA_BOUNDARY_PERIODIC) {
10540bb2b966SJungho Lee         ratioi = mx/Mx;
10550bb2b966SJungho Lee         if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx  must be integer: mx %D Mx %D",mx,Mx);
10560bb2b966SJungho Lee     } else {
10570bb2b966SJungho Lee         ratioi = (mx-1)/(Mx-1);
10580bb2b966SJungho Lee         if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx);
10590bb2b966SJungho Lee     }
10600bb2b966SJungho Lee 
10610bb2b966SJungho Lee     ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
10620bb2b966SJungho Lee     ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
10630bb2b966SJungho Lee     ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
10640bb2b966SJungho Lee 
10650bb2b966SJungho Lee     ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
10660bb2b966SJungho Lee     ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
10670bb2b966SJungho Lee     ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
10680bb2b966SJungho Lee 
10690bb2b966SJungho Lee 
10700bb2b966SJungho Lee     /* loop over local fine grid nodes setting interpolation for those*/
10710bb2b966SJungho Lee     nc = 0;
10720bb2b966SJungho Lee     ierr = PetscMalloc(m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr);
10730bb2b966SJungho Lee 
10740bb2b966SJungho Lee 
10750bb2b966SJungho Lee     for (i=i_start_c; i<i_start_c+m_c; i++) {
10760bb2b966SJungho Lee         PetscInt i_f = i*ratioi;
10770bb2b966SJungho Lee 
10780bb2b966SJungho Lee            if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
10790bb2b966SJungho Lee  i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
10800bb2b966SJungho Lee             row = idx_f[dof*(i_f-i_start_ghost)];
10810bb2b966SJungho Lee             cols[nc++] = row/dof;
10820bb2b966SJungho Lee     }
10830bb2b966SJungho Lee 
10840bb2b966SJungho Lee 
10850bb2b966SJungho Lee     ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
10860bb2b966SJungho Lee     ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
10870bb2b966SJungho Lee     ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
10880bb2b966SJungho Lee     ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr);
10890bb2b966SJungho Lee     ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
10900bb2b966SJungho Lee     ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
10910bb2b966SJungho Lee     ierr = ISDestroy(&isf);CHKERRQ(ierr);
10920bb2b966SJungho Lee     PetscFunctionReturn(0);
10930bb2b966SJungho Lee }
10940bb2b966SJungho Lee 
10950bb2b966SJungho Lee #undef __FUNCT__
1096e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_2D"
1097e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject)
109847c6ae99SBarry Smith {
109947c6ae99SBarry Smith   PetscErrorCode   ierr;
110047c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof;
110147c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c;
110247c6ae99SBarry Smith   PetscInt         row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj;
1103076202ddSJed Brown   PetscInt         i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c;
110447c6ae99SBarry Smith   PetscInt         *cols;
11051321219cSEthan Coon   DMDABoundaryType bx,by;
110647c6ae99SBarry Smith   Vec              vecf,vecc;
110747c6ae99SBarry Smith   IS               isf;
110847c6ae99SBarry Smith 
110947c6ae99SBarry Smith   PetscFunctionBegin;
11101321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
11111321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
11121321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) {
111347c6ae99SBarry Smith     ratioi = mx/Mx;
111447c6ae99SBarry Smith     if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx  must be integer: mx %D Mx %D",mx,Mx);
111547c6ae99SBarry Smith   } else {
111647c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
111747c6ae99SBarry Smith     if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx);
111847c6ae99SBarry Smith   }
11191321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) {
112047c6ae99SBarry Smith     ratioj = my/My;
112147c6ae99SBarry Smith     if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My  must be integer: my %D My %D",my,My);
112247c6ae99SBarry Smith   } else {
112347c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
112447c6ae99SBarry Smith     if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My);
112547c6ae99SBarry Smith   }
112647c6ae99SBarry Smith 
1127aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
1128aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
1129aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
113047c6ae99SBarry Smith 
1131aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
1132aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
1133aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
113447c6ae99SBarry Smith 
113547c6ae99SBarry Smith 
113647c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
113747c6ae99SBarry Smith   nc = 0;
113847c6ae99SBarry Smith   ierr = PetscMalloc(n_f*m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr);
1139076202ddSJed Brown   for (j=j_start_c; j<j_start_c+n_c; j++) {
1140076202ddSJed Brown     for (i=i_start_c; i<i_start_c+m_c; i++) {
1141076202ddSJed Brown       PetscInt i_f = i*ratioi,j_f = j*ratioj;
1142076202ddSJed Brown       if (j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
1143076202ddSJed Brown     j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost);
1144076202ddSJed Brown       if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
1145076202ddSJed Brown     i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
1146076202ddSJed Brown       row = idx_f[dof*(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))];
114747c6ae99SBarry Smith       cols[nc++] = row/dof;
114847c6ae99SBarry Smith     }
114947c6ae99SBarry Smith   }
115047c6ae99SBarry Smith 
115147c6ae99SBarry Smith   ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
11529a42bb27SBarry Smith   ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
11539a42bb27SBarry Smith   ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
115447c6ae99SBarry Smith   ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr);
11559a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
11569a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
1157fcfd50ebSBarry Smith   ierr = ISDestroy(&isf);CHKERRQ(ierr);
115847c6ae99SBarry Smith   PetscFunctionReturn(0);
115947c6ae99SBarry Smith }
116047c6ae99SBarry Smith 
116147c6ae99SBarry Smith #undef __FUNCT__
1162e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_3D"
1163e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject)
1164b1757049SJed Brown {
1165b1757049SJed Brown   PetscErrorCode   ierr;
1166b1757049SJed Brown   PetscInt         i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz;
1167b1757049SJed Brown   PetscInt         m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c;
1168b1757049SJed Brown   PetscInt         i_start_ghost,j_start_ghost,k_start_ghost;
1169b1757049SJed Brown   PetscInt         mx,my,mz,ratioi,ratioj,ratiok;
1170b1757049SJed Brown   PetscInt         i_start_c,j_start_c,k_start_c;
1171b1757049SJed Brown   PetscInt         m_c,n_c,p_c;
1172b1757049SJed Brown   PetscInt         i_start_ghost_c,j_start_ghost_c,k_start_ghost_c;
1173b1757049SJed Brown   PetscInt         row,nc,dof;
1174b1757049SJed Brown   PetscInt         *idx_c,*idx_f;
1175b1757049SJed Brown   PetscInt         *cols;
11761321219cSEthan Coon   DMDABoundaryType bx,by,bz;
1177b1757049SJed Brown   Vec              vecf,vecc;
1178b1757049SJed Brown   IS               isf;
1179b1757049SJed Brown 
1180b1757049SJed Brown   PetscFunctionBegin;
11811321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
11821321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
1183b1757049SJed Brown 
11841321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
1185b1757049SJed Brown     ratioi = mx/Mx;
1186b1757049SJed Brown     if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx  must be integer: mx %D Mx %D",mx,Mx);
1187b1757049SJed Brown   } else {
1188b1757049SJed Brown     ratioi = (mx-1)/(Mx-1);
1189b1757049SJed Brown     if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx);
1190b1757049SJed Brown   }
11911321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC){
1192b1757049SJed Brown     ratioj = my/My;
1193b1757049SJed Brown     if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My  must be integer: my %D My %D",my,My);
1194b1757049SJed Brown   } else {
1195b1757049SJed Brown     ratioj = (my-1)/(My-1);
1196b1757049SJed Brown     if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My);
1197b1757049SJed Brown   }
11981321219cSEthan Coon   if (bz == DMDA_BOUNDARY_PERIODIC){
1199b1757049SJed Brown     ratiok = mz/Mz;
1200b1757049SJed Brown     if (ratiok*Mz != mz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz  must be integer: mz %D My %D",mz,Mz);
1201b1757049SJed Brown   } else {
1202b1757049SJed Brown     ratiok = (mz-1)/(Mz-1);
1203b1757049SJed Brown     if (ratiok*(Mz-1) != mz-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz);
1204b1757049SJed Brown   }
1205b1757049SJed Brown 
1206b1757049SJed Brown   ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
1207b1757049SJed Brown   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
1208b1757049SJed Brown   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
1209b1757049SJed Brown 
1210b1757049SJed Brown   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
1211b1757049SJed Brown   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&k_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr);
1212b1757049SJed Brown   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
1213b1757049SJed Brown 
1214b1757049SJed Brown 
1215b1757049SJed Brown   /* loop over local fine grid nodes setting interpolation for those*/
1216b1757049SJed Brown   nc = 0;
1217b1757049SJed Brown   ierr = PetscMalloc(n_f*m_f*p_f*sizeof(PetscInt),&cols);CHKERRQ(ierr);
1218b1757049SJed Brown   for (k=k_start_c; k<k_start_c+p_c; k++) {
1219b1757049SJed Brown     for (j=j_start_c; j<j_start_c+n_c; j++) {
1220b1757049SJed Brown       for (i=i_start_c; i<i_start_c+m_c; i++) {
1221b1757049SJed Brown         PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok;
1222b1757049SJed Brown         if (k_f < k_start_ghost || k_f >= k_start_ghost+p_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA  "
1223b1757049SJed Brown                                                                           "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost);
1224b1757049SJed Brown         if (j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA  "
1225b1757049SJed Brown                                                                           "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost);
1226b1757049SJed Brown         if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA  "
1227b1757049SJed Brown                                                                           "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
1228b1757049SJed Brown         row = idx_f[dof*(m_ghost*n_ghost*(k_f-k_start_ghost) + m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))];
1229b1757049SJed Brown         cols[nc++] = row/dof;
1230b1757049SJed Brown       }
1231b1757049SJed Brown     }
1232b1757049SJed Brown   }
1233b1757049SJed Brown 
1234b1757049SJed Brown   ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
1235b1757049SJed Brown   ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
1236b1757049SJed Brown   ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
1237b1757049SJed Brown   ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr);
1238b1757049SJed Brown   ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
1239b1757049SJed Brown   ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
1240fcfd50ebSBarry Smith   ierr = ISDestroy(&isf);CHKERRQ(ierr);
1241b1757049SJed Brown   PetscFunctionReturn(0);
1242b1757049SJed Brown }
1243b1757049SJed Brown 
1244b1757049SJed Brown #undef __FUNCT__
1245e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA"
1246e727c939SJed Brown PetscErrorCode  DMCreateInjection_DA(DM dac,DM daf,VecScatter *inject)
124747c6ae99SBarry Smith {
124847c6ae99SBarry Smith   PetscErrorCode   ierr;
124947c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
12501321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
1251aa219208SBarry Smith   DMDAStencilType  stc,stf;
125247c6ae99SBarry Smith 
125347c6ae99SBarry Smith   PetscFunctionBegin;
125447c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
125547c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
125647c6ae99SBarry Smith   PetscValidPointer(inject,3);
125747c6ae99SBarry Smith 
12581321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
12591321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1260aa219208SBarry Smith   if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1261aa219208SBarry Smith   if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1262aa219208SBarry Smith   if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
12631321219cSEthan Coon   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1264aa219208SBarry Smith   if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
126547c6ae99SBarry Smith   if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction");
126647c6ae99SBarry Smith   if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction");
126747c6ae99SBarry Smith   if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction");
126847c6ae99SBarry Smith 
12690bb2b966SJungho Lee   if (dimc == 1){
1270e727c939SJed Brown     ierr = DMCreateInjection_DA_1D(dac,daf,inject);CHKERRQ(ierr);
12710bb2b966SJungho Lee   } else if (dimc == 2) {
1272e727c939SJed Brown     ierr = DMCreateInjection_DA_2D(dac,daf,inject);CHKERRQ(ierr);
1273b1757049SJed Brown   } else if (dimc == 3) {
1274e727c939SJed Brown     ierr = DMCreateInjection_DA_3D(dac,daf,inject);CHKERRQ(ierr);
127547c6ae99SBarry Smith   }
127647c6ae99SBarry Smith   PetscFunctionReturn(0);
127747c6ae99SBarry Smith }
127847c6ae99SBarry Smith 
127947c6ae99SBarry Smith #undef __FUNCT__
1280e727c939SJed Brown #define __FUNCT__ "DMCreateAggregates_DA"
1281e727c939SJed Brown PetscErrorCode  DMCreateAggregates_DA(DM dac,DM daf,Mat *rest)
128247c6ae99SBarry Smith {
128347c6ae99SBarry Smith   PetscErrorCode   ierr;
128447c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc;
128547c6ae99SBarry Smith   PetscInt         dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
12861321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
1287aa219208SBarry Smith   DMDAStencilType  stc,stf;
128847c6ae99SBarry Smith   PetscInt         i,j,l;
128947c6ae99SBarry Smith   PetscInt         i_start,j_start,l_start, m_f,n_f,p_f;
129047c6ae99SBarry Smith   PetscInt         i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost;
129147c6ae99SBarry Smith   PetscInt         *idx_f;
129247c6ae99SBarry Smith   PetscInt         i_c,j_c,l_c;
129347c6ae99SBarry Smith   PetscInt         i_start_c,j_start_c,l_start_c, m_c,n_c,p_c;
129447c6ae99SBarry Smith   PetscInt         i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c;
129547c6ae99SBarry Smith   PetscInt         *idx_c;
129647c6ae99SBarry Smith   PetscInt         d;
129747c6ae99SBarry Smith   PetscInt         a;
129847c6ae99SBarry Smith   PetscInt         max_agg_size;
129947c6ae99SBarry Smith   PetscInt         *fine_nodes;
130047c6ae99SBarry Smith   PetscScalar      *one_vec;
130147c6ae99SBarry Smith   PetscInt         fn_idx;
130247c6ae99SBarry Smith 
130347c6ae99SBarry Smith   PetscFunctionBegin;
130447c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
130547c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
130647c6ae99SBarry Smith   PetscValidPointer(rest,3);
130747c6ae99SBarry Smith 
13081321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
13091321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1310aa219208SBarry Smith   if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1311aa219208SBarry Smith   if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1312aa219208SBarry Smith   if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
13131321219cSEthan Coon   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1314aa219208SBarry Smith   if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
131547c6ae99SBarry Smith 
131647c6ae99SBarry Smith   if( Mf < Mc ) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Mc %D, Mf %D", Mc, Mf);
131747c6ae99SBarry Smith   if( Nf < Nc ) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Nc %D, Nf %D", Nc, Nf);
131847c6ae99SBarry Smith   if( Pf < Pc ) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Pc %D, Pf %D", Pc, Pf);
131947c6ae99SBarry Smith 
132047c6ae99SBarry Smith   if (Pc < 0) Pc = 1;
132147c6ae99SBarry Smith   if (Pf < 0) Pf = 1;
132247c6ae99SBarry Smith   if (Nc < 0) Nc = 1;
132347c6ae99SBarry Smith   if (Nf < 0) Nf = 1;
132447c6ae99SBarry Smith 
1325aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
1326aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
1327aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
132847c6ae99SBarry Smith 
1329aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
1330aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr);
1331aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
133247c6ae99SBarry Smith 
133347c6ae99SBarry Smith   /*
133447c6ae99SBarry Smith      Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios
133547c6ae99SBarry Smith      for dimension 1 and 2 respectively.
133647c6ae99SBarry Smith      Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1)
133747c6ae99SBarry Smith      and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate.
133847c6ae99SBarry Smith      Each specific dof on the fine grid is mapped to one dof on the coarse grid.
133947c6ae99SBarry Smith   */
134047c6ae99SBarry Smith 
134147c6ae99SBarry Smith   max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1);
134247c6ae99SBarry Smith 
134347c6ae99SBarry Smith   /* create the matrix that will contain the restriction operator */
134447c6ae99SBarry Smith   ierr = MatCreateMPIAIJ( ((PetscObject)daf)->comm, m_c*n_c*p_c*dofc, m_f*n_f*p_f*doff, Mc*Nc*Pc*dofc, Mf*Nf*Pf*doff,
134547c6ae99SBarry Smith 			  max_agg_size, PETSC_NULL, max_agg_size, PETSC_NULL, rest);CHKERRQ(ierr);
134647c6ae99SBarry Smith 
134747c6ae99SBarry Smith   /* store nodes in the fine grid here */
134847c6ae99SBarry Smith   ierr = PetscMalloc2(max_agg_size,PetscScalar, &one_vec,max_agg_size,PetscInt, &fine_nodes);CHKERRQ(ierr);
134947c6ae99SBarry Smith   for(i=0; i<max_agg_size; i++) one_vec[i] = 1.0;
135047c6ae99SBarry Smith 
135147c6ae99SBarry Smith   /* loop over all coarse nodes */
135247c6ae99SBarry Smith   for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) {
135347c6ae99SBarry Smith     for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) {
135447c6ae99SBarry Smith       for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) {
135547c6ae99SBarry Smith 	for(d=0; d<dofc; d++) {
135647c6ae99SBarry Smith 	  /* convert to local "natural" numbering and then to PETSc global numbering */
135747c6ae99SBarry Smith 	  a = idx_c[dofc*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c))] + d;
135847c6ae99SBarry Smith 
135947c6ae99SBarry Smith 	  fn_idx = 0;
136047c6ae99SBarry Smith 	  /* Corresponding fine points are all points (i_f, j_f, l_f) such that
136147c6ae99SBarry Smith 	     i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc
136247c6ae99SBarry Smith 	     (same for other dimensions)
136347c6ae99SBarry Smith 	  */
136447c6ae99SBarry Smith 	  for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) {
136547c6ae99SBarry Smith 	    for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) {
136647c6ae99SBarry Smith 	      for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) {
136747c6ae99SBarry Smith 		fine_nodes[fn_idx] = idx_f[doff*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))] + d;
136847c6ae99SBarry Smith 		fn_idx++;
136947c6ae99SBarry Smith 	      }
137047c6ae99SBarry Smith 	    }
137147c6ae99SBarry Smith 	  }
137247c6ae99SBarry Smith 	  /* add all these points to one aggregate */
137347c6ae99SBarry Smith 	  ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr);
137447c6ae99SBarry Smith 	}
137547c6ae99SBarry Smith       }
137647c6ae99SBarry Smith     }
137747c6ae99SBarry Smith   }
137847c6ae99SBarry Smith   ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr);
137947c6ae99SBarry Smith   ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
138047c6ae99SBarry Smith   ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
138147c6ae99SBarry Smith   PetscFunctionReturn(0);
138247c6ae99SBarry Smith }
1383