xref: /petsc/src/dm/impls/da/dainterp.c (revision 6712e2f1ace79231a3dc52d650f8fe8f207c217c)
147c6ae99SBarry Smith 
247c6ae99SBarry Smith /*
3aa219208SBarry Smith   Code for interpolating between grids represented by DMDAs
447c6ae99SBarry Smith */
547c6ae99SBarry Smith 
6d52bd9f3SBarry Smith /*
7d52bd9f3SBarry Smith       For linear elements there are two branches of code to compute the interpolation. They should compute the same results but may not. The "new version" does
8d52bd9f3SBarry Smith    not work for periodic domains, the old does. Change NEWVERSION to 1 to compile in the new version. Eventually when we are sure the two produce identical results
92adb9dcfSBarry Smith    we will remove/merge the new version. Based on current tests, these both produce the same results. We are leaving NEWVERSION for now in the code since some
102adb9dcfSBarry Smith    consider it cleaner, but old version is turned on since it handles periodic case.
11d52bd9f3SBarry Smith */
129314d695SBarry Smith #define NEWVERSION 0
1385afcc9aSBarry Smith 
144035e84dSBarry Smith #include <petsc-private/dmdaimpl.h>    /*I   "petscdmda.h"   I*/
1547c6ae99SBarry Smith 
1647c6ae99SBarry Smith #undef __FUNCT__
17e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolationScale"
1847c6ae99SBarry Smith /*@
19e727c939SJed Brown     DMCreateInterpolationScale - Forms L = R*1/diag(R*1) - L.*v is like a coarse grid average of the
2047c6ae99SBarry Smith       nearby fine grid points.
2147c6ae99SBarry Smith 
2247c6ae99SBarry Smith   Input Parameters:
2347c6ae99SBarry Smith +      dac - DM that defines a coarse mesh
2447c6ae99SBarry Smith .      daf - DM that defines a fine mesh
2547c6ae99SBarry Smith -      mat - the restriction (or interpolation operator) from fine to coarse
2647c6ae99SBarry Smith 
2747c6ae99SBarry Smith   Output Parameter:
2847c6ae99SBarry Smith .    scale - the scaled vector
2947c6ae99SBarry Smith 
3047c6ae99SBarry Smith   Level: developer
3147c6ae99SBarry Smith 
32e727c939SJed Brown .seealso: DMCreateInterpolation()
3347c6ae99SBarry Smith 
3447c6ae99SBarry Smith @*/
35e727c939SJed Brown PetscErrorCode  DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale)
3647c6ae99SBarry Smith {
3747c6ae99SBarry Smith   PetscErrorCode ierr;
3847c6ae99SBarry Smith   Vec            fine;
3947c6ae99SBarry Smith   PetscScalar    one = 1.0;
4047c6ae99SBarry Smith 
4147c6ae99SBarry Smith   PetscFunctionBegin;
4247c6ae99SBarry Smith   ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr);
4347c6ae99SBarry Smith   ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr);
4447c6ae99SBarry Smith   ierr = VecSet(fine,one);CHKERRQ(ierr);
4547c6ae99SBarry Smith   ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr);
46fcfd50ebSBarry Smith   ierr = VecDestroy(&fine);CHKERRQ(ierr);
4747c6ae99SBarry Smith   ierr = VecReciprocal(*scale);CHKERRQ(ierr);
4847c6ae99SBarry Smith   PetscFunctionReturn(0);
4947c6ae99SBarry Smith }
5047c6ae99SBarry Smith 
5147c6ae99SBarry Smith #undef __FUNCT__
52e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_1D_Q1"
53e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A)
5447c6ae99SBarry Smith {
5547c6ae99SBarry Smith   PetscErrorCode         ierr;
568ea3bf28SBarry Smith   PetscInt               i,i_start,m_f,Mx;
578ea3bf28SBarry Smith   const PetscInt         *idx_f,*idx_c;
588ea3bf28SBarry Smith   PetscInt               m_ghost,m_ghost_c;
5947c6ae99SBarry Smith   PetscInt               row,col,i_start_ghost,mx,m_c,nc,ratio;
6047c6ae99SBarry Smith   PetscInt               i_c,i_start_c,i_start_ghost_c,cols[2],dof;
6185afcc9aSBarry Smith   PetscScalar            v[2],x;
6247c6ae99SBarry Smith   Mat                    mat;
631321219cSEthan Coon   DMDABoundaryType       bx;
64e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
65e3fbd1f4SBarry Smith 
6647c6ae99SBarry Smith 
6747c6ae99SBarry Smith   PetscFunctionBegin;
681321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
691321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
701321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) {
7147c6ae99SBarry Smith     ratio = mx/Mx;
7247c6ae99SBarry 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);
7347c6ae99SBarry Smith   } else {
7447c6ae99SBarry Smith     ratio = (mx-1)/(Mx-1);
7547c6ae99SBarry 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);
7647c6ae99SBarry Smith   }
7747c6ae99SBarry Smith 
78aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
79aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
80e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
81e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
8247c6ae99SBarry Smith 
83aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
84aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
85e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
86e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
8747c6ae99SBarry Smith 
8847c6ae99SBarry Smith   /* create interpolation matrix */
89ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr);
9047c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr);
9147c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
920298fd71SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr);
930298fd71SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,2,NULL,1,NULL);CHKERRQ(ierr);
9447c6ae99SBarry Smith 
9547c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
9685afcc9aSBarry Smith   if (!NEWVERSION) {
97b3bd94feSDave May 
9847c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
9947c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
100e3fbd1f4SBarry Smith       row = idx_f[i-i_start_ghost];
10147c6ae99SBarry Smith 
10247c6ae99SBarry Smith       i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
103aa219208SBarry 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\
10447c6ae99SBarry Smith                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
10547c6ae99SBarry Smith 
10647c6ae99SBarry Smith       /*
10747c6ae99SBarry Smith        Only include those interpolation points that are truly
10847c6ae99SBarry Smith        nonzero. Note this is very important for final grid lines
10947c6ae99SBarry Smith        in x direction; since they have no right neighbor
11047c6ae99SBarry Smith        */
111*6712e2f1SBarry Smith       x  = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio);
11247c6ae99SBarry Smith       nc = 0;
11347c6ae99SBarry Smith       /* one left and below; or we are right on it */
114e3fbd1f4SBarry Smith       col      = (i_c-i_start_ghost_c);
115e3fbd1f4SBarry Smith       cols[nc] = idx_c[col];
11647c6ae99SBarry Smith       v[nc++]  = -x + 1.0;
11747c6ae99SBarry Smith       /* one right? */
11847c6ae99SBarry Smith       if (i_c*ratio != i) {
119e3fbd1f4SBarry Smith         cols[nc] = idx_c[col+1];
12047c6ae99SBarry Smith         v[nc++]  = x;
12147c6ae99SBarry Smith       }
12247c6ae99SBarry Smith       ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
12347c6ae99SBarry Smith     }
124b3bd94feSDave May 
125b3bd94feSDave May   } else {
126b3bd94feSDave May     PetscScalar *xi;
127b3bd94feSDave May     PetscInt    li,nxi,n;
128b3bd94feSDave May     PetscScalar Ni[2];
129b3bd94feSDave May 
130b3bd94feSDave May     /* compute local coordinate arrays */
131b3bd94feSDave May     nxi  = ratio + 1;
132b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
133b3bd94feSDave May     for (li=0; li<nxi; li++) {
13452218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
135b3bd94feSDave May     }
136b3bd94feSDave May 
137b3bd94feSDave May     for (i=i_start; i<i_start+m_f; i++) {
138b3bd94feSDave May       /* convert to local "natural" numbering and then to PETSc global numbering */
139e3fbd1f4SBarry Smith       row = idx_f[(i-i_start_ghost)];
140b3bd94feSDave May 
141b3bd94feSDave May       i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
142b3bd94feSDave 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\
143b3bd94feSDave May                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
144b3bd94feSDave May 
145b3bd94feSDave May       /* remainders */
146b3bd94feSDave May       li = i - ratio * (i/ratio);
1478865f1eaSKarl Rupp       if (i==mx-1) li = nxi-1;
148b3bd94feSDave May 
149b3bd94feSDave May       /* corners */
150e3fbd1f4SBarry Smith       col     = (i_c-i_start_ghost_c);
151e3fbd1f4SBarry Smith       cols[0] = idx_c[col];
152b3bd94feSDave May       Ni[0]   = 1.0;
153b3bd94feSDave May       if ((li==0) || (li==nxi-1)) {
154b3bd94feSDave May         ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
155b3bd94feSDave May         continue;
156b3bd94feSDave May       }
157b3bd94feSDave May 
158b3bd94feSDave May       /* edges + interior */
159b3bd94feSDave May       /* remainders */
1608865f1eaSKarl Rupp       if (i==mx-1) i_c--;
161b3bd94feSDave May 
162e3fbd1f4SBarry Smith       col     = (i_c-i_start_ghost_c);
163e3fbd1f4SBarry Smith       cols[0] = idx_c[col]; /* one left and below; or we are right on it */
164e3fbd1f4SBarry Smith       cols[1] = idx_c[col+1];
165b3bd94feSDave May 
166b3bd94feSDave May       Ni[0] = 0.5*(1.0-xi[li]);
167b3bd94feSDave May       Ni[1] = 0.5*(1.0+xi[li]);
168b3bd94feSDave May       for (n=0; n<2; n++) {
1698865f1eaSKarl Rupp         if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1;
170b3bd94feSDave May       }
171b3bd94feSDave May       ierr = MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
172b3bd94feSDave May     }
173b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
174b3bd94feSDave May   }
175e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
176e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
17747c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17847c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17947c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
180fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
18147c6ae99SBarry Smith   PetscFunctionReturn(0);
18247c6ae99SBarry Smith }
18347c6ae99SBarry Smith 
18447c6ae99SBarry Smith #undef __FUNCT__
185e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_1D_Q0"
186e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A)
18747c6ae99SBarry Smith {
18847c6ae99SBarry Smith   PetscErrorCode         ierr;
1898ea3bf28SBarry Smith   PetscInt               i,i_start,m_f,Mx;
1908ea3bf28SBarry Smith   const PetscInt         *idx_f,*idx_c;
191e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
1928ea3bf28SBarry Smith   PetscInt               m_ghost,m_ghost_c;
19347c6ae99SBarry Smith   PetscInt               row,col,i_start_ghost,mx,m_c,nc,ratio;
19447c6ae99SBarry Smith   PetscInt               i_c,i_start_c,i_start_ghost_c,cols[2],dof;
19547c6ae99SBarry Smith   PetscScalar            v[2],x;
19647c6ae99SBarry Smith   Mat                    mat;
1971321219cSEthan Coon   DMDABoundaryType       bx;
19847c6ae99SBarry Smith 
19947c6ae99SBarry Smith   PetscFunctionBegin;
2001321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
2011321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
2021321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) {
20347c6ae99SBarry Smith     ratio = mx/Mx;
20447c6ae99SBarry 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);
20547c6ae99SBarry Smith   } else {
20647c6ae99SBarry Smith     ratio = (mx-1)/(Mx-1);
20747c6ae99SBarry 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);
20847c6ae99SBarry Smith   }
20947c6ae99SBarry Smith 
210aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
211aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
212e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
213e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
21447c6ae99SBarry Smith 
215aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
216aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
217e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
218e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
21947c6ae99SBarry Smith 
22047c6ae99SBarry Smith   /* create interpolation matrix */
221ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr);
22247c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr);
22347c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
2240298fd71SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr);
2250298fd71SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,2,NULL,0,NULL);CHKERRQ(ierr);
22647c6ae99SBarry Smith 
22747c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
22847c6ae99SBarry Smith   for (i=i_start; i<i_start+m_f; i++) {
22947c6ae99SBarry Smith     /* convert to local "natural" numbering and then to PETSc global numbering */
230e3fbd1f4SBarry Smith     row = idx_f[(i-i_start_ghost)];
23147c6ae99SBarry Smith 
23247c6ae99SBarry Smith     i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
23347c6ae99SBarry Smith 
23447c6ae99SBarry Smith     /*
23547c6ae99SBarry Smith          Only include those interpolation points that are truly
23647c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
23747c6ae99SBarry Smith          in x direction; since they have no right neighbor
23847c6ae99SBarry Smith     */
239*6712e2f1SBarry Smith     x  = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio);
24047c6ae99SBarry Smith     nc = 0;
24147c6ae99SBarry Smith     /* one left and below; or we are right on it */
242e3fbd1f4SBarry Smith     col      = (i_c-i_start_ghost_c);
243e3fbd1f4SBarry Smith     cols[nc] = idx_c[col];
24447c6ae99SBarry Smith     v[nc++]  = -x + 1.0;
24547c6ae99SBarry Smith     /* one right? */
24647c6ae99SBarry Smith     if (i_c*ratio != i) {
247e3fbd1f4SBarry Smith       cols[nc] = idx_c[col+1];
24847c6ae99SBarry Smith       v[nc++]  = x;
24947c6ae99SBarry Smith     }
25047c6ae99SBarry Smith     ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
25147c6ae99SBarry Smith   }
252e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
253e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
25447c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25547c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25647c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
257fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
25847c6ae99SBarry Smith   ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr);
25947c6ae99SBarry Smith   PetscFunctionReturn(0);
26047c6ae99SBarry Smith }
26147c6ae99SBarry Smith 
26247c6ae99SBarry Smith #undef __FUNCT__
263e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_2D_Q1"
264e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A)
26547c6ae99SBarry Smith {
26647c6ae99SBarry Smith   PetscErrorCode         ierr;
2678ea3bf28SBarry Smith   PetscInt               i,j,i_start,j_start,m_f,n_f,Mx,My,dof;
2688ea3bf28SBarry Smith   const PetscInt         *idx_c,*idx_f;
269e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
2708ea3bf28SBarry Smith   PetscInt               m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz;
27147c6ae99SBarry Smith   PetscInt               row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj;
27247c6ae99SBarry 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;
27347c6ae99SBarry Smith   PetscMPIInt            size_c,size_f,rank_f;
27447c6ae99SBarry Smith   PetscScalar            v[4],x,y;
27547c6ae99SBarry Smith   Mat                    mat;
2761321219cSEthan Coon   DMDABoundaryType       bx,by;
27747c6ae99SBarry Smith 
27847c6ae99SBarry Smith   PetscFunctionBegin;
2791321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
2801321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
2811321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) {
28247c6ae99SBarry Smith     ratioi = mx/Mx;
28347c6ae99SBarry 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);
28447c6ae99SBarry Smith   } else {
28547c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
28647c6ae99SBarry 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);
28747c6ae99SBarry Smith   }
2881321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) {
28947c6ae99SBarry Smith     ratioj = my/My;
29047c6ae99SBarry 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);
29147c6ae99SBarry Smith   } else {
29247c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
29347c6ae99SBarry 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);
29447c6ae99SBarry Smith   }
29547c6ae99SBarry Smith 
29647c6ae99SBarry Smith 
297aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
298aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
299e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
300e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
30147c6ae99SBarry Smith 
302aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
303aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
304e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
305e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
30647c6ae99SBarry Smith 
30747c6ae99SBarry Smith   /*
308aa219208SBarry Smith    Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
30947c6ae99SBarry Smith    The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
31047c6ae99SBarry Smith    processors). It's effective length is hence 4 times its normal length, this is
31147c6ae99SBarry Smith    why the col_scale is multiplied by the interpolation matrix column sizes.
31247c6ae99SBarry Smith    sol_shift allows each set of 1/4 processors do its own interpolation using ITS
31347c6ae99SBarry Smith    copy of the coarse vector. A bit of a hack but you do better.
31447c6ae99SBarry Smith 
31547c6ae99SBarry Smith    In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
31647c6ae99SBarry Smith    */
317ce94432eSBarry Smith   ierr      = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr);
318ce94432eSBarry Smith   ierr      = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr);
319ce94432eSBarry Smith   ierr      = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr);
32047c6ae99SBarry Smith   col_scale = size_f/size_c;
32147c6ae99SBarry Smith   col_shift = Mx*My*(rank_f/size_c);
32247c6ae99SBarry Smith 
323ce94432eSBarry Smith   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr);
32447c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
32547c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
32647c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
327e3fbd1f4SBarry Smith       row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
32847c6ae99SBarry Smith 
32947c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
33047c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
33147c6ae99SBarry Smith 
332aa219208SBarry 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\
33347c6ae99SBarry Smith                                           j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
334aa219208SBarry 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\
33547c6ae99SBarry Smith                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
33647c6ae99SBarry Smith 
33747c6ae99SBarry Smith       /*
33847c6ae99SBarry Smith        Only include those interpolation points that are truly
33947c6ae99SBarry Smith        nonzero. Note this is very important for final grid lines
34047c6ae99SBarry Smith        in x and y directions; since they have no right/top neighbors
34147c6ae99SBarry Smith        */
34247c6ae99SBarry Smith       nc = 0;
34347c6ae99SBarry Smith       /* one left and below; or we are right on it */
344e3fbd1f4SBarry Smith       col        = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
345e3fbd1f4SBarry Smith       cols[nc++] = col_shift + idx_c[col];
34647c6ae99SBarry Smith       /* one right and below */
347e3fbd1f4SBarry Smith       if (i_c*ratioi != i) cols[nc++] = col_shift + idx_c[col+1];
34847c6ae99SBarry Smith       /* one left and above */
349e3fbd1f4SBarry Smith       if (j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+m_ghost_c];
35047c6ae99SBarry Smith       /* one right and above */
351e3fbd1f4SBarry Smith       if (i_c*ratioi != i && j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)];
35247c6ae99SBarry Smith       ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
35347c6ae99SBarry Smith     }
35447c6ae99SBarry Smith   }
355ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr);
35647c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr);
35747c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
35847c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
35947c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
36047c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
36147c6ae99SBarry Smith 
36247c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
36385afcc9aSBarry Smith   if (!NEWVERSION) {
364b3bd94feSDave May 
36547c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
36647c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
36747c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
368e3fbd1f4SBarry Smith         row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
36947c6ae99SBarry Smith 
37047c6ae99SBarry Smith         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
37147c6ae99SBarry Smith         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
37247c6ae99SBarry Smith 
37347c6ae99SBarry Smith         /*
37447c6ae99SBarry Smith          Only include those interpolation points that are truly
37547c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
37647c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
37747c6ae99SBarry Smith          */
378*6712e2f1SBarry Smith         x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi);
379*6712e2f1SBarry Smith         y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj);
380b3bd94feSDave May 
38147c6ae99SBarry Smith         nc = 0;
38247c6ae99SBarry Smith         /* one left and below; or we are right on it */
383e3fbd1f4SBarry Smith         col      = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
384e3fbd1f4SBarry Smith         cols[nc] = col_shift + idx_c[col];
38547c6ae99SBarry Smith         v[nc++]  = x*y - x - y + 1.0;
38647c6ae99SBarry Smith         /* one right and below */
38747c6ae99SBarry Smith         if (i_c*ratioi != i) {
388e3fbd1f4SBarry Smith           cols[nc] = col_shift + idx_c[col+1];
38947c6ae99SBarry Smith           v[nc++]  = -x*y + x;
39047c6ae99SBarry Smith         }
39147c6ae99SBarry Smith         /* one left and above */
39247c6ae99SBarry Smith         if (j_c*ratioj != j) {
393e3fbd1f4SBarry Smith           cols[nc] = col_shift + idx_c[col+m_ghost_c];
39447c6ae99SBarry Smith           v[nc++]  = -x*y + y;
39547c6ae99SBarry Smith         }
39647c6ae99SBarry Smith         /* one right and above */
39747c6ae99SBarry Smith         if (j_c*ratioj != j && i_c*ratioi != i) {
398e3fbd1f4SBarry Smith           cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)];
39947c6ae99SBarry Smith           v[nc++]  = x*y;
40047c6ae99SBarry Smith         }
40147c6ae99SBarry Smith         ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
40247c6ae99SBarry Smith       }
40347c6ae99SBarry Smith     }
404b3bd94feSDave May 
405b3bd94feSDave May   } else {
406b3bd94feSDave May     PetscScalar Ni[4];
407b3bd94feSDave May     PetscScalar *xi,*eta;
408b3bd94feSDave May     PetscInt    li,nxi,lj,neta;
409b3bd94feSDave May 
410b3bd94feSDave May     /* compute local coordinate arrays */
411b3bd94feSDave May     nxi  = ratioi + 1;
412b3bd94feSDave May     neta = ratioj + 1;
413b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
414b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr);
415b3bd94feSDave May     for (li=0; li<nxi; li++) {
41652218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
417b3bd94feSDave May     }
418b3bd94feSDave May     for (lj=0; lj<neta; lj++) {
41952218ef2SJed Brown       eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1));
420b3bd94feSDave May     }
421b3bd94feSDave May 
422b3bd94feSDave May     /* loop over local fine grid nodes setting interpolation for those*/
423b3bd94feSDave May     for (j=j_start; j<j_start+n_f; j++) {
424b3bd94feSDave May       for (i=i_start; i<i_start+m_f; i++) {
425b3bd94feSDave May         /* convert to local "natural" numbering and then to PETSc global numbering */
426e3fbd1f4SBarry Smith         row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
427b3bd94feSDave May 
428b3bd94feSDave May         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
429b3bd94feSDave May         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
430b3bd94feSDave May 
431b3bd94feSDave May         /* remainders */
432b3bd94feSDave May         li = i - ratioi * (i/ratioi);
4338865f1eaSKarl Rupp         if (i==mx-1) li = nxi-1;
434b3bd94feSDave May         lj = j - ratioj * (j/ratioj);
4358865f1eaSKarl Rupp         if (j==my-1) lj = neta-1;
436b3bd94feSDave May 
437b3bd94feSDave May         /* corners */
438e3fbd1f4SBarry Smith         col     = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
439e3fbd1f4SBarry Smith         cols[0] = col_shift + idx_c[col]; /* left, below */
440b3bd94feSDave May         Ni[0]   = 1.0;
441b3bd94feSDave May         if ((li==0) || (li==nxi-1)) {
442b3bd94feSDave May           if ((lj==0) || (lj==neta-1)) {
443b3bd94feSDave May             ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
444b3bd94feSDave May             continue;
445b3bd94feSDave May           }
446b3bd94feSDave May         }
447b3bd94feSDave May 
448b3bd94feSDave May         /* edges + interior */
449b3bd94feSDave May         /* remainders */
4508865f1eaSKarl Rupp         if (i==mx-1) i_c--;
4518865f1eaSKarl Rupp         if (j==my-1) j_c--;
452b3bd94feSDave May 
453e3fbd1f4SBarry Smith         col     = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
454e3fbd1f4SBarry Smith         cols[0] = col_shift + idx_c[col]; /* left, below */
455e3fbd1f4SBarry Smith         cols[1] = col_shift + idx_c[col+1]; /* right, below */
456e3fbd1f4SBarry Smith         cols[2] = col_shift + idx_c[col+m_ghost_c]; /* left, above */
457e3fbd1f4SBarry Smith         cols[3] = col_shift + idx_c[col+(m_ghost_c+1)]; /* right, above */
458b3bd94feSDave May 
459b3bd94feSDave May         Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]);
460b3bd94feSDave May         Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]);
461b3bd94feSDave May         Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]);
462b3bd94feSDave May         Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]);
463b3bd94feSDave May 
464b3bd94feSDave May         nc = 0;
4658865f1eaSKarl Rupp         if (PetscAbsScalar(Ni[0])<1.0e-32) cols[0]=-1;
4668865f1eaSKarl Rupp         if (PetscAbsScalar(Ni[1])<1.0e-32) cols[1]=-1;
4678865f1eaSKarl Rupp         if (PetscAbsScalar(Ni[2])<1.0e-32) cols[2]=-1;
4688865f1eaSKarl Rupp         if (PetscAbsScalar(Ni[3])<1.0e-32) cols[3]=-1;
469b3bd94feSDave May 
470b3bd94feSDave May         ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
471b3bd94feSDave May       }
472b3bd94feSDave May     }
473b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
474b3bd94feSDave May     ierr = PetscFree(eta);CHKERRQ(ierr);
475b3bd94feSDave May   }
476e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
477e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
47847c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47947c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
48047c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
481fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
48247c6ae99SBarry Smith   PetscFunctionReturn(0);
48347c6ae99SBarry Smith }
48447c6ae99SBarry Smith 
48547c6ae99SBarry Smith /*
48647c6ae99SBarry Smith        Contributed by Andrei Draganescu <aidraga@sandia.gov>
48747c6ae99SBarry Smith */
48847c6ae99SBarry Smith #undef __FUNCT__
489e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_2D_Q0"
490e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A)
49147c6ae99SBarry Smith {
49247c6ae99SBarry Smith   PetscErrorCode         ierr;
4938ea3bf28SBarry Smith   PetscInt               i,j,i_start,j_start,m_f,n_f,Mx,My,dof;
4948ea3bf28SBarry Smith   const PetscInt         *idx_c,*idx_f;
495e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
4968ea3bf28SBarry Smith   PetscInt               m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz;
49747c6ae99SBarry Smith   PetscInt               row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj;
49847c6ae99SBarry 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;
49947c6ae99SBarry Smith   PetscMPIInt            size_c,size_f,rank_f;
50047c6ae99SBarry Smith   PetscScalar            v[4];
50147c6ae99SBarry Smith   Mat                    mat;
5021321219cSEthan Coon   DMDABoundaryType       bx,by;
50347c6ae99SBarry Smith 
50447c6ae99SBarry Smith   PetscFunctionBegin;
5051321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
5061321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
507ce94432eSBarry Smith   if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x");
508ce94432eSBarry Smith   if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y");
50947c6ae99SBarry Smith   ratioi = mx/Mx;
51047c6ae99SBarry Smith   ratioj = my/My;
511ce94432eSBarry Smith   if (ratioi*Mx != mx) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x");
512ce94432eSBarry Smith   if (ratioj*My != my) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y");
513ce94432eSBarry Smith   if (ratioi != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2");
514ce94432eSBarry Smith   if (ratioj != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2");
51547c6ae99SBarry Smith 
516aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
517aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
518e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
519e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
52047c6ae99SBarry Smith 
521aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
522aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
523e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
524e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
52547c6ae99SBarry Smith 
52647c6ae99SBarry Smith   /*
527aa219208SBarry Smith      Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
52847c6ae99SBarry Smith      The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
52947c6ae99SBarry Smith      processors). It's effective length is hence 4 times its normal length, this is
53047c6ae99SBarry Smith      why the col_scale is multiplied by the interpolation matrix column sizes.
53147c6ae99SBarry Smith      sol_shift allows each set of 1/4 processors do its own interpolation using ITS
53247c6ae99SBarry Smith      copy of the coarse vector. A bit of a hack but you do better.
53347c6ae99SBarry Smith 
53447c6ae99SBarry Smith      In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
53547c6ae99SBarry Smith   */
536ce94432eSBarry Smith   ierr      = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr);
537ce94432eSBarry Smith   ierr      = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr);
538ce94432eSBarry Smith   ierr      = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr);
53947c6ae99SBarry Smith   col_scale = size_f/size_c;
54047c6ae99SBarry Smith   col_shift = Mx*My*(rank_f/size_c);
54147c6ae99SBarry Smith 
542ce94432eSBarry Smith   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr);
54347c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
54447c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
54547c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
546e3fbd1f4SBarry Smith       row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
54747c6ae99SBarry Smith 
54847c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
54947c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
55047c6ae99SBarry Smith 
551aa219208SBarry 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\
55247c6ae99SBarry Smith     j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
553aa219208SBarry 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\
55447c6ae99SBarry Smith     i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
55547c6ae99SBarry Smith 
55647c6ae99SBarry Smith       /*
55747c6ae99SBarry Smith          Only include those interpolation points that are truly
55847c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
55947c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
56047c6ae99SBarry Smith       */
56147c6ae99SBarry Smith       nc = 0;
56247c6ae99SBarry Smith       /* one left and below; or we are right on it */
563e3fbd1f4SBarry Smith       col        = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
564e3fbd1f4SBarry Smith       cols[nc++] = col_shift + idx_c[col];
56547c6ae99SBarry Smith       ierr       = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
56647c6ae99SBarry Smith     }
56747c6ae99SBarry Smith   }
568ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr);
56947c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr);
57047c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
57147c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
57247c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
57347c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
57447c6ae99SBarry Smith 
57547c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
57647c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
57747c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
57847c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
579e3fbd1f4SBarry Smith       row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
58047c6ae99SBarry Smith 
58147c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
58247c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
58347c6ae99SBarry Smith       nc  = 0;
58447c6ae99SBarry Smith       /* one left and below; or we are right on it */
585e3fbd1f4SBarry Smith       col      = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
586e3fbd1f4SBarry Smith       cols[nc] = col_shift + idx_c[col];
58747c6ae99SBarry Smith       v[nc++]  = 1.0;
58847c6ae99SBarry Smith 
58947c6ae99SBarry Smith       ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
59047c6ae99SBarry Smith     }
59147c6ae99SBarry Smith   }
592e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
593e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
59447c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
59547c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
59647c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
597fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
59847c6ae99SBarry Smith   ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr);
59947c6ae99SBarry Smith   PetscFunctionReturn(0);
60047c6ae99SBarry Smith }
60147c6ae99SBarry Smith 
60247c6ae99SBarry Smith /*
60347c6ae99SBarry Smith        Contributed by Jianming Yang <jianming-yang@uiowa.edu>
60447c6ae99SBarry Smith */
60547c6ae99SBarry Smith #undef __FUNCT__
606e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_3D_Q0"
607e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A)
60847c6ae99SBarry Smith {
60947c6ae99SBarry Smith   PetscErrorCode         ierr;
6108ea3bf28SBarry Smith   PetscInt               i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,dof;
6118ea3bf28SBarry Smith   const PetscInt         *idx_c,*idx_f;
612e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
6138ea3bf28SBarry Smith   PetscInt               m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz;
61447c6ae99SBarry 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;
61547c6ae99SBarry 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;
61647c6ae99SBarry Smith   PetscMPIInt            size_c,size_f,rank_f;
61747c6ae99SBarry Smith   PetscScalar            v[8];
61847c6ae99SBarry Smith   Mat                    mat;
6191321219cSEthan Coon   DMDABoundaryType       bx,by,bz;
62047c6ae99SBarry Smith 
62147c6ae99SBarry Smith   PetscFunctionBegin;
6221321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
6231321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
624ce94432eSBarry Smith   if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x");
625ce94432eSBarry Smith   if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y");
626ce94432eSBarry Smith   if (bz == DMDA_BOUNDARY_PERIODIC) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in z");
62747c6ae99SBarry Smith   ratioi = mx/Mx;
62847c6ae99SBarry Smith   ratioj = my/My;
62947c6ae99SBarry Smith   ratiol = mz/Mz;
630ce94432eSBarry Smith   if (ratioi*Mx != mx) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x");
631ce94432eSBarry Smith   if (ratioj*My != my) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y");
632ce94432eSBarry Smith   if (ratiol*Mz != mz) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z");
633ce94432eSBarry Smith   if (ratioi != 2 && ratioi != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2");
634ce94432eSBarry Smith   if (ratioj != 2 && ratioj != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2");
635ce94432eSBarry Smith   if (ratiol != 2 && ratiol != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2");
63647c6ae99SBarry Smith 
637aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
638aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
639e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
640e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
64147c6ae99SBarry Smith 
642aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
643aa219208SBarry 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);
644e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
645e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
646e3fbd1f4SBarry Smith 
64747c6ae99SBarry Smith   /*
648aa219208SBarry Smith      Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
64947c6ae99SBarry Smith      The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
65047c6ae99SBarry Smith      processors). It's effective length is hence 4 times its normal length, this is
65147c6ae99SBarry Smith      why the col_scale is multiplied by the interpolation matrix column sizes.
65247c6ae99SBarry Smith      sol_shift allows each set of 1/4 processors do its own interpolation using ITS
65347c6ae99SBarry Smith      copy of the coarse vector. A bit of a hack but you do better.
65447c6ae99SBarry Smith 
65547c6ae99SBarry Smith      In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
65647c6ae99SBarry Smith   */
657ce94432eSBarry Smith   ierr      = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr);
658ce94432eSBarry Smith   ierr      = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr);
659ce94432eSBarry Smith   ierr      = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr);
66047c6ae99SBarry Smith   col_scale = size_f/size_c;
66147c6ae99SBarry Smith   col_shift = Mx*My*Mz*(rank_f/size_c);
66247c6ae99SBarry Smith 
663ce94432eSBarry Smith   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr);
66447c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
66547c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
66647c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
66747c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
668e3fbd1f4SBarry Smith         row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
66947c6ae99SBarry Smith 
67047c6ae99SBarry Smith         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
67147c6ae99SBarry Smith         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
67247c6ae99SBarry Smith         l_c = (l/ratiol);
67347c6ae99SBarry Smith 
674aa219208SBarry 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\
67547c6ae99SBarry Smith     l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c);
676aa219208SBarry 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\
67747c6ae99SBarry Smith     j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
678aa219208SBarry 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\
67947c6ae99SBarry Smith     i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
68047c6ae99SBarry Smith 
68147c6ae99SBarry Smith         /*
68247c6ae99SBarry Smith            Only include those interpolation points that are truly
68347c6ae99SBarry Smith            nonzero. Note this is very important for final grid lines
68447c6ae99SBarry Smith            in x and y directions; since they have no right/top neighbors
68547c6ae99SBarry Smith         */
68647c6ae99SBarry Smith         nc = 0;
68747c6ae99SBarry Smith         /* one left and below; or we are right on it */
688e3fbd1f4SBarry Smith         col        = (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));
689e3fbd1f4SBarry Smith         cols[nc++] = col_shift + idx_c[col];
69047c6ae99SBarry Smith         ierr       = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
69147c6ae99SBarry Smith       }
69247c6ae99SBarry Smith     }
69347c6ae99SBarry Smith   }
694ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr);
69547c6ae99SBarry 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);
69647c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
69747c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
69847c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
69947c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
70047c6ae99SBarry Smith 
70147c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
70247c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
70347c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
70447c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
70547c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
706e3fbd1f4SBarry Smith         row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
70747c6ae99SBarry Smith 
70847c6ae99SBarry Smith         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
70947c6ae99SBarry Smith         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
71047c6ae99SBarry Smith         l_c = (l/ratiol);
71147c6ae99SBarry Smith         nc  = 0;
71247c6ae99SBarry Smith         /* one left and below; or we are right on it */
713e3fbd1f4SBarry Smith         col      = (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));
714e3fbd1f4SBarry Smith         cols[nc] = col_shift + idx_c[col];
71547c6ae99SBarry Smith         v[nc++]  = 1.0;
71647c6ae99SBarry Smith 
71747c6ae99SBarry Smith         ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
71847c6ae99SBarry Smith       }
71947c6ae99SBarry Smith     }
72047c6ae99SBarry Smith   }
721e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
722e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
72347c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
72447c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
72547c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
726fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
72747c6ae99SBarry Smith   ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr);
72847c6ae99SBarry Smith   PetscFunctionReturn(0);
72947c6ae99SBarry Smith }
73047c6ae99SBarry Smith 
73147c6ae99SBarry Smith #undef __FUNCT__
732e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_3D_Q1"
733e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A)
73447c6ae99SBarry Smith {
73547c6ae99SBarry Smith   PetscErrorCode         ierr;
7368ea3bf28SBarry Smith   PetscInt               i,j,i_start,j_start,m_f,n_f,Mx,My,dof,l;
7378ea3bf28SBarry Smith   const PetscInt         *idx_c,*idx_f;
738e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
7398ea3bf28SBarry Smith   PetscInt               m_ghost,n_ghost,m_ghost_c,n_ghost_c,Mz,mz;
74047c6ae99SBarry Smith   PetscInt               row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok;
74147c6ae99SBarry Smith   PetscInt               i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c;
74247c6ae99SBarry Smith   PetscInt               l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c;
74347c6ae99SBarry Smith   PetscInt               l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz;
74447c6ae99SBarry Smith   PetscScalar            v[8],x,y,z;
74547c6ae99SBarry Smith   Mat                    mat;
7461321219cSEthan Coon   DMDABoundaryType       bx,by,bz;
74747c6ae99SBarry Smith 
74847c6ae99SBarry Smith   PetscFunctionBegin;
7491321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
7501321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
75147c6ae99SBarry Smith   if (mx == Mx) {
75247c6ae99SBarry Smith     ratioi = 1;
7531321219cSEthan Coon   } else if (bx == DMDA_BOUNDARY_PERIODIC) {
75447c6ae99SBarry Smith     ratioi = mx/Mx;
75547c6ae99SBarry 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);
75647c6ae99SBarry Smith   } else {
75747c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
75847c6ae99SBarry 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);
75947c6ae99SBarry Smith   }
76047c6ae99SBarry Smith   if (my == My) {
76147c6ae99SBarry Smith     ratioj = 1;
7621321219cSEthan Coon   } else if (by == DMDA_BOUNDARY_PERIODIC) {
76347c6ae99SBarry Smith     ratioj = my/My;
76447c6ae99SBarry 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);
76547c6ae99SBarry Smith   } else {
76647c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
76747c6ae99SBarry 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);
76847c6ae99SBarry Smith   }
76947c6ae99SBarry Smith   if (mz == Mz) {
77047c6ae99SBarry Smith     ratiok = 1;
7711321219cSEthan Coon   } else if (bz == DMDA_BOUNDARY_PERIODIC) {
77247c6ae99SBarry Smith     ratiok = mz/Mz;
77347c6ae99SBarry 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);
77447c6ae99SBarry Smith   } else {
77547c6ae99SBarry Smith     ratiok = (mz-1)/(Mz-1);
77647c6ae99SBarry 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);
77747c6ae99SBarry Smith   }
77847c6ae99SBarry Smith 
779aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
780aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
781e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
782e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
78347c6ae99SBarry Smith 
784aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
785aa219208SBarry 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);
786e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
787e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
78847c6ae99SBarry Smith 
78947c6ae99SBarry Smith   /* create interpolation matrix, determining exact preallocation */
790ce94432eSBarry Smith   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)dac),m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr);
79147c6ae99SBarry Smith   /* loop over local fine grid nodes counting interpolating points */
79247c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
79347c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
79447c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
79547c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
796e3fbd1f4SBarry Smith         row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
79747c6ae99SBarry Smith         i_c = (i/ratioi);
79847c6ae99SBarry Smith         j_c = (j/ratioj);
79947c6ae99SBarry Smith         l_c = (l/ratiok);
800aa219208SBarry 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\
80147c6ae99SBarry Smith                                             l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c);
802aa219208SBarry 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\
80347c6ae99SBarry Smith                                             j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
804aa219208SBarry 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\
80547c6ae99SBarry Smith                                             i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
80647c6ae99SBarry Smith 
80747c6ae99SBarry Smith         /*
80847c6ae99SBarry Smith          Only include those interpolation points that are truly
80947c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
81047c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
81147c6ae99SBarry Smith          */
81247c6ae99SBarry Smith         nc         = 0;
813e3fbd1f4SBarry Smith         col        = (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));
814e3fbd1f4SBarry Smith         cols[nc++] = idx_c[col];
81547c6ae99SBarry Smith         if (i_c*ratioi != i) {
816e3fbd1f4SBarry Smith           cols[nc++] = idx_c[col+1];
81747c6ae99SBarry Smith         }
81847c6ae99SBarry Smith         if (j_c*ratioj != j) {
819e3fbd1f4SBarry Smith           cols[nc++] = idx_c[col+m_ghost_c];
82047c6ae99SBarry Smith         }
82147c6ae99SBarry Smith         if (l_c*ratiok != l) {
822e3fbd1f4SBarry Smith           cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c];
82347c6ae99SBarry Smith         }
82447c6ae99SBarry Smith         if (j_c*ratioj != j && i_c*ratioi != i) {
825e3fbd1f4SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c+1)];
82647c6ae99SBarry Smith         }
82747c6ae99SBarry Smith         if (j_c*ratioj != j && l_c*ratiok != l) {
828e3fbd1f4SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)];
82947c6ae99SBarry Smith         }
83047c6ae99SBarry Smith         if (i_c*ratioi != i && l_c*ratiok != l) {
831e3fbd1f4SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)];
83247c6ae99SBarry Smith         }
83347c6ae99SBarry Smith         if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) {
834e3fbd1f4SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)];
83547c6ae99SBarry Smith         }
83647c6ae99SBarry Smith         ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
83747c6ae99SBarry Smith       }
83847c6ae99SBarry Smith     }
83947c6ae99SBarry Smith   }
840ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr);
84147c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr);
84247c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
84347c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
84447c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
84547c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
84647c6ae99SBarry Smith 
84747c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
8482adb9dcfSBarry Smith   if (!NEWVERSION) {
849b3bd94feSDave May 
85047c6ae99SBarry Smith     for (l=l_start; l<l_start+p_f; l++) {
85147c6ae99SBarry Smith       for (j=j_start; j<j_start+n_f; j++) {
85247c6ae99SBarry Smith         for (i=i_start; i<i_start+m_f; i++) {
85347c6ae99SBarry Smith           /* convert to local "natural" numbering and then to PETSc global numbering */
854e3fbd1f4SBarry Smith           row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
85547c6ae99SBarry Smith 
85647c6ae99SBarry Smith           i_c = (i/ratioi);
85747c6ae99SBarry Smith           j_c = (j/ratioj);
85847c6ae99SBarry Smith           l_c = (l/ratiok);
85947c6ae99SBarry Smith 
86047c6ae99SBarry Smith           /*
86147c6ae99SBarry Smith            Only include those interpolation points that are truly
86247c6ae99SBarry Smith            nonzero. Note this is very important for final grid lines
86347c6ae99SBarry Smith            in x and y directions; since they have no right/top neighbors
86447c6ae99SBarry Smith            */
865*6712e2f1SBarry Smith           x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi);
866*6712e2f1SBarry Smith           y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj);
867*6712e2f1SBarry Smith           z = ((PetscReal)(l - l_c*ratiok))/((PetscReal)ratiok);
868b3bd94feSDave May 
86947c6ae99SBarry Smith           nc = 0;
87047c6ae99SBarry Smith           /* one left and below; or we are right on it */
871e3fbd1f4SBarry Smith           col = (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));
87247c6ae99SBarry Smith 
873e3fbd1f4SBarry Smith           cols[nc] = idx_c[col];
87447c6ae99SBarry Smith           v[nc++]  = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.));
87547c6ae99SBarry Smith 
87647c6ae99SBarry Smith           if (i_c*ratioi != i) {
877e3fbd1f4SBarry Smith             cols[nc] = idx_c[col+1];
87847c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.));
87947c6ae99SBarry Smith           }
88047c6ae99SBarry Smith 
88147c6ae99SBarry Smith           if (j_c*ratioj != j) {
882e3fbd1f4SBarry Smith             cols[nc] = idx_c[col+m_ghost_c];
88347c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.));
88447c6ae99SBarry Smith           }
88547c6ae99SBarry Smith 
88647c6ae99SBarry Smith           if (l_c*ratiok != l) {
887e3fbd1f4SBarry Smith             cols[nc] = idx_c[col+m_ghost_c*n_ghost_c];
88847c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.));
88947c6ae99SBarry Smith           }
89047c6ae99SBarry Smith 
89147c6ae99SBarry Smith           if (j_c*ratioj != j && i_c*ratioi != i) {
892e3fbd1f4SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c+1)];
89347c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.));
89447c6ae99SBarry Smith           }
89547c6ae99SBarry Smith 
89647c6ae99SBarry Smith           if (j_c*ratioj != j && l_c*ratiok != l) {
897e3fbd1f4SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)];
89847c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.));
89947c6ae99SBarry Smith           }
90047c6ae99SBarry Smith 
90147c6ae99SBarry Smith           if (i_c*ratioi != i && l_c*ratiok != l) {
902e3fbd1f4SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)];
90347c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.));
90447c6ae99SBarry Smith           }
90547c6ae99SBarry Smith 
90647c6ae99SBarry Smith           if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) {
907e3fbd1f4SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)];
90847c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.));
90947c6ae99SBarry Smith           }
91047c6ae99SBarry Smith           ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
91147c6ae99SBarry Smith         }
91247c6ae99SBarry Smith       }
91347c6ae99SBarry Smith     }
914b3bd94feSDave May 
915b3bd94feSDave May   } else {
916b3bd94feSDave May     PetscScalar *xi,*eta,*zeta;
917b3bd94feSDave May     PetscInt    li,nxi,lj,neta,lk,nzeta,n;
918b3bd94feSDave May     PetscScalar Ni[8];
919b3bd94feSDave May 
920b3bd94feSDave May     /* compute local coordinate arrays */
921b3bd94feSDave May     nxi   = ratioi + 1;
922b3bd94feSDave May     neta  = ratioj + 1;
923b3bd94feSDave May     nzeta = ratiok + 1;
924b3bd94feSDave May     ierr  = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
925b3bd94feSDave May     ierr  = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr);
926b3bd94feSDave May     ierr  = PetscMalloc(sizeof(PetscScalar)*nzeta,&zeta);CHKERRQ(ierr);
9278865f1eaSKarl Rupp     for (li=0; li<nxi; li++) xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
9288865f1eaSKarl Rupp     for (lj=0; lj<neta; lj++) eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1));
9298865f1eaSKarl Rupp     for (lk=0; lk<nzeta; lk++) zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1));
930b3bd94feSDave May 
931b3bd94feSDave May     for (l=l_start; l<l_start+p_f; l++) {
932b3bd94feSDave May       for (j=j_start; j<j_start+n_f; j++) {
933b3bd94feSDave May         for (i=i_start; i<i_start+m_f; i++) {
934b3bd94feSDave May           /* convert to local "natural" numbering and then to PETSc global numbering */
935e3fbd1f4SBarry Smith           row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))];
936b3bd94feSDave May 
937b3bd94feSDave May           i_c = (i/ratioi);
938b3bd94feSDave May           j_c = (j/ratioj);
939b3bd94feSDave May           l_c = (l/ratiok);
940b3bd94feSDave May 
941b3bd94feSDave May           /* remainders */
942b3bd94feSDave May           li = i - ratioi * (i/ratioi);
9438865f1eaSKarl Rupp           if (i==mx-1) li = nxi-1;
944b3bd94feSDave May           lj = j - ratioj * (j/ratioj);
9458865f1eaSKarl Rupp           if (j==my-1) lj = neta-1;
946b3bd94feSDave May           lk = l - ratiok * (l/ratiok);
9478865f1eaSKarl Rupp           if (l==mz-1) lk = nzeta-1;
948b3bd94feSDave May 
949b3bd94feSDave May           /* corners */
950e3fbd1f4SBarry Smith           col     = (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));
951e3fbd1f4SBarry Smith           cols[0] = idx_c[col];
952b3bd94feSDave May           Ni[0]   = 1.0;
953b3bd94feSDave May           if ((li==0) || (li==nxi-1)) {
954b3bd94feSDave May             if ((lj==0) || (lj==neta-1)) {
955b3bd94feSDave May               if ((lk==0) || (lk==nzeta-1)) {
956b3bd94feSDave May                 ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
957b3bd94feSDave May                 continue;
958b3bd94feSDave May               }
959b3bd94feSDave May             }
960b3bd94feSDave May           }
961b3bd94feSDave May 
962b3bd94feSDave May           /* edges + interior */
963b3bd94feSDave May           /* remainders */
9648865f1eaSKarl Rupp           if (i==mx-1) i_c--;
9658865f1eaSKarl Rupp           if (j==my-1) j_c--;
9668865f1eaSKarl Rupp           if (l==mz-1) l_c--;
967b3bd94feSDave May 
968e3fbd1f4SBarry Smith           col     = (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));
969e3fbd1f4SBarry Smith           cols[0] = idx_c[col]; /* one left and below; or we are right on it */
970e3fbd1f4SBarry Smith           cols[1] = idx_c[col+1]; /* one right and below */
971e3fbd1f4SBarry Smith           cols[2] = idx_c[col+m_ghost_c];  /* one left and above */
972e3fbd1f4SBarry Smith           cols[3] = idx_c[col+(m_ghost_c+1)]; /* one right and above */
973b3bd94feSDave May 
974e3fbd1f4SBarry Smith           cols[4] = idx_c[col+m_ghost_c*n_ghost_c]; /* one left and below and front; or we are right on it */
975e3fbd1f4SBarry Smith           cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; /* one right and below, and front */
976e3fbd1f4SBarry Smith           cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; /* one left and above and front*/
977e3fbd1f4SBarry Smith           cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; /* one right and above and front */
978b3bd94feSDave May 
979b3bd94feSDave May           Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]);
980b3bd94feSDave May           Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]);
981b3bd94feSDave May           Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]);
982b3bd94feSDave May           Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]);
983b3bd94feSDave May 
984b3bd94feSDave May           Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]);
985b3bd94feSDave May           Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]);
986b3bd94feSDave May           Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]);
987b3bd94feSDave May           Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]);
988b3bd94feSDave May 
989b3bd94feSDave May           for (n=0; n<8; n++) {
9908865f1eaSKarl Rupp             if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1;
991b3bd94feSDave May           }
992b3bd94feSDave May           ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
993b3bd94feSDave May 
994b3bd94feSDave May         }
995b3bd94feSDave May       }
996b3bd94feSDave May     }
997b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
998b3bd94feSDave May     ierr = PetscFree(eta);CHKERRQ(ierr);
999b3bd94feSDave May     ierr = PetscFree(zeta);CHKERRQ(ierr);
1000b3bd94feSDave May   }
1001e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
1002e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
100347c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
100447c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
100547c6ae99SBarry Smith 
100647c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
1007fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
100847c6ae99SBarry Smith   PetscFunctionReturn(0);
100947c6ae99SBarry Smith }
101047c6ae99SBarry Smith 
101147c6ae99SBarry Smith #undef __FUNCT__
1012e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA"
1013e727c939SJed Brown PetscErrorCode  DMCreateInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale)
101447c6ae99SBarry Smith {
101547c6ae99SBarry Smith   PetscErrorCode   ierr;
101647c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
10171321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
1018aa219208SBarry Smith   DMDAStencilType  stc,stf;
101947c6ae99SBarry Smith   DM_DA            *ddc = (DM_DA*)dac->data;
102047c6ae99SBarry Smith 
102147c6ae99SBarry Smith   PetscFunctionBegin;
102247c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
102347c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
102447c6ae99SBarry Smith   PetscValidPointer(A,3);
102547c6ae99SBarry Smith   if (scale) PetscValidPointer(scale,4);
102647c6ae99SBarry Smith 
10271321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
10281321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1029ce94432eSBarry Smith   if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1030ce94432eSBarry Smith   if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1031ce94432eSBarry Smith   if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
1032ce94432eSBarry Smith   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1033ce94432eSBarry Smith   if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
103447c6ae99SBarry Smith   if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction");
103547c6ae99SBarry 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");
103647c6ae99SBarry 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");
103747c6ae99SBarry Smith 
1038aa219208SBarry Smith   if (ddc->interptype == DMDA_Q1) {
103947c6ae99SBarry Smith     if (dimc == 1) {
1040e727c939SJed Brown       ierr = DMCreateInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr);
104147c6ae99SBarry Smith     } else if (dimc == 2) {
1042e727c939SJed Brown       ierr = DMCreateInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr);
104347c6ae99SBarry Smith     } else if (dimc == 3) {
1044e727c939SJed Brown       ierr = DMCreateInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr);
1045ce94432eSBarry Smith     } else SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype);
1046aa219208SBarry Smith   } else if (ddc->interptype == DMDA_Q0) {
104747c6ae99SBarry Smith     if (dimc == 1) {
1048e727c939SJed Brown       ierr = DMCreateInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr);
104947c6ae99SBarry Smith     } else if (dimc == 2) {
1050e727c939SJed Brown       ierr = DMCreateInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr);
105147c6ae99SBarry Smith     } else if (dimc == 3) {
1052e727c939SJed Brown       ierr = DMCreateInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr);
1053ce94432eSBarry Smith     } else SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype);
105447c6ae99SBarry Smith   }
105547c6ae99SBarry Smith   if (scale) {
1056e727c939SJed Brown     ierr = DMCreateInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr);
105747c6ae99SBarry Smith   }
105847c6ae99SBarry Smith   PetscFunctionReturn(0);
105947c6ae99SBarry Smith }
106047c6ae99SBarry Smith 
106147c6ae99SBarry Smith #undef __FUNCT__
1062e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_1D"
1063e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_1D(DM dac,DM daf,VecScatter *inject)
10640bb2b966SJungho Lee {
10650bb2b966SJungho Lee   PetscErrorCode         ierr;
10668ea3bf28SBarry Smith   PetscInt               i,i_start,m_f,Mx,dof;
10678ea3bf28SBarry Smith   const PetscInt         *idx_f;
1068e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f;
10698ea3bf28SBarry Smith   PetscInt               m_ghost,m_ghost_c;
10700bb2b966SJungho Lee   PetscInt               row,i_start_ghost,mx,m_c,nc,ratioi;
10710bb2b966SJungho Lee   PetscInt               i_start_c,i_start_ghost_c;
10720bb2b966SJungho Lee   PetscInt               *cols;
10730bb2b966SJungho Lee   DMDABoundaryType       bx;
10740bb2b966SJungho Lee   Vec                    vecf,vecc;
10750bb2b966SJungho Lee   IS                     isf;
10760bb2b966SJungho Lee 
10770bb2b966SJungho Lee   PetscFunctionBegin;
10780bb2b966SJungho Lee   ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
10790bb2b966SJungho Lee   ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
10800bb2b966SJungho Lee   if (bx == DMDA_BOUNDARY_PERIODIC) {
10810bb2b966SJungho Lee     ratioi = mx/Mx;
10820bb2b966SJungho 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);
10830bb2b966SJungho Lee   } else {
10840bb2b966SJungho Lee     ratioi = (mx-1)/(Mx-1);
10850bb2b966SJungho 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);
10860bb2b966SJungho Lee   }
10870bb2b966SJungho Lee 
10880bb2b966SJungho Lee   ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
10890bb2b966SJungho Lee   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
1090e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
1091e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
10920bb2b966SJungho Lee 
10930bb2b966SJungho Lee   ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
10940bb2b966SJungho Lee   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
10950bb2b966SJungho Lee 
10960bb2b966SJungho Lee 
10970bb2b966SJungho Lee   /* loop over local fine grid nodes setting interpolation for those*/
10980bb2b966SJungho Lee   nc   = 0;
1099785e854fSJed Brown   ierr = PetscMalloc1(m_f,&cols);CHKERRQ(ierr);
11000bb2b966SJungho Lee 
11010bb2b966SJungho Lee 
11020bb2b966SJungho Lee   for (i=i_start_c; i<i_start_c+m_c; i++) {
11030bb2b966SJungho Lee     PetscInt i_f = i*ratioi;
11040bb2b966SJungho Lee 
11058865f1eaSKarl Rupp     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\ni_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
11068865f1eaSKarl Rupp 
1107e3fbd1f4SBarry Smith     row        = idx_f[(i_f-i_start_ghost)];
1108e3fbd1f4SBarry Smith     cols[nc++] = row;
11090bb2b966SJungho Lee   }
11100bb2b966SJungho Lee 
1111e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
1112ce94432eSBarry Smith   ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
11130bb2b966SJungho Lee   ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
11140bb2b966SJungho Lee   ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
11150298fd71SBarry Smith   ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr);
11160bb2b966SJungho Lee   ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
11170bb2b966SJungho Lee   ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
11180bb2b966SJungho Lee   ierr = ISDestroy(&isf);CHKERRQ(ierr);
11190bb2b966SJungho Lee   PetscFunctionReturn(0);
11200bb2b966SJungho Lee }
11210bb2b966SJungho Lee 
11220bb2b966SJungho Lee #undef __FUNCT__
1123e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_2D"
1124e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject)
112547c6ae99SBarry Smith {
112647c6ae99SBarry Smith   PetscErrorCode         ierr;
11278ea3bf28SBarry Smith   PetscInt               i,j,i_start,j_start,m_f,n_f,Mx,My,dof;
11288ea3bf28SBarry Smith   const PetscInt         *idx_c,*idx_f;
1129e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
11308ea3bf28SBarry Smith   PetscInt               m_ghost,n_ghost,m_ghost_c,n_ghost_c;
113147c6ae99SBarry Smith   PetscInt               row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj;
1132076202ddSJed Brown   PetscInt               i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c;
113347c6ae99SBarry Smith   PetscInt               *cols;
11341321219cSEthan Coon   DMDABoundaryType       bx,by;
113547c6ae99SBarry Smith   Vec                    vecf,vecc;
113647c6ae99SBarry Smith   IS                     isf;
113747c6ae99SBarry Smith 
113847c6ae99SBarry Smith   PetscFunctionBegin;
11391321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
11401321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
11411321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) {
114247c6ae99SBarry Smith     ratioi = mx/Mx;
114347c6ae99SBarry 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);
114447c6ae99SBarry Smith   } else {
114547c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
114647c6ae99SBarry 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);
114747c6ae99SBarry Smith   }
11481321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) {
114947c6ae99SBarry Smith     ratioj = my/My;
115047c6ae99SBarry 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);
115147c6ae99SBarry Smith   } else {
115247c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
115347c6ae99SBarry 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);
115447c6ae99SBarry Smith   }
115547c6ae99SBarry Smith 
1156aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
1157aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
1158e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
1159e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
116047c6ae99SBarry Smith 
1161aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
1162aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
1163e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
1164e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
116547c6ae99SBarry Smith 
116647c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
116747c6ae99SBarry Smith   nc   = 0;
1168785e854fSJed Brown   ierr = PetscMalloc1(n_f*m_f,&cols);CHKERRQ(ierr);
1169076202ddSJed Brown   for (j=j_start_c; j<j_start_c+n_c; j++) {
1170076202ddSJed Brown     for (i=i_start_c; i<i_start_c+m_c; i++) {
1171076202ddSJed Brown       PetscInt i_f = i*ratioi,j_f = j*ratioj;
1172076202ddSJed 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\
1173076202ddSJed Brown     j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost);
1174076202ddSJed 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\
1175076202ddSJed Brown     i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
1176e3fbd1f4SBarry Smith       row        = idx_f[(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))];
1177e3fbd1f4SBarry Smith       cols[nc++] = row;
117847c6ae99SBarry Smith     }
117947c6ae99SBarry Smith   }
1180e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
1181e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
118247c6ae99SBarry Smith 
1183ce94432eSBarry Smith   ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
11849a42bb27SBarry Smith   ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
11859a42bb27SBarry Smith   ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
11860298fd71SBarry Smith   ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr);
11879a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
11889a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
1189fcfd50ebSBarry Smith   ierr = ISDestroy(&isf);CHKERRQ(ierr);
119047c6ae99SBarry Smith   PetscFunctionReturn(0);
119147c6ae99SBarry Smith }
119247c6ae99SBarry Smith 
119347c6ae99SBarry Smith #undef __FUNCT__
1194e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_3D"
1195e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject)
1196b1757049SJed Brown {
1197b1757049SJed Brown   PetscErrorCode         ierr;
1198b1757049SJed Brown   PetscInt               i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz;
1199b1757049SJed Brown   PetscInt               m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c;
1200b1757049SJed Brown   PetscInt               i_start_ghost,j_start_ghost,k_start_ghost;
1201b1757049SJed Brown   PetscInt               mx,my,mz,ratioi,ratioj,ratiok;
1202b1757049SJed Brown   PetscInt               i_start_c,j_start_c,k_start_c;
1203b1757049SJed Brown   PetscInt               m_c,n_c,p_c;
1204b1757049SJed Brown   PetscInt               i_start_ghost_c,j_start_ghost_c,k_start_ghost_c;
1205b1757049SJed Brown   PetscInt               row,nc,dof;
12068ea3bf28SBarry Smith   const PetscInt         *idx_c,*idx_f;
1207e3fbd1f4SBarry Smith   ISLocalToGlobalMapping ltog_f,ltog_c;
1208b1757049SJed Brown   PetscInt               *cols;
12091321219cSEthan Coon   DMDABoundaryType       bx,by,bz;
1210b1757049SJed Brown   Vec                    vecf,vecc;
1211b1757049SJed Brown   IS                     isf;
1212b1757049SJed Brown 
1213b1757049SJed Brown   PetscFunctionBegin;
12141321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
12151321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
1216b1757049SJed Brown 
12171321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) {
1218b1757049SJed Brown     ratioi = mx/Mx;
1219b1757049SJed 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);
1220b1757049SJed Brown   } else {
1221b1757049SJed Brown     ratioi = (mx-1)/(Mx-1);
1222b1757049SJed 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);
1223b1757049SJed Brown   }
12241321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) {
1225b1757049SJed Brown     ratioj = my/My;
1226b1757049SJed 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);
1227b1757049SJed Brown   } else {
1228b1757049SJed Brown     ratioj = (my-1)/(My-1);
1229b1757049SJed 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);
1230b1757049SJed Brown   }
12311321219cSEthan Coon   if (bz == DMDA_BOUNDARY_PERIODIC) {
1232b1757049SJed Brown     ratiok = mz/Mz;
1233b1757049SJed 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);
1234b1757049SJed Brown   } else {
1235b1757049SJed Brown     ratiok = (mz-1)/(Mz-1);
1236b1757049SJed 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);
1237b1757049SJed Brown   }
1238b1757049SJed Brown 
1239b1757049SJed Brown   ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
1240b1757049SJed Brown   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
1241e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(daf,&ltog_f);CHKERRQ(ierr);
1242e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_f,&idx_f);CHKERRQ(ierr);
1243b1757049SJed Brown 
1244b1757049SJed Brown   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
1245b1757049SJed 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);
1246e3fbd1f4SBarry Smith   ierr = DMGetLocalToGlobalMappingBlock(dac,&ltog_c);CHKERRQ(ierr);
1247e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog_c,&idx_c);CHKERRQ(ierr);
1248b1757049SJed Brown 
1249b1757049SJed Brown 
1250b1757049SJed Brown   /* loop over local fine grid nodes setting interpolation for those*/
1251b1757049SJed Brown   nc   = 0;
1252785e854fSJed Brown   ierr = PetscMalloc1(n_f*m_f*p_f,&cols);CHKERRQ(ierr);
1253b1757049SJed Brown   for (k=k_start_c; k<k_start_c+p_c; k++) {
1254b1757049SJed Brown     for (j=j_start_c; j<j_start_c+n_c; j++) {
1255b1757049SJed Brown       for (i=i_start_c; i<i_start_c+m_c; i++) {
1256b1757049SJed Brown         PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok;
1257b1757049SJed 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  "
1258b1757049SJed Brown                                                                           "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost);
1259b1757049SJed 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  "
1260b1757049SJed Brown                                                                           "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost);
1261b1757049SJed 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  "
1262b1757049SJed Brown                                                                           "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
1263e3fbd1f4SBarry Smith         row        = idx_f[(m_ghost*n_ghost*(k_f-k_start_ghost) + m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))];
1264e3fbd1f4SBarry Smith         cols[nc++] = row;
1265b1757049SJed Brown       }
1266b1757049SJed Brown     }
1267b1757049SJed Brown   }
1268e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_f,&idx_f);CHKERRQ(ierr);
1269e3fbd1f4SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog_c,&idx_c);CHKERRQ(ierr);
1270b1757049SJed Brown 
1271ce94432eSBarry Smith   ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
1272b1757049SJed Brown   ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
1273b1757049SJed Brown   ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
12740298fd71SBarry Smith   ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr);
1275b1757049SJed Brown   ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
1276b1757049SJed Brown   ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
1277fcfd50ebSBarry Smith   ierr = ISDestroy(&isf);CHKERRQ(ierr);
1278b1757049SJed Brown   PetscFunctionReturn(0);
1279b1757049SJed Brown }
1280b1757049SJed Brown 
1281b1757049SJed Brown #undef __FUNCT__
1282e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA"
1283e727c939SJed Brown PetscErrorCode  DMCreateInjection_DA(DM dac,DM daf,VecScatter *inject)
128447c6ae99SBarry Smith {
128547c6ae99SBarry Smith   PetscErrorCode   ierr;
128647c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
12871321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
1288aa219208SBarry Smith   DMDAStencilType  stc,stf;
128947c6ae99SBarry Smith 
129047c6ae99SBarry Smith   PetscFunctionBegin;
129147c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
129247c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
129347c6ae99SBarry Smith   PetscValidPointer(inject,3);
129447c6ae99SBarry Smith 
12951321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
12961321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1297ce94432eSBarry Smith   if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1298ce94432eSBarry Smith   if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1299ce94432eSBarry Smith   if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
1300ce94432eSBarry Smith   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1301ce94432eSBarry Smith   if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
130247c6ae99SBarry Smith   if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction");
130347c6ae99SBarry Smith   if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction");
130447c6ae99SBarry Smith   if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction");
130547c6ae99SBarry Smith 
13060bb2b966SJungho Lee   if (dimc == 1) {
1307e727c939SJed Brown     ierr = DMCreateInjection_DA_1D(dac,daf,inject);CHKERRQ(ierr);
13080bb2b966SJungho Lee   } else if (dimc == 2) {
1309e727c939SJed Brown     ierr = DMCreateInjection_DA_2D(dac,daf,inject);CHKERRQ(ierr);
1310b1757049SJed Brown   } else if (dimc == 3) {
1311e727c939SJed Brown     ierr = DMCreateInjection_DA_3D(dac,daf,inject);CHKERRQ(ierr);
131247c6ae99SBarry Smith   }
131347c6ae99SBarry Smith   PetscFunctionReturn(0);
131447c6ae99SBarry Smith }
131547c6ae99SBarry Smith 
131647c6ae99SBarry Smith #undef __FUNCT__
1317e727c939SJed Brown #define __FUNCT__ "DMCreateAggregates_DA"
1318e727c939SJed Brown PetscErrorCode  DMCreateAggregates_DA(DM dac,DM daf,Mat *rest)
131947c6ae99SBarry Smith {
132047c6ae99SBarry Smith   PetscErrorCode   ierr;
132147c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc;
132247c6ae99SBarry Smith   PetscInt         dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
13231321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
1324aa219208SBarry Smith   DMDAStencilType  stc,stf;
132547c6ae99SBarry Smith   PetscInt         i,j,l;
132647c6ae99SBarry Smith   PetscInt         i_start,j_start,l_start, m_f,n_f,p_f;
132747c6ae99SBarry Smith   PetscInt         i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost;
13288ea3bf28SBarry Smith   const PetscInt   *idx_f;
132947c6ae99SBarry Smith   PetscInt         i_c,j_c,l_c;
133047c6ae99SBarry Smith   PetscInt         i_start_c,j_start_c,l_start_c, m_c,n_c,p_c;
133147c6ae99SBarry Smith   PetscInt         i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c;
13328ea3bf28SBarry Smith   const PetscInt   *idx_c;
133347c6ae99SBarry Smith   PetscInt         d;
133447c6ae99SBarry Smith   PetscInt         a;
133547c6ae99SBarry Smith   PetscInt         max_agg_size;
133647c6ae99SBarry Smith   PetscInt         *fine_nodes;
133747c6ae99SBarry Smith   PetscScalar      *one_vec;
133847c6ae99SBarry Smith   PetscInt         fn_idx;
133947c6ae99SBarry Smith 
134047c6ae99SBarry Smith   PetscFunctionBegin;
134147c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
134247c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
134347c6ae99SBarry Smith   PetscValidPointer(rest,3);
134447c6ae99SBarry Smith 
13451321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
13461321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1347ce94432eSBarry Smith   if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1348ce94432eSBarry Smith   if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1349ce94432eSBarry Smith   if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
1350ce94432eSBarry Smith   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1351ce94432eSBarry Smith   if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
135247c6ae99SBarry Smith 
135347c6ae99SBarry 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);
135447c6ae99SBarry 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);
135547c6ae99SBarry 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);
135647c6ae99SBarry Smith 
135747c6ae99SBarry Smith   if (Pc < 0) Pc = 1;
135847c6ae99SBarry Smith   if (Pf < 0) Pf = 1;
135947c6ae99SBarry Smith   if (Nc < 0) Nc = 1;
136047c6ae99SBarry Smith   if (Nf < 0) Nf = 1;
136147c6ae99SBarry Smith 
1362aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
1363aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
13640298fd71SBarry Smith   ierr = DMDAGetGlobalIndices(daf,NULL,&idx_f);CHKERRQ(ierr);
136547c6ae99SBarry Smith 
1366aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
1367aa219208SBarry 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);
13680298fd71SBarry Smith   ierr = DMDAGetGlobalIndices(dac,NULL,&idx_c);CHKERRQ(ierr);
136947c6ae99SBarry Smith 
137047c6ae99SBarry Smith   /*
137147c6ae99SBarry Smith      Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios
137247c6ae99SBarry Smith      for dimension 1 and 2 respectively.
137347c6ae99SBarry Smith      Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1)
137447c6ae99SBarry Smith      and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate.
137547c6ae99SBarry Smith      Each specific dof on the fine grid is mapped to one dof on the coarse grid.
137647c6ae99SBarry Smith   */
137747c6ae99SBarry Smith 
137847c6ae99SBarry Smith   max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1);
137947c6ae99SBarry Smith 
138047c6ae99SBarry Smith   /* create the matrix that will contain the restriction operator */
1381ce94432eSBarry Smith   ierr = MatCreateAIJ(PetscObjectComm((PetscObject)daf), m_c*n_c*p_c*dofc, m_f*n_f*p_f*doff, Mc*Nc*Pc*dofc, Mf*Nf*Pf*doff,
13820298fd71SBarry Smith                       max_agg_size, NULL, max_agg_size, NULL, rest);CHKERRQ(ierr);
138347c6ae99SBarry Smith 
138447c6ae99SBarry Smith   /* store nodes in the fine grid here */
1385dcca6d9dSJed Brown   ierr = PetscMalloc2(max_agg_size, &one_vec,max_agg_size, &fine_nodes);CHKERRQ(ierr);
138647c6ae99SBarry Smith   for (i=0; i<max_agg_size; i++) one_vec[i] = 1.0;
138747c6ae99SBarry Smith 
138847c6ae99SBarry Smith   /* loop over all coarse nodes */
138947c6ae99SBarry Smith   for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) {
139047c6ae99SBarry Smith     for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) {
139147c6ae99SBarry Smith       for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) {
139247c6ae99SBarry Smith         for (d=0; d<dofc; d++) {
139347c6ae99SBarry Smith           /* convert to local "natural" numbering and then to PETSc global numbering */
139447c6ae99SBarry 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;
139547c6ae99SBarry Smith 
139647c6ae99SBarry Smith           fn_idx = 0;
139747c6ae99SBarry Smith           /* Corresponding fine points are all points (i_f, j_f, l_f) such that
139847c6ae99SBarry Smith              i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc
139947c6ae99SBarry Smith              (same for other dimensions)
140047c6ae99SBarry Smith           */
140147c6ae99SBarry Smith           for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) {
140247c6ae99SBarry Smith             for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) {
140347c6ae99SBarry Smith               for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) {
140447c6ae99SBarry 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;
140547c6ae99SBarry Smith                 fn_idx++;
140647c6ae99SBarry Smith               }
140747c6ae99SBarry Smith             }
140847c6ae99SBarry Smith           }
140947c6ae99SBarry Smith           /* add all these points to one aggregate */
141047c6ae99SBarry Smith           ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr);
141147c6ae99SBarry Smith         }
141247c6ae99SBarry Smith       }
141347c6ae99SBarry Smith     }
141447c6ae99SBarry Smith   }
14158ea3bf28SBarry Smith   ierr = DMDARestoreGlobalIndices(daf,NULL,&idx_f);CHKERRQ(ierr);
14168ea3bf28SBarry Smith   ierr = DMDARestoreGlobalIndices(dac,NULL,&idx_c);CHKERRQ(ierr);
141747c6ae99SBarry Smith   ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr);
141847c6ae99SBarry Smith   ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
141947c6ae99SBarry Smith   ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
142047c6ae99SBarry Smith   PetscFunctionReturn(0);
142147c6ae99SBarry Smith }
1422