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