xref: /petsc/src/dm/impls/da/dainterp.c (revision d52bd9f3ee665b897a5f0dc75d2f9f8201159d66)
147c6ae99SBarry Smith 
247c6ae99SBarry Smith /*
3aa219208SBarry Smith   Code for interpolating between grids represented by DMDAs
447c6ae99SBarry Smith */
547c6ae99SBarry Smith 
6*d52bd9f3SBarry Smith /*
7*d52bd9f3SBarry 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
8*d52bd9f3SBarry 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
9*d52bd9f3SBarry Smith    we will remove/merge the new version.
10*d52bd9f3SBarry Smith */
119314d695SBarry Smith #define NEWVERSION 0
1285afcc9aSBarry Smith 
13c6db04a5SJed Brown #include <private/daimpl.h>    /*I   "petscdmda.h"   I*/
14c6db04a5SJed Brown #include <petscpcmg.h>
1547c6ae99SBarry Smith 
1647c6ae99SBarry Smith #undef __FUNCT__
1747c6ae99SBarry Smith #define __FUNCT__ "DMGetInterpolationScale"
1847c6ae99SBarry Smith /*@
1947c6ae99SBarry Smith     DMGetInterpolationScale - 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 
3247c6ae99SBarry Smith .seealso: DMGetInterpolation()
3347c6ae99SBarry Smith 
3447c6ae99SBarry Smith @*/
357087cfbeSBarry Smith PetscErrorCode  DMGetInterpolationScale(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__
5294013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_1D_Q1"
5394013140SBarry Smith PetscErrorCode DMGetInterpolation_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);
8847c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,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__
17894013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_1D_Q0"
17994013140SBarry Smith PetscErrorCode DMGetInterpolation_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__
25094013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_2D_Q1"
25194013140SBarry Smith PetscErrorCode DMGetInterpolation_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__
47694013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_2D_Q0"
47794013140SBarry Smith PetscErrorCode DMGetInterpolation_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__
58794013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_3D_Q0"
58894013140SBarry Smith PetscErrorCode DMGetInterpolation_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__
70694013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_3D_Q1"
70794013140SBarry Smith PetscErrorCode DMGetInterpolation_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*/
81885afcc9aSBarry 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__
98794013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA"
9887087cfbeSBarry Smith PetscErrorCode  DMGetInterpolation_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){
101594013140SBarry Smith       ierr = DMGetInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr);
101647c6ae99SBarry Smith     } else if (dimc == 2){
101794013140SBarry Smith       ierr = DMGetInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr);
101847c6ae99SBarry Smith     } else if (dimc == 3){
101994013140SBarry Smith       ierr = DMGetInterpolation_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){
102394013140SBarry Smith       ierr = DMGetInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr);
102447c6ae99SBarry Smith     } else if (dimc == 2){
102594013140SBarry Smith        ierr = DMGetInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr);
102647c6ae99SBarry Smith     } else if (dimc == 3){
102794013140SBarry Smith        ierr = DMGetInterpolation_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) {
103147c6ae99SBarry Smith     ierr = DMGetInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr);
103247c6ae99SBarry Smith   }
103347c6ae99SBarry Smith   PetscFunctionReturn(0);
103447c6ae99SBarry Smith }
103547c6ae99SBarry Smith 
103647c6ae99SBarry Smith #undef __FUNCT__
10370bb2b966SJungho Lee #define __FUNCT__ "DMGetInjection_DA_1D"
10380bb2b966SJungho Lee PetscErrorCode DMGetInjection_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__
109694013140SBarry Smith #define __FUNCT__ "DMGetInjection_DA_2D"
109794013140SBarry Smith PetscErrorCode DMGetInjection_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__
1162b1757049SJed Brown #define __FUNCT__ "DMGetInjection_DA_3D"
1163b1757049SJed Brown PetscErrorCode DMGetInjection_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__
124594013140SBarry Smith #define __FUNCT__ "DMGetInjection_DA"
12467087cfbeSBarry Smith PetscErrorCode  DMGetInjection_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){
12700bb2b966SJungho Lee     ierr = DMGetInjection_DA_1D(dac,daf,inject);CHKERRQ(ierr);
12710bb2b966SJungho Lee   } else if (dimc == 2) {
127294013140SBarry Smith     ierr = DMGetInjection_DA_2D(dac,daf,inject);CHKERRQ(ierr);
1273b1757049SJed Brown   } else if (dimc == 3) {
1274b1757049SJed Brown     ierr = DMGetInjection_DA_3D(dac,daf,inject);CHKERRQ(ierr);
127547c6ae99SBarry Smith   }
127647c6ae99SBarry Smith   PetscFunctionReturn(0);
127747c6ae99SBarry Smith }
127847c6ae99SBarry Smith 
127947c6ae99SBarry Smith #undef __FUNCT__
128094013140SBarry Smith #define __FUNCT__ "DMGetAggregates_DA"
12817087cfbeSBarry Smith PetscErrorCode  DMGetAggregates_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