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 PetscInt i; 25fdc842d1SBarry Smith char const *types[3] = {MATAIJ,MATSEQAIJ,MATMPIAIJ}; 26fdc842d1SBarry Smith PetscBool flg; 27fdc842d1SBarry Smith 28fdc842d1SBarry Smith PetscFunctionBegin; 2933a4d587SStefano Zampini *outtype = MATAIJ; 30fdc842d1SBarry Smith for (i=0; i<3; i++) { 319566063dSJacob Faibussowitsch PetscCall(PetscStrbeginswith(intype,types[i],&flg)); 32fdc842d1SBarry Smith if (flg) { 33fdc842d1SBarry Smith *outtype = intype; 34fdc842d1SBarry Smith PetscFunctionReturn(0); 35fdc842d1SBarry Smith } 36fdc842d1SBarry Smith } 37fdc842d1SBarry Smith PetscFunctionReturn(0); 38fdc842d1SBarry Smith } 39fdc842d1SBarry Smith 40e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A) 4147c6ae99SBarry Smith { 428ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 438ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 448ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 4547c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 4647c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 4785afcc9aSBarry Smith PetscScalar v[2],x; 4847c6ae99SBarry Smith Mat mat; 49bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 50e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 51fdc842d1SBarry Smith MatType mattype; 5247c6ae99SBarry Smith 5347c6ae99SBarry Smith PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&bx,NULL,NULL,NULL)); 559566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 56bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 5747c6ae99SBarry Smith ratio = mx/Mx; 58*08401ef6SPierre Jolivet PetscCheck(ratio*Mx == mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 5947c6ae99SBarry Smith } else { 6047c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 612c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratio*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 6247c6ae99SBarry Smith } 6347c6ae99SBarry Smith 649566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,NULL,NULL,&m_f,NULL,NULL)); 659566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,NULL,NULL,&m_ghost,NULL,NULL)); 669566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 6847c6ae99SBarry Smith 699566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,NULL,NULL,&m_c,NULL,NULL)); 709566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,NULL,NULL,&m_ghost_c,NULL,NULL)); 719566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 7347c6ae99SBarry Smith 7447c6ae99SBarry Smith /* create interpolation matrix */ 759566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dac),&mat)); 76fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 77fdc842d1SBarry Smith /* 78fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 79fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 80fdc842d1SBarry Smith */ 81fdc842d1SBarry Smith if (dof > 1) { 829566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(mat,PETSC_TRUE)); 83fdc842d1SBarry Smith } 84fdc842d1SBarry Smith #endif 859566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat,m_f,m_c,mx,Mx)); 869566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype,&mattype)); 879566063dSJacob Faibussowitsch PetscCall(MatSetType(mat,mattype)); 889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat,2,NULL)); 899566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat,2,NULL,1,NULL)); 9047c6ae99SBarry Smith 9147c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 9285afcc9aSBarry Smith if (!NEWVERSION) { 93b3bd94feSDave May 9447c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 9547c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 96e3fbd1f4SBarry Smith row = idx_f[i-i_start_ghost]; 9747c6ae99SBarry Smith 9847c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 99*08401ef6SPierre Jolivet PetscCheck(i_c >= i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 10047c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 10147c6ae99SBarry Smith 10247c6ae99SBarry Smith /* 10347c6ae99SBarry Smith Only include those interpolation points that are truly 10447c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 10547c6ae99SBarry Smith in x direction; since they have no right neighbor 10647c6ae99SBarry Smith */ 1076712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 10847c6ae99SBarry Smith nc = 0; 10947c6ae99SBarry Smith /* one left and below; or we are right on it */ 110e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 111e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 11247c6ae99SBarry Smith v[nc++] = -x + 1.0; 11347c6ae99SBarry Smith /* one right? */ 11447c6ae99SBarry Smith if (i_c*ratio != i) { 115e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 11647c6ae99SBarry Smith v[nc++] = x; 11747c6ae99SBarry Smith } 1189566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES)); 11947c6ae99SBarry Smith } 120b3bd94feSDave May 121b3bd94feSDave May } else { 122b3bd94feSDave May PetscScalar *xi; 123b3bd94feSDave May PetscInt li,nxi,n; 124b3bd94feSDave May PetscScalar Ni[2]; 125b3bd94feSDave May 126b3bd94feSDave May /* compute local coordinate arrays */ 127b3bd94feSDave May nxi = ratio + 1; 1289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nxi,&xi)); 129b3bd94feSDave May for (li=0; li<nxi; li++) { 13052218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 131b3bd94feSDave May } 132b3bd94feSDave May 133b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 134b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 135e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 136b3bd94feSDave May 137b3bd94feSDave May i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 138*08401ef6SPierre Jolivet PetscCheck(i_c >= i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 139b3bd94feSDave May i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 140b3bd94feSDave May 141b3bd94feSDave May /* remainders */ 142b3bd94feSDave May li = i - ratio * (i/ratio); 1438865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 144b3bd94feSDave May 145b3bd94feSDave May /* corners */ 146e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 147e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 148b3bd94feSDave May Ni[0] = 1.0; 149b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 1509566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES)); 151b3bd94feSDave May continue; 152b3bd94feSDave May } 153b3bd94feSDave May 154b3bd94feSDave May /* edges + interior */ 155b3bd94feSDave May /* remainders */ 1568865f1eaSKarl Rupp if (i==mx-1) i_c--; 157b3bd94feSDave May 158e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 159e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 160e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; 161b3bd94feSDave May 162b3bd94feSDave May Ni[0] = 0.5*(1.0-xi[li]); 163b3bd94feSDave May Ni[1] = 0.5*(1.0+xi[li]); 164b3bd94feSDave May for (n=0; n<2; n++) { 1658865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 166b3bd94feSDave May } 1679566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES)); 168b3bd94feSDave May } 1699566063dSJacob Faibussowitsch PetscCall(PetscFree(xi)); 170b3bd94feSDave May } 1719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 1729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 1739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 1749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 1759566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat,dof,A)); 1769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 17747c6ae99SBarry Smith PetscFunctionReturn(0); 17847c6ae99SBarry Smith } 17947c6ae99SBarry Smith 180e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A) 18147c6ae99SBarry Smith { 1828ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 1838ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 184e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1858ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 18647c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 18747c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 18847c6ae99SBarry Smith PetscScalar v[2],x; 18947c6ae99SBarry Smith Mat mat; 190bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 191fdc842d1SBarry Smith MatType mattype; 19247c6ae99SBarry Smith 19347c6ae99SBarry Smith PetscFunctionBegin; 1949566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&bx,NULL,NULL,NULL)); 1959566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 196bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 1977a8be351SBarry Smith PetscCheck(Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 19847c6ae99SBarry Smith ratio = mx/Mx; 199*08401ef6SPierre Jolivet PetscCheck(ratio*Mx == mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 20047c6ae99SBarry Smith } else { 201*08401ef6SPierre Jolivet PetscCheck(Mx >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 20247c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 2032c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratio*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 20447c6ae99SBarry Smith } 20547c6ae99SBarry Smith 2069566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,NULL,NULL,&m_f,NULL,NULL)); 2079566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,NULL,NULL,&m_ghost,NULL,NULL)); 2089566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 2099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 21047c6ae99SBarry Smith 2119566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,NULL,NULL,&m_c,NULL,NULL)); 2129566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,NULL,NULL,&m_ghost_c,NULL,NULL)); 2139566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 2149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 21547c6ae99SBarry Smith 21647c6ae99SBarry Smith /* create interpolation matrix */ 2179566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dac),&mat)); 218fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 219fdc842d1SBarry Smith /* 220fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 221fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 222fdc842d1SBarry Smith */ 223fdc842d1SBarry Smith if (dof > 1) { 2249566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(mat,PETSC_TRUE)); 225fdc842d1SBarry Smith } 226fdc842d1SBarry Smith #endif 2279566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat,m_f,m_c,mx,Mx)); 2289566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype,&mattype)); 2299566063dSJacob Faibussowitsch PetscCall(MatSetType(mat,mattype)); 2309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat,2,NULL)); 2319566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat,2,NULL,0,NULL)); 23247c6ae99SBarry Smith 23347c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 23447c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 23547c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 236e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 23747c6ae99SBarry Smith 23847c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 23947c6ae99SBarry Smith 24047c6ae99SBarry Smith /* 24147c6ae99SBarry Smith Only include those interpolation points that are truly 24247c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 24347c6ae99SBarry Smith in x direction; since they have no right neighbor 24447c6ae99SBarry Smith */ 2456712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 24647c6ae99SBarry Smith nc = 0; 24747c6ae99SBarry Smith /* one left and below; or we are right on it */ 248e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 249e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 25047c6ae99SBarry Smith v[nc++] = -x + 1.0; 25147c6ae99SBarry Smith /* one right? */ 25247c6ae99SBarry Smith if (i_c*ratio != i) { 253e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 25447c6ae99SBarry Smith v[nc++] = x; 25547c6ae99SBarry Smith } 2569566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES)); 25747c6ae99SBarry Smith } 2589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 2599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 2609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 2619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 2629566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat,dof,A)); 2639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 2649566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(5.0*m_f)); 26547c6ae99SBarry Smith PetscFunctionReturn(0); 26647c6ae99SBarry Smith } 26747c6ae99SBarry Smith 268e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A) 26947c6ae99SBarry Smith { 27047c6ae99SBarry Smith PetscErrorCode ierr; 2718ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 2728ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 273e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 2748ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 27547c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 27647c6ae99SBarry 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; 27747c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 27847c6ae99SBarry Smith PetscScalar v[4],x,y; 27947c6ae99SBarry Smith Mat mat; 280bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 281fdc842d1SBarry Smith MatType mattype; 28247c6ae99SBarry Smith 28347c6ae99SBarry Smith PetscFunctionBegin; 2849566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,&My,NULL,NULL,NULL,NULL,NULL,NULL,&bx,&by,NULL,NULL)); 2859566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,&my,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 286bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 2877a8be351SBarry Smith PetscCheck(Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 28847c6ae99SBarry Smith ratioi = mx/Mx; 289*08401ef6SPierre Jolivet PetscCheck(ratioi*Mx == mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 29047c6ae99SBarry Smith } else { 291*08401ef6SPierre Jolivet PetscCheck(Mx >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 29247c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 2932c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 29447c6ae99SBarry Smith } 295bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 2967a8be351SBarry Smith PetscCheck(My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 29747c6ae99SBarry Smith ratioj = my/My; 298*08401ef6SPierre Jolivet PetscCheck(ratioj*My == my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 29947c6ae99SBarry Smith } else { 300*08401ef6SPierre Jolivet PetscCheck(My >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be greater than 1",My); 30147c6ae99SBarry Smith ratioj = (my-1)/(My-1); 3022c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 30347c6ae99SBarry Smith } 30447c6ae99SBarry Smith 3059566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,&j_start,NULL,&m_f,&n_f,NULL)); 3069566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,NULL,&m_ghost,&n_ghost,NULL)); 3079566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 3089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 30947c6ae99SBarry Smith 3109566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,&j_start_c,NULL,&m_c,&n_c,NULL)); 3119566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,NULL,&m_ghost_c,&n_ghost_c,NULL)); 3129566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 3139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 31447c6ae99SBarry Smith 31547c6ae99SBarry Smith /* 316aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 31747c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 31847c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 31947c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 32047c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 32147c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 32247c6ae99SBarry Smith 32347c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 32447c6ae99SBarry Smith */ 3259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c)); 3269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f)); 3279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f)); 32847c6ae99SBarry Smith col_scale = size_f/size_c; 32947c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 33047c6ae99SBarry Smith 3319566063dSJacob Faibussowitsch ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);PetscCall(ierr); 33247c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 33347c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 33447c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 335e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 33647c6ae99SBarry Smith 33747c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 33847c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 33947c6ae99SBarry Smith 340*08401ef6SPierre Jolivet PetscCheck(j_c >= j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 34147c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 342*08401ef6SPierre Jolivet PetscCheck(i_c >= i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 34347c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 34447c6ae99SBarry Smith 34547c6ae99SBarry Smith /* 34647c6ae99SBarry Smith Only include those interpolation points that are truly 34747c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 34847c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 34947c6ae99SBarry Smith */ 35047c6ae99SBarry Smith nc = 0; 35147c6ae99SBarry Smith /* one left and below; or we are right on it */ 352e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 353e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 35447c6ae99SBarry Smith /* one right and below */ 355e3fbd1f4SBarry Smith if (i_c*ratioi != i) cols[nc++] = col_shift + idx_c[col+1]; 35647c6ae99SBarry Smith /* one left and above */ 357e3fbd1f4SBarry Smith if (j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+m_ghost_c]; 35847c6ae99SBarry Smith /* one right and above */ 359e3fbd1f4SBarry Smith if (i_c*ratioi != i && j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)]; 3609566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row,nc,cols,dnz,onz)); 36147c6ae99SBarry Smith } 36247c6ae99SBarry Smith } 3639566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)daf),&mat)); 364fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 365fdc842d1SBarry Smith /* 366fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 367fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 368fdc842d1SBarry Smith */ 369fdc842d1SBarry Smith if (dof > 1) { 3709566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(mat,PETSC_TRUE)); 371fdc842d1SBarry Smith } 372fdc842d1SBarry Smith #endif 3739566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My)); 3749566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype,&mattype)); 3759566063dSJacob Faibussowitsch PetscCall(MatSetType(mat,mattype)); 3769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat,0,dnz)); 3779566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat,0,dnz,0,onz)); 3789566063dSJacob Faibussowitsch ierr = MatPreallocateFinalize(dnz,onz);PetscCall(ierr); 37947c6ae99SBarry Smith 38047c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 38185afcc9aSBarry Smith if (!NEWVERSION) { 382b3bd94feSDave May 38347c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 38447c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 38547c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 386e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 38747c6ae99SBarry Smith 38847c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 38947c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 39047c6ae99SBarry Smith 39147c6ae99SBarry Smith /* 39247c6ae99SBarry Smith Only include those interpolation points that are truly 39347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 39447c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 39547c6ae99SBarry Smith */ 3966712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 3976712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 398b3bd94feSDave May 39947c6ae99SBarry Smith nc = 0; 40047c6ae99SBarry Smith /* one left and below; or we are right on it */ 401e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 402e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 40347c6ae99SBarry Smith v[nc++] = x*y - x - y + 1.0; 40447c6ae99SBarry Smith /* one right and below */ 40547c6ae99SBarry Smith if (i_c*ratioi != i) { 406e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+1]; 40747c6ae99SBarry Smith v[nc++] = -x*y + x; 40847c6ae99SBarry Smith } 40947c6ae99SBarry Smith /* one left and above */ 41047c6ae99SBarry Smith if (j_c*ratioj != j) { 411e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+m_ghost_c]; 41247c6ae99SBarry Smith v[nc++] = -x*y + y; 41347c6ae99SBarry Smith } 41447c6ae99SBarry Smith /* one right and above */ 41547c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 416e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)]; 41747c6ae99SBarry Smith v[nc++] = x*y; 41847c6ae99SBarry Smith } 4199566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES)); 42047c6ae99SBarry Smith } 42147c6ae99SBarry Smith } 422b3bd94feSDave May 423b3bd94feSDave May } else { 424b3bd94feSDave May PetscScalar Ni[4]; 425b3bd94feSDave May PetscScalar *xi,*eta; 426b3bd94feSDave May PetscInt li,nxi,lj,neta; 427b3bd94feSDave May 428b3bd94feSDave May /* compute local coordinate arrays */ 429b3bd94feSDave May nxi = ratioi + 1; 430b3bd94feSDave May neta = ratioj + 1; 4319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nxi,&xi)); 4329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(neta,&eta)); 433b3bd94feSDave May for (li=0; li<nxi; li++) { 43452218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 435b3bd94feSDave May } 436b3bd94feSDave May for (lj=0; lj<neta; lj++) { 43752218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 438b3bd94feSDave May } 439b3bd94feSDave May 440b3bd94feSDave May /* loop over local fine grid nodes setting interpolation for those*/ 441b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 442b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 443b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 444e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 445b3bd94feSDave May 446b3bd94feSDave May i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 447b3bd94feSDave May j_c = (j/ratioj); /* coarse grid node below fine grid node */ 448b3bd94feSDave May 449b3bd94feSDave May /* remainders */ 450b3bd94feSDave May li = i - ratioi * (i/ratioi); 4518865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 452b3bd94feSDave May lj = j - ratioj * (j/ratioj); 4538865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 454b3bd94feSDave May 455b3bd94feSDave May /* corners */ 456e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 457e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 458b3bd94feSDave May Ni[0] = 1.0; 459b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 460b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 4619566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES)); 462b3bd94feSDave May continue; 463b3bd94feSDave May } 464b3bd94feSDave May } 465b3bd94feSDave May 466b3bd94feSDave May /* edges + interior */ 467b3bd94feSDave May /* remainders */ 4688865f1eaSKarl Rupp if (i==mx-1) i_c--; 4698865f1eaSKarl Rupp if (j==my-1) j_c--; 470b3bd94feSDave May 471e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 472e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 473e3fbd1f4SBarry Smith cols[1] = col_shift + idx_c[col+1]; /* right, below */ 474e3fbd1f4SBarry Smith cols[2] = col_shift + idx_c[col+m_ghost_c]; /* left, above */ 475e3fbd1f4SBarry Smith cols[3] = col_shift + idx_c[col+(m_ghost_c+1)]; /* right, above */ 476b3bd94feSDave May 477b3bd94feSDave May Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]); 478b3bd94feSDave May Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]); 479b3bd94feSDave May Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]); 480b3bd94feSDave May Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]); 481b3bd94feSDave May 482b3bd94feSDave May nc = 0; 4838865f1eaSKarl Rupp if (PetscAbsScalar(Ni[0])<1.0e-32) cols[0]=-1; 4848865f1eaSKarl Rupp if (PetscAbsScalar(Ni[1])<1.0e-32) cols[1]=-1; 4858865f1eaSKarl Rupp if (PetscAbsScalar(Ni[2])<1.0e-32) cols[2]=-1; 4868865f1eaSKarl Rupp if (PetscAbsScalar(Ni[3])<1.0e-32) cols[3]=-1; 487b3bd94feSDave May 4889566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES)); 489b3bd94feSDave May } 490b3bd94feSDave May } 4919566063dSJacob Faibussowitsch PetscCall(PetscFree(xi)); 4929566063dSJacob Faibussowitsch PetscCall(PetscFree(eta)); 493b3bd94feSDave May } 4949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 4959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 4969566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 4979566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 4989566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat,dof,A)); 4999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 50047c6ae99SBarry Smith PetscFunctionReturn(0); 50147c6ae99SBarry Smith } 50247c6ae99SBarry Smith 50347c6ae99SBarry Smith /* 50447c6ae99SBarry Smith Contributed by Andrei Draganescu <aidraga@sandia.gov> 50547c6ae99SBarry Smith */ 506e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A) 50747c6ae99SBarry Smith { 50847c6ae99SBarry Smith PetscErrorCode ierr; 5098ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 5108ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 511e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 5128ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 51347c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 51447c6ae99SBarry 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; 51547c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 51647c6ae99SBarry Smith PetscScalar v[4]; 51747c6ae99SBarry Smith Mat mat; 518bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 519fdc842d1SBarry Smith MatType mattype; 52047c6ae99SBarry Smith 52147c6ae99SBarry Smith PetscFunctionBegin; 5229566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,&My,NULL,NULL,NULL,NULL,NULL,NULL,&bx,&by,NULL,NULL)); 5239566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,&my,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 5247a8be351SBarry Smith PetscCheck(Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 5257a8be351SBarry Smith PetscCheck(My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 52647c6ae99SBarry Smith ratioi = mx/Mx; 52747c6ae99SBarry Smith ratioj = my/My; 528*08401ef6SPierre Jolivet PetscCheck(ratioi*Mx == mx,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 529*08401ef6SPierre Jolivet PetscCheck(ratioj*My == my,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 530*08401ef6SPierre Jolivet PetscCheck(ratioi == 2,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2"); 531*08401ef6SPierre Jolivet PetscCheck(ratioj == 2,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2"); 53247c6ae99SBarry Smith 5339566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,&j_start,NULL,&m_f,&n_f,NULL)); 5349566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,NULL,&m_ghost,&n_ghost,NULL)); 5359566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 5369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 53747c6ae99SBarry Smith 5389566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,&j_start_c,NULL,&m_c,&n_c,NULL)); 5399566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,NULL,&m_ghost_c,&n_ghost_c,NULL)); 5409566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 5419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 54247c6ae99SBarry Smith 54347c6ae99SBarry Smith /* 544aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 54547c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 54647c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 54747c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 54847c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 54947c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 55047c6ae99SBarry Smith 55147c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 55247c6ae99SBarry Smith */ 5539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c)); 5549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f)); 5559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f)); 55647c6ae99SBarry Smith col_scale = size_f/size_c; 55747c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 55847c6ae99SBarry Smith 5599566063dSJacob Faibussowitsch ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);PetscCall(ierr); 56047c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 56147c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 56247c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 563e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 56447c6ae99SBarry Smith 56547c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 56647c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 56747c6ae99SBarry Smith 568*08401ef6SPierre Jolivet PetscCheck(j_c >= j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 56947c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 570*08401ef6SPierre Jolivet PetscCheck(i_c >= i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 57147c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 57247c6ae99SBarry Smith 57347c6ae99SBarry Smith /* 57447c6ae99SBarry Smith Only include those interpolation points that are truly 57547c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 57647c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 57747c6ae99SBarry Smith */ 57847c6ae99SBarry Smith nc = 0; 57947c6ae99SBarry Smith /* one left and below; or we are right on it */ 580e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 581e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 5829566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row,nc,cols,dnz,onz)); 58347c6ae99SBarry Smith } 58447c6ae99SBarry Smith } 5859566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)daf),&mat)); 586fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 587fdc842d1SBarry Smith /* 588fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 589fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 590fdc842d1SBarry Smith */ 591fdc842d1SBarry Smith if (dof > 1) { 5929566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(mat,PETSC_TRUE)); 593fdc842d1SBarry Smith } 594fdc842d1SBarry Smith #endif 5959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My)); 5969566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype,&mattype)); 5979566063dSJacob Faibussowitsch PetscCall(MatSetType(mat,mattype)); 5989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat,0,dnz)); 5999566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat,0,dnz,0,onz)); 6009566063dSJacob Faibussowitsch ierr = MatPreallocateFinalize(dnz,onz);PetscCall(ierr); 60147c6ae99SBarry Smith 60247c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 60347c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 60447c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 60547c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 606e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 60747c6ae99SBarry Smith 60847c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 60947c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 61047c6ae99SBarry Smith nc = 0; 61147c6ae99SBarry Smith /* one left and below; or we are right on it */ 612e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 613e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 61447c6ae99SBarry Smith v[nc++] = 1.0; 61547c6ae99SBarry Smith 6169566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES)); 61747c6ae99SBarry Smith } 61847c6ae99SBarry Smith } 6199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 6209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 6219566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 6229566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 6239566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat,dof,A)); 6249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 6259566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(13.0*m_f*n_f)); 62647c6ae99SBarry Smith PetscFunctionReturn(0); 62747c6ae99SBarry Smith } 62847c6ae99SBarry Smith 62947c6ae99SBarry Smith /* 63047c6ae99SBarry Smith Contributed by Jianming Yang <jianming-yang@uiowa.edu> 63147c6ae99SBarry Smith */ 632e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A) 63347c6ae99SBarry Smith { 63447c6ae99SBarry Smith PetscErrorCode ierr; 6358ea3bf28SBarry Smith PetscInt i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,dof; 6368ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 637e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 6388ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz; 63947c6ae99SBarry 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; 64047c6ae99SBarry 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; 64147c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 64247c6ae99SBarry Smith PetscScalar v[8]; 64347c6ae99SBarry Smith Mat mat; 644bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 645fdc842d1SBarry Smith MatType mattype; 64647c6ae99SBarry Smith 64747c6ae99SBarry Smith PetscFunctionBegin; 6489566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,&My,&Mz,NULL,NULL,NULL,NULL,NULL,&bx,&by,&bz,NULL)); 6497a8be351SBarry Smith PetscCheck(Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 6507a8be351SBarry Smith PetscCheck(My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 6517a8be351SBarry Smith PetscCheck(Mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 6529566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,&my,&mz,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 65347c6ae99SBarry Smith ratioi = mx/Mx; 65447c6ae99SBarry Smith ratioj = my/My; 65547c6ae99SBarry Smith ratiol = mz/Mz; 656*08401ef6SPierre Jolivet PetscCheck(ratioi*Mx == mx,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 657*08401ef6SPierre Jolivet PetscCheck(ratioj*My == my,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 658*08401ef6SPierre Jolivet PetscCheck(ratiol*Mz == mz,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z"); 6592c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi != 2 && ratioi != 1,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2"); 6602c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj != 2 && ratioj != 1,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2"); 6612c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiol != 2 && ratiol != 1,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2"); 66247c6ae99SBarry Smith 6639566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f)); 6649566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost)); 6659566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 6669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 66747c6ae99SBarry Smith 6689566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c)); 6699566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c)); 6709566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 6719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 672e3fbd1f4SBarry Smith 67347c6ae99SBarry Smith /* 674aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 67547c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 67647c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 67747c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 67847c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 67947c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 68047c6ae99SBarry Smith 68147c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 68247c6ae99SBarry Smith */ 6839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c)); 6849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f)); 6859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f)); 68647c6ae99SBarry Smith col_scale = size_f/size_c; 68747c6ae99SBarry Smith col_shift = Mx*My*Mz*(rank_f/size_c); 68847c6ae99SBarry Smith 6899566063dSJacob Faibussowitsch ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);PetscCall(ierr); 69047c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 69147c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 69247c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 69347c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 694e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 69547c6ae99SBarry Smith 69647c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 69747c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 69847c6ae99SBarry Smith l_c = (l/ratiol); 69947c6ae99SBarry Smith 700*08401ef6SPierre Jolivet PetscCheck(l_c >= l_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70147c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 702*08401ef6SPierre Jolivet PetscCheck(j_c >= j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70347c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 704*08401ef6SPierre Jolivet PetscCheck(i_c >= i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 70547c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 70647c6ae99SBarry Smith 70747c6ae99SBarry Smith /* 70847c6ae99SBarry Smith Only include those interpolation points that are truly 70947c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 71047c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 71147c6ae99SBarry Smith */ 71247c6ae99SBarry Smith nc = 0; 71347c6ae99SBarry Smith /* one left and below; or we are right on it */ 714e3fbd1f4SBarry 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)); 715e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 7169566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row,nc,cols,dnz,onz)); 71747c6ae99SBarry Smith } 71847c6ae99SBarry Smith } 71947c6ae99SBarry Smith } 7209566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)daf),&mat)); 721fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 722fdc842d1SBarry Smith /* 723fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 724fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 725fdc842d1SBarry Smith */ 726fdc842d1SBarry Smith if (dof > 1) { 7279566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(mat,PETSC_TRUE)); 728fdc842d1SBarry Smith } 729fdc842d1SBarry Smith #endif 7309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat,m_f*n_f*p_f,col_scale*m_c*n_c*p_c,mx*my*mz,col_scale*Mx*My*Mz)); 7319566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype,&mattype)); 7329566063dSJacob Faibussowitsch PetscCall(MatSetType(mat,mattype)); 7339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat,0,dnz)); 7349566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat,0,dnz,0,onz)); 7359566063dSJacob Faibussowitsch ierr = MatPreallocateFinalize(dnz,onz);PetscCall(ierr); 73647c6ae99SBarry Smith 73747c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 73847c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 73947c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 74047c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 74147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 742e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 74347c6ae99SBarry Smith 74447c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 74547c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 74647c6ae99SBarry Smith l_c = (l/ratiol); 74747c6ae99SBarry Smith nc = 0; 74847c6ae99SBarry Smith /* one left and below; or we are right on it */ 749e3fbd1f4SBarry 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)); 750e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 75147c6ae99SBarry Smith v[nc++] = 1.0; 75247c6ae99SBarry Smith 7539566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES)); 75447c6ae99SBarry Smith } 75547c6ae99SBarry Smith } 75647c6ae99SBarry Smith } 7579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 7589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 7599566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 7609566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 7619566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat,dof,A)); 7629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 7639566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(13.0*m_f*n_f*p_f)); 76447c6ae99SBarry Smith PetscFunctionReturn(0); 76547c6ae99SBarry Smith } 76647c6ae99SBarry Smith 767e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A) 76847c6ae99SBarry Smith { 76947c6ae99SBarry Smith PetscErrorCode ierr; 7708ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof,l; 7718ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 772e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 7738ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,Mz,mz; 77447c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok; 77547c6ae99SBarry Smith PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 77647c6ae99SBarry Smith PetscInt l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c; 77747c6ae99SBarry Smith PetscInt l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz; 77847c6ae99SBarry Smith PetscScalar v[8],x,y,z; 77947c6ae99SBarry Smith Mat mat; 780bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 781fdc842d1SBarry Smith MatType mattype; 78247c6ae99SBarry Smith 78347c6ae99SBarry Smith PetscFunctionBegin; 7849566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,&My,&Mz,NULL,NULL,NULL,NULL,NULL,&bx,&by,&bz,NULL)); 7859566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,&my,&mz,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 78647c6ae99SBarry Smith if (mx == Mx) { 78747c6ae99SBarry Smith ratioi = 1; 788bff4a2f0SMatthew G. Knepley } else if (bx == DM_BOUNDARY_PERIODIC) { 7897a8be351SBarry Smith PetscCheck(Mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 79047c6ae99SBarry Smith ratioi = mx/Mx; 791*08401ef6SPierre Jolivet PetscCheck(ratioi*Mx == mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 79247c6ae99SBarry Smith } else { 793*08401ef6SPierre Jolivet PetscCheck(Mx >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 79447c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 7952c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 79647c6ae99SBarry Smith } 79747c6ae99SBarry Smith if (my == My) { 79847c6ae99SBarry Smith ratioj = 1; 799bff4a2f0SMatthew G. Knepley } else if (by == DM_BOUNDARY_PERIODIC) { 8007a8be351SBarry Smith PetscCheck(My,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 80147c6ae99SBarry Smith ratioj = my/My; 802*08401ef6SPierre Jolivet PetscCheck(ratioj*My == my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 80347c6ae99SBarry Smith } else { 804*08401ef6SPierre Jolivet PetscCheck(My >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be greater than 1",My); 80547c6ae99SBarry Smith ratioj = (my-1)/(My-1); 8062c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 80747c6ae99SBarry Smith } 80847c6ae99SBarry Smith if (mz == Mz) { 80947c6ae99SBarry Smith ratiok = 1; 810bff4a2f0SMatthew G. Knepley } else if (bz == DM_BOUNDARY_PERIODIC) { 8117a8be351SBarry Smith PetscCheck(Mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 81247c6ae99SBarry Smith ratiok = mz/Mz; 813*08401ef6SPierre Jolivet PetscCheck(ratiok*Mz == mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D Mz %D",mz,Mz); 81447c6ae99SBarry Smith } else { 815*08401ef6SPierre Jolivet PetscCheck(Mz >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be greater than 1",Mz); 81647c6ae99SBarry Smith ratiok = (mz-1)/(Mz-1); 8172c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiok*(Mz-1) != mz-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 81847c6ae99SBarry Smith } 81947c6ae99SBarry Smith 8209566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f)); 8219566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost)); 8229566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 8239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 82447c6ae99SBarry Smith 8259566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c)); 8269566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c)); 8279566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 8289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 82947c6ae99SBarry Smith 83047c6ae99SBarry Smith /* create interpolation matrix, determining exact preallocation */ 8319566063dSJacob Faibussowitsch ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)dac),m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);PetscCall(ierr); 83247c6ae99SBarry Smith /* loop over local fine grid nodes counting interpolating points */ 83347c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 83447c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 83547c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 83647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 837e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 83847c6ae99SBarry Smith i_c = (i/ratioi); 83947c6ae99SBarry Smith j_c = (j/ratioj); 84047c6ae99SBarry Smith l_c = (l/ratiok); 841*08401ef6SPierre Jolivet PetscCheck(l_c >= l_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84247c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 843*08401ef6SPierre Jolivet PetscCheck(j_c >= j_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84447c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 845*08401ef6SPierre Jolivet PetscCheck(i_c >= i_start_ghost_c,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 84647c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 84747c6ae99SBarry Smith 84847c6ae99SBarry Smith /* 84947c6ae99SBarry Smith Only include those interpolation points that are truly 85047c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 85147c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 85247c6ae99SBarry Smith */ 85347c6ae99SBarry Smith nc = 0; 854e3fbd1f4SBarry 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)); 855e3fbd1f4SBarry Smith cols[nc++] = idx_c[col]; 85647c6ae99SBarry Smith if (i_c*ratioi != i) { 857e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+1]; 85847c6ae99SBarry Smith } 85947c6ae99SBarry Smith if (j_c*ratioj != j) { 860e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c]; 86147c6ae99SBarry Smith } 86247c6ae99SBarry Smith if (l_c*ratiok != l) { 863e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c]; 86447c6ae99SBarry Smith } 86547c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 866e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c+1)]; 86747c6ae99SBarry Smith } 86847c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 869e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 87047c6ae99SBarry Smith } 87147c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 872e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 87347c6ae99SBarry Smith } 87447c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 875e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 87647c6ae99SBarry Smith } 8779566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row,nc,cols,dnz,onz)); 87847c6ae99SBarry Smith } 87947c6ae99SBarry Smith } 88047c6ae99SBarry Smith } 8819566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dac),&mat)); 882fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 883fdc842d1SBarry Smith /* 884fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 885fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 886fdc842d1SBarry Smith */ 887fdc842d1SBarry Smith if (dof > 1) { 8889566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(mat,PETSC_TRUE)); 889fdc842d1SBarry Smith } 890fdc842d1SBarry Smith #endif 8919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz)); 8929566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype,&mattype)); 8939566063dSJacob Faibussowitsch PetscCall(MatSetType(mat,mattype)); 8949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat,0,dnz)); 8959566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat,0,dnz,0,onz)); 8969566063dSJacob Faibussowitsch ierr = MatPreallocateFinalize(dnz,onz);PetscCall(ierr); 89747c6ae99SBarry Smith 89847c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 8992adb9dcfSBarry Smith if (!NEWVERSION) { 900b3bd94feSDave May 90147c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 90247c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 90347c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 90447c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 905e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 90647c6ae99SBarry Smith 90747c6ae99SBarry Smith i_c = (i/ratioi); 90847c6ae99SBarry Smith j_c = (j/ratioj); 90947c6ae99SBarry Smith l_c = (l/ratiok); 91047c6ae99SBarry Smith 91147c6ae99SBarry Smith /* 91247c6ae99SBarry Smith Only include those interpolation points that are truly 91347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 91447c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 91547c6ae99SBarry Smith */ 9166712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 9176712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 9186712e2f1SBarry Smith z = ((PetscReal)(l - l_c*ratiok))/((PetscReal)ratiok); 919b3bd94feSDave May 92047c6ae99SBarry Smith nc = 0; 92147c6ae99SBarry Smith /* one left and below; or we are right on it */ 922e3fbd1f4SBarry 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)); 92347c6ae99SBarry Smith 924e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 92547c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 92647c6ae99SBarry Smith 92747c6ae99SBarry Smith if (i_c*ratioi != i) { 928e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 92947c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 93047c6ae99SBarry Smith } 93147c6ae99SBarry Smith 93247c6ae99SBarry Smith if (j_c*ratioj != j) { 933e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c]; 93447c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 93547c6ae99SBarry Smith } 93647c6ae99SBarry Smith 93747c6ae99SBarry Smith if (l_c*ratiok != l) { 938e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c*n_ghost_c]; 93947c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 94047c6ae99SBarry Smith } 94147c6ae99SBarry Smith 94247c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 943e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c+1)]; 94447c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 94547c6ae99SBarry Smith } 94647c6ae99SBarry Smith 94747c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 948e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 94947c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 95047c6ae99SBarry Smith } 95147c6ae99SBarry Smith 95247c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 953e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 95447c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 95547c6ae99SBarry Smith } 95647c6ae99SBarry Smith 95747c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 958e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 95947c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 96047c6ae99SBarry Smith } 9619566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES)); 96247c6ae99SBarry Smith } 96347c6ae99SBarry Smith } 96447c6ae99SBarry Smith } 965b3bd94feSDave May 966b3bd94feSDave May } else { 967b3bd94feSDave May PetscScalar *xi,*eta,*zeta; 968b3bd94feSDave May PetscInt li,nxi,lj,neta,lk,nzeta,n; 969b3bd94feSDave May PetscScalar Ni[8]; 970b3bd94feSDave May 971b3bd94feSDave May /* compute local coordinate arrays */ 972b3bd94feSDave May nxi = ratioi + 1; 973b3bd94feSDave May neta = ratioj + 1; 974b3bd94feSDave May nzeta = ratiok + 1; 9759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nxi,&xi)); 9769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(neta,&eta)); 9779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzeta,&zeta)); 9788865f1eaSKarl Rupp for (li=0; li<nxi; li++) xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 9798865f1eaSKarl Rupp for (lj=0; lj<neta; lj++) eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 9808865f1eaSKarl Rupp for (lk=0; lk<nzeta; lk++) zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1)); 981b3bd94feSDave May 982b3bd94feSDave May for (l=l_start; l<l_start+p_f; l++) { 983b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 984b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 985b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 986e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 987b3bd94feSDave May 988b3bd94feSDave May i_c = (i/ratioi); 989b3bd94feSDave May j_c = (j/ratioj); 990b3bd94feSDave May l_c = (l/ratiok); 991b3bd94feSDave May 992b3bd94feSDave May /* remainders */ 993b3bd94feSDave May li = i - ratioi * (i/ratioi); 9948865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 995b3bd94feSDave May lj = j - ratioj * (j/ratioj); 9968865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 997b3bd94feSDave May lk = l - ratiok * (l/ratiok); 9988865f1eaSKarl Rupp if (l==mz-1) lk = nzeta-1; 999b3bd94feSDave May 1000b3bd94feSDave May /* corners */ 1001e3fbd1f4SBarry 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)); 1002e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 1003b3bd94feSDave May Ni[0] = 1.0; 1004b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 1005b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 1006b3bd94feSDave May if ((lk==0) || (lk==nzeta-1)) { 10079566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES)); 1008b3bd94feSDave May continue; 1009b3bd94feSDave May } 1010b3bd94feSDave May } 1011b3bd94feSDave May } 1012b3bd94feSDave May 1013b3bd94feSDave May /* edges + interior */ 1014b3bd94feSDave May /* remainders */ 10158865f1eaSKarl Rupp if (i==mx-1) i_c--; 10168865f1eaSKarl Rupp if (j==my-1) j_c--; 10178865f1eaSKarl Rupp if (l==mz-1) l_c--; 1018b3bd94feSDave May 1019e3fbd1f4SBarry 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)); 1020e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 1021e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; /* one right and below */ 1022e3fbd1f4SBarry Smith cols[2] = idx_c[col+m_ghost_c]; /* one left and above */ 1023e3fbd1f4SBarry Smith cols[3] = idx_c[col+(m_ghost_c+1)]; /* one right and above */ 1024b3bd94feSDave May 1025e3fbd1f4SBarry Smith cols[4] = idx_c[col+m_ghost_c*n_ghost_c]; /* one left and below and front; or we are right on it */ 1026e3fbd1f4SBarry Smith cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; /* one right and below, and front */ 1027e3fbd1f4SBarry Smith cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; /* one left and above and front*/ 1028e3fbd1f4SBarry Smith cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; /* one right and above and front */ 1029b3bd94feSDave May 1030b3bd94feSDave May Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 1031b3bd94feSDave May Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 1032b3bd94feSDave May Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 1033b3bd94feSDave May Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 1034b3bd94feSDave May 1035b3bd94feSDave May Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 1036b3bd94feSDave May Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 1037b3bd94feSDave May Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 1038b3bd94feSDave May Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 1039b3bd94feSDave May 1040b3bd94feSDave May for (n=0; n<8; n++) { 10418865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 1042b3bd94feSDave May } 10439566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES)); 1044b3bd94feSDave May 1045b3bd94feSDave May } 1046b3bd94feSDave May } 1047b3bd94feSDave May } 10489566063dSJacob Faibussowitsch PetscCall(PetscFree(xi)); 10499566063dSJacob Faibussowitsch PetscCall(PetscFree(eta)); 10509566063dSJacob Faibussowitsch PetscCall(PetscFree(zeta)); 1051b3bd94feSDave May } 10529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 10539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 10549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY)); 10559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY)); 105647c6ae99SBarry Smith 10579566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat,dof,A)); 10589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 105947c6ae99SBarry Smith PetscFunctionReturn(0); 106047c6ae99SBarry Smith } 106147c6ae99SBarry Smith 1062e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale) 106347c6ae99SBarry Smith { 106447c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1065bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1066aa219208SBarry Smith DMDAStencilType stc,stf; 106747c6ae99SBarry Smith DM_DA *ddc = (DM_DA*)dac->data; 106847c6ae99SBarry Smith 106947c6ae99SBarry Smith PetscFunctionBegin; 107047c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 107147c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 107247c6ae99SBarry Smith PetscValidPointer(A,3); 107347c6ae99SBarry Smith if (scale) PetscValidPointer(scale,4); 107447c6ae99SBarry Smith 10759566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc)); 10769566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf)); 1077*08401ef6SPierre Jolivet PetscCheck(dimc == dimf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1078*08401ef6SPierre Jolivet PetscCheck(dofc == doff,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1079*08401ef6SPierre Jolivet PetscCheck(sc == sf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 10802c71b3e2SJacob Faibussowitsch PetscCheckFalse(bxc != bxf || byc != byf || bzc != bzf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1081*08401ef6SPierre Jolivet PetscCheck(stc == stf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 10822c71b3e2SJacob Faibussowitsch PetscCheckFalse(Mc < 2 && Mf > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 10832c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 1 && Nc < 2 && Nf > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 10842c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 2 && Pc < 2 && Pf > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 108547c6ae99SBarry Smith 1086aa219208SBarry Smith if (ddc->interptype == DMDA_Q1) { 108747c6ae99SBarry Smith if (dimc == 1) { 10889566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_1D_Q1(dac,daf,A)); 108947c6ae99SBarry Smith } else if (dimc == 2) { 10909566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_2D_Q1(dac,daf,A)); 109147c6ae99SBarry Smith } else if (dimc == 3) { 10929566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_3D_Q1(dac,daf,A)); 109398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 1094aa219208SBarry Smith } else if (ddc->interptype == DMDA_Q0) { 109547c6ae99SBarry Smith if (dimc == 1) { 10969566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_1D_Q0(dac,daf,A)); 109747c6ae99SBarry Smith } else if (dimc == 2) { 10989566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_2D_Q0(dac,daf,A)); 109947c6ae99SBarry Smith } else if (dimc == 3) { 11009566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_3D_Q0(dac,daf,A)); 110198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 110247c6ae99SBarry Smith } 110347c6ae99SBarry Smith if (scale) { 11049566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale((DM)dac,(DM)daf,*A,scale)); 110547c6ae99SBarry Smith } 110647c6ae99SBarry Smith PetscFunctionReturn(0); 110747c6ae99SBarry Smith } 110847c6ae99SBarry Smith 1109e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_1D(DM dac,DM daf,VecScatter *inject) 11100bb2b966SJungho Lee { 11118ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx,dof; 11128ea3bf28SBarry Smith const PetscInt *idx_f; 1113e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f; 11148ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 11150bb2b966SJungho Lee PetscInt row,i_start_ghost,mx,m_c,nc,ratioi; 11160bb2b966SJungho Lee PetscInt i_start_c,i_start_ghost_c; 11170bb2b966SJungho Lee PetscInt *cols; 1118bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 11190bb2b966SJungho Lee Vec vecf,vecc; 11200bb2b966SJungho Lee IS isf; 11210bb2b966SJungho Lee 11220bb2b966SJungho Lee PetscFunctionBegin; 11239566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&bx,NULL,NULL,NULL)); 11249566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 1125bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 11260bb2b966SJungho Lee ratioi = mx/Mx; 1127*08401ef6SPierre Jolivet PetscCheck(ratioi*Mx == mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 11280bb2b966SJungho Lee } else { 11290bb2b966SJungho Lee ratioi = (mx-1)/(Mx-1); 11302c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 11310bb2b966SJungho Lee } 11320bb2b966SJungho Lee 11339566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,NULL,NULL,&m_f,NULL,NULL)); 11349566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,NULL,NULL,&m_ghost,NULL,NULL)); 11359566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 11369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 11370bb2b966SJungho Lee 11389566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,NULL,NULL,&m_c,NULL,NULL)); 11399566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,NULL,NULL,&m_ghost_c,NULL,NULL)); 11400bb2b966SJungho Lee 11410bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 11420bb2b966SJungho Lee nc = 0; 11439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m_f,&cols)); 11440bb2b966SJungho Lee 11450bb2b966SJungho Lee for (i=i_start_c; i<i_start_c+m_c; i++) { 11460bb2b966SJungho Lee PetscInt i_f = i*ratioi; 11470bb2b966SJungho Lee 11482c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\ni_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 11498865f1eaSKarl Rupp 1150e3fbd1f4SBarry Smith row = idx_f[(i_f-i_start_ghost)]; 1151e3fbd1f4SBarry Smith cols[nc++] = row; 11520bb2b966SJungho Lee } 11530bb2b966SJungho Lee 11549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 11559566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf)); 11569566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dac,&vecc)); 11579566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(daf,&vecf)); 11589566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vecf,isf,vecc,NULL,inject)); 11599566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dac,&vecc)); 11609566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(daf,&vecf)); 11619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isf)); 11620bb2b966SJungho Lee PetscFunctionReturn(0); 11630bb2b966SJungho Lee } 11640bb2b966SJungho Lee 1165e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject) 116647c6ae99SBarry Smith { 11678ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 11688ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1169e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 11708ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c; 117147c6ae99SBarry Smith PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; 1172076202ddSJed Brown PetscInt i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 117347c6ae99SBarry Smith PetscInt *cols; 1174bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 117547c6ae99SBarry Smith Vec vecf,vecc; 117647c6ae99SBarry Smith IS isf; 117747c6ae99SBarry Smith 117847c6ae99SBarry Smith PetscFunctionBegin; 11799566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,&My,NULL,NULL,NULL,NULL,NULL,NULL,&bx,&by,NULL,NULL)); 11809566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,&my,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 1181bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 118247c6ae99SBarry Smith ratioi = mx/Mx; 1183*08401ef6SPierre Jolivet PetscCheck(ratioi*Mx == mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 118447c6ae99SBarry Smith } else { 118547c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 11862c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 118747c6ae99SBarry Smith } 1188bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 118947c6ae99SBarry Smith ratioj = my/My; 1190*08401ef6SPierre Jolivet PetscCheck(ratioj*My == my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 119147c6ae99SBarry Smith } else { 119247c6ae99SBarry Smith ratioj = (my-1)/(My-1); 11932c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 119447c6ae99SBarry Smith } 119547c6ae99SBarry Smith 11969566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,&j_start,NULL,&m_f,&n_f,NULL)); 11979566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,NULL,&m_ghost,&n_ghost,NULL)); 11989566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 11999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 120047c6ae99SBarry Smith 12019566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,&j_start_c,NULL,&m_c,&n_c,NULL)); 12029566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,NULL,&m_ghost_c,&n_ghost_c,NULL)); 12039566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 12049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 120547c6ae99SBarry Smith 120647c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 120747c6ae99SBarry Smith nc = 0; 12089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_f*m_f,&cols)); 1209076202ddSJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1210076202ddSJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1211076202ddSJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj; 12122c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1213076202ddSJed Brown j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 12142c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1215076202ddSJed Brown i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1216e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 1217e3fbd1f4SBarry Smith cols[nc++] = row; 121847c6ae99SBarry Smith } 121947c6ae99SBarry Smith } 12209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 12219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 122247c6ae99SBarry Smith 12239566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf)); 12249566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dac,&vecc)); 12259566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(daf,&vecf)); 12269566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vecf,isf,vecc,NULL,inject)); 12279566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dac,&vecc)); 12289566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(daf,&vecf)); 12299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isf)); 123047c6ae99SBarry Smith PetscFunctionReturn(0); 123147c6ae99SBarry Smith } 123247c6ae99SBarry Smith 1233e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject) 1234b1757049SJed Brown { 1235b1757049SJed Brown PetscInt i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz; 1236b1757049SJed Brown PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c; 1237b1757049SJed Brown PetscInt i_start_ghost,j_start_ghost,k_start_ghost; 1238b1757049SJed Brown PetscInt mx,my,mz,ratioi,ratioj,ratiok; 1239b1757049SJed Brown PetscInt i_start_c,j_start_c,k_start_c; 1240b1757049SJed Brown PetscInt m_c,n_c,p_c; 1241b1757049SJed Brown PetscInt i_start_ghost_c,j_start_ghost_c,k_start_ghost_c; 1242b1757049SJed Brown PetscInt row,nc,dof; 12438ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1244e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1245b1757049SJed Brown PetscInt *cols; 1246bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 1247b1757049SJed Brown Vec vecf,vecc; 1248b1757049SJed Brown IS isf; 1249b1757049SJed Brown 1250b1757049SJed Brown PetscFunctionBegin; 12519566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,NULL,&Mx,&My,&Mz,NULL,NULL,NULL,NULL,NULL,&bx,&by,&bz,NULL)); 12529566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,NULL,&mx,&my,&mz,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 1253b1757049SJed Brown 1254bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 1255b1757049SJed Brown ratioi = mx/Mx; 1256*08401ef6SPierre Jolivet PetscCheck(ratioi*Mx == mx,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 1257b1757049SJed Brown } else { 1258b1757049SJed Brown ratioi = (mx-1)/(Mx-1); 12592c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioi*(Mx-1) != mx-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 1260b1757049SJed Brown } 1261bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 1262b1757049SJed Brown ratioj = my/My; 1263*08401ef6SPierre Jolivet PetscCheck(ratioj*My == my,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 1264b1757049SJed Brown } else { 1265b1757049SJed Brown ratioj = (my-1)/(My-1); 12662c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratioj*(My-1) != my-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 1267b1757049SJed Brown } 1268bff4a2f0SMatthew G. Knepley if (bz == DM_BOUNDARY_PERIODIC) { 1269b1757049SJed Brown ratiok = mz/Mz; 1270*08401ef6SPierre Jolivet PetscCheck(ratiok*Mz == mz,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D My %D",mz,Mz); 1271b1757049SJed Brown } else { 1272b1757049SJed Brown ratiok = (mz-1)/(Mz-1); 12732c71b3e2SJacob Faibussowitsch PetscCheckFalse(ratiok*(Mz-1) != mz-1,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 1274b1757049SJed Brown } 1275b1757049SJed Brown 12769566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f)); 12779566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost)); 12789566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<og_f)); 12799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f)); 1280b1757049SJed Brown 12819566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c)); 12829566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&k_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c)); 12839566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<og_c)); 12849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c)); 1285b1757049SJed Brown 1286b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1287b1757049SJed Brown nc = 0; 12889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_f*m_f*p_f,&cols)); 1289b1757049SJed Brown for (k=k_start_c; k<k_start_c+p_c; k++) { 1290b1757049SJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1291b1757049SJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1292b1757049SJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok; 12932c71b3e2SJacob Faibussowitsch PetscCheckFalse(k_f < k_start_ghost || k_f >= k_start_ghost+p_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1294b1757049SJed Brown "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost); 12952c71b3e2SJacob Faibussowitsch PetscCheckFalse(j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1296b1757049SJed Brown "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 12972c71b3e2SJacob Faibussowitsch PetscCheckFalse(i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1298b1757049SJed Brown "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1299e3fbd1f4SBarry 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))]; 1300e3fbd1f4SBarry Smith cols[nc++] = row; 1301b1757049SJed Brown } 1302b1757049SJed Brown } 1303b1757049SJed Brown } 13049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f)); 13059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c)); 1306b1757049SJed Brown 13079566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf)); 13089566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dac,&vecc)); 13099566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(daf,&vecf)); 13109566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vecf,isf,vecc,NULL,inject)); 13119566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dac,&vecc)); 13129566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(daf,&vecf)); 13139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isf)); 1314b1757049SJed Brown PetscFunctionReturn(0); 1315b1757049SJed Brown } 1316b1757049SJed Brown 13176dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_DA(DM dac,DM daf,Mat *mat) 131847c6ae99SBarry Smith { 131947c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1320bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1321aa219208SBarry Smith DMDAStencilType stc,stf; 132260c16ac1SBarry Smith VecScatter inject = NULL; 132347c6ae99SBarry Smith 132447c6ae99SBarry Smith PetscFunctionBegin; 132547c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 132647c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 13276dbf9973SLawrence Mitchell PetscValidPointer(mat,3); 132847c6ae99SBarry Smith 13299566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc)); 13309566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf)); 1331*08401ef6SPierre Jolivet PetscCheck(dimc == dimf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1332*08401ef6SPierre Jolivet PetscCheck(dofc == doff,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1333*08401ef6SPierre Jolivet PetscCheck(sc == sf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 13342c71b3e2SJacob Faibussowitsch PetscCheckFalse(bxc != bxf || byc != byf || bzc != bzf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1335*08401ef6SPierre Jolivet PetscCheck(stc == stf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 1336*08401ef6SPierre Jolivet PetscCheck(Mc >= 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 13372c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 1 && Nc < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 13382c71b3e2SJacob Faibussowitsch PetscCheckFalse(dimc > 2 && Pc < 2,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 133947c6ae99SBarry Smith 13400bb2b966SJungho Lee if (dimc == 1) { 13419566063dSJacob Faibussowitsch PetscCall(DMCreateInjection_DA_1D(dac,daf,&inject)); 13420bb2b966SJungho Lee } else if (dimc == 2) { 13439566063dSJacob Faibussowitsch PetscCall(DMCreateInjection_DA_2D(dac,daf,&inject)); 1344b1757049SJed Brown } else if (dimc == 3) { 13459566063dSJacob Faibussowitsch PetscCall(DMCreateInjection_DA_3D(dac,daf,&inject)); 134647c6ae99SBarry Smith } 13479566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)inject), inject, mat)); 13489566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&inject)); 134947c6ae99SBarry Smith PetscFunctionReturn(0); 135047c6ae99SBarry Smith } 135147c6ae99SBarry Smith 135297779f9aSLisandro Dalcin /*@ 135397779f9aSLisandro Dalcin DMCreateAggregates - Deprecated, see DMDACreateAggregates. 13546c877ef6SSatish Balay 13556c877ef6SSatish Balay Level: intermediate 135697779f9aSLisandro Dalcin @*/ 1357a5bc1bf3SBarry Smith PetscErrorCode DMCreateAggregates(DM dac,DM daf,Mat *mat) 135897779f9aSLisandro Dalcin { 1359a5bc1bf3SBarry Smith return DMDACreateAggregates(dac,daf,mat); 136097779f9aSLisandro Dalcin } 136197779f9aSLisandro Dalcin 136297779f9aSLisandro Dalcin /*@ 136397779f9aSLisandro Dalcin DMDACreateAggregates - Gets the aggregates that map between 136497779f9aSLisandro Dalcin grids associated with two DMDAs. 136597779f9aSLisandro Dalcin 136697779f9aSLisandro Dalcin Collective on dmc 136797779f9aSLisandro Dalcin 136897779f9aSLisandro Dalcin Input Parameters: 136997779f9aSLisandro Dalcin + dmc - the coarse grid DMDA 137097779f9aSLisandro Dalcin - dmf - the fine grid DMDA 137197779f9aSLisandro Dalcin 137297779f9aSLisandro Dalcin Output Parameters: 137397779f9aSLisandro Dalcin . rest - the restriction matrix (transpose of the projection matrix) 137497779f9aSLisandro Dalcin 137597779f9aSLisandro Dalcin Level: intermediate 137697779f9aSLisandro Dalcin 137797779f9aSLisandro Dalcin Note: This routine is not used by PETSc. 137897779f9aSLisandro Dalcin It is not clear what its use case is and it may be removed in a future release. 137997779f9aSLisandro Dalcin Users should contact petsc-maint@mcs.anl.gov if they plan to use it. 138097779f9aSLisandro Dalcin 138197779f9aSLisandro Dalcin .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 138297779f9aSLisandro Dalcin @*/ 138397779f9aSLisandro Dalcin PetscErrorCode DMDACreateAggregates(DM dac,DM daf,Mat *rest) 138447c6ae99SBarry Smith { 138547c6ae99SBarry Smith PetscErrorCode ierr; 138647c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc; 138747c6ae99SBarry Smith PetscInt dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1388bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1389aa219208SBarry Smith DMDAStencilType stc,stf; 139047c6ae99SBarry Smith PetscInt i,j,l; 139147c6ae99SBarry Smith PetscInt i_start,j_start,l_start, m_f,n_f,p_f; 139247c6ae99SBarry Smith PetscInt i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost; 13938ea3bf28SBarry Smith const PetscInt *idx_f; 139447c6ae99SBarry Smith PetscInt i_c,j_c,l_c; 139547c6ae99SBarry Smith PetscInt i_start_c,j_start_c,l_start_c, m_c,n_c,p_c; 139647c6ae99SBarry Smith PetscInt i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c; 13978ea3bf28SBarry Smith const PetscInt *idx_c; 139847c6ae99SBarry Smith PetscInt d; 139947c6ae99SBarry Smith PetscInt a; 140047c6ae99SBarry Smith PetscInt max_agg_size; 140147c6ae99SBarry Smith PetscInt *fine_nodes; 140247c6ae99SBarry Smith PetscScalar *one_vec; 140347c6ae99SBarry Smith PetscInt fn_idx; 1404565245c5SBarry Smith ISLocalToGlobalMapping ltogmf,ltogmc; 140547c6ae99SBarry Smith 140647c6ae99SBarry Smith PetscFunctionBegin; 140797779f9aSLisandro Dalcin PetscValidHeaderSpecificType(dac,DM_CLASSID,1,DMDA); 140897779f9aSLisandro Dalcin PetscValidHeaderSpecificType(daf,DM_CLASSID,2,DMDA); 140947c6ae99SBarry Smith PetscValidPointer(rest,3); 141047c6ae99SBarry Smith 14119566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc)); 14129566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf)); 1413*08401ef6SPierre Jolivet PetscCheck(dimc == dimf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1414*08401ef6SPierre Jolivet PetscCheck(dofc == doff,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1415*08401ef6SPierre Jolivet PetscCheck(sc == sf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 14162c71b3e2SJacob Faibussowitsch PetscCheckFalse(bxc != bxf || byc != byf || bzc != bzf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1417*08401ef6SPierre Jolivet PetscCheck(stc == stf,PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 141847c6ae99SBarry Smith 1419*08401ef6SPierre Jolivet PetscCheck(Mf >= Mc,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Mc %D, Mf %D", Mc, Mf); 1420*08401ef6SPierre Jolivet PetscCheck(Nf >= Nc,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Nc %D, Nf %D", Nc, Nf); 1421*08401ef6SPierre Jolivet PetscCheck(Pf >= Pc,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Pc %D, Pf %D", Pc, Pf); 142247c6ae99SBarry Smith 142347c6ae99SBarry Smith if (Pc < 0) Pc = 1; 142447c6ae99SBarry Smith if (Pf < 0) Pf = 1; 142547c6ae99SBarry Smith if (Nc < 0) Nc = 1; 142647c6ae99SBarry Smith if (Nf < 0) Nf = 1; 142747c6ae99SBarry Smith 14289566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f)); 14299566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost)); 1430565245c5SBarry Smith 14319566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf,<ogmf)); 14329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(ltogmf,&idx_f)); 143347c6ae99SBarry Smith 14349566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c)); 14359566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c)); 1436565245c5SBarry Smith 14379566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac,<ogmc)); 14389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(ltogmc,&idx_c)); 143947c6ae99SBarry Smith 144047c6ae99SBarry Smith /* 144147c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 144247c6ae99SBarry Smith for dimension 1 and 2 respectively. 144347c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 144447c6ae99SBarry Smith and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate. 144547c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 144647c6ae99SBarry Smith */ 144747c6ae99SBarry Smith 144847c6ae99SBarry Smith max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1); 144947c6ae99SBarry Smith 145047c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 1451ce94432eSBarry 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, 14529566063dSJacob Faibussowitsch max_agg_size, NULL, max_agg_size, NULL, rest);PetscCall(ierr); 145347c6ae99SBarry Smith 145447c6ae99SBarry Smith /* store nodes in the fine grid here */ 14559566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(max_agg_size, &one_vec,max_agg_size, &fine_nodes)); 145647c6ae99SBarry Smith for (i=0; i<max_agg_size; i++) one_vec[i] = 1.0; 145747c6ae99SBarry Smith 145847c6ae99SBarry Smith /* loop over all coarse nodes */ 145947c6ae99SBarry Smith for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) { 146047c6ae99SBarry Smith for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) { 146147c6ae99SBarry Smith for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) { 146247c6ae99SBarry Smith for (d=0; d<dofc; d++) { 146347c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 146447c6ae99SBarry 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; 146547c6ae99SBarry Smith 146647c6ae99SBarry Smith fn_idx = 0; 146747c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 146847c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 146947c6ae99SBarry Smith (same for other dimensions) 147047c6ae99SBarry Smith */ 147147c6ae99SBarry Smith for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) { 147247c6ae99SBarry Smith for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) { 147347c6ae99SBarry Smith for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) { 147447c6ae99SBarry 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; 147547c6ae99SBarry Smith fn_idx++; 147647c6ae99SBarry Smith } 147747c6ae99SBarry Smith } 147847c6ae99SBarry Smith } 147947c6ae99SBarry Smith /* add all these points to one aggregate */ 14809566063dSJacob Faibussowitsch PetscCall(MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES)); 148147c6ae99SBarry Smith } 148247c6ae99SBarry Smith } 148347c6ae99SBarry Smith } 148447c6ae99SBarry Smith } 14859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogmf,&idx_f)); 14869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogmc,&idx_c)); 14879566063dSJacob Faibussowitsch PetscCall(PetscFree2(one_vec,fine_nodes)); 14889566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY)); 14899566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY)); 149047c6ae99SBarry Smith PetscFunctionReturn(0); 149147c6ae99SBarry Smith } 1492