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