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 14af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/ 1547c6ae99SBarry Smith 16fdc842d1SBarry Smith /* 17fdc842d1SBarry Smith Since the interpolation uses MATMAIJ for dof > 0 we convert request for non-MATAIJ baseded matrices to MATAIJ. 18fdc842d1SBarry Smith This is a bit of a hack, the reason for it is partially because -dm_mat_type defines the 19fdc842d1SBarry Smith matrix type for both the operator matrices and the interpolation matrices so that users 20fdc842d1SBarry Smith can select matrix types of base MATAIJ for accelerators 21fdc842d1SBarry Smith */ 22fdc842d1SBarry Smith static PetscErrorCode ConvertToAIJ(MatType intype,MatType *outtype) 23fdc842d1SBarry Smith { 24fdc842d1SBarry Smith PetscErrorCode ierr; 25fdc842d1SBarry Smith PetscInt i; 26fdc842d1SBarry Smith char const *types[3] = {MATAIJ,MATSEQAIJ,MATMPIAIJ}; 27fdc842d1SBarry Smith PetscBool flg; 28fdc842d1SBarry Smith 29fdc842d1SBarry Smith PetscFunctionBegin; 3033a4d587SStefano Zampini *outtype = MATAIJ; 31fdc842d1SBarry Smith for (i=0; i<3; i++) { 32fdc842d1SBarry Smith ierr = PetscStrbeginswith(intype,types[i],&flg);CHKERRQ(ierr); 33fdc842d1SBarry Smith if (flg) { 34fdc842d1SBarry Smith *outtype = intype; 35fdc842d1SBarry Smith PetscFunctionReturn(0); 36fdc842d1SBarry Smith } 37fdc842d1SBarry Smith } 38fdc842d1SBarry Smith PetscFunctionReturn(0); 39fdc842d1SBarry Smith } 40fdc842d1SBarry Smith 41e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A) 4247c6ae99SBarry Smith { 4347c6ae99SBarry Smith PetscErrorCode ierr; 448ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 458ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 468ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 4747c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 4847c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 4985afcc9aSBarry Smith PetscScalar v[2],x; 5047c6ae99SBarry Smith Mat mat; 51bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 52e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 53fdc842d1SBarry Smith MatType mattype; 5447c6ae99SBarry Smith 5547c6ae99SBarry Smith PetscFunctionBegin; 56ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&bx,NULL,NULL,NULL);CHKERRQ(ierr); 57ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 58bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 5947c6ae99SBarry Smith ratio = mx/Mx; 60*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratio*Mx != mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 6147c6ae99SBarry Smith } else { 6247c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 63*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratio*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 6447c6ae99SBarry Smith } 6547c6ae99SBarry Smith 66ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(daf,&i_start,NULL,NULL,&m_f,NULL,NULL);CHKERRQ(ierr); 67ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(daf,&i_start_ghost,NULL,NULL,&m_ghost,NULL,NULL);CHKERRQ(ierr); 6845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 6945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 7047c6ae99SBarry Smith 71ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(dac,&i_start_c,NULL,NULL,&m_c,NULL,NULL);CHKERRQ(ierr); 72ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,NULL,NULL,&m_ghost_c,NULL,NULL);CHKERRQ(ierr); 7345b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 7445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 7547c6ae99SBarry Smith 7647c6ae99SBarry Smith /* create interpolation matrix */ 77ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 78fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 79fdc842d1SBarry Smith /* 80fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 81fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 82fdc842d1SBarry Smith */ 83fdc842d1SBarry Smith if (dof > 1) { 84b470e4b4SRichard Tran Mills ierr = MatBindToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 85fdc842d1SBarry Smith } 86fdc842d1SBarry Smith #endif 8747c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 88fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 89fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 900298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr); 910298fd71SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,NULL,1,NULL);CHKERRQ(ierr); 9247c6ae99SBarry Smith 9347c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 9485afcc9aSBarry Smith if (!NEWVERSION) { 95b3bd94feSDave May 9647c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 9747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 98e3fbd1f4SBarry Smith row = idx_f[i-i_start_ghost]; 9947c6ae99SBarry Smith 10047c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 101*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_c < i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 10247c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 10347c6ae99SBarry Smith 10447c6ae99SBarry Smith /* 10547c6ae99SBarry Smith Only include those interpolation points that are truly 10647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 10747c6ae99SBarry Smith in x direction; since they have no right neighbor 10847c6ae99SBarry Smith */ 1096712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 11047c6ae99SBarry Smith nc = 0; 11147c6ae99SBarry Smith /* one left and below; or we are right on it */ 112e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 113e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 11447c6ae99SBarry Smith v[nc++] = -x + 1.0; 11547c6ae99SBarry Smith /* one right? */ 11647c6ae99SBarry Smith if (i_c*ratio != i) { 117e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 11847c6ae99SBarry Smith v[nc++] = x; 11947c6ae99SBarry Smith } 12047c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 12147c6ae99SBarry Smith } 122b3bd94feSDave May 123b3bd94feSDave May } else { 124b3bd94feSDave May PetscScalar *xi; 125b3bd94feSDave May PetscInt li,nxi,n; 126b3bd94feSDave May PetscScalar Ni[2]; 127b3bd94feSDave May 128b3bd94feSDave May /* compute local coordinate arrays */ 129b3bd94feSDave May nxi = ratio + 1; 130854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 131b3bd94feSDave May for (li=0; li<nxi; li++) { 13252218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 133b3bd94feSDave May } 134b3bd94feSDave May 135b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 136b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 137e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 138b3bd94feSDave May 139b3bd94feSDave May i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 140*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_c < i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 141b3bd94feSDave May i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 142b3bd94feSDave May 143b3bd94feSDave May /* remainders */ 144b3bd94feSDave May li = i - ratio * (i/ratio); 1458865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 146b3bd94feSDave May 147b3bd94feSDave May /* corners */ 148e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 149e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 150b3bd94feSDave May Ni[0] = 1.0; 151b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 152b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 153b3bd94feSDave May continue; 154b3bd94feSDave May } 155b3bd94feSDave May 156b3bd94feSDave May /* edges + interior */ 157b3bd94feSDave May /* remainders */ 1588865f1eaSKarl Rupp if (i==mx-1) i_c--; 159b3bd94feSDave May 160e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 161e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 162e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; 163b3bd94feSDave May 164b3bd94feSDave May Ni[0] = 0.5*(1.0-xi[li]); 165b3bd94feSDave May Ni[1] = 0.5*(1.0+xi[li]); 166b3bd94feSDave May for (n=0; n<2; n++) { 1678865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 168b3bd94feSDave May } 169b3bd94feSDave May ierr = MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 170b3bd94feSDave May } 171b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 172b3bd94feSDave May } 17345b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 17445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 17547c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17647c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17747c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 178fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 17947c6ae99SBarry Smith PetscFunctionReturn(0); 18047c6ae99SBarry Smith } 18147c6ae99SBarry Smith 182e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A) 18347c6ae99SBarry Smith { 18447c6ae99SBarry Smith PetscErrorCode ierr; 1858ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 1868ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 187e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1888ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 18947c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 19047c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 19147c6ae99SBarry Smith PetscScalar v[2],x; 19247c6ae99SBarry Smith Mat mat; 193bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 194fdc842d1SBarry Smith MatType mattype; 19547c6ae99SBarry Smith 19647c6ae99SBarry Smith PetscFunctionBegin; 197ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&bx,NULL,NULL,NULL);CHKERRQ(ierr); 198ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 199bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 200*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 20147c6ae99SBarry Smith ratio = mx/Mx; 202*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratio*Mx != mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 20347c6ae99SBarry Smith } else { 204*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mx < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 20547c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 206*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratio*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 20747c6ae99SBarry Smith } 20847c6ae99SBarry Smith 209ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(daf,&i_start,NULL,NULL,&m_f,NULL,NULL);CHKERRQ(ierr); 210ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(daf,&i_start_ghost,NULL,NULL,&m_ghost,NULL,NULL);CHKERRQ(ierr); 21145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 21245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 21347c6ae99SBarry Smith 214ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(dac,&i_start_c,NULL,NULL,&m_c,NULL,NULL);CHKERRQ(ierr); 215ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,NULL,NULL,&m_ghost_c,NULL,NULL);CHKERRQ(ierr); 21645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 21745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 21847c6ae99SBarry Smith 21947c6ae99SBarry Smith /* create interpolation matrix */ 220ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 221fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 222fdc842d1SBarry Smith /* 223fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 224fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 225fdc842d1SBarry Smith */ 226fdc842d1SBarry Smith if (dof > 1) { 227b470e4b4SRichard Tran Mills ierr = MatBindToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 228fdc842d1SBarry Smith } 229fdc842d1SBarry Smith #endif 23047c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 231fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 232fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 2330298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr); 2340298fd71SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,NULL,0,NULL);CHKERRQ(ierr); 23547c6ae99SBarry Smith 23647c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 23747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 23847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 239e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 24047c6ae99SBarry Smith 24147c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 24247c6ae99SBarry Smith 24347c6ae99SBarry Smith /* 24447c6ae99SBarry Smith Only include those interpolation points that are truly 24547c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 24647c6ae99SBarry Smith in x direction; since they have no right neighbor 24747c6ae99SBarry Smith */ 2486712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 24947c6ae99SBarry Smith nc = 0; 25047c6ae99SBarry Smith /* one left and below; or we are right on it */ 251e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 252e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 25347c6ae99SBarry Smith v[nc++] = -x + 1.0; 25447c6ae99SBarry Smith /* one right? */ 25547c6ae99SBarry Smith if (i_c*ratio != i) { 256e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 25747c6ae99SBarry Smith v[nc++] = x; 25847c6ae99SBarry Smith } 25947c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 26047c6ae99SBarry Smith } 26145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 26245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 26347c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 26447c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 26547c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 266fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 26747c6ae99SBarry Smith ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr); 26847c6ae99SBarry Smith PetscFunctionReturn(0); 26947c6ae99SBarry Smith } 27047c6ae99SBarry Smith 271e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A) 27247c6ae99SBarry Smith { 27347c6ae99SBarry Smith PetscErrorCode ierr; 2748ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 2758ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 276e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 2778ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 27847c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 27947c6ae99SBarry 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; 28047c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 28147c6ae99SBarry Smith PetscScalar v[4],x,y; 28247c6ae99SBarry Smith Mat mat; 283bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 284fdc842d1SBarry Smith MatType mattype; 28547c6ae99SBarry Smith 28647c6ae99SBarry Smith PetscFunctionBegin; 287ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,&My,NULL,NULL,NULL,NULL,NULL,NULL,&bx,&by,NULL,NULL);CHKERRQ(ierr); 288ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,&my,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 289bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 290*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 29147c6ae99SBarry Smith ratioi = mx/Mx; 292*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*Mx != mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 29347c6ae99SBarry Smith } else { 294*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mx < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 29547c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 296*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 29747c6ae99SBarry Smith } 298bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 299*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 30047c6ae99SBarry Smith ratioj = my/My; 301*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*My != my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 30247c6ae99SBarry Smith } else { 303*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(My < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be greater than 1",My); 30447c6ae99SBarry Smith ratioj = (my-1)/(My-1); 305*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 30647c6ae99SBarry Smith } 30747c6ae99SBarry Smith 308ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(daf,&i_start,&j_start,NULL,&m_f,&n_f,NULL);CHKERRQ(ierr); 309ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,NULL,&m_ghost,&n_ghost,NULL);CHKERRQ(ierr); 31045b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 31145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 31247c6ae99SBarry Smith 313ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,NULL,&m_c,&n_c,NULL);CHKERRQ(ierr); 314ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,NULL,&m_ghost_c,&n_ghost_c,NULL);CHKERRQ(ierr); 31545b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 31645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 31747c6ae99SBarry Smith 31847c6ae99SBarry Smith /* 319aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 32047c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 32147c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 32247c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 32347c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 32447c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 32547c6ae99SBarry Smith 32647c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 32747c6ae99SBarry Smith */ 32855b25c41SPierre Jolivet ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRMPI(ierr); 32955b25c41SPierre Jolivet ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRMPI(ierr); 33055b25c41SPierre Jolivet ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRMPI(ierr); 33147c6ae99SBarry Smith col_scale = size_f/size_c; 33247c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 33347c6ae99SBarry Smith 334ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 33547c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 33647c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 33747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 338e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 33947c6ae99SBarry Smith 34047c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 34147c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 34247c6ae99SBarry Smith 343*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_c < j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 34447c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 345*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_c < i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 34647c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 34747c6ae99SBarry Smith 34847c6ae99SBarry Smith /* 34947c6ae99SBarry Smith Only include those interpolation points that are truly 35047c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 35147c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 35247c6ae99SBarry Smith */ 35347c6ae99SBarry Smith nc = 0; 35447c6ae99SBarry Smith /* one left and below; or we are right on it */ 355e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 356e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 35747c6ae99SBarry Smith /* one right and below */ 358e3fbd1f4SBarry Smith if (i_c*ratioi != i) cols[nc++] = col_shift + idx_c[col+1]; 35947c6ae99SBarry Smith /* one left and above */ 360e3fbd1f4SBarry Smith if (j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+m_ghost_c]; 36147c6ae99SBarry Smith /* one right and above */ 362e3fbd1f4SBarry Smith if (i_c*ratioi != i && j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)]; 36347c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 36447c6ae99SBarry Smith } 36547c6ae99SBarry Smith } 366ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 367fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 368fdc842d1SBarry Smith /* 369fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 370fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 371fdc842d1SBarry Smith */ 372fdc842d1SBarry Smith if (dof > 1) { 373b470e4b4SRichard Tran Mills ierr = MatBindToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 374fdc842d1SBarry Smith } 375fdc842d1SBarry Smith #endif 37647c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 377fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 378fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 37947c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 38047c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 38147c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 38247c6ae99SBarry Smith 38347c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 38485afcc9aSBarry Smith if (!NEWVERSION) { 385b3bd94feSDave May 38647c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 38747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 38847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 389e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 39047c6ae99SBarry Smith 39147c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 39247c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 39347c6ae99SBarry Smith 39447c6ae99SBarry Smith /* 39547c6ae99SBarry Smith Only include those interpolation points that are truly 39647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 39747c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 39847c6ae99SBarry Smith */ 3996712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 4006712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 401b3bd94feSDave May 40247c6ae99SBarry Smith nc = 0; 40347c6ae99SBarry Smith /* one left and below; or we are right on it */ 404e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 405e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 40647c6ae99SBarry Smith v[nc++] = x*y - x - y + 1.0; 40747c6ae99SBarry Smith /* one right and below */ 40847c6ae99SBarry Smith if (i_c*ratioi != i) { 409e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+1]; 41047c6ae99SBarry Smith v[nc++] = -x*y + x; 41147c6ae99SBarry Smith } 41247c6ae99SBarry Smith /* one left and above */ 41347c6ae99SBarry Smith if (j_c*ratioj != j) { 414e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+m_ghost_c]; 41547c6ae99SBarry Smith v[nc++] = -x*y + y; 41647c6ae99SBarry Smith } 41747c6ae99SBarry Smith /* one right and above */ 41847c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 419e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)]; 42047c6ae99SBarry Smith v[nc++] = x*y; 42147c6ae99SBarry Smith } 42247c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 42347c6ae99SBarry Smith } 42447c6ae99SBarry Smith } 425b3bd94feSDave May 426b3bd94feSDave May } else { 427b3bd94feSDave May PetscScalar Ni[4]; 428b3bd94feSDave May PetscScalar *xi,*eta; 429b3bd94feSDave May PetscInt li,nxi,lj,neta; 430b3bd94feSDave May 431b3bd94feSDave May /* compute local coordinate arrays */ 432b3bd94feSDave May nxi = ratioi + 1; 433b3bd94feSDave May neta = ratioj + 1; 434854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 435854ce69bSBarry Smith ierr = PetscMalloc1(neta,&eta);CHKERRQ(ierr); 436b3bd94feSDave May for (li=0; li<nxi; li++) { 43752218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 438b3bd94feSDave May } 439b3bd94feSDave May for (lj=0; lj<neta; lj++) { 44052218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 441b3bd94feSDave May } 442b3bd94feSDave May 443b3bd94feSDave May /* loop over local fine grid nodes setting interpolation for those*/ 444b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 445b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 446b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 447e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 448b3bd94feSDave May 449b3bd94feSDave May i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 450b3bd94feSDave May j_c = (j/ratioj); /* coarse grid node below fine grid node */ 451b3bd94feSDave May 452b3bd94feSDave May /* remainders */ 453b3bd94feSDave May li = i - ratioi * (i/ratioi); 4548865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 455b3bd94feSDave May lj = j - ratioj * (j/ratioj); 4568865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 457b3bd94feSDave May 458b3bd94feSDave May /* corners */ 459e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 460e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 461b3bd94feSDave May Ni[0] = 1.0; 462b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 463b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 464b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 465b3bd94feSDave May continue; 466b3bd94feSDave May } 467b3bd94feSDave May } 468b3bd94feSDave May 469b3bd94feSDave May /* edges + interior */ 470b3bd94feSDave May /* remainders */ 4718865f1eaSKarl Rupp if (i==mx-1) i_c--; 4728865f1eaSKarl Rupp if (j==my-1) j_c--; 473b3bd94feSDave May 474e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 475e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 476e3fbd1f4SBarry Smith cols[1] = col_shift + idx_c[col+1]; /* right, below */ 477e3fbd1f4SBarry Smith cols[2] = col_shift + idx_c[col+m_ghost_c]; /* left, above */ 478e3fbd1f4SBarry Smith cols[3] = col_shift + idx_c[col+(m_ghost_c+1)]; /* right, above */ 479b3bd94feSDave May 480b3bd94feSDave May Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]); 481b3bd94feSDave May Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]); 482b3bd94feSDave May Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]); 483b3bd94feSDave May Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]); 484b3bd94feSDave May 485b3bd94feSDave May nc = 0; 4868865f1eaSKarl Rupp if (PetscAbsScalar(Ni[0])<1.0e-32) cols[0]=-1; 4878865f1eaSKarl Rupp if (PetscAbsScalar(Ni[1])<1.0e-32) cols[1]=-1; 4888865f1eaSKarl Rupp if (PetscAbsScalar(Ni[2])<1.0e-32) cols[2]=-1; 4898865f1eaSKarl Rupp if (PetscAbsScalar(Ni[3])<1.0e-32) cols[3]=-1; 490b3bd94feSDave May 491b3bd94feSDave May ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 492b3bd94feSDave May } 493b3bd94feSDave May } 494b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 495b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 496b3bd94feSDave May } 49745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 49845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 49947c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 50047c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 50147c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 502fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 50347c6ae99SBarry Smith PetscFunctionReturn(0); 50447c6ae99SBarry Smith } 50547c6ae99SBarry Smith 50647c6ae99SBarry Smith /* 50747c6ae99SBarry Smith Contributed by Andrei Draganescu <aidraga@sandia.gov> 50847c6ae99SBarry Smith */ 509e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A) 51047c6ae99SBarry Smith { 51147c6ae99SBarry Smith PetscErrorCode ierr; 5128ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 5138ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 514e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 5158ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 51647c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 51747c6ae99SBarry 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; 51847c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 51947c6ae99SBarry Smith PetscScalar v[4]; 52047c6ae99SBarry Smith Mat mat; 521bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 522fdc842d1SBarry Smith MatType mattype; 52347c6ae99SBarry Smith 52447c6ae99SBarry Smith PetscFunctionBegin; 525ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,&My,NULL,NULL,NULL,NULL,NULL,NULL,&bx,&by,NULL,NULL);CHKERRQ(ierr); 526ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,&my,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 527*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 528*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 52947c6ae99SBarry Smith ratioi = mx/Mx; 53047c6ae99SBarry Smith ratioj = my/My; 531*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*Mx != mx,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 532*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*My != my,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 533*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi != 2,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2"); 534*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj != 2,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2"); 53547c6ae99SBarry Smith 536ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(daf,&i_start,&j_start,NULL,&m_f,&n_f,NULL);CHKERRQ(ierr); 537ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,NULL,&m_ghost,&n_ghost,NULL);CHKERRQ(ierr); 53845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 53945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 54047c6ae99SBarry Smith 541ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,NULL,&m_c,&n_c,NULL);CHKERRQ(ierr); 542ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,NULL,&m_ghost_c,&n_ghost_c,NULL);CHKERRQ(ierr); 54345b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 54445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 54547c6ae99SBarry Smith 54647c6ae99SBarry Smith /* 547aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 54847c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 54947c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 55047c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 55147c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 55247c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 55347c6ae99SBarry Smith 55447c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 55547c6ae99SBarry Smith */ 55655b25c41SPierre Jolivet ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRMPI(ierr); 55755b25c41SPierre Jolivet ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRMPI(ierr); 55855b25c41SPierre Jolivet ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRMPI(ierr); 55947c6ae99SBarry Smith col_scale = size_f/size_c; 56047c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 56147c6ae99SBarry Smith 562ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 56347c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 56447c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 56547c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 566e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 56747c6ae99SBarry Smith 56847c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 56947c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 57047c6ae99SBarry Smith 571*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_c < j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 57247c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 573*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_c < i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 57447c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 57547c6ae99SBarry Smith 57647c6ae99SBarry Smith /* 57747c6ae99SBarry Smith Only include those interpolation points that are truly 57847c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 57947c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 58047c6ae99SBarry Smith */ 58147c6ae99SBarry Smith nc = 0; 58247c6ae99SBarry Smith /* one left and below; or we are right on it */ 583e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 584e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 58547c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 58647c6ae99SBarry Smith } 58747c6ae99SBarry Smith } 588ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 589fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 590fdc842d1SBarry Smith /* 591fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 592fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 593fdc842d1SBarry Smith */ 594fdc842d1SBarry Smith if (dof > 1) { 595b470e4b4SRichard Tran Mills ierr = MatBindToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 596fdc842d1SBarry Smith } 597fdc842d1SBarry Smith #endif 59847c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 599fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 600fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 60147c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 60247c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 60347c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 60447c6ae99SBarry Smith 60547c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 60647c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 60747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 60847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 609e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 61047c6ae99SBarry Smith 61147c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 61247c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 61347c6ae99SBarry Smith nc = 0; 61447c6ae99SBarry Smith /* one left and below; or we are right on it */ 615e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 616e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 61747c6ae99SBarry Smith v[nc++] = 1.0; 61847c6ae99SBarry Smith 61947c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 62047c6ae99SBarry Smith } 62147c6ae99SBarry Smith } 62245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 62345b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 62447c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 62547c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 62647c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 627fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 62847c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr); 62947c6ae99SBarry Smith PetscFunctionReturn(0); 63047c6ae99SBarry Smith } 63147c6ae99SBarry Smith 63247c6ae99SBarry Smith /* 63347c6ae99SBarry Smith Contributed by Jianming Yang <jianming-yang@uiowa.edu> 63447c6ae99SBarry Smith */ 635e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A) 63647c6ae99SBarry Smith { 63747c6ae99SBarry Smith PetscErrorCode ierr; 6388ea3bf28SBarry Smith PetscInt i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,dof; 6398ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 640e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 6418ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz; 64247c6ae99SBarry 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; 64347c6ae99SBarry 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; 64447c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 64547c6ae99SBarry Smith PetscScalar v[8]; 64647c6ae99SBarry Smith Mat mat; 647bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 648fdc842d1SBarry Smith MatType mattype; 64947c6ae99SBarry Smith 65047c6ae99SBarry Smith PetscFunctionBegin; 651ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,&My,&Mz,NULL,NULL,NULL,NULL,NULL,&bx,&by,&bz,NULL);CHKERRQ(ierr); 652*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 653*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 654*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 655ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,&my,&mz,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 65647c6ae99SBarry Smith ratioi = mx/Mx; 65747c6ae99SBarry Smith ratioj = my/My; 65847c6ae99SBarry Smith ratiol = mz/Mz; 659*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*Mx != mx,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 660*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*My != my,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 661*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiol*Mz != mz,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z"); 662*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi != 2 && ratioi != 1,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2"); 663*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj != 2 && ratioj != 1,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2"); 664*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiol != 2 && ratiol != 1,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2"); 66547c6ae99SBarry Smith 666aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 667aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 66845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 66945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 67047c6ae99SBarry Smith 671aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 672aa219208SBarry 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); 67345b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 67445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 675e3fbd1f4SBarry Smith 67647c6ae99SBarry Smith /* 677aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 67847c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 67947c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 68047c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 68147c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 68247c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 68347c6ae99SBarry Smith 68447c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 68547c6ae99SBarry Smith */ 68655b25c41SPierre Jolivet ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRMPI(ierr); 68755b25c41SPierre Jolivet ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRMPI(ierr); 68855b25c41SPierre Jolivet ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRMPI(ierr); 68947c6ae99SBarry Smith col_scale = size_f/size_c; 69047c6ae99SBarry Smith col_shift = Mx*My*Mz*(rank_f/size_c); 69147c6ae99SBarry Smith 692ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 69347c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 69447c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 69547c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 69647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 697e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 69847c6ae99SBarry Smith 69947c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 70047c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 70147c6ae99SBarry Smith l_c = (l/ratiol); 70247c6ae99SBarry Smith 703*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(l_c < l_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70447c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 705*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_c < j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70647c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 707*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_c < i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70847c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 70947c6ae99SBarry Smith 71047c6ae99SBarry Smith /* 71147c6ae99SBarry Smith Only include those interpolation points that are truly 71247c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 71347c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 71447c6ae99SBarry Smith */ 71547c6ae99SBarry Smith nc = 0; 71647c6ae99SBarry Smith /* one left and below; or we are right on it */ 717e3fbd1f4SBarry 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)); 718e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 71947c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 72047c6ae99SBarry Smith } 72147c6ae99SBarry Smith } 72247c6ae99SBarry Smith } 723ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 724fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 725fdc842d1SBarry Smith /* 726fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 727fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 728fdc842d1SBarry Smith */ 729fdc842d1SBarry Smith if (dof > 1) { 730b470e4b4SRichard Tran Mills ierr = MatBindToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 731fdc842d1SBarry Smith } 732fdc842d1SBarry Smith #endif 73347c6ae99SBarry 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); 734fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 735fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 73647c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 73747c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 73847c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 73947c6ae99SBarry Smith 74047c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 74147c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 74247c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 74347c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 74447c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 745e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 74647c6ae99SBarry Smith 74747c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 74847c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 74947c6ae99SBarry Smith l_c = (l/ratiol); 75047c6ae99SBarry Smith nc = 0; 75147c6ae99SBarry Smith /* one left and below; or we are right on it */ 752e3fbd1f4SBarry 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)); 753e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 75447c6ae99SBarry Smith v[nc++] = 1.0; 75547c6ae99SBarry Smith 75647c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 75747c6ae99SBarry Smith } 75847c6ae99SBarry Smith } 75947c6ae99SBarry Smith } 76045b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 76145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 76247c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 76347c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 76447c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 765fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 76647c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr); 76747c6ae99SBarry Smith PetscFunctionReturn(0); 76847c6ae99SBarry Smith } 76947c6ae99SBarry Smith 770e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A) 77147c6ae99SBarry Smith { 77247c6ae99SBarry Smith PetscErrorCode ierr; 7738ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof,l; 7748ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 775e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 7768ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,Mz,mz; 77747c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok; 77847c6ae99SBarry Smith PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 77947c6ae99SBarry Smith PetscInt l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c; 78047c6ae99SBarry Smith PetscInt l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz; 78147c6ae99SBarry Smith PetscScalar v[8],x,y,z; 78247c6ae99SBarry Smith Mat mat; 783bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 784fdc842d1SBarry Smith MatType mattype; 78547c6ae99SBarry Smith 78647c6ae99SBarry Smith PetscFunctionBegin; 787ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,&My,&Mz,NULL,NULL,NULL,NULL,NULL,&bx,&by,&bz,NULL);CHKERRQ(ierr); 788ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,&my,&mz,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 78947c6ae99SBarry Smith if (mx == Mx) { 79047c6ae99SBarry Smith ratioi = 1; 791bff4a2f0SMatthew G. Knepley } else if (bx == DM_BOUNDARY_PERIODIC) { 792*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 79347c6ae99SBarry Smith ratioi = mx/Mx; 794*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*Mx != mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 79547c6ae99SBarry Smith } else { 796*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mx < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 79747c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 798*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 79947c6ae99SBarry Smith } 80047c6ae99SBarry Smith if (my == My) { 80147c6ae99SBarry Smith ratioj = 1; 802bff4a2f0SMatthew G. Knepley } else if (by == DM_BOUNDARY_PERIODIC) { 803*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 80447c6ae99SBarry Smith ratioj = my/My; 805*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*My != my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 80647c6ae99SBarry Smith } else { 807*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(My < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be greater than 1",My); 80847c6ae99SBarry Smith ratioj = (my-1)/(My-1); 809*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 81047c6ae99SBarry Smith } 81147c6ae99SBarry Smith if (mz == Mz) { 81247c6ae99SBarry Smith ratiok = 1; 813bff4a2f0SMatthew G. Knepley } else if (bz == DM_BOUNDARY_PERIODIC) { 814*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(!Mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 81547c6ae99SBarry Smith ratiok = mz/Mz; 816*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiok*Mz != mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D Mz %D",mz,Mz); 81747c6ae99SBarry Smith } else { 818*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mz < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be greater than 1",Mz); 81947c6ae99SBarry Smith ratiok = (mz-1)/(Mz-1); 820*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiok*(Mz-1) != mz-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 82147c6ae99SBarry Smith } 82247c6ae99SBarry Smith 823aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 824aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 82545b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 82645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 82747c6ae99SBarry Smith 828aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 829aa219208SBarry 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); 83045b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 83145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 83247c6ae99SBarry Smith 83347c6ae99SBarry Smith /* create interpolation matrix, determining exact preallocation */ 834ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)dac),m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 83547c6ae99SBarry Smith /* loop over local fine grid nodes counting interpolating points */ 83647c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 83747c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 83847c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 83947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 840e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 84147c6ae99SBarry Smith i_c = (i/ratioi); 84247c6ae99SBarry Smith j_c = (j/ratioj); 84347c6ae99SBarry Smith l_c = (l/ratiok); 844*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(l_c < l_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84547c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 846*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_c < j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84747c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 848*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_c < i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84947c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 85047c6ae99SBarry Smith 85147c6ae99SBarry Smith /* 85247c6ae99SBarry Smith Only include those interpolation points that are truly 85347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 85447c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 85547c6ae99SBarry Smith */ 85647c6ae99SBarry Smith nc = 0; 857e3fbd1f4SBarry 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)); 858e3fbd1f4SBarry Smith cols[nc++] = idx_c[col]; 85947c6ae99SBarry Smith if (i_c*ratioi != i) { 860e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+1]; 86147c6ae99SBarry Smith } 86247c6ae99SBarry Smith if (j_c*ratioj != j) { 863e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c]; 86447c6ae99SBarry Smith } 86547c6ae99SBarry Smith if (l_c*ratiok != l) { 866e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c]; 86747c6ae99SBarry Smith } 86847c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 869e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c+1)]; 87047c6ae99SBarry Smith } 87147c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 872e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 87347c6ae99SBarry Smith } 87447c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 875e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 87647c6ae99SBarry Smith } 87747c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 878e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 87947c6ae99SBarry Smith } 88047c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 88147c6ae99SBarry Smith } 88247c6ae99SBarry Smith } 88347c6ae99SBarry Smith } 884ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 885fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 886fdc842d1SBarry Smith /* 887fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 888fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 889fdc842d1SBarry Smith */ 890fdc842d1SBarry Smith if (dof > 1) { 891b470e4b4SRichard Tran Mills ierr = MatBindToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 892fdc842d1SBarry Smith } 893fdc842d1SBarry Smith #endif 89447c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr); 895fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 896fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 89747c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 89847c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 89947c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 90047c6ae99SBarry Smith 90147c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 9022adb9dcfSBarry Smith if (!NEWVERSION) { 903b3bd94feSDave May 90447c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 90547c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 90647c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 90747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 908e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 90947c6ae99SBarry Smith 91047c6ae99SBarry Smith i_c = (i/ratioi); 91147c6ae99SBarry Smith j_c = (j/ratioj); 91247c6ae99SBarry Smith l_c = (l/ratiok); 91347c6ae99SBarry Smith 91447c6ae99SBarry Smith /* 91547c6ae99SBarry Smith Only include those interpolation points that are truly 91647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 91747c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 91847c6ae99SBarry Smith */ 9196712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 9206712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 9216712e2f1SBarry Smith z = ((PetscReal)(l - l_c*ratiok))/((PetscReal)ratiok); 922b3bd94feSDave May 92347c6ae99SBarry Smith nc = 0; 92447c6ae99SBarry Smith /* one left and below; or we are right on it */ 925e3fbd1f4SBarry 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)); 92647c6ae99SBarry Smith 927e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 92847c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 92947c6ae99SBarry Smith 93047c6ae99SBarry Smith if (i_c*ratioi != i) { 931e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 93247c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 93347c6ae99SBarry Smith } 93447c6ae99SBarry Smith 93547c6ae99SBarry Smith if (j_c*ratioj != j) { 936e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c]; 93747c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 93847c6ae99SBarry Smith } 93947c6ae99SBarry Smith 94047c6ae99SBarry Smith if (l_c*ratiok != l) { 941e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c*n_ghost_c]; 94247c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 94347c6ae99SBarry Smith } 94447c6ae99SBarry Smith 94547c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 946e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c+1)]; 94747c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 94847c6ae99SBarry Smith } 94947c6ae99SBarry Smith 95047c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 951e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 95247c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 95347c6ae99SBarry Smith } 95447c6ae99SBarry Smith 95547c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 956e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 95747c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 95847c6ae99SBarry Smith } 95947c6ae99SBarry Smith 96047c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 961e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 96247c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 96347c6ae99SBarry Smith } 96447c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 96547c6ae99SBarry Smith } 96647c6ae99SBarry Smith } 96747c6ae99SBarry Smith } 968b3bd94feSDave May 969b3bd94feSDave May } else { 970b3bd94feSDave May PetscScalar *xi,*eta,*zeta; 971b3bd94feSDave May PetscInt li,nxi,lj,neta,lk,nzeta,n; 972b3bd94feSDave May PetscScalar Ni[8]; 973b3bd94feSDave May 974b3bd94feSDave May /* compute local coordinate arrays */ 975b3bd94feSDave May nxi = ratioi + 1; 976b3bd94feSDave May neta = ratioj + 1; 977b3bd94feSDave May nzeta = ratiok + 1; 978854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 979854ce69bSBarry Smith ierr = PetscMalloc1(neta,&eta);CHKERRQ(ierr); 980854ce69bSBarry Smith ierr = PetscMalloc1(nzeta,&zeta);CHKERRQ(ierr); 9818865f1eaSKarl Rupp for (li=0; li<nxi; li++) xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 9828865f1eaSKarl Rupp for (lj=0; lj<neta; lj++) eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 9838865f1eaSKarl Rupp for (lk=0; lk<nzeta; lk++) zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1)); 984b3bd94feSDave May 985b3bd94feSDave May for (l=l_start; l<l_start+p_f; l++) { 986b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 987b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 988b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 989e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 990b3bd94feSDave May 991b3bd94feSDave May i_c = (i/ratioi); 992b3bd94feSDave May j_c = (j/ratioj); 993b3bd94feSDave May l_c = (l/ratiok); 994b3bd94feSDave May 995b3bd94feSDave May /* remainders */ 996b3bd94feSDave May li = i - ratioi * (i/ratioi); 9978865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 998b3bd94feSDave May lj = j - ratioj * (j/ratioj); 9998865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 1000b3bd94feSDave May lk = l - ratiok * (l/ratiok); 10018865f1eaSKarl Rupp if (l==mz-1) lk = nzeta-1; 1002b3bd94feSDave May 1003b3bd94feSDave May /* corners */ 1004e3fbd1f4SBarry 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)); 1005e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 1006b3bd94feSDave May Ni[0] = 1.0; 1007b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 1008b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 1009b3bd94feSDave May if ((lk==0) || (lk==nzeta-1)) { 1010b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 1011b3bd94feSDave May continue; 1012b3bd94feSDave May } 1013b3bd94feSDave May } 1014b3bd94feSDave May } 1015b3bd94feSDave May 1016b3bd94feSDave May /* edges + interior */ 1017b3bd94feSDave May /* remainders */ 10188865f1eaSKarl Rupp if (i==mx-1) i_c--; 10198865f1eaSKarl Rupp if (j==my-1) j_c--; 10208865f1eaSKarl Rupp if (l==mz-1) l_c--; 1021b3bd94feSDave May 1022e3fbd1f4SBarry 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)); 1023e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 1024e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; /* one right and below */ 1025e3fbd1f4SBarry Smith cols[2] = idx_c[col+m_ghost_c]; /* one left and above */ 1026e3fbd1f4SBarry Smith cols[3] = idx_c[col+(m_ghost_c+1)]; /* one right and above */ 1027b3bd94feSDave May 1028e3fbd1f4SBarry Smith cols[4] = idx_c[col+m_ghost_c*n_ghost_c]; /* one left and below and front; or we are right on it */ 1029e3fbd1f4SBarry Smith cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; /* one right and below, and front */ 1030e3fbd1f4SBarry Smith cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; /* one left and above and front*/ 1031e3fbd1f4SBarry Smith cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; /* one right and above and front */ 1032b3bd94feSDave May 1033b3bd94feSDave May Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 1034b3bd94feSDave May Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 1035b3bd94feSDave May Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 1036b3bd94feSDave May Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 1037b3bd94feSDave May 1038b3bd94feSDave May Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 1039b3bd94feSDave May Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 1040b3bd94feSDave May Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 1041b3bd94feSDave May Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 1042b3bd94feSDave May 1043b3bd94feSDave May for (n=0; n<8; n++) { 10448865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 1045b3bd94feSDave May } 1046b3bd94feSDave May ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 1047b3bd94feSDave May 1048b3bd94feSDave May } 1049b3bd94feSDave May } 1050b3bd94feSDave May } 1051b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 1052b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 1053b3bd94feSDave May ierr = PetscFree(zeta);CHKERRQ(ierr); 1054b3bd94feSDave May } 105545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 105645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 105747c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 105847c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 105947c6ae99SBarry Smith 106047c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 1061fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 106247c6ae99SBarry Smith PetscFunctionReturn(0); 106347c6ae99SBarry Smith } 106447c6ae99SBarry Smith 1065e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale) 106647c6ae99SBarry Smith { 106747c6ae99SBarry Smith PetscErrorCode ierr; 106847c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1069bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1070aa219208SBarry Smith DMDAStencilType stc,stf; 107147c6ae99SBarry Smith DM_DA *ddc = (DM_DA*)dac->data; 107247c6ae99SBarry Smith 107347c6ae99SBarry Smith PetscFunctionBegin; 107447c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 107547c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 107647c6ae99SBarry Smith PetscValidPointer(A,3); 107747c6ae99SBarry Smith if (scale) PetscValidPointer(scale,4); 107847c6ae99SBarry Smith 10791321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 10801321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1081*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc != dimf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1082*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dofc != doff,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1083*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(sc != sf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 1084*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(bxc != bxf || byc != byf || bzc != bzf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1085*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(stc != stf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 1086*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mc < 2 && Mf > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 1087*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 1 && Nc < 2 && Nf > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 1088*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 2 && Pc < 2 && Pf > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 108947c6ae99SBarry Smith 1090aa219208SBarry Smith if (ddc->interptype == DMDA_Q1) { 109147c6ae99SBarry Smith if (dimc == 1) { 1092e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr); 109347c6ae99SBarry Smith } else if (dimc == 2) { 1094e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr); 109547c6ae99SBarry Smith } else if (dimc == 3) { 1096e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr); 109798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 1098aa219208SBarry Smith } else if (ddc->interptype == DMDA_Q0) { 109947c6ae99SBarry Smith if (dimc == 1) { 1100e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr); 110147c6ae99SBarry Smith } else if (dimc == 2) { 1102e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr); 110347c6ae99SBarry Smith } else if (dimc == 3) { 1104e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr); 110598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 110647c6ae99SBarry Smith } 110747c6ae99SBarry Smith if (scale) { 1108e727c939SJed Brown ierr = DMCreateInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr); 110947c6ae99SBarry Smith } 111047c6ae99SBarry Smith PetscFunctionReturn(0); 111147c6ae99SBarry Smith } 111247c6ae99SBarry Smith 1113e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_1D(DM dac,DM daf,VecScatter *inject) 11140bb2b966SJungho Lee { 11150bb2b966SJungho Lee PetscErrorCode ierr; 11168ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx,dof; 11178ea3bf28SBarry Smith const PetscInt *idx_f; 1118e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f; 11198ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 11200bb2b966SJungho Lee PetscInt row,i_start_ghost,mx,m_c,nc,ratioi; 11210bb2b966SJungho Lee PetscInt i_start_c,i_start_ghost_c; 11220bb2b966SJungho Lee PetscInt *cols; 1123bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 11240bb2b966SJungho Lee Vec vecf,vecc; 11250bb2b966SJungho Lee IS isf; 11260bb2b966SJungho Lee 11270bb2b966SJungho Lee PetscFunctionBegin; 1128ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&bx,NULL,NULL,NULL);CHKERRQ(ierr); 1129ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 1130bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 11310bb2b966SJungho Lee ratioi = mx/Mx; 1132*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*Mx != mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 11330bb2b966SJungho Lee } else { 11340bb2b966SJungho Lee ratioi = (mx-1)/(Mx-1); 1135*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 11360bb2b966SJungho Lee } 11370bb2b966SJungho Lee 1138ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(daf,&i_start,NULL,NULL,&m_f,NULL,NULL);CHKERRQ(ierr); 1139ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(daf,&i_start_ghost,NULL,NULL,&m_ghost,NULL,NULL);CHKERRQ(ierr); 114045b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 114145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 11420bb2b966SJungho Lee 1143ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(dac,&i_start_c,NULL,NULL,&m_c,NULL,NULL);CHKERRQ(ierr); 1144ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,NULL,NULL,&m_ghost_c,NULL,NULL);CHKERRQ(ierr); 11450bb2b966SJungho Lee 11460bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 11470bb2b966SJungho Lee nc = 0; 1148785e854fSJed Brown ierr = PetscMalloc1(m_f,&cols);CHKERRQ(ierr); 11490bb2b966SJungho Lee 11500bb2b966SJungho Lee for (i=i_start_c; i<i_start_c+m_c; i++) { 11510bb2b966SJungho Lee PetscInt i_f = i*ratioi; 11520bb2b966SJungho Lee 1153*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost,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); 11548865f1eaSKarl Rupp 1155e3fbd1f4SBarry Smith row = idx_f[(i_f-i_start_ghost)]; 1156e3fbd1f4SBarry Smith cols[nc++] = row; 11570bb2b966SJungho Lee } 11580bb2b966SJungho Lee 115945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1160ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 11610bb2b966SJungho Lee ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 11620bb2b966SJungho Lee ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 11639448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 11640bb2b966SJungho Lee ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 11650bb2b966SJungho Lee ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 11660bb2b966SJungho Lee ierr = ISDestroy(&isf);CHKERRQ(ierr); 11670bb2b966SJungho Lee PetscFunctionReturn(0); 11680bb2b966SJungho Lee } 11690bb2b966SJungho Lee 1170e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject) 117147c6ae99SBarry Smith { 117247c6ae99SBarry Smith PetscErrorCode ierr; 11738ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 11748ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1175e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 11768ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c; 117747c6ae99SBarry Smith PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; 1178076202ddSJed Brown PetscInt i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 117947c6ae99SBarry Smith PetscInt *cols; 1180bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 118147c6ae99SBarry Smith Vec vecf,vecc; 118247c6ae99SBarry Smith IS isf; 118347c6ae99SBarry Smith 118447c6ae99SBarry Smith PetscFunctionBegin; 1185ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,&My,NULL,NULL,NULL,NULL,NULL,NULL,&bx,&by,NULL,NULL);CHKERRQ(ierr); 1186ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,&my,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 1187bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 118847c6ae99SBarry Smith ratioi = mx/Mx; 1189*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*Mx != mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 119047c6ae99SBarry Smith } else { 119147c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 1192*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 119347c6ae99SBarry Smith } 1194bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 119547c6ae99SBarry Smith ratioj = my/My; 1196*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*My != my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 119747c6ae99SBarry Smith } else { 119847c6ae99SBarry Smith ratioj = (my-1)/(My-1); 1199*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 120047c6ae99SBarry Smith } 120147c6ae99SBarry Smith 1202ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(daf,&i_start,&j_start,NULL,&m_f,&n_f,NULL);CHKERRQ(ierr); 1203ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,NULL,&m_ghost,&n_ghost,NULL);CHKERRQ(ierr); 120445b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 120545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 120647c6ae99SBarry Smith 1207ea78f98cSLisandro Dalcin ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,NULL,&m_c,&n_c,NULL);CHKERRQ(ierr); 1208ea78f98cSLisandro Dalcin ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,NULL,&m_ghost_c,&n_ghost_c,NULL);CHKERRQ(ierr); 120945b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 121045b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 121147c6ae99SBarry Smith 121247c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 121347c6ae99SBarry Smith nc = 0; 1214785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f,&cols);CHKERRQ(ierr); 1215076202ddSJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1216076202ddSJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1217076202ddSJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj; 1218*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1219076202ddSJed Brown j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1220*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1221076202ddSJed Brown i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1222e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 1223e3fbd1f4SBarry Smith cols[nc++] = row; 122447c6ae99SBarry Smith } 122547c6ae99SBarry Smith } 122645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 122745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 122847c6ae99SBarry Smith 1229ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 12309a42bb27SBarry Smith ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 12319a42bb27SBarry Smith ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 12329448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 12339a42bb27SBarry Smith ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 12349a42bb27SBarry Smith ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1235fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 123647c6ae99SBarry Smith PetscFunctionReturn(0); 123747c6ae99SBarry Smith } 123847c6ae99SBarry Smith 1239e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject) 1240b1757049SJed Brown { 1241b1757049SJed Brown PetscErrorCode ierr; 1242b1757049SJed Brown PetscInt i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz; 1243b1757049SJed Brown PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c; 1244b1757049SJed Brown PetscInt i_start_ghost,j_start_ghost,k_start_ghost; 1245b1757049SJed Brown PetscInt mx,my,mz,ratioi,ratioj,ratiok; 1246b1757049SJed Brown PetscInt i_start_c,j_start_c,k_start_c; 1247b1757049SJed Brown PetscInt m_c,n_c,p_c; 1248b1757049SJed Brown PetscInt i_start_ghost_c,j_start_ghost_c,k_start_ghost_c; 1249b1757049SJed Brown PetscInt row,nc,dof; 12508ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1251e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1252b1757049SJed Brown PetscInt *cols; 1253bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 1254b1757049SJed Brown Vec vecf,vecc; 1255b1757049SJed Brown IS isf; 1256b1757049SJed Brown 1257b1757049SJed Brown PetscFunctionBegin; 1258ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(dac,NULL,&Mx,&My,&Mz,NULL,NULL,NULL,NULL,NULL,&bx,&by,&bz,NULL);CHKERRQ(ierr); 1259ea78f98cSLisandro Dalcin ierr = DMDAGetInfo(daf,NULL,&mx,&my,&mz,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 1260b1757049SJed Brown 1261bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 1262b1757049SJed Brown ratioi = mx/Mx; 1263*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*Mx != mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 1264b1757049SJed Brown } else { 1265b1757049SJed Brown ratioi = (mx-1)/(Mx-1); 1266*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 1267b1757049SJed Brown } 1268bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 1269b1757049SJed Brown ratioj = my/My; 1270*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*My != my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 1271b1757049SJed Brown } else { 1272b1757049SJed Brown ratioj = (my-1)/(My-1); 1273*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 1274b1757049SJed Brown } 1275bff4a2f0SMatthew G. Knepley if (bz == DM_BOUNDARY_PERIODIC) { 1276b1757049SJed Brown ratiok = mz/Mz; 1277*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiok*Mz != mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D My %D",mz,Mz); 1278b1757049SJed Brown } else { 1279b1757049SJed Brown ratiok = (mz-1)/(Mz-1); 1280*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiok*(Mz-1) != mz-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 1281b1757049SJed Brown } 1282b1757049SJed Brown 1283b1757049SJed Brown ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1284b1757049SJed Brown ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 128545b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 128645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1287b1757049SJed Brown 1288b1757049SJed Brown ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1289b1757049SJed 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); 129045b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 129145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1292b1757049SJed Brown 1293b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1294b1757049SJed Brown nc = 0; 1295785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f*p_f,&cols);CHKERRQ(ierr); 1296b1757049SJed Brown for (k=k_start_c; k<k_start_c+p_c; k++) { 1297b1757049SJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1298b1757049SJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1299b1757049SJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok; 1300*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(k_f < k_start_ghost || k_f >= k_start_ghost+p_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1301b1757049SJed Brown "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost); 1302*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1303b1757049SJed Brown "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1304*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1305b1757049SJed Brown "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1306e3fbd1f4SBarry 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))]; 1307e3fbd1f4SBarry Smith cols[nc++] = row; 1308b1757049SJed Brown } 1309b1757049SJed Brown } 1310b1757049SJed Brown } 131145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 131245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1313b1757049SJed Brown 1314ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 1315b1757049SJed Brown ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 1316b1757049SJed Brown ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 13179448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 1318b1757049SJed Brown ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 1319b1757049SJed Brown ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1320fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 1321b1757049SJed Brown PetscFunctionReturn(0); 1322b1757049SJed Brown } 1323b1757049SJed Brown 13246dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_DA(DM dac,DM daf,Mat *mat) 132547c6ae99SBarry Smith { 132647c6ae99SBarry Smith PetscErrorCode ierr; 132747c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1328bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1329aa219208SBarry Smith DMDAStencilType stc,stf; 133060c16ac1SBarry Smith VecScatter inject = NULL; 133147c6ae99SBarry Smith 133247c6ae99SBarry Smith PetscFunctionBegin; 133347c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 133447c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 13356dbf9973SLawrence Mitchell PetscValidPointer(mat,3); 133647c6ae99SBarry Smith 13371321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 13381321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1339*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc != dimf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1340*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dofc != doff,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1341*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(sc != sf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 1342*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(bxc != bxf || byc != byf || bzc != bzf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1343*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(stc != stf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 1344*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mc < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 1345*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 1 && Nc < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 1346*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 2 && Pc < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 134747c6ae99SBarry Smith 13480bb2b966SJungho Lee if (dimc == 1) { 13496dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_1D(dac,daf,&inject);CHKERRQ(ierr); 13500bb2b966SJungho Lee } else if (dimc == 2) { 13516dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_2D(dac,daf,&inject);CHKERRQ(ierr); 1352b1757049SJed Brown } else if (dimc == 3) { 13536dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_3D(dac,daf,&inject);CHKERRQ(ierr); 135447c6ae99SBarry Smith } 13556dbf9973SLawrence Mitchell ierr = MatCreateScatter(PetscObjectComm((PetscObject)inject), inject, mat);CHKERRQ(ierr); 13566dbf9973SLawrence Mitchell ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 135747c6ae99SBarry Smith PetscFunctionReturn(0); 135847c6ae99SBarry Smith } 135947c6ae99SBarry Smith 136097779f9aSLisandro Dalcin /*@ 136197779f9aSLisandro Dalcin DMCreateAggregates - Deprecated, see DMDACreateAggregates. 13626c877ef6SSatish Balay 13636c877ef6SSatish Balay Level: intermediate 136497779f9aSLisandro Dalcin @*/ 1365a5bc1bf3SBarry Smith PetscErrorCode DMCreateAggregates(DM dac,DM daf,Mat *mat) 136697779f9aSLisandro Dalcin { 1367a5bc1bf3SBarry Smith return DMDACreateAggregates(dac,daf,mat); 136897779f9aSLisandro Dalcin } 136997779f9aSLisandro Dalcin 137097779f9aSLisandro Dalcin /*@ 137197779f9aSLisandro Dalcin DMDACreateAggregates - Gets the aggregates that map between 137297779f9aSLisandro Dalcin grids associated with two DMDAs. 137397779f9aSLisandro Dalcin 137497779f9aSLisandro Dalcin Collective on dmc 137597779f9aSLisandro Dalcin 137697779f9aSLisandro Dalcin Input Parameters: 137797779f9aSLisandro Dalcin + dmc - the coarse grid DMDA 137897779f9aSLisandro Dalcin - dmf - the fine grid DMDA 137997779f9aSLisandro Dalcin 138097779f9aSLisandro Dalcin Output Parameters: 138197779f9aSLisandro Dalcin . rest - the restriction matrix (transpose of the projection matrix) 138297779f9aSLisandro Dalcin 138397779f9aSLisandro Dalcin Level: intermediate 138497779f9aSLisandro Dalcin 138597779f9aSLisandro Dalcin Note: This routine is not used by PETSc. 138697779f9aSLisandro Dalcin It is not clear what its use case is and it may be removed in a future release. 138797779f9aSLisandro Dalcin Users should contact petsc-maint@mcs.anl.gov if they plan to use it. 138897779f9aSLisandro Dalcin 138997779f9aSLisandro Dalcin .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 139097779f9aSLisandro Dalcin @*/ 139197779f9aSLisandro Dalcin PetscErrorCode DMDACreateAggregates(DM dac,DM daf,Mat *rest) 139247c6ae99SBarry Smith { 139347c6ae99SBarry Smith PetscErrorCode ierr; 139447c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc; 139547c6ae99SBarry Smith PetscInt dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1396bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1397aa219208SBarry Smith DMDAStencilType stc,stf; 139847c6ae99SBarry Smith PetscInt i,j,l; 139947c6ae99SBarry Smith PetscInt i_start,j_start,l_start, m_f,n_f,p_f; 140047c6ae99SBarry Smith PetscInt i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost; 14018ea3bf28SBarry Smith const PetscInt *idx_f; 140247c6ae99SBarry Smith PetscInt i_c,j_c,l_c; 140347c6ae99SBarry Smith PetscInt i_start_c,j_start_c,l_start_c, m_c,n_c,p_c; 140447c6ae99SBarry Smith PetscInt i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c; 14058ea3bf28SBarry Smith const PetscInt *idx_c; 140647c6ae99SBarry Smith PetscInt d; 140747c6ae99SBarry Smith PetscInt a; 140847c6ae99SBarry Smith PetscInt max_agg_size; 140947c6ae99SBarry Smith PetscInt *fine_nodes; 141047c6ae99SBarry Smith PetscScalar *one_vec; 141147c6ae99SBarry Smith PetscInt fn_idx; 1412565245c5SBarry Smith ISLocalToGlobalMapping ltogmf,ltogmc; 141347c6ae99SBarry Smith 141447c6ae99SBarry Smith PetscFunctionBegin; 141597779f9aSLisandro Dalcin PetscValidHeaderSpecificType(dac,DM_CLASSID,1,DMDA); 141697779f9aSLisandro Dalcin PetscValidHeaderSpecificType(daf,DM_CLASSID,2,DMDA); 141747c6ae99SBarry Smith PetscValidPointer(rest,3); 141847c6ae99SBarry Smith 14191321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 14201321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1421*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc != dimf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1422*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(dofc != doff,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1423*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(sc != sf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 1424*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(bxc != bxf || byc != byf || bzc != bzf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1425*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(stc != stf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 142647c6ae99SBarry Smith 1427*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mf < Mc,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Mc %D, Mf %D", Mc, Mf); 1428*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nf < Nc,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Nc %D, Nf %D", Nc, Nf); 1429*2c71b3e2SJacob Faibussowitsch PetscCheckFalse(Pf < Pc,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Pc %D, Pf %D", Pc, Pf); 143047c6ae99SBarry Smith 143147c6ae99SBarry Smith if (Pc < 0) Pc = 1; 143247c6ae99SBarry Smith if (Pf < 0) Pf = 1; 143347c6ae99SBarry Smith if (Nc < 0) Nc = 1; 143447c6ae99SBarry Smith if (Nf < 0) Nf = 1; 143547c6ae99SBarry Smith 1436aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1437aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1438565245c5SBarry Smith 1439565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<ogmf);CHKERRQ(ierr); 1440565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmf,&idx_f);CHKERRQ(ierr); 144147c6ae99SBarry Smith 1442aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1443aa219208SBarry 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); 1444565245c5SBarry Smith 1445565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<ogmc);CHKERRQ(ierr); 1446565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmc,&idx_c);CHKERRQ(ierr); 144747c6ae99SBarry Smith 144847c6ae99SBarry Smith /* 144947c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 145047c6ae99SBarry Smith for dimension 1 and 2 respectively. 145147c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 145247c6ae99SBarry Smith and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate. 145347c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 145447c6ae99SBarry Smith */ 145547c6ae99SBarry Smith 145647c6ae99SBarry Smith max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1); 145747c6ae99SBarry Smith 145847c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 1459ce94432eSBarry 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, 14600298fd71SBarry Smith max_agg_size, NULL, max_agg_size, NULL, rest);CHKERRQ(ierr); 146147c6ae99SBarry Smith 146247c6ae99SBarry Smith /* store nodes in the fine grid here */ 1463dcca6d9dSJed Brown ierr = PetscMalloc2(max_agg_size, &one_vec,max_agg_size, &fine_nodes);CHKERRQ(ierr); 146447c6ae99SBarry Smith for (i=0; i<max_agg_size; i++) one_vec[i] = 1.0; 146547c6ae99SBarry Smith 146647c6ae99SBarry Smith /* loop over all coarse nodes */ 146747c6ae99SBarry Smith for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) { 146847c6ae99SBarry Smith for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) { 146947c6ae99SBarry Smith for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) { 147047c6ae99SBarry Smith for (d=0; d<dofc; d++) { 147147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 147247c6ae99SBarry 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; 147347c6ae99SBarry Smith 147447c6ae99SBarry Smith fn_idx = 0; 147547c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 147647c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 147747c6ae99SBarry Smith (same for other dimensions) 147847c6ae99SBarry Smith */ 147947c6ae99SBarry Smith for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) { 148047c6ae99SBarry Smith for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) { 148147c6ae99SBarry Smith for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) { 148247c6ae99SBarry 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; 148347c6ae99SBarry Smith fn_idx++; 148447c6ae99SBarry Smith } 148547c6ae99SBarry Smith } 148647c6ae99SBarry Smith } 148747c6ae99SBarry Smith /* add all these points to one aggregate */ 148847c6ae99SBarry Smith ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr); 148947c6ae99SBarry Smith } 149047c6ae99SBarry Smith } 149147c6ae99SBarry Smith } 149247c6ae99SBarry Smith } 1493565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmf,&idx_f);CHKERRQ(ierr); 1494565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmc,&idx_c);CHKERRQ(ierr); 149547c6ae99SBarry Smith ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr); 149647c6ae99SBarry Smith ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 149747c6ae99SBarry Smith ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 149847c6ae99SBarry Smith PetscFunctionReturn(0); 149947c6ae99SBarry Smith } 1500