xref: /petsc/src/dm/impls/da/dainterp.c (revision 2adb9dcf37aade1df7d83092429d5fd007a232d3)
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
9*2adb9dcfSBarry 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
10*2adb9dcfSBarry Smith    consider it cleaner, but old version is turned on since it handles periodic case.
11d52bd9f3SBarry Smith */
129314d695SBarry Smith #define NEWVERSION 0
1385afcc9aSBarry Smith 
14c6db04a5SJed Brown #include <private/daimpl.h>    /*I   "petscdmda.h"   I*/
15c6db04a5SJed Brown #include <petscpcmg.h>
1647c6ae99SBarry Smith 
1747c6ae99SBarry Smith #undef __FUNCT__
1847c6ae99SBarry Smith #define __FUNCT__ "DMGetInterpolationScale"
1947c6ae99SBarry Smith /*@
2047c6ae99SBarry Smith     DMGetInterpolationScale - Forms L = R*1/diag(R*1) - L.*v is like a coarse grid average of the
2147c6ae99SBarry Smith       nearby fine grid points.
2247c6ae99SBarry Smith 
2347c6ae99SBarry Smith   Input Parameters:
2447c6ae99SBarry Smith +      dac - DM that defines a coarse mesh
2547c6ae99SBarry Smith .      daf - DM that defines a fine mesh
2647c6ae99SBarry Smith -      mat - the restriction (or interpolation operator) from fine to coarse
2747c6ae99SBarry Smith 
2847c6ae99SBarry Smith   Output Parameter:
2947c6ae99SBarry Smith .    scale - the scaled vector
3047c6ae99SBarry Smith 
3147c6ae99SBarry Smith   Level: developer
3247c6ae99SBarry Smith 
3347c6ae99SBarry Smith .seealso: DMGetInterpolation()
3447c6ae99SBarry Smith 
3547c6ae99SBarry Smith @*/
367087cfbeSBarry Smith PetscErrorCode  DMGetInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale)
3747c6ae99SBarry Smith {
3847c6ae99SBarry Smith   PetscErrorCode ierr;
3947c6ae99SBarry Smith   Vec            fine;
4047c6ae99SBarry Smith   PetscScalar    one = 1.0;
4147c6ae99SBarry Smith 
4247c6ae99SBarry Smith   PetscFunctionBegin;
4347c6ae99SBarry Smith   ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr);
4447c6ae99SBarry Smith   ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr);
4547c6ae99SBarry Smith   ierr = VecSet(fine,one);CHKERRQ(ierr);
4647c6ae99SBarry Smith   ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr);
47fcfd50ebSBarry Smith   ierr = VecDestroy(&fine);CHKERRQ(ierr);
4847c6ae99SBarry Smith   ierr = VecReciprocal(*scale);CHKERRQ(ierr);
4947c6ae99SBarry Smith   PetscFunctionReturn(0);
5047c6ae99SBarry Smith }
5147c6ae99SBarry Smith 
5247c6ae99SBarry Smith #undef __FUNCT__
5394013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_1D_Q1"
5494013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A)
5547c6ae99SBarry Smith {
5647c6ae99SBarry Smith   PetscErrorCode   ierr;
5747c6ae99SBarry Smith   PetscInt         i,i_start,m_f,Mx,*idx_f;
5847c6ae99SBarry Smith   PetscInt         m_ghost,*idx_c,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;
6447c6ae99SBarry Smith 
6547c6ae99SBarry Smith   PetscFunctionBegin;
661321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
671321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
681321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
6947c6ae99SBarry Smith     ratio = mx/Mx;
7047c6ae99SBarry 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);
7147c6ae99SBarry Smith   } else {
7247c6ae99SBarry Smith     ratio = (mx-1)/(Mx-1);
7347c6ae99SBarry 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);
7447c6ae99SBarry Smith   }
7547c6ae99SBarry Smith 
76aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
77aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
78aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
7947c6ae99SBarry Smith 
80aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
81aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
82aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
8347c6ae99SBarry Smith 
8447c6ae99SBarry Smith   /* create interpolation matrix */
8547c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr);
8647c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr);
8747c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
8847c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr);
8947c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
9047c6ae99SBarry Smith 
9147c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
9285afcc9aSBarry Smith   if (!NEWVERSION) {
93b3bd94feSDave May 
9447c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
9547c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
9647c6ae99SBarry Smith       row    = idx_f[dof*(i-i_start_ghost)]/dof;
9747c6ae99SBarry Smith 
9847c6ae99SBarry Smith       i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
99aa219208SBarry 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\
10047c6ae99SBarry Smith                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
10147c6ae99SBarry Smith 
10247c6ae99SBarry Smith       /*
10347c6ae99SBarry Smith        Only include those interpolation points that are truly
10447c6ae99SBarry Smith        nonzero. Note this is very important for final grid lines
10547c6ae99SBarry Smith        in x direction; since they have no right neighbor
10647c6ae99SBarry Smith        */
10747c6ae99SBarry Smith       x  = ((double)(i - i_c*ratio))/((double)ratio);
10847c6ae99SBarry Smith       nc = 0;
10947c6ae99SBarry Smith       /* one left and below; or we are right on it */
11047c6ae99SBarry Smith       col      = dof*(i_c-i_start_ghost_c);
11147c6ae99SBarry Smith       cols[nc] = idx_c[col]/dof;
11247c6ae99SBarry Smith       v[nc++]  = - x + 1.0;
11347c6ae99SBarry Smith       /* one right? */
11447c6ae99SBarry Smith       if (i_c*ratio != i) {
11547c6ae99SBarry Smith         cols[nc] = idx_c[col+dof]/dof;
11647c6ae99SBarry Smith         v[nc++]  = x;
11747c6ae99SBarry Smith       }
11847c6ae99SBarry Smith       ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
11947c6ae99SBarry Smith     }
120b3bd94feSDave May 
121b3bd94feSDave May   } else {
122b3bd94feSDave May     PetscScalar    *xi;
123b3bd94feSDave May     PetscInt       li,nxi,n;
124b3bd94feSDave May     PetscScalar    Ni[2];
125b3bd94feSDave May 
126b3bd94feSDave May     /* compute local coordinate arrays */
127b3bd94feSDave May     nxi   = ratio + 1;
128b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
129b3bd94feSDave May     for (li=0; li<nxi; li++) {
13052218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
131b3bd94feSDave May     }
132b3bd94feSDave May 
133b3bd94feSDave May     for (i=i_start; i<i_start+m_f; i++) {
134b3bd94feSDave May       /* convert to local "natural" numbering and then to PETSc global numbering */
135b3bd94feSDave May       row    = idx_f[dof*(i-i_start_ghost)]/dof;
136b3bd94feSDave May 
137b3bd94feSDave May       i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
138b3bd94feSDave 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\
139b3bd94feSDave May                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
140b3bd94feSDave May 
141b3bd94feSDave May       /* remainders */
142b3bd94feSDave May       li = i - ratio * (i/ratio);
143b3bd94feSDave May       if (i==mx-1){ li = nxi-1; }
144b3bd94feSDave May 
145b3bd94feSDave May       /* corners */
146b3bd94feSDave May       col     = dof*(i_c-i_start_ghost_c);
147b3bd94feSDave May       cols[0] = idx_c[col]/dof;
148b3bd94feSDave May       Ni[0]   = 1.0;
149b3bd94feSDave May       if ( (li==0) || (li==nxi-1) ) {
150b3bd94feSDave May         ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
151b3bd94feSDave May         continue;
152b3bd94feSDave May       }
153b3bd94feSDave May 
154b3bd94feSDave May       /* edges + interior */
155b3bd94feSDave May       /* remainders */
156b3bd94feSDave May       if (i==mx-1){ i_c--; }
157b3bd94feSDave May 
158b3bd94feSDave May       col     = dof*(i_c-i_start_ghost_c);
159b3bd94feSDave May       cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */
160b3bd94feSDave May       cols[1] = idx_c[col+dof]/dof;
161b3bd94feSDave May 
162b3bd94feSDave May       Ni[0] = 0.5*(1.0-xi[li]);
163b3bd94feSDave May       Ni[1] = 0.5*(1.0+xi[li]);
164b3bd94feSDave May       for (n=0; n<2; n++) {
165b3bd94feSDave May         if( PetscAbsScalar(Ni[n])<1.0e-32) { cols[n]=-1; }
166b3bd94feSDave May       }
167b3bd94feSDave May       ierr = MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
168b3bd94feSDave May     }
169b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
170b3bd94feSDave May   }
17147c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17247c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17347c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
174fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
17547c6ae99SBarry Smith   PetscFunctionReturn(0);
17647c6ae99SBarry Smith }
17747c6ae99SBarry Smith 
17847c6ae99SBarry Smith #undef __FUNCT__
17994013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_1D_Q0"
18094013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A)
18147c6ae99SBarry Smith {
18247c6ae99SBarry Smith   PetscErrorCode   ierr;
18347c6ae99SBarry Smith   PetscInt         i,i_start,m_f,Mx,*idx_f;
18447c6ae99SBarry Smith   PetscInt         m_ghost,*idx_c,m_ghost_c;
18547c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,mx,m_c,nc,ratio;
18647c6ae99SBarry Smith   PetscInt         i_c,i_start_c,i_start_ghost_c,cols[2],dof;
18747c6ae99SBarry Smith   PetscScalar      v[2],x;
18847c6ae99SBarry Smith   Mat              mat;
1891321219cSEthan Coon   DMDABoundaryType bx;
19047c6ae99SBarry Smith 
19147c6ae99SBarry Smith   PetscFunctionBegin;
1921321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
1931321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
1941321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
19547c6ae99SBarry Smith     ratio = mx/Mx;
19647c6ae99SBarry 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);
19747c6ae99SBarry Smith   } else {
19847c6ae99SBarry Smith     ratio = (mx-1)/(Mx-1);
19947c6ae99SBarry 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);
20047c6ae99SBarry Smith   }
20147c6ae99SBarry Smith 
202aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
203aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
204aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
20547c6ae99SBarry Smith 
206aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
207aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
208aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
20947c6ae99SBarry Smith 
21047c6ae99SBarry Smith   /* create interpolation matrix */
21147c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr);
21247c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr);
21347c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
21447c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr);
21547c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr);
21647c6ae99SBarry Smith 
21747c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
21847c6ae99SBarry Smith   for (i=i_start; i<i_start+m_f; i++) {
21947c6ae99SBarry Smith     /* convert to local "natural" numbering and then to PETSc global numbering */
22047c6ae99SBarry Smith     row    = idx_f[dof*(i-i_start_ghost)]/dof;
22147c6ae99SBarry Smith 
22247c6ae99SBarry Smith     i_c = (i/ratio);    /* coarse grid node to left of fine grid node */
22347c6ae99SBarry Smith 
22447c6ae99SBarry Smith     /*
22547c6ae99SBarry Smith          Only include those interpolation points that are truly
22647c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
22747c6ae99SBarry Smith          in x direction; since they have no right neighbor
22847c6ae99SBarry Smith     */
22947c6ae99SBarry Smith     x  = ((double)(i - i_c*ratio))/((double)ratio);
23047c6ae99SBarry Smith     nc = 0;
23147c6ae99SBarry Smith       /* one left and below; or we are right on it */
23247c6ae99SBarry Smith     col      = dof*(i_c-i_start_ghost_c);
23347c6ae99SBarry Smith     cols[nc] = idx_c[col]/dof;
23447c6ae99SBarry Smith     v[nc++]  = - x + 1.0;
23547c6ae99SBarry Smith     /* one right? */
23647c6ae99SBarry Smith     if (i_c*ratio != i) {
23747c6ae99SBarry Smith       cols[nc] = idx_c[col+dof]/dof;
23847c6ae99SBarry Smith       v[nc++]  = x;
23947c6ae99SBarry Smith     }
24047c6ae99SBarry Smith     ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
24147c6ae99SBarry Smith   }
24247c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24347c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24447c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
245fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
24647c6ae99SBarry Smith   ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr);
24747c6ae99SBarry Smith   PetscFunctionReturn(0);
24847c6ae99SBarry Smith }
24947c6ae99SBarry Smith 
25047c6ae99SBarry Smith #undef __FUNCT__
25194013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_2D_Q1"
25294013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A)
25347c6ae99SBarry Smith {
25447c6ae99SBarry Smith   PetscErrorCode   ierr;
25547c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof;
25647c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz;
25747c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj;
25847c6ae99SBarry 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;
25947c6ae99SBarry Smith   PetscMPIInt      size_c,size_f,rank_f;
26047c6ae99SBarry Smith   PetscScalar      v[4],x,y;
26147c6ae99SBarry Smith   Mat              mat;
2621321219cSEthan Coon   DMDABoundaryType bx,by;
26347c6ae99SBarry Smith 
26447c6ae99SBarry Smith   PetscFunctionBegin;
2651321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
2661321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
2671321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
26847c6ae99SBarry Smith     ratioi = mx/Mx;
26947c6ae99SBarry 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);
27047c6ae99SBarry Smith   } else {
27147c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
27247c6ae99SBarry 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);
27347c6ae99SBarry Smith   }
2741321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC){
27547c6ae99SBarry Smith     ratioj = my/My;
27647c6ae99SBarry 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);
27747c6ae99SBarry Smith   } else {
27847c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
27947c6ae99SBarry 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);
28047c6ae99SBarry Smith   }
28147c6ae99SBarry Smith 
28247c6ae99SBarry Smith 
283aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
284aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
285aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
28647c6ae99SBarry Smith 
287aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
288aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
289aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
29047c6ae99SBarry Smith 
29147c6ae99SBarry Smith   /*
292aa219208SBarry Smith    Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
29347c6ae99SBarry Smith    The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
29447c6ae99SBarry Smith    processors). It's effective length is hence 4 times its normal length, this is
29547c6ae99SBarry Smith    why the col_scale is multiplied by the interpolation matrix column sizes.
29647c6ae99SBarry Smith    sol_shift allows each set of 1/4 processors do its own interpolation using ITS
29747c6ae99SBarry Smith    copy of the coarse vector. A bit of a hack but you do better.
29847c6ae99SBarry Smith 
29947c6ae99SBarry Smith    In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
30047c6ae99SBarry Smith    */
30147c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr);
30247c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr);
30347c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr);
30447c6ae99SBarry Smith   col_scale = size_f/size_c;
30547c6ae99SBarry Smith   col_shift = Mx*My*(rank_f/size_c);
30647c6ae99SBarry Smith 
30747c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr);
30847c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
30947c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
31047c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
31147c6ae99SBarry Smith       row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
31247c6ae99SBarry Smith 
31347c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
31447c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
31547c6ae99SBarry Smith 
316aa219208SBarry 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\
31747c6ae99SBarry Smith                                           j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
318aa219208SBarry 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\
31947c6ae99SBarry Smith                                           i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
32047c6ae99SBarry Smith 
32147c6ae99SBarry Smith       /*
32247c6ae99SBarry Smith        Only include those interpolation points that are truly
32347c6ae99SBarry Smith        nonzero. Note this is very important for final grid lines
32447c6ae99SBarry Smith        in x and y directions; since they have no right/top neighbors
32547c6ae99SBarry Smith        */
32647c6ae99SBarry Smith       nc = 0;
32747c6ae99SBarry Smith       /* one left and below; or we are right on it */
32847c6ae99SBarry Smith       col        = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
32947c6ae99SBarry Smith       cols[nc++] = col_shift + idx_c[col]/dof;
33047c6ae99SBarry Smith       /* one right and below */
33147c6ae99SBarry Smith       if (i_c*ratioi != i) {
33247c6ae99SBarry Smith         cols[nc++] = col_shift + idx_c[col+dof]/dof;
33347c6ae99SBarry Smith       }
33447c6ae99SBarry Smith       /* one left and above */
33547c6ae99SBarry Smith       if (j_c*ratioj != j) {
33647c6ae99SBarry Smith         cols[nc++] = col_shift + idx_c[col+m_ghost_c*dof]/dof;
33747c6ae99SBarry Smith       }
33847c6ae99SBarry Smith       /* one right and above */
3390c82216cSJed Brown       if (i_c*ratioi != i && j_c*ratioj != j) {
34047c6ae99SBarry Smith         cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof;
34147c6ae99SBarry Smith       }
34247c6ae99SBarry Smith       ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
34347c6ae99SBarry Smith     }
34447c6ae99SBarry Smith   }
34547c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr);
34647c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr);
34747c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
34847c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
34947c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
35047c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
35147c6ae99SBarry Smith 
35247c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
35385afcc9aSBarry Smith   if (!NEWVERSION) {
354b3bd94feSDave May 
35547c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
35647c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
35747c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
35847c6ae99SBarry Smith         row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
35947c6ae99SBarry Smith 
36047c6ae99SBarry Smith         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
36147c6ae99SBarry Smith         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
36247c6ae99SBarry Smith 
36347c6ae99SBarry Smith         /*
36447c6ae99SBarry Smith          Only include those interpolation points that are truly
36547c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
36647c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
36747c6ae99SBarry Smith          */
36847c6ae99SBarry Smith         x  = ((double)(i - i_c*ratioi))/((double)ratioi);
36947c6ae99SBarry Smith         y  = ((double)(j - j_c*ratioj))/((double)ratioj);
370b3bd94feSDave May 
37147c6ae99SBarry Smith         nc = 0;
37247c6ae99SBarry Smith         /* one left and below; or we are right on it */
37347c6ae99SBarry Smith         col      = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
37447c6ae99SBarry Smith         cols[nc] = col_shift + idx_c[col]/dof;
37547c6ae99SBarry Smith         v[nc++]  = x*y - x - y + 1.0;
37647c6ae99SBarry Smith         /* one right and below */
37747c6ae99SBarry Smith         if (i_c*ratioi != i) {
37847c6ae99SBarry Smith           cols[nc] = col_shift + idx_c[col+dof]/dof;
37947c6ae99SBarry Smith           v[nc++]  = -x*y + x;
38047c6ae99SBarry Smith         }
38147c6ae99SBarry Smith         /* one left and above */
38247c6ae99SBarry Smith         if (j_c*ratioj != j) {
38347c6ae99SBarry Smith           cols[nc] = col_shift + idx_c[col+m_ghost_c*dof]/dof;
38447c6ae99SBarry Smith           v[nc++]  = -x*y + y;
38547c6ae99SBarry Smith         }
38647c6ae99SBarry Smith         /* one right and above */
38747c6ae99SBarry Smith         if (j_c*ratioj != j && i_c*ratioi != i) {
38847c6ae99SBarry Smith           cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof;
38947c6ae99SBarry Smith           v[nc++]  = x*y;
39047c6ae99SBarry Smith         }
39147c6ae99SBarry Smith         ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
39247c6ae99SBarry Smith       }
39347c6ae99SBarry Smith     }
394b3bd94feSDave May 
395b3bd94feSDave May   } else {
396b3bd94feSDave May     PetscScalar    Ni[4];
397b3bd94feSDave May     PetscScalar    *xi,*eta;
398b3bd94feSDave May     PetscInt       li,nxi,lj,neta;
399b3bd94feSDave May 
400b3bd94feSDave May     /* compute local coordinate arrays */
401b3bd94feSDave May     nxi  = ratioi + 1;
402b3bd94feSDave May     neta = ratioj + 1;
403b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
404b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr);
405b3bd94feSDave May     for (li=0; li<nxi; li++) {
40652218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
407b3bd94feSDave May     }
408b3bd94feSDave May     for (lj=0; lj<neta; lj++) {
40952218ef2SJed Brown       eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1));
410b3bd94feSDave May     }
411b3bd94feSDave May 
412b3bd94feSDave May     /* loop over local fine grid nodes setting interpolation for those*/
413b3bd94feSDave May     for (j=j_start; j<j_start+n_f; j++) {
414b3bd94feSDave May       for (i=i_start; i<i_start+m_f; i++) {
415b3bd94feSDave May         /* convert to local "natural" numbering and then to PETSc global numbering */
416b3bd94feSDave May         row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
417b3bd94feSDave May 
418b3bd94feSDave May         i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
419b3bd94feSDave May         j_c = (j/ratioj);    /* coarse grid node below fine grid node */
420b3bd94feSDave May 
421b3bd94feSDave May         /* remainders */
422b3bd94feSDave May         li = i - ratioi * (i/ratioi);
423b3bd94feSDave May         if (i==mx-1){ li = nxi-1; }
424b3bd94feSDave May         lj = j - ratioj * (j/ratioj);
425b3bd94feSDave May         if (j==my-1){ lj = neta-1; }
426b3bd94feSDave May 
427b3bd94feSDave May         /* corners */
428b3bd94feSDave May         col     = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
429b3bd94feSDave May         cols[0] = col_shift + idx_c[col]/dof; /* left, below */
430b3bd94feSDave May         Ni[0]   = 1.0;
431b3bd94feSDave May         if ( (li==0) || (li==nxi-1) ) {
432b3bd94feSDave May           if ( (lj==0) || (lj==neta-1) ) {
433b3bd94feSDave May             ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
434b3bd94feSDave May             continue;
435b3bd94feSDave May           }
436b3bd94feSDave May         }
437b3bd94feSDave May 
438b3bd94feSDave May         /* edges + interior */
439b3bd94feSDave May         /* remainders */
440b3bd94feSDave May         if (i==mx-1){ i_c--; }
441b3bd94feSDave May         if (j==my-1){ j_c--; }
442b3bd94feSDave May 
443b3bd94feSDave May         col     = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
444b3bd94feSDave May         cols[0] = col_shift + idx_c[col]/dof; /* left, below */
445b3bd94feSDave May         cols[1] = col_shift + idx_c[col+dof]/dof; /* right, below */
446b3bd94feSDave May         cols[2] = col_shift + idx_c[col+m_ghost_c*dof]/dof; /* left, above */
447b3bd94feSDave May         cols[3] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; /* right, above */
448b3bd94feSDave May 
449b3bd94feSDave May         Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]);
450b3bd94feSDave May         Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]);
451b3bd94feSDave May         Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]);
452b3bd94feSDave May         Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]);
453b3bd94feSDave May 
454b3bd94feSDave May         nc = 0;
455b3bd94feSDave May         if( PetscAbsScalar(Ni[0])<1.0e-32) { cols[0]=-1; }
456b3bd94feSDave May         if( PetscAbsScalar(Ni[1])<1.0e-32) { cols[1]=-1; }
457b3bd94feSDave May         if( PetscAbsScalar(Ni[2])<1.0e-32) { cols[2]=-1; }
458b3bd94feSDave May         if( PetscAbsScalar(Ni[3])<1.0e-32) { cols[3]=-1; }
459b3bd94feSDave May 
460b3bd94feSDave May         ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
461b3bd94feSDave May       }
462b3bd94feSDave May     }
463b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
464b3bd94feSDave May     ierr = PetscFree(eta);CHKERRQ(ierr);
465b3bd94feSDave May   }
46647c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46747c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46847c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
469fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
47047c6ae99SBarry Smith   PetscFunctionReturn(0);
47147c6ae99SBarry Smith }
47247c6ae99SBarry Smith 
47347c6ae99SBarry Smith /*
47447c6ae99SBarry Smith        Contributed by Andrei Draganescu <aidraga@sandia.gov>
47547c6ae99SBarry Smith */
47647c6ae99SBarry Smith #undef __FUNCT__
47794013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_2D_Q0"
47894013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A)
47947c6ae99SBarry Smith {
48047c6ae99SBarry Smith   PetscErrorCode   ierr;
48147c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof;
48247c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz;
48347c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj;
48447c6ae99SBarry 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;
48547c6ae99SBarry Smith   PetscMPIInt      size_c,size_f,rank_f;
48647c6ae99SBarry Smith   PetscScalar      v[4];
48747c6ae99SBarry Smith   Mat              mat;
4881321219cSEthan Coon   DMDABoundaryType bx,by;
48947c6ae99SBarry Smith 
49047c6ae99SBarry Smith   PetscFunctionBegin;
4911321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
4921321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
4931321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x");
4941321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y");
49547c6ae99SBarry Smith   ratioi = mx/Mx;
49647c6ae99SBarry Smith   ratioj = my/My;
49747c6ae99SBarry Smith   if (ratioi*Mx != mx) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x");
49847c6ae99SBarry Smith   if (ratioj*My != my) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y");
49947c6ae99SBarry Smith   if (ratioi != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2");
50047c6ae99SBarry Smith   if (ratioj != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2");
50147c6ae99SBarry Smith 
502aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
503aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
504aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
50547c6ae99SBarry Smith 
506aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
507aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
508aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
50947c6ae99SBarry Smith 
51047c6ae99SBarry Smith   /*
511aa219208SBarry Smith      Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
51247c6ae99SBarry Smith      The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
51347c6ae99SBarry Smith      processors). It's effective length is hence 4 times its normal length, this is
51447c6ae99SBarry Smith      why the col_scale is multiplied by the interpolation matrix column sizes.
51547c6ae99SBarry Smith      sol_shift allows each set of 1/4 processors do its own interpolation using ITS
51647c6ae99SBarry Smith      copy of the coarse vector. A bit of a hack but you do better.
51747c6ae99SBarry Smith 
51847c6ae99SBarry Smith      In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
51947c6ae99SBarry Smith   */
52047c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr);
52147c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr);
52247c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr);
52347c6ae99SBarry Smith   col_scale = size_f/size_c;
52447c6ae99SBarry Smith   col_shift = Mx*My*(rank_f/size_c);
52547c6ae99SBarry Smith 
52647c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr);
52747c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
52847c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
52947c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
53047c6ae99SBarry Smith       row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
53147c6ae99SBarry Smith 
53247c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
53347c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
53447c6ae99SBarry Smith 
535aa219208SBarry 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\
53647c6ae99SBarry Smith     j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
537aa219208SBarry 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\
53847c6ae99SBarry Smith     i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
53947c6ae99SBarry Smith 
54047c6ae99SBarry Smith       /*
54147c6ae99SBarry Smith          Only include those interpolation points that are truly
54247c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
54347c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
54447c6ae99SBarry Smith       */
54547c6ae99SBarry Smith       nc = 0;
54647c6ae99SBarry Smith       /* one left and below; or we are right on it */
54747c6ae99SBarry Smith       col        = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
54847c6ae99SBarry Smith       cols[nc++] = col_shift + idx_c[col]/dof;
54947c6ae99SBarry Smith       ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
55047c6ae99SBarry Smith     }
55147c6ae99SBarry Smith   }
55247c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr);
55347c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr);
55447c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
55547c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
55647c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
55747c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
55847c6ae99SBarry Smith 
55947c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
56047c6ae99SBarry Smith   for (j=j_start; j<j_start+n_f; j++) {
56147c6ae99SBarry Smith     for (i=i_start; i<i_start+m_f; i++) {
56247c6ae99SBarry Smith       /* convert to local "natural" numbering and then to PETSc global numbering */
56347c6ae99SBarry Smith       row    = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
56447c6ae99SBarry Smith 
56547c6ae99SBarry Smith       i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
56647c6ae99SBarry Smith       j_c = (j/ratioj);    /* coarse grid node below fine grid node */
56747c6ae99SBarry Smith       nc = 0;
56847c6ae99SBarry Smith       /* one left and below; or we are right on it */
56947c6ae99SBarry Smith       col      = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
57047c6ae99SBarry Smith       cols[nc] = col_shift + idx_c[col]/dof;
57147c6ae99SBarry Smith       v[nc++]  = 1.0;
57247c6ae99SBarry Smith 
57347c6ae99SBarry Smith       ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
57447c6ae99SBarry Smith     }
57547c6ae99SBarry Smith   }
57647c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57747c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57847c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
579fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
58047c6ae99SBarry Smith   ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr);
58147c6ae99SBarry Smith   PetscFunctionReturn(0);
58247c6ae99SBarry Smith }
58347c6ae99SBarry Smith 
58447c6ae99SBarry Smith /*
58547c6ae99SBarry Smith        Contributed by Jianming Yang <jianming-yang@uiowa.edu>
58647c6ae99SBarry Smith */
58747c6ae99SBarry Smith #undef __FUNCT__
58894013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_3D_Q0"
58994013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A)
59047c6ae99SBarry Smith {
59147c6ae99SBarry Smith   PetscErrorCode   ierr;
59247c6ae99SBarry Smith   PetscInt         i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,*idx_f,dof;
59347c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,p_ghost,*idx_c,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz;
59447c6ae99SBarry 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;
59547c6ae99SBarry 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;
59647c6ae99SBarry Smith   PetscMPIInt      size_c,size_f,rank_f;
59747c6ae99SBarry Smith   PetscScalar      v[8];
59847c6ae99SBarry Smith   Mat              mat;
5991321219cSEthan Coon   DMDABoundaryType bx,by,bz;
60047c6ae99SBarry Smith 
60147c6ae99SBarry Smith   PetscFunctionBegin;
6021321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
6031321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
6041321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x");
6051321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y");
6061321219cSEthan Coon   if (bz == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in z");
60747c6ae99SBarry Smith   ratioi = mx/Mx;
60847c6ae99SBarry Smith   ratioj = my/My;
60947c6ae99SBarry Smith   ratiol = mz/Mz;
61047c6ae99SBarry Smith   if (ratioi*Mx != mx) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x");
61147c6ae99SBarry Smith   if (ratioj*My != my) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y");
61247c6ae99SBarry Smith   if (ratiol*Mz != mz) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z");
61347c6ae99SBarry Smith   if (ratioi != 2 && ratioi != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2");
61447c6ae99SBarry Smith   if (ratioj != 2 && ratioj != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2");
61547c6ae99SBarry Smith   if (ratiol != 2 && ratiol != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2");
61647c6ae99SBarry Smith 
617aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
618aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
619aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
62047c6ae99SBarry Smith 
621aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
622aa219208SBarry 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);
623aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
62447c6ae99SBarry Smith   /*
625aa219208SBarry Smith      Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA.
62647c6ae99SBarry Smith      The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the
62747c6ae99SBarry Smith      processors). It's effective length is hence 4 times its normal length, this is
62847c6ae99SBarry Smith      why the col_scale is multiplied by the interpolation matrix column sizes.
62947c6ae99SBarry Smith      sol_shift allows each set of 1/4 processors do its own interpolation using ITS
63047c6ae99SBarry Smith      copy of the coarse vector. A bit of a hack but you do better.
63147c6ae99SBarry Smith 
63247c6ae99SBarry Smith      In the standard case when size_f == size_c col_scale == 1 and col_shift == 0
63347c6ae99SBarry Smith   */
63447c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr);
63547c6ae99SBarry Smith   ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr);
63647c6ae99SBarry Smith   ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr);
63747c6ae99SBarry Smith   col_scale = size_f/size_c;
63847c6ae99SBarry Smith   col_shift = Mx*My*Mz*(rank_f/size_c);
63947c6ae99SBarry Smith 
64047c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr);
64147c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
64247c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
64347c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
64447c6ae99SBarry Smith 	/* convert to local "natural" numbering and then to PETSc global numbering */
64547c6ae99SBarry Smith 	row    = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
64647c6ae99SBarry Smith 
64747c6ae99SBarry Smith 	i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
64847c6ae99SBarry Smith 	j_c = (j/ratioj);    /* coarse grid node below fine grid node */
64947c6ae99SBarry Smith 	l_c = (l/ratiol);
65047c6ae99SBarry Smith 
651aa219208SBarry 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\
65247c6ae99SBarry Smith     l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c);
653aa219208SBarry 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\
65447c6ae99SBarry Smith     j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
655aa219208SBarry 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\
65647c6ae99SBarry Smith     i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
65747c6ae99SBarry Smith 
65847c6ae99SBarry Smith 	/*
65947c6ae99SBarry Smith 	   Only include those interpolation points that are truly
66047c6ae99SBarry Smith 	   nonzero. Note this is very important for final grid lines
66147c6ae99SBarry Smith 	   in x and y directions; since they have no right/top neighbors
66247c6ae99SBarry Smith 	*/
66347c6ae99SBarry Smith 	nc = 0;
66447c6ae99SBarry Smith 	/* one left and below; or we are right on it */
66547c6ae99SBarry Smith 	col        = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
66647c6ae99SBarry Smith 	cols[nc++] = col_shift + idx_c[col]/dof;
66747c6ae99SBarry Smith 	ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
66847c6ae99SBarry Smith       }
66947c6ae99SBarry Smith     }
67047c6ae99SBarry Smith   }
67147c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr);
67247c6ae99SBarry 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);
67347c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
67447c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
67547c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
67647c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
67747c6ae99SBarry Smith 
67847c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
67947c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
68047c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
68147c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
68247c6ae99SBarry Smith 	/* convert to local "natural" numbering and then to PETSc global numbering */
68347c6ae99SBarry Smith 	row    = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
68447c6ae99SBarry Smith 
68547c6ae99SBarry Smith 	i_c = (i/ratioi);    /* coarse grid node to left of fine grid node */
68647c6ae99SBarry Smith 	j_c = (j/ratioj);    /* coarse grid node below fine grid node */
68747c6ae99SBarry Smith 	l_c = (l/ratiol);
68847c6ae99SBarry Smith 	nc = 0;
68947c6ae99SBarry Smith 	/* one left and below; or we are right on it */
69047c6ae99SBarry Smith 	col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
69147c6ae99SBarry Smith 	cols[nc] = col_shift + idx_c[col]/dof;
69247c6ae99SBarry Smith 	v[nc++]  = 1.0;
69347c6ae99SBarry Smith 
69447c6ae99SBarry Smith 	ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
69547c6ae99SBarry Smith       }
69647c6ae99SBarry Smith     }
69747c6ae99SBarry Smith   }
69847c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
69947c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
70047c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
701fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
70247c6ae99SBarry Smith   ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr);
70347c6ae99SBarry Smith   PetscFunctionReturn(0);
70447c6ae99SBarry Smith }
70547c6ae99SBarry Smith 
70647c6ae99SBarry Smith #undef __FUNCT__
70794013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_3D_Q1"
70894013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A)
70947c6ae99SBarry Smith {
71047c6ae99SBarry Smith   PetscErrorCode   ierr;
71147c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof,l;
71247c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,Mz,mz;
71347c6ae99SBarry Smith   PetscInt         row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok;
71447c6ae99SBarry Smith   PetscInt         i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c;
71547c6ae99SBarry Smith   PetscInt         l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c;
71647c6ae99SBarry Smith   PetscInt         l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz;
71747c6ae99SBarry Smith   PetscScalar      v[8],x,y,z;
71847c6ae99SBarry Smith   Mat              mat;
7191321219cSEthan Coon   DMDABoundaryType bx,by,bz;
72047c6ae99SBarry Smith 
72147c6ae99SBarry Smith   PetscFunctionBegin;
7221321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
7231321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
72447c6ae99SBarry Smith   if (mx == Mx) {
72547c6ae99SBarry Smith     ratioi = 1;
7261321219cSEthan Coon   } else if (bx == DMDA_BOUNDARY_PERIODIC) {
72747c6ae99SBarry Smith     ratioi = mx/Mx;
72847c6ae99SBarry 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);
72947c6ae99SBarry Smith   } else {
73047c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
73147c6ae99SBarry 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);
73247c6ae99SBarry Smith   }
73347c6ae99SBarry Smith   if (my == My) {
73447c6ae99SBarry Smith     ratioj = 1;
7351321219cSEthan Coon   } else if (by == DMDA_BOUNDARY_PERIODIC) {
73647c6ae99SBarry Smith     ratioj = my/My;
73747c6ae99SBarry 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);
73847c6ae99SBarry Smith   } else {
73947c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
74047c6ae99SBarry 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);
74147c6ae99SBarry Smith   }
74247c6ae99SBarry Smith   if (mz == Mz) {
74347c6ae99SBarry Smith     ratiok = 1;
7441321219cSEthan Coon   } else if (bz == DMDA_BOUNDARY_PERIODIC) {
74547c6ae99SBarry Smith     ratiok = mz/Mz;
74647c6ae99SBarry 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);
74747c6ae99SBarry Smith   } else {
74847c6ae99SBarry Smith     ratiok = (mz-1)/(Mz-1);
74947c6ae99SBarry 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);
75047c6ae99SBarry Smith   }
75147c6ae99SBarry Smith 
752aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
753aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
754aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
75547c6ae99SBarry Smith 
756aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
757aa219208SBarry 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);
758aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
75947c6ae99SBarry Smith 
76047c6ae99SBarry Smith   /* create interpolation matrix, determining exact preallocation */
76147c6ae99SBarry Smith   ierr = MatPreallocateInitialize(((PetscObject)dac)->comm,m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr);
76247c6ae99SBarry Smith   /* loop over local fine grid nodes counting interpolating points */
76347c6ae99SBarry Smith   for (l=l_start; l<l_start+p_f; l++) {
76447c6ae99SBarry Smith     for (j=j_start; j<j_start+n_f; j++) {
76547c6ae99SBarry Smith       for (i=i_start; i<i_start+m_f; i++) {
76647c6ae99SBarry Smith         /* convert to local "natural" numbering and then to PETSc global numbering */
76747c6ae99SBarry Smith         row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
76847c6ae99SBarry Smith         i_c = (i/ratioi);
76947c6ae99SBarry Smith         j_c = (j/ratioj);
77047c6ae99SBarry Smith         l_c = (l/ratiok);
771aa219208SBarry 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\
77247c6ae99SBarry Smith                                             l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c);
773aa219208SBarry 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\
77447c6ae99SBarry Smith                                             j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c);
775aa219208SBarry 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\
77647c6ae99SBarry Smith                                             i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c);
77747c6ae99SBarry Smith 
77847c6ae99SBarry Smith         /*
77947c6ae99SBarry Smith          Only include those interpolation points that are truly
78047c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
78147c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
78247c6ae99SBarry Smith          */
78347c6ae99SBarry Smith         nc       = 0;
78447c6ae99SBarry Smith         col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
78547c6ae99SBarry Smith         cols[nc++] = idx_c[col]/dof;
78647c6ae99SBarry Smith         if (i_c*ratioi != i) {
78747c6ae99SBarry Smith           cols[nc++] = idx_c[col+dof]/dof;
78847c6ae99SBarry Smith         }
78947c6ae99SBarry Smith         if (j_c*ratioj != j) {
79047c6ae99SBarry Smith           cols[nc++] = idx_c[col+m_ghost_c*dof]/dof;
79147c6ae99SBarry Smith         }
79247c6ae99SBarry Smith         if (l_c*ratiok != l) {
79347c6ae99SBarry Smith           cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof;
79447c6ae99SBarry Smith         }
79547c6ae99SBarry Smith         if (j_c*ratioj != j && i_c*ratioi != i) {
79647c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c+1)*dof]/dof;
79747c6ae99SBarry Smith         }
79847c6ae99SBarry Smith         if (j_c*ratioj != j && l_c*ratiok != l) {
79947c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;
80047c6ae99SBarry Smith         }
80147c6ae99SBarry Smith         if (i_c*ratioi != i && l_c*ratiok != l) {
80247c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof;
80347c6ae99SBarry Smith         }
80447c6ae99SBarry Smith         if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) {
80547c6ae99SBarry Smith           cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof;
80647c6ae99SBarry Smith         }
80747c6ae99SBarry Smith         ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr);
80847c6ae99SBarry Smith       }
80947c6ae99SBarry Smith     }
81047c6ae99SBarry Smith   }
81147c6ae99SBarry Smith   ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr);
81247c6ae99SBarry Smith   ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr);
81347c6ae99SBarry Smith   ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr);
81447c6ae99SBarry Smith   ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr);
81547c6ae99SBarry Smith   ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr);
81647c6ae99SBarry Smith   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
81747c6ae99SBarry Smith 
81847c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
819*2adb9dcfSBarry Smith   if (!NEWVERSION) {
820b3bd94feSDave May 
82147c6ae99SBarry Smith     for (l=l_start; l<l_start+p_f; l++) {
82247c6ae99SBarry Smith       for (j=j_start; j<j_start+n_f; j++) {
82347c6ae99SBarry Smith         for (i=i_start; i<i_start+m_f; i++) {
82447c6ae99SBarry Smith           /* convert to local "natural" numbering and then to PETSc global numbering */
82547c6ae99SBarry Smith           row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
82647c6ae99SBarry Smith 
82747c6ae99SBarry Smith           i_c = (i/ratioi);
82847c6ae99SBarry Smith           j_c = (j/ratioj);
82947c6ae99SBarry Smith           l_c = (l/ratiok);
83047c6ae99SBarry Smith 
83147c6ae99SBarry Smith         /*
83247c6ae99SBarry Smith          Only include those interpolation points that are truly
83347c6ae99SBarry Smith          nonzero. Note this is very important for final grid lines
83447c6ae99SBarry Smith          in x and y directions; since they have no right/top neighbors
83547c6ae99SBarry Smith          */
83647c6ae99SBarry Smith           x  = ((double)(i - i_c*ratioi))/((double)ratioi);
83747c6ae99SBarry Smith           y  = ((double)(j - j_c*ratioj))/((double)ratioj);
83847c6ae99SBarry Smith           z  = ((double)(l - l_c*ratiok))/((double)ratiok);
839b3bd94feSDave May 
84047c6ae99SBarry Smith           nc = 0;
84147c6ae99SBarry Smith           /* one left and below; or we are right on it */
84247c6ae99SBarry Smith           col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c)+m_ghost_c*(j_c-j_start_ghost_c)+(i_c-i_start_ghost_c));
84347c6ae99SBarry Smith 
84447c6ae99SBarry Smith           cols[nc] = idx_c[col]/dof;
84547c6ae99SBarry Smith           v[nc++]  = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.));
84647c6ae99SBarry Smith 
84747c6ae99SBarry Smith           if (i_c*ratioi != i) {
84847c6ae99SBarry Smith             cols[nc] = idx_c[col+dof]/dof;
84947c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.));
85047c6ae99SBarry Smith           }
85147c6ae99SBarry Smith 
85247c6ae99SBarry Smith           if (j_c*ratioj != j) {
85347c6ae99SBarry Smith             cols[nc] = idx_c[col+m_ghost_c*dof]/dof;
85447c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.));
85547c6ae99SBarry Smith           }
85647c6ae99SBarry Smith 
85747c6ae99SBarry Smith           if (l_c*ratiok != l) {
85847c6ae99SBarry Smith             cols[nc] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof;
85947c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.));
86047c6ae99SBarry Smith           }
86147c6ae99SBarry Smith 
86247c6ae99SBarry Smith           if (j_c*ratioj != j && i_c*ratioi != i) {
86347c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c+1)*dof]/dof;
86447c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.));
86547c6ae99SBarry Smith           }
86647c6ae99SBarry Smith 
86747c6ae99SBarry Smith           if (j_c*ratioj != j && l_c*ratiok != l) {
86847c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;
86947c6ae99SBarry Smith             v[nc++]  = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.));
87047c6ae99SBarry Smith           }
87147c6ae99SBarry Smith 
87247c6ae99SBarry Smith           if (i_c*ratioi != i && l_c*ratiok != l) {
87347c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof;
87447c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.));
87547c6ae99SBarry Smith           }
87647c6ae99SBarry Smith 
87747c6ae99SBarry Smith           if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) {
87847c6ae99SBarry Smith             cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof;
87947c6ae99SBarry Smith             v[nc++]  = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.));
88047c6ae99SBarry Smith           }
88147c6ae99SBarry Smith           ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr);
88247c6ae99SBarry Smith         }
88347c6ae99SBarry Smith       }
88447c6ae99SBarry Smith     }
885b3bd94feSDave May 
886b3bd94feSDave May   } else {
887b3bd94feSDave May     PetscScalar    *xi,*eta,*zeta;
888b3bd94feSDave May     PetscInt       li,nxi,lj,neta,lk,nzeta,n;
889b3bd94feSDave May     PetscScalar    Ni[8];
890b3bd94feSDave May 
891b3bd94feSDave May     /* compute local coordinate arrays */
892b3bd94feSDave May     nxi   = ratioi + 1;
893b3bd94feSDave May     neta  = ratioj + 1;
894b3bd94feSDave May     nzeta = ratiok + 1;
895b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr);
896b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr);
897b3bd94feSDave May     ierr = PetscMalloc(sizeof(PetscScalar)*nzeta,&zeta);CHKERRQ(ierr);
898b3bd94feSDave May     for (li=0; li<nxi; li++) {
89952218ef2SJed Brown       xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1));
900b3bd94feSDave May     }
901b3bd94feSDave May     for (lj=0; lj<neta; lj++) {
90252218ef2SJed Brown       eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1));
903b3bd94feSDave May     }
904b3bd94feSDave May     for (lk=0; lk<nzeta; lk++) {
90552218ef2SJed Brown       zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1));
906b3bd94feSDave May     }
907b3bd94feSDave May 
908b3bd94feSDave May     for (l=l_start; l<l_start+p_f; l++) {
909b3bd94feSDave May       for (j=j_start; j<j_start+n_f; j++) {
910b3bd94feSDave May         for (i=i_start; i<i_start+m_f; i++) {
911b3bd94feSDave May           /* convert to local "natural" numbering and then to PETSc global numbering */
912b3bd94feSDave May           row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof;
913b3bd94feSDave May 
914b3bd94feSDave May           i_c = (i/ratioi);
915b3bd94feSDave May           j_c = (j/ratioj);
916b3bd94feSDave May           l_c = (l/ratiok);
917b3bd94feSDave May 
918b3bd94feSDave May           /* remainders */
919b3bd94feSDave May           li = i - ratioi * (i/ratioi);
920b3bd94feSDave May           if (i==mx-1){ li = nxi-1; }
921b3bd94feSDave May           lj = j - ratioj * (j/ratioj);
922b3bd94feSDave May           if (j==my-1){ lj = neta-1; }
923b3bd94feSDave May           lk = l - ratiok * (l/ratiok);
924b3bd94feSDave May           if (l==mz-1){ lk = nzeta-1; }
925b3bd94feSDave May 
926b3bd94feSDave May           /* corners */
927b3bd94feSDave May           col     = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c)+m_ghost_c*(j_c-j_start_ghost_c)+(i_c-i_start_ghost_c));
928b3bd94feSDave May           cols[0] = idx_c[col]/dof;
929b3bd94feSDave May           Ni[0]   = 1.0;
930b3bd94feSDave May           if ( (li==0) || (li==nxi-1) ) {
931b3bd94feSDave May             if ( (lj==0) || (lj==neta-1) ) {
932b3bd94feSDave May               if ( (lk==0) || (lk==nzeta-1) ) {
933b3bd94feSDave May                 ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr);
934b3bd94feSDave May                 continue;
935b3bd94feSDave May               }
936b3bd94feSDave May             }
937b3bd94feSDave May           }
938b3bd94feSDave May 
939b3bd94feSDave May           /* edges + interior */
940b3bd94feSDave May           /* remainders */
941b3bd94feSDave May           if (i==mx-1){ i_c--; }
942b3bd94feSDave May           if (j==my-1){ j_c--; }
943b3bd94feSDave May           if (l==mz-1){ l_c--; }
944b3bd94feSDave May 
945b3bd94feSDave May           col      = dof*(m_ghost_c*n_ghost_c*(l_c-l_start_ghost_c) + m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c));
946b3bd94feSDave May           cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */
947b3bd94feSDave May           cols[1] = idx_c[col+dof]/dof; /* one right and below */
948b3bd94feSDave May           cols[2] = idx_c[col+m_ghost_c*dof]/dof;  /* one left and above */
949b3bd94feSDave May           cols[3] = idx_c[col+(m_ghost_c+1)*dof]/dof; /* one right and above */
950b3bd94feSDave May 
951b3bd94feSDave May           cols[4] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof; /* one left and below and front; or we are right on it */
952b3bd94feSDave May           cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; /* one right and below, and front */
953b3bd94feSDave May           cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;/* one left and above and front*/
954b3bd94feSDave May           cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; /* one right and above and front */
955b3bd94feSDave May 
956b3bd94feSDave May           Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]);
957b3bd94feSDave May           Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]);
958b3bd94feSDave May           Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]);
959b3bd94feSDave May           Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]);
960b3bd94feSDave May 
961b3bd94feSDave May           Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]);
962b3bd94feSDave May           Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]);
963b3bd94feSDave May           Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]);
964b3bd94feSDave May           Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]);
965b3bd94feSDave May 
966b3bd94feSDave May           for (n=0; n<8; n++) {
967b3bd94feSDave May             if( PetscAbsScalar(Ni[n])<1.0e-32) { cols[n]=-1; }
968b3bd94feSDave May           }
969b3bd94feSDave May           ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr);
970b3bd94feSDave May 
971b3bd94feSDave May         }
972b3bd94feSDave May       }
973b3bd94feSDave May     }
974b3bd94feSDave May     ierr = PetscFree(xi);CHKERRQ(ierr);
975b3bd94feSDave May     ierr = PetscFree(eta);CHKERRQ(ierr);
976b3bd94feSDave May     ierr = PetscFree(zeta);CHKERRQ(ierr);
977b3bd94feSDave May   }
978b3bd94feSDave May 
97947c6ae99SBarry Smith   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
98047c6ae99SBarry Smith   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
98147c6ae99SBarry Smith 
98247c6ae99SBarry Smith   ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr);
983fcfd50ebSBarry Smith   ierr = MatDestroy(&mat);CHKERRQ(ierr);
98447c6ae99SBarry Smith   PetscFunctionReturn(0);
98547c6ae99SBarry Smith }
98647c6ae99SBarry Smith 
98747c6ae99SBarry Smith #undef __FUNCT__
98894013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA"
9897087cfbeSBarry Smith PetscErrorCode  DMGetInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale)
99047c6ae99SBarry Smith {
99147c6ae99SBarry Smith   PetscErrorCode   ierr;
99247c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
9931321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
994aa219208SBarry Smith   DMDAStencilType  stc,stf;
99547c6ae99SBarry Smith   DM_DA            *ddc = (DM_DA*)dac->data;
99647c6ae99SBarry Smith 
99747c6ae99SBarry Smith   PetscFunctionBegin;
99847c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
99947c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
100047c6ae99SBarry Smith   PetscValidPointer(A,3);
100147c6ae99SBarry Smith   if (scale) PetscValidPointer(scale,4);
100247c6ae99SBarry Smith 
10031321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
10041321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1005aa219208SBarry Smith   if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1006aa219208SBarry Smith   if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1007aa219208SBarry Smith   if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
10081321219cSEthan Coon   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1009aa219208SBarry Smith   if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
101047c6ae99SBarry Smith   if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction");
101147c6ae99SBarry 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");
101247c6ae99SBarry 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");
101347c6ae99SBarry Smith 
1014aa219208SBarry Smith   if (ddc->interptype == DMDA_Q1){
101547c6ae99SBarry Smith     if (dimc == 1){
101694013140SBarry Smith       ierr = DMGetInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr);
101747c6ae99SBarry Smith     } else if (dimc == 2){
101894013140SBarry Smith       ierr = DMGetInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr);
101947c6ae99SBarry Smith     } else if (dimc == 3){
102094013140SBarry Smith       ierr = DMGetInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr);
102185afcc9aSBarry Smith     } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype);
1022aa219208SBarry Smith   } else if (ddc->interptype == DMDA_Q0){
102347c6ae99SBarry Smith     if (dimc == 1){
102494013140SBarry Smith       ierr = DMGetInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr);
102547c6ae99SBarry Smith     } else if (dimc == 2){
102694013140SBarry Smith        ierr = DMGetInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr);
102747c6ae99SBarry Smith     } else if (dimc == 3){
102894013140SBarry Smith        ierr = DMGetInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr);
102985afcc9aSBarry Smith     } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype);
103047c6ae99SBarry Smith   }
103147c6ae99SBarry Smith   if (scale) {
103247c6ae99SBarry Smith     ierr = DMGetInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr);
103347c6ae99SBarry Smith   }
103447c6ae99SBarry Smith   PetscFunctionReturn(0);
103547c6ae99SBarry Smith }
103647c6ae99SBarry Smith 
103747c6ae99SBarry Smith #undef __FUNCT__
10380bb2b966SJungho Lee #define __FUNCT__ "DMGetInjection_DA_1D"
10390bb2b966SJungho Lee PetscErrorCode DMGetInjection_DA_1D(DM dac,DM daf,VecScatter *inject)
10400bb2b966SJungho Lee {
10410bb2b966SJungho Lee     PetscErrorCode   ierr;
10420bb2b966SJungho Lee     PetscInt         i,i_start,m_f,Mx,*idx_f,dof;
10430bb2b966SJungho Lee     PetscInt         m_ghost,*idx_c,m_ghost_c;
10440bb2b966SJungho Lee     PetscInt         row,i_start_ghost,mx,m_c,nc,ratioi;
10450bb2b966SJungho Lee     PetscInt         i_start_c,i_start_ghost_c;
10460bb2b966SJungho Lee     PetscInt         *cols;
10470bb2b966SJungho Lee     DMDABoundaryType bx;
10480bb2b966SJungho Lee     Vec              vecf,vecc;
10490bb2b966SJungho Lee     IS               isf;
10500bb2b966SJungho Lee 
10510bb2b966SJungho Lee     PetscFunctionBegin;
10520bb2b966SJungho Lee     ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr);
10530bb2b966SJungho Lee     ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
10540bb2b966SJungho Lee     if (bx == DMDA_BOUNDARY_PERIODIC) {
10550bb2b966SJungho Lee         ratioi = mx/Mx;
10560bb2b966SJungho 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);
10570bb2b966SJungho Lee     } else {
10580bb2b966SJungho Lee         ratioi = (mx-1)/(Mx-1);
10590bb2b966SJungho 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);
10600bb2b966SJungho Lee     }
10610bb2b966SJungho Lee 
10620bb2b966SJungho Lee     ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr);
10630bb2b966SJungho Lee     ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr);
10640bb2b966SJungho Lee     ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
10650bb2b966SJungho Lee 
10660bb2b966SJungho Lee     ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr);
10670bb2b966SJungho Lee     ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr);
10680bb2b966SJungho Lee     ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
10690bb2b966SJungho Lee 
10700bb2b966SJungho Lee 
10710bb2b966SJungho Lee     /* loop over local fine grid nodes setting interpolation for those*/
10720bb2b966SJungho Lee     nc = 0;
10730bb2b966SJungho Lee     ierr = PetscMalloc(m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr);
10740bb2b966SJungho Lee 
10750bb2b966SJungho Lee 
10760bb2b966SJungho Lee     for (i=i_start_c; i<i_start_c+m_c; i++) {
10770bb2b966SJungho Lee         PetscInt i_f = i*ratioi;
10780bb2b966SJungho Lee 
10790bb2b966SJungho Lee            if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\
10800bb2b966SJungho Lee  i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
10810bb2b966SJungho Lee             row = idx_f[dof*(i_f-i_start_ghost)];
10820bb2b966SJungho Lee             cols[nc++] = row/dof;
10830bb2b966SJungho Lee     }
10840bb2b966SJungho Lee 
10850bb2b966SJungho Lee 
10860bb2b966SJungho Lee     ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
10870bb2b966SJungho Lee     ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
10880bb2b966SJungho Lee     ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
10890bb2b966SJungho Lee     ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr);
10900bb2b966SJungho Lee     ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
10910bb2b966SJungho Lee     ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
10920bb2b966SJungho Lee     ierr = ISDestroy(&isf);CHKERRQ(ierr);
10930bb2b966SJungho Lee     PetscFunctionReturn(0);
10940bb2b966SJungho Lee }
10950bb2b966SJungho Lee 
10960bb2b966SJungho Lee #undef __FUNCT__
109794013140SBarry Smith #define __FUNCT__ "DMGetInjection_DA_2D"
109894013140SBarry Smith PetscErrorCode DMGetInjection_DA_2D(DM dac,DM daf,VecScatter *inject)
109947c6ae99SBarry Smith {
110047c6ae99SBarry Smith   PetscErrorCode   ierr;
110147c6ae99SBarry Smith   PetscInt         i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof;
110247c6ae99SBarry Smith   PetscInt         m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c;
110347c6ae99SBarry Smith   PetscInt         row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj;
1104076202ddSJed Brown   PetscInt         i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c;
110547c6ae99SBarry Smith   PetscInt         *cols;
11061321219cSEthan Coon   DMDABoundaryType bx,by;
110747c6ae99SBarry Smith   Vec              vecf,vecc;
110847c6ae99SBarry Smith   IS               isf;
110947c6ae99SBarry Smith 
111047c6ae99SBarry Smith   PetscFunctionBegin;
11111321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr);
11121321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
11131321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC) {
111447c6ae99SBarry Smith     ratioi = mx/Mx;
111547c6ae99SBarry 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);
111647c6ae99SBarry Smith   } else {
111747c6ae99SBarry Smith     ratioi = (mx-1)/(Mx-1);
111847c6ae99SBarry 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);
111947c6ae99SBarry Smith   }
11201321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC) {
112147c6ae99SBarry Smith     ratioj = my/My;
112247c6ae99SBarry 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);
112347c6ae99SBarry Smith   } else {
112447c6ae99SBarry Smith     ratioj = (my-1)/(My-1);
112547c6ae99SBarry 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);
112647c6ae99SBarry Smith   }
112747c6ae99SBarry Smith 
1128aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr);
1129aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr);
1130aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
113147c6ae99SBarry Smith 
1132aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr);
1133aa219208SBarry Smith   ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr);
1134aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
113547c6ae99SBarry Smith 
113647c6ae99SBarry Smith 
113747c6ae99SBarry Smith   /* loop over local fine grid nodes setting interpolation for those*/
113847c6ae99SBarry Smith   nc = 0;
113947c6ae99SBarry Smith   ierr = PetscMalloc(n_f*m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr);
1140076202ddSJed Brown   for (j=j_start_c; j<j_start_c+n_c; j++) {
1141076202ddSJed Brown     for (i=i_start_c; i<i_start_c+m_c; i++) {
1142076202ddSJed Brown       PetscInt i_f = i*ratioi,j_f = j*ratioj;
1143076202ddSJed 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\
1144076202ddSJed Brown     j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost);
1145076202ddSJed 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\
1146076202ddSJed Brown     i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
1147076202ddSJed Brown       row = idx_f[dof*(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))];
114847c6ae99SBarry Smith       cols[nc++] = row/dof;
114947c6ae99SBarry Smith     }
115047c6ae99SBarry Smith   }
115147c6ae99SBarry Smith 
115247c6ae99SBarry Smith   ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
11539a42bb27SBarry Smith   ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
11549a42bb27SBarry Smith   ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
115547c6ae99SBarry Smith   ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr);
11569a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
11579a42bb27SBarry Smith   ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
1158fcfd50ebSBarry Smith   ierr = ISDestroy(&isf);CHKERRQ(ierr);
115947c6ae99SBarry Smith   PetscFunctionReturn(0);
116047c6ae99SBarry Smith }
116147c6ae99SBarry Smith 
116247c6ae99SBarry Smith #undef __FUNCT__
1163b1757049SJed Brown #define __FUNCT__ "DMGetInjection_DA_3D"
1164b1757049SJed Brown PetscErrorCode DMGetInjection_DA_3D(DM dac,DM daf,VecScatter *inject)
1165b1757049SJed Brown {
1166b1757049SJed Brown   PetscErrorCode   ierr;
1167b1757049SJed Brown   PetscInt         i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz;
1168b1757049SJed Brown   PetscInt         m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c;
1169b1757049SJed Brown   PetscInt         i_start_ghost,j_start_ghost,k_start_ghost;
1170b1757049SJed Brown   PetscInt         mx,my,mz,ratioi,ratioj,ratiok;
1171b1757049SJed Brown   PetscInt         i_start_c,j_start_c,k_start_c;
1172b1757049SJed Brown   PetscInt         m_c,n_c,p_c;
1173b1757049SJed Brown   PetscInt         i_start_ghost_c,j_start_ghost_c,k_start_ghost_c;
1174b1757049SJed Brown   PetscInt         row,nc,dof;
1175b1757049SJed Brown   PetscInt         *idx_c,*idx_f;
1176b1757049SJed Brown   PetscInt         *cols;
11771321219cSEthan Coon   DMDABoundaryType bx,by,bz;
1178b1757049SJed Brown   Vec              vecf,vecc;
1179b1757049SJed Brown   IS               isf;
1180b1757049SJed Brown 
1181b1757049SJed Brown   PetscFunctionBegin;
11821321219cSEthan Coon   ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr);
11831321219cSEthan Coon   ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
1184b1757049SJed Brown 
11851321219cSEthan Coon   if (bx == DMDA_BOUNDARY_PERIODIC){
1186b1757049SJed Brown     ratioi = mx/Mx;
1187b1757049SJed 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);
1188b1757049SJed Brown   } else {
1189b1757049SJed Brown     ratioi = (mx-1)/(Mx-1);
1190b1757049SJed 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);
1191b1757049SJed Brown   }
11921321219cSEthan Coon   if (by == DMDA_BOUNDARY_PERIODIC){
1193b1757049SJed Brown     ratioj = my/My;
1194b1757049SJed 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);
1195b1757049SJed Brown   } else {
1196b1757049SJed Brown     ratioj = (my-1)/(My-1);
1197b1757049SJed 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);
1198b1757049SJed Brown   }
11991321219cSEthan Coon   if (bz == DMDA_BOUNDARY_PERIODIC){
1200b1757049SJed Brown     ratiok = mz/Mz;
1201b1757049SJed 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);
1202b1757049SJed Brown   } else {
1203b1757049SJed Brown     ratiok = (mz-1)/(Mz-1);
1204b1757049SJed 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);
1205b1757049SJed Brown   }
1206b1757049SJed Brown 
1207b1757049SJed Brown   ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
1208b1757049SJed Brown   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
1209b1757049SJed Brown   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
1210b1757049SJed Brown 
1211b1757049SJed Brown   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
1212b1757049SJed 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);
1213b1757049SJed Brown   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
1214b1757049SJed Brown 
1215b1757049SJed Brown 
1216b1757049SJed Brown   /* loop over local fine grid nodes setting interpolation for those*/
1217b1757049SJed Brown   nc = 0;
1218b1757049SJed Brown   ierr = PetscMalloc(n_f*m_f*p_f*sizeof(PetscInt),&cols);CHKERRQ(ierr);
1219b1757049SJed Brown   for (k=k_start_c; k<k_start_c+p_c; k++) {
1220b1757049SJed Brown     for (j=j_start_c; j<j_start_c+n_c; j++) {
1221b1757049SJed Brown       for (i=i_start_c; i<i_start_c+m_c; i++) {
1222b1757049SJed Brown         PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok;
1223b1757049SJed 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  "
1224b1757049SJed Brown                                                                           "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost);
1225b1757049SJed 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  "
1226b1757049SJed Brown                                                                           "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost);
1227b1757049SJed 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  "
1228b1757049SJed Brown                                                                           "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost);
1229b1757049SJed Brown         row = idx_f[dof*(m_ghost*n_ghost*(k_f-k_start_ghost) + m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))];
1230b1757049SJed Brown         cols[nc++] = row/dof;
1231b1757049SJed Brown       }
1232b1757049SJed Brown     }
1233b1757049SJed Brown   }
1234b1757049SJed Brown 
1235b1757049SJed Brown   ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr);
1236b1757049SJed Brown   ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr);
1237b1757049SJed Brown   ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr);
1238b1757049SJed Brown   ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr);
1239b1757049SJed Brown   ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr);
1240b1757049SJed Brown   ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr);
1241fcfd50ebSBarry Smith   ierr = ISDestroy(&isf);CHKERRQ(ierr);
1242b1757049SJed Brown   PetscFunctionReturn(0);
1243b1757049SJed Brown }
1244b1757049SJed Brown 
1245b1757049SJed Brown #undef __FUNCT__
124694013140SBarry Smith #define __FUNCT__ "DMGetInjection_DA"
12477087cfbeSBarry Smith PetscErrorCode  DMGetInjection_DA(DM dac,DM daf,VecScatter *inject)
124847c6ae99SBarry Smith {
124947c6ae99SBarry Smith   PetscErrorCode   ierr;
125047c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf;
12511321219cSEthan Coon   DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf;
1252aa219208SBarry Smith   DMDAStencilType  stc,stf;
125347c6ae99SBarry Smith 
125447c6ae99SBarry Smith   PetscFunctionBegin;
125547c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
125647c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
125747c6ae99SBarry Smith   PetscValidPointer(inject,3);
125847c6ae99SBarry Smith 
12591321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
12601321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1261aa219208SBarry Smith   if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1262aa219208SBarry Smith   if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1263aa219208SBarry Smith   if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
12641321219cSEthan Coon   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1265aa219208SBarry Smith   if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
126647c6ae99SBarry Smith   if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction");
126747c6ae99SBarry Smith   if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction");
126847c6ae99SBarry Smith   if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction");
126947c6ae99SBarry Smith 
12700bb2b966SJungho Lee   if (dimc == 1){
12710bb2b966SJungho Lee     ierr = DMGetInjection_DA_1D(dac,daf,inject);CHKERRQ(ierr);
12720bb2b966SJungho Lee   } else if (dimc == 2) {
127394013140SBarry Smith     ierr = DMGetInjection_DA_2D(dac,daf,inject);CHKERRQ(ierr);
1274b1757049SJed Brown   } else if (dimc == 3) {
1275b1757049SJed Brown     ierr = DMGetInjection_DA_3D(dac,daf,inject);CHKERRQ(ierr);
127647c6ae99SBarry Smith   }
127747c6ae99SBarry Smith   PetscFunctionReturn(0);
127847c6ae99SBarry Smith }
127947c6ae99SBarry Smith 
128047c6ae99SBarry Smith #undef __FUNCT__
128194013140SBarry Smith #define __FUNCT__ "DMGetAggregates_DA"
12827087cfbeSBarry Smith PetscErrorCode  DMGetAggregates_DA(DM dac,DM daf,Mat *rest)
128347c6ae99SBarry Smith {
128447c6ae99SBarry Smith   PetscErrorCode   ierr;
128547c6ae99SBarry Smith   PetscInt         dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc;
128647c6ae99SBarry Smith   PetscInt         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   PetscInt         i,j,l;
129047c6ae99SBarry Smith   PetscInt         i_start,j_start,l_start, m_f,n_f,p_f;
129147c6ae99SBarry Smith   PetscInt         i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost;
129247c6ae99SBarry Smith   PetscInt         *idx_f;
129347c6ae99SBarry Smith   PetscInt         i_c,j_c,l_c;
129447c6ae99SBarry Smith   PetscInt         i_start_c,j_start_c,l_start_c, m_c,n_c,p_c;
129547c6ae99SBarry Smith   PetscInt         i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c;
129647c6ae99SBarry Smith   PetscInt         *idx_c;
129747c6ae99SBarry Smith   PetscInt         d;
129847c6ae99SBarry Smith   PetscInt         a;
129947c6ae99SBarry Smith   PetscInt         max_agg_size;
130047c6ae99SBarry Smith   PetscInt         *fine_nodes;
130147c6ae99SBarry Smith   PetscScalar      *one_vec;
130247c6ae99SBarry Smith   PetscInt         fn_idx;
130347c6ae99SBarry Smith 
130447c6ae99SBarry Smith   PetscFunctionBegin;
130547c6ae99SBarry Smith   PetscValidHeaderSpecific(dac,DM_CLASSID,1);
130647c6ae99SBarry Smith   PetscValidHeaderSpecific(daf,DM_CLASSID,2);
130747c6ae99SBarry Smith   PetscValidPointer(rest,3);
130847c6ae99SBarry Smith 
13091321219cSEthan Coon   ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr);
13101321219cSEthan Coon   ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr);
1311aa219208SBarry Smith   if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr);
1312aa219208SBarry Smith   if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr);
1313aa219208SBarry Smith   if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr);
13141321219cSEthan Coon   if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr);
1315aa219208SBarry Smith   if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr);
131647c6ae99SBarry Smith 
131747c6ae99SBarry 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);
131847c6ae99SBarry 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);
131947c6ae99SBarry 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);
132047c6ae99SBarry Smith 
132147c6ae99SBarry Smith   if (Pc < 0) Pc = 1;
132247c6ae99SBarry Smith   if (Pf < 0) Pf = 1;
132347c6ae99SBarry Smith   if (Nc < 0) Nc = 1;
132447c6ae99SBarry Smith   if (Nf < 0) Nf = 1;
132547c6ae99SBarry Smith 
1326aa219208SBarry Smith   ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr);
1327aa219208SBarry Smith   ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr);
1328aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr);
132947c6ae99SBarry Smith 
1330aa219208SBarry Smith   ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr);
1331aa219208SBarry 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);
1332aa219208SBarry Smith   ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr);
133347c6ae99SBarry Smith 
133447c6ae99SBarry Smith   /*
133547c6ae99SBarry Smith      Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios
133647c6ae99SBarry Smith      for dimension 1 and 2 respectively.
133747c6ae99SBarry Smith      Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1)
133847c6ae99SBarry Smith      and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate.
133947c6ae99SBarry Smith      Each specific dof on the fine grid is mapped to one dof on the coarse grid.
134047c6ae99SBarry Smith   */
134147c6ae99SBarry Smith 
134247c6ae99SBarry Smith   max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1);
134347c6ae99SBarry Smith 
134447c6ae99SBarry Smith   /* create the matrix that will contain the restriction operator */
134547c6ae99SBarry Smith   ierr = MatCreateMPIAIJ( ((PetscObject)daf)->comm, m_c*n_c*p_c*dofc, m_f*n_f*p_f*doff, Mc*Nc*Pc*dofc, Mf*Nf*Pf*doff,
134647c6ae99SBarry Smith 			  max_agg_size, PETSC_NULL, max_agg_size, PETSC_NULL, rest);CHKERRQ(ierr);
134747c6ae99SBarry Smith 
134847c6ae99SBarry Smith   /* store nodes in the fine grid here */
134947c6ae99SBarry Smith   ierr = PetscMalloc2(max_agg_size,PetscScalar, &one_vec,max_agg_size,PetscInt, &fine_nodes);CHKERRQ(ierr);
135047c6ae99SBarry Smith   for(i=0; i<max_agg_size; i++) one_vec[i] = 1.0;
135147c6ae99SBarry Smith 
135247c6ae99SBarry Smith   /* loop over all coarse nodes */
135347c6ae99SBarry Smith   for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) {
135447c6ae99SBarry Smith     for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) {
135547c6ae99SBarry Smith       for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) {
135647c6ae99SBarry Smith 	for(d=0; d<dofc; d++) {
135747c6ae99SBarry Smith 	  /* convert to local "natural" numbering and then to PETSc global numbering */
135847c6ae99SBarry 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;
135947c6ae99SBarry Smith 
136047c6ae99SBarry Smith 	  fn_idx = 0;
136147c6ae99SBarry Smith 	  /* Corresponding fine points are all points (i_f, j_f, l_f) such that
136247c6ae99SBarry Smith 	     i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc
136347c6ae99SBarry Smith 	     (same for other dimensions)
136447c6ae99SBarry Smith 	  */
136547c6ae99SBarry Smith 	  for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) {
136647c6ae99SBarry Smith 	    for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) {
136747c6ae99SBarry Smith 	      for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) {
136847c6ae99SBarry 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;
136947c6ae99SBarry Smith 		fn_idx++;
137047c6ae99SBarry Smith 	      }
137147c6ae99SBarry Smith 	    }
137247c6ae99SBarry Smith 	  }
137347c6ae99SBarry Smith 	  /* add all these points to one aggregate */
137447c6ae99SBarry Smith 	  ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr);
137547c6ae99SBarry Smith 	}
137647c6ae99SBarry Smith       }
137747c6ae99SBarry Smith     }
137847c6ae99SBarry Smith   }
137947c6ae99SBarry Smith   ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr);
138047c6ae99SBarry Smith   ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
138147c6ae99SBarry Smith   ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
138247c6ae99SBarry Smith   PetscFunctionReturn(0);
138347c6ae99SBarry Smith }
1384