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; 561321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 571321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 58bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 5947c6ae99SBarry Smith ratio = mx/Mx; 6047c6ae99SBarry Smith if (ratio*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 6147c6ae99SBarry Smith } else { 6247c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 6347c6ae99SBarry Smith if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 6447c6ae99SBarry Smith } 6547c6ae99SBarry Smith 66aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 67aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 6845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 6945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 7047c6ae99SBarry Smith 71aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 72aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);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 */ 101aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 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 */ 140b3bd94feSDave May if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 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; 1971321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 1981321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 199bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 2003a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 20147c6ae99SBarry Smith ratio = mx/Mx; 20247c6ae99SBarry Smith if (ratio*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 20347c6ae99SBarry Smith } else { 2043a586487SStefano Zampini if (Mx < 2) SETERRQ1(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); 20647c6ae99SBarry Smith if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 20747c6ae99SBarry Smith } 20847c6ae99SBarry Smith 209aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 210aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 21145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 21245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 21347c6ae99SBarry Smith 214aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 215aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);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; 2871321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 2881321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 289bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 2903a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 29147c6ae99SBarry Smith ratioi = mx/Mx; 29247c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 29347c6ae99SBarry Smith } else { 2943a586487SStefano Zampini if (Mx < 2) SETERRQ1(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); 29647c6ae99SBarry Smith if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 29747c6ae99SBarry Smith } 298bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 2993a586487SStefano Zampini if (!My) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 30047c6ae99SBarry Smith ratioj = my/My; 30147c6ae99SBarry Smith if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 30247c6ae99SBarry Smith } else { 3033a586487SStefano Zampini if (My < 2) SETERRQ1(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); 30547c6ae99SBarry Smith if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 30647c6ae99SBarry Smith } 30747c6ae99SBarry Smith 308aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 309aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 31045b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 31145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 31247c6ae99SBarry Smith 313aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 314aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);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 */ 328ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 329ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 330ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(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 343aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 34447c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 345aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 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; 5251321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 5261321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 5273a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 5283a586487SStefano Zampini if (!My) SETERRQ1(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; 531ce94432eSBarry Smith if (ratioi*Mx != mx) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 532ce94432eSBarry Smith if (ratioj*My != my) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 533ce94432eSBarry Smith if (ratioi != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2"); 534ce94432eSBarry Smith if (ratioj != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2"); 53547c6ae99SBarry Smith 536aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 537aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 53845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 53945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 54047c6ae99SBarry Smith 541aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 542aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);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 */ 556ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 557ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 558ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(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 571aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 57247c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 573aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 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; 6511321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 6523a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 6533a586487SStefano Zampini if (!My) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 6543a586487SStefano Zampini if (!Mz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 6551321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 65647c6ae99SBarry Smith ratioi = mx/Mx; 65747c6ae99SBarry Smith ratioj = my/My; 65847c6ae99SBarry Smith ratiol = mz/Mz; 659ce94432eSBarry Smith if (ratioi*Mx != mx) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 660ce94432eSBarry Smith if (ratioj*My != my) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 661ce94432eSBarry Smith if (ratiol*Mz != mz) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z"); 662ce94432eSBarry Smith if (ratioi != 2 && ratioi != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2"); 663ce94432eSBarry Smith if (ratioj != 2 && ratioj != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2"); 664ce94432eSBarry Smith if (ratiol != 2 && ratiol != 1) SETERRQ(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 */ 686ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 687ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 688ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(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 703aa219208SBarry Smith if (l_c < l_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70447c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 705aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70647c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 707aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 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; 7871321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 7881321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 78947c6ae99SBarry Smith if (mx == Mx) { 79047c6ae99SBarry Smith ratioi = 1; 791bff4a2f0SMatthew G. Knepley } else if (bx == DM_BOUNDARY_PERIODIC) { 7923a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 79347c6ae99SBarry Smith ratioi = mx/Mx; 79447c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 79547c6ae99SBarry Smith } else { 7963a586487SStefano Zampini if (Mx < 2) SETERRQ1(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); 79847c6ae99SBarry Smith if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 79947c6ae99SBarry Smith } 80047c6ae99SBarry Smith if (my == My) { 80147c6ae99SBarry Smith ratioj = 1; 802bff4a2f0SMatthew G. Knepley } else if (by == DM_BOUNDARY_PERIODIC) { 8033a586487SStefano Zampini if (!My) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 80447c6ae99SBarry Smith ratioj = my/My; 80547c6ae99SBarry Smith if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 80647c6ae99SBarry Smith } else { 8073a586487SStefano Zampini if (My < 2) SETERRQ1(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); 80947c6ae99SBarry Smith if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 81047c6ae99SBarry Smith } 81147c6ae99SBarry Smith if (mz == Mz) { 81247c6ae99SBarry Smith ratiok = 1; 813bff4a2f0SMatthew G. Knepley } else if (bz == DM_BOUNDARY_PERIODIC) { 8143a586487SStefano Zampini if (!Mz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 81547c6ae99SBarry Smith ratiok = mz/Mz; 81647c6ae99SBarry Smith if (ratiok*Mz != mz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D Mz %D",mz,Mz); 81747c6ae99SBarry Smith } else { 8183a586487SStefano Zampini if (Mz < 2) SETERRQ1(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); 82047c6ae99SBarry Smith if (ratiok*(Mz-1) != mz-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 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); 844aa219208SBarry Smith if (l_c < l_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84547c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 846aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84747c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 848aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 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); 108113903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 108213903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 108313903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 108413903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 108513903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 108647c6ae99SBarry Smith if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 108747c6ae99SBarry Smith if (dimc > 1 && Nc < 2 && Nf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 108847c6ae99SBarry Smith if (dimc > 2 && Pc < 2 && Pf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 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); 1097ce94432eSBarry Smith } else SETERRQ2(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); 1105ce94432eSBarry Smith } else SETERRQ2(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; 11280bb2b966SJungho Lee ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 11290bb2b966SJungho Lee ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1130bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 11310bb2b966SJungho Lee ratioi = mx/Mx; 11320bb2b966SJungho Lee if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 11330bb2b966SJungho Lee } else { 11340bb2b966SJungho Lee ratioi = (mx-1)/(Mx-1); 11350bb2b966SJungho Lee if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 11360bb2b966SJungho Lee } 11370bb2b966SJungho Lee 11380bb2b966SJungho Lee ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 11390bb2b966SJungho Lee ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 114045b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 114145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 11420bb2b966SJungho Lee 11430bb2b966SJungho Lee ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 11440bb2b966SJungho Lee ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 11450bb2b966SJungho Lee 11460bb2b966SJungho Lee 11470bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 11480bb2b966SJungho Lee nc = 0; 1149785e854fSJed Brown ierr = PetscMalloc1(m_f,&cols);CHKERRQ(ierr); 11500bb2b966SJungho Lee 11510bb2b966SJungho Lee 11520bb2b966SJungho Lee for (i=i_start_c; i<i_start_c+m_c; i++) { 11530bb2b966SJungho Lee PetscInt i_f = i*ratioi; 11540bb2b966SJungho Lee 11558865f1eaSKarl Rupp if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\ni_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 11568865f1eaSKarl Rupp 1157e3fbd1f4SBarry Smith row = idx_f[(i_f-i_start_ghost)]; 1158e3fbd1f4SBarry Smith cols[nc++] = row; 11590bb2b966SJungho Lee } 11600bb2b966SJungho Lee 116145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1162ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 11630bb2b966SJungho Lee ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 11640bb2b966SJungho Lee ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 11659448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 11660bb2b966SJungho Lee ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 11670bb2b966SJungho Lee ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 11680bb2b966SJungho Lee ierr = ISDestroy(&isf);CHKERRQ(ierr); 11690bb2b966SJungho Lee PetscFunctionReturn(0); 11700bb2b966SJungho Lee } 11710bb2b966SJungho Lee 1172e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject) 117347c6ae99SBarry Smith { 117447c6ae99SBarry Smith PetscErrorCode ierr; 11758ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 11768ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1177e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 11788ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c; 117947c6ae99SBarry Smith PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; 1180076202ddSJed Brown PetscInt i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 118147c6ae99SBarry Smith PetscInt *cols; 1182bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 118347c6ae99SBarry Smith Vec vecf,vecc; 118447c6ae99SBarry Smith IS isf; 118547c6ae99SBarry Smith 118647c6ae99SBarry Smith PetscFunctionBegin; 11871321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 11881321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1189bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 119047c6ae99SBarry Smith ratioi = mx/Mx; 119147c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 119247c6ae99SBarry Smith } else { 119347c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 119447c6ae99SBarry Smith if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 119547c6ae99SBarry Smith } 1196bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 119747c6ae99SBarry Smith ratioj = my/My; 119847c6ae99SBarry Smith if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 119947c6ae99SBarry Smith } else { 120047c6ae99SBarry Smith ratioj = (my-1)/(My-1); 120147c6ae99SBarry Smith if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 120247c6ae99SBarry Smith } 120347c6ae99SBarry Smith 1204aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 1205aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 120645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 120745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 120847c6ae99SBarry Smith 1209aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 1210aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 121145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 121245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 121347c6ae99SBarry Smith 121447c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 121547c6ae99SBarry Smith nc = 0; 1216785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f,&cols);CHKERRQ(ierr); 1217076202ddSJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1218076202ddSJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1219076202ddSJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj; 1220076202ddSJed Brown if (j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1221076202ddSJed Brown j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1222076202ddSJed Brown if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1223076202ddSJed Brown i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1224e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 1225e3fbd1f4SBarry Smith cols[nc++] = row; 122647c6ae99SBarry Smith } 122747c6ae99SBarry Smith } 122845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 122945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 123047c6ae99SBarry Smith 1231ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 12329a42bb27SBarry Smith ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 12339a42bb27SBarry Smith ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 12349448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 12359a42bb27SBarry Smith ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 12369a42bb27SBarry Smith ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1237fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 123847c6ae99SBarry Smith PetscFunctionReturn(0); 123947c6ae99SBarry Smith } 124047c6ae99SBarry Smith 1241e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject) 1242b1757049SJed Brown { 1243b1757049SJed Brown PetscErrorCode ierr; 1244b1757049SJed Brown PetscInt i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz; 1245b1757049SJed Brown PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c; 1246b1757049SJed Brown PetscInt i_start_ghost,j_start_ghost,k_start_ghost; 1247b1757049SJed Brown PetscInt mx,my,mz,ratioi,ratioj,ratiok; 1248b1757049SJed Brown PetscInt i_start_c,j_start_c,k_start_c; 1249b1757049SJed Brown PetscInt m_c,n_c,p_c; 1250b1757049SJed Brown PetscInt i_start_ghost_c,j_start_ghost_c,k_start_ghost_c; 1251b1757049SJed Brown PetscInt row,nc,dof; 12528ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1253e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1254b1757049SJed Brown PetscInt *cols; 1255bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 1256b1757049SJed Brown Vec vecf,vecc; 1257b1757049SJed Brown IS isf; 1258b1757049SJed Brown 1259b1757049SJed Brown PetscFunctionBegin; 12601321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 12611321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1262b1757049SJed Brown 1263bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 1264b1757049SJed Brown ratioi = mx/Mx; 1265b1757049SJed Brown if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 1266b1757049SJed Brown } else { 1267b1757049SJed Brown ratioi = (mx-1)/(Mx-1); 1268b1757049SJed Brown if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 1269b1757049SJed Brown } 1270bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 1271b1757049SJed Brown ratioj = my/My; 1272b1757049SJed Brown if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 1273b1757049SJed Brown } else { 1274b1757049SJed Brown ratioj = (my-1)/(My-1); 1275b1757049SJed Brown if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 1276b1757049SJed Brown } 1277bff4a2f0SMatthew G. Knepley if (bz == DM_BOUNDARY_PERIODIC) { 1278b1757049SJed Brown ratiok = mz/Mz; 1279b1757049SJed Brown if (ratiok*Mz != mz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D My %D",mz,Mz); 1280b1757049SJed Brown } else { 1281b1757049SJed Brown ratiok = (mz-1)/(Mz-1); 1282b1757049SJed Brown if (ratiok*(Mz-1) != mz-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 1283b1757049SJed Brown } 1284b1757049SJed Brown 1285b1757049SJed Brown ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1286b1757049SJed Brown ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 128745b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 128845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1289b1757049SJed Brown 1290b1757049SJed Brown ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1291b1757049SJed 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); 129245b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 129345b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1294b1757049SJed Brown 1295b1757049SJed Brown 1296b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1297b1757049SJed Brown nc = 0; 1298785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f*p_f,&cols);CHKERRQ(ierr); 1299b1757049SJed Brown for (k=k_start_c; k<k_start_c+p_c; k++) { 1300b1757049SJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1301b1757049SJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1302b1757049SJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok; 1303b1757049SJed Brown if (k_f < k_start_ghost || k_f >= k_start_ghost+p_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1304b1757049SJed Brown "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost); 1305b1757049SJed Brown if (j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1306b1757049SJed Brown "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1307b1757049SJed Brown if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1308b1757049SJed Brown "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1309e3fbd1f4SBarry 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))]; 1310e3fbd1f4SBarry Smith cols[nc++] = row; 1311b1757049SJed Brown } 1312b1757049SJed Brown } 1313b1757049SJed Brown } 131445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 131545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1316b1757049SJed Brown 1317ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 1318b1757049SJed Brown ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 1319b1757049SJed Brown ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 13209448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 1321b1757049SJed Brown ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 1322b1757049SJed Brown ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1323fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 1324b1757049SJed Brown PetscFunctionReturn(0); 1325b1757049SJed Brown } 1326b1757049SJed Brown 13276dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_DA(DM dac,DM daf,Mat *mat) 132847c6ae99SBarry Smith { 132947c6ae99SBarry Smith PetscErrorCode ierr; 133047c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1331bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1332aa219208SBarry Smith DMDAStencilType stc,stf; 133360c16ac1SBarry Smith VecScatter inject = NULL; 133447c6ae99SBarry Smith 133547c6ae99SBarry Smith PetscFunctionBegin; 133647c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 133747c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 13386dbf9973SLawrence Mitchell PetscValidPointer(mat,3); 133947c6ae99SBarry Smith 13401321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 13411321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 134213903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 134313903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 134413903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 134513903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 134613903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 134747c6ae99SBarry Smith if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 134847c6ae99SBarry Smith if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 134947c6ae99SBarry Smith if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 135047c6ae99SBarry Smith 13510bb2b966SJungho Lee if (dimc == 1) { 13526dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_1D(dac,daf,&inject);CHKERRQ(ierr); 13530bb2b966SJungho Lee } else if (dimc == 2) { 13546dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_2D(dac,daf,&inject);CHKERRQ(ierr); 1355b1757049SJed Brown } else if (dimc == 3) { 13566dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_3D(dac,daf,&inject);CHKERRQ(ierr); 135747c6ae99SBarry Smith } 13586dbf9973SLawrence Mitchell ierr = MatCreateScatter(PetscObjectComm((PetscObject)inject), inject, mat);CHKERRQ(ierr); 13596dbf9973SLawrence Mitchell ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 136047c6ae99SBarry Smith PetscFunctionReturn(0); 136147c6ae99SBarry Smith } 136247c6ae99SBarry Smith 136397779f9aSLisandro Dalcin /*@ 136497779f9aSLisandro Dalcin DMCreateAggregates - Deprecated, see DMDACreateAggregates. 136597779f9aSLisandro Dalcin @*/ 1366*a5bc1bf3SBarry Smith PetscErrorCode DMCreateAggregates(DM dac,DM daf,Mat *mat) 136797779f9aSLisandro Dalcin { 1368*a5bc1bf3SBarry Smith return DMDACreateAggregates(dac,daf,mat); 136997779f9aSLisandro Dalcin } 137097779f9aSLisandro Dalcin 137197779f9aSLisandro Dalcin /*@ 137297779f9aSLisandro Dalcin DMDACreateAggregates - Gets the aggregates that map between 137397779f9aSLisandro Dalcin grids associated with two DMDAs. 137497779f9aSLisandro Dalcin 137597779f9aSLisandro Dalcin Collective on dmc 137697779f9aSLisandro Dalcin 137797779f9aSLisandro Dalcin Input Parameters: 137897779f9aSLisandro Dalcin + dmc - the coarse grid DMDA 137997779f9aSLisandro Dalcin - dmf - the fine grid DMDA 138097779f9aSLisandro Dalcin 138197779f9aSLisandro Dalcin Output Parameters: 138297779f9aSLisandro Dalcin . rest - the restriction matrix (transpose of the projection matrix) 138397779f9aSLisandro Dalcin 138497779f9aSLisandro Dalcin Level: intermediate 138597779f9aSLisandro Dalcin 138697779f9aSLisandro Dalcin Note: This routine is not used by PETSc. 138797779f9aSLisandro Dalcin It is not clear what its use case is and it may be removed in a future release. 138897779f9aSLisandro Dalcin Users should contact petsc-maint@mcs.anl.gov if they plan to use it. 138997779f9aSLisandro Dalcin 139097779f9aSLisandro Dalcin .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 139197779f9aSLisandro Dalcin @*/ 139297779f9aSLisandro Dalcin PetscErrorCode DMDACreateAggregates(DM dac,DM daf,Mat *rest) 139347c6ae99SBarry Smith { 139447c6ae99SBarry Smith PetscErrorCode ierr; 139547c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc; 139647c6ae99SBarry Smith PetscInt dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1397bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1398aa219208SBarry Smith DMDAStencilType stc,stf; 139947c6ae99SBarry Smith PetscInt i,j,l; 140047c6ae99SBarry Smith PetscInt i_start,j_start,l_start, m_f,n_f,p_f; 140147c6ae99SBarry Smith PetscInt i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost; 14028ea3bf28SBarry Smith const PetscInt *idx_f; 140347c6ae99SBarry Smith PetscInt i_c,j_c,l_c; 140447c6ae99SBarry Smith PetscInt i_start_c,j_start_c,l_start_c, m_c,n_c,p_c; 140547c6ae99SBarry Smith PetscInt i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c; 14068ea3bf28SBarry Smith const PetscInt *idx_c; 140747c6ae99SBarry Smith PetscInt d; 140847c6ae99SBarry Smith PetscInt a; 140947c6ae99SBarry Smith PetscInt max_agg_size; 141047c6ae99SBarry Smith PetscInt *fine_nodes; 141147c6ae99SBarry Smith PetscScalar *one_vec; 141247c6ae99SBarry Smith PetscInt fn_idx; 1413565245c5SBarry Smith ISLocalToGlobalMapping ltogmf,ltogmc; 141447c6ae99SBarry Smith 141547c6ae99SBarry Smith PetscFunctionBegin; 141697779f9aSLisandro Dalcin PetscValidHeaderSpecificType(dac,DM_CLASSID,1,DMDA); 141797779f9aSLisandro Dalcin PetscValidHeaderSpecificType(daf,DM_CLASSID,2,DMDA); 141847c6ae99SBarry Smith PetscValidPointer(rest,3); 141947c6ae99SBarry Smith 14201321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 14211321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 142213903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 142313903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 142413903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 142513903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 142613903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 142747c6ae99SBarry Smith 142847c6ae99SBarry Smith if (Mf < Mc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Mc %D, Mf %D", Mc, Mf); 142947c6ae99SBarry Smith if (Nf < Nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Nc %D, Nf %D", Nc, Nf); 143047c6ae99SBarry Smith if (Pf < Pc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Pc %D, Pf %D", Pc, Pf); 143147c6ae99SBarry Smith 143247c6ae99SBarry Smith if (Pc < 0) Pc = 1; 143347c6ae99SBarry Smith if (Pf < 0) Pf = 1; 143447c6ae99SBarry Smith if (Nc < 0) Nc = 1; 143547c6ae99SBarry Smith if (Nf < 0) Nf = 1; 143647c6ae99SBarry Smith 1437aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1438aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1439565245c5SBarry Smith 1440565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<ogmf);CHKERRQ(ierr); 1441565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmf,&idx_f);CHKERRQ(ierr); 144247c6ae99SBarry Smith 1443aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1444aa219208SBarry 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); 1445565245c5SBarry Smith 1446565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<ogmc);CHKERRQ(ierr); 1447565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmc,&idx_c);CHKERRQ(ierr); 144847c6ae99SBarry Smith 144947c6ae99SBarry Smith /* 145047c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 145147c6ae99SBarry Smith for dimension 1 and 2 respectively. 145247c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 145347c6ae99SBarry Smith and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate. 145447c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 145547c6ae99SBarry Smith */ 145647c6ae99SBarry Smith 145747c6ae99SBarry Smith max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1); 145847c6ae99SBarry Smith 145947c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 1460ce94432eSBarry 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, 14610298fd71SBarry Smith max_agg_size, NULL, max_agg_size, NULL, rest);CHKERRQ(ierr); 146247c6ae99SBarry Smith 146347c6ae99SBarry Smith /* store nodes in the fine grid here */ 1464dcca6d9dSJed Brown ierr = PetscMalloc2(max_agg_size, &one_vec,max_agg_size, &fine_nodes);CHKERRQ(ierr); 146547c6ae99SBarry Smith for (i=0; i<max_agg_size; i++) one_vec[i] = 1.0; 146647c6ae99SBarry Smith 146747c6ae99SBarry Smith /* loop over all coarse nodes */ 146847c6ae99SBarry Smith for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) { 146947c6ae99SBarry Smith for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) { 147047c6ae99SBarry Smith for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) { 147147c6ae99SBarry Smith for (d=0; d<dofc; d++) { 147247c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 147347c6ae99SBarry 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; 147447c6ae99SBarry Smith 147547c6ae99SBarry Smith fn_idx = 0; 147647c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 147747c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 147847c6ae99SBarry Smith (same for other dimensions) 147947c6ae99SBarry Smith */ 148047c6ae99SBarry Smith for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) { 148147c6ae99SBarry Smith for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) { 148247c6ae99SBarry Smith for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) { 148347c6ae99SBarry 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; 148447c6ae99SBarry Smith fn_idx++; 148547c6ae99SBarry Smith } 148647c6ae99SBarry Smith } 148747c6ae99SBarry Smith } 148847c6ae99SBarry Smith /* add all these points to one aggregate */ 148947c6ae99SBarry Smith ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr); 149047c6ae99SBarry Smith } 149147c6ae99SBarry Smith } 149247c6ae99SBarry Smith } 149347c6ae99SBarry Smith } 1494565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmf,&idx_f);CHKERRQ(ierr); 1495565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmc,&idx_c);CHKERRQ(ierr); 149647c6ae99SBarry Smith ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr); 149747c6ae99SBarry Smith ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 149847c6ae99SBarry Smith ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 149947c6ae99SBarry Smith PetscFunctionReturn(0); 150047c6ae99SBarry Smith } 1501