147c6ae99SBarry Smith /* 2aa219208SBarry Smith Code for interpolating between grids represented by DMDAs 347c6ae99SBarry Smith */ 447c6ae99SBarry Smith 5d52bd9f3SBarry Smith /* 6d52bd9f3SBarry 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 7d52bd9f3SBarry 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 82adb9dcfSBarry 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 92adb9dcfSBarry Smith consider it cleaner, but old version is turned on since it handles periodic case. 10d52bd9f3SBarry Smith */ 119314d695SBarry Smith #define NEWVERSION 0 1285afcc9aSBarry Smith 13af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/ 1447c6ae99SBarry Smith 15fdc842d1SBarry Smith /* 16fdc842d1SBarry Smith Since the interpolation uses MATMAIJ for dof > 0 we convert request for non-MATAIJ baseded matrices to MATAIJ. 17fdc842d1SBarry Smith This is a bit of a hack, the reason for it is partially because -dm_mat_type defines the 18fdc842d1SBarry Smith matrix type for both the operator matrices and the interpolation matrices so that users 19fdc842d1SBarry Smith can select matrix types of base MATAIJ for accelerators 20fdc842d1SBarry Smith */ 21d71ae5a4SJacob Faibussowitsch static PetscErrorCode ConvertToAIJ(MatType intype, MatType *outtype) 22d71ae5a4SJacob Faibussowitsch { 23fdc842d1SBarry Smith PetscInt i; 24fdc842d1SBarry Smith char const *types[3] = {MATAIJ, MATSEQAIJ, MATMPIAIJ}; 25fdc842d1SBarry Smith PetscBool flg; 26fdc842d1SBarry Smith 27fdc842d1SBarry Smith PetscFunctionBegin; 2833a4d587SStefano Zampini *outtype = MATAIJ; 29fdc842d1SBarry Smith for (i = 0; i < 3; i++) { 309566063dSJacob Faibussowitsch PetscCall(PetscStrbeginswith(intype, types[i], &flg)); 31fdc842d1SBarry Smith if (flg) { 32fdc842d1SBarry Smith *outtype = intype; 333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34fdc842d1SBarry Smith } 35fdc842d1SBarry Smith } 363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37fdc842d1SBarry Smith } 38fdc842d1SBarry Smith 3966976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac, DM daf, Mat *A) 40d71ae5a4SJacob Faibussowitsch { 418ea3bf28SBarry Smith PetscInt i, i_start, m_f, Mx; 428ea3bf28SBarry Smith const PetscInt *idx_f, *idx_c; 438ea3bf28SBarry Smith PetscInt m_ghost, m_ghost_c; 4447c6ae99SBarry Smith PetscInt row, col, i_start_ghost, mx, m_c, nc, ratio; 4547c6ae99SBarry Smith PetscInt i_c, i_start_c, i_start_ghost_c, cols[2], dof; 4685afcc9aSBarry Smith PetscScalar v[2], x; 4747c6ae99SBarry Smith Mat mat; 48bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 49e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 50fdc842d1SBarry Smith MatType mattype; 5147c6ae99SBarry Smith 5247c6ae99SBarry Smith PetscFunctionBegin; 539566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &bx, NULL, NULL, NULL)); 549566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 55bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 5647c6ae99SBarry Smith ratio = mx / Mx; 5763a3b9bcSJacob Faibussowitsch PetscCheck(ratio * Mx == mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mx/Mx must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 5847c6ae99SBarry Smith } else { 5947c6ae99SBarry Smith ratio = (mx - 1) / (Mx - 1); 601dca8a05SBarry Smith PetscCheck(ratio * (Mx - 1) == mx - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 6147c6ae99SBarry Smith } 6247c6ae99SBarry Smith 639566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, NULL, NULL, &m_f, NULL, NULL)); 649566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, NULL, NULL, &m_ghost, NULL, NULL)); 659566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 6747c6ae99SBarry Smith 689566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, NULL, NULL, &m_c, NULL, NULL)); 699566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac, &i_start_ghost_c, NULL, NULL, &m_ghost_c, NULL, NULL)); 709566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 7247c6ae99SBarry Smith 7347c6ae99SBarry Smith /* create interpolation matrix */ 749566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dac), &mat)); 75fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 76fdc842d1SBarry Smith /* 77fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 78fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 79fdc842d1SBarry Smith */ 8048a46eb9SPierre Jolivet if (dof > 1) PetscCall(MatBindToCPU(mat, PETSC_TRUE)); 81fdc842d1SBarry Smith #endif 829566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, m_f, m_c, mx, Mx)); 839566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype, &mattype)); 849566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, mattype)); 859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat, 2, NULL)); 869566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat, 2, NULL, 1, NULL)); 8747c6ae99SBarry Smith 8847c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 8985afcc9aSBarry Smith if (!NEWVERSION) { 9047c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 9147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 92e3fbd1f4SBarry Smith row = idx_f[i - i_start_ghost]; 9347c6ae99SBarry Smith 9447c6ae99SBarry Smith i_c = (i / ratio); /* coarse grid node to left of fine grid node */ 9508401ef6SPierre 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\ 969371c9d4SSatish Balay i_start %" PetscInt_FMT " i_c %" PetscInt_FMT " i_start_ghost_c %" PetscInt_FMT, 979371c9d4SSatish Balay i_start, i_c, i_start_ghost_c); 9847c6ae99SBarry Smith 9947c6ae99SBarry Smith /* 10047c6ae99SBarry Smith Only include those interpolation points that are truly 10147c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 10247c6ae99SBarry Smith in x direction; since they have no right neighbor 10347c6ae99SBarry Smith */ 1046712e2f1SBarry Smith x = ((PetscReal)(i - i_c * ratio)) / ((PetscReal)ratio); 10547c6ae99SBarry Smith nc = 0; 10647c6ae99SBarry Smith /* one left and below; or we are right on it */ 107e3fbd1f4SBarry Smith col = (i_c - i_start_ghost_c); 108e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 10947c6ae99SBarry Smith v[nc++] = -x + 1.0; 11047c6ae99SBarry Smith /* one right? */ 11147c6ae99SBarry Smith if (i_c * ratio != i) { 112e3fbd1f4SBarry Smith cols[nc] = idx_c[col + 1]; 11347c6ae99SBarry Smith v[nc++] = x; 11447c6ae99SBarry Smith } 1159566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, nc, cols, v, INSERT_VALUES)); 11647c6ae99SBarry Smith } 117b3bd94feSDave May 118b3bd94feSDave May } else { 119b3bd94feSDave May PetscScalar *xi; 120b3bd94feSDave May PetscInt li, nxi, n; 121b3bd94feSDave May PetscScalar Ni[2]; 122b3bd94feSDave May 123b3bd94feSDave May /* compute local coordinate arrays */ 124b3bd94feSDave May nxi = ratio + 1; 1259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nxi, &xi)); 126ad540459SPierre Jolivet for (li = 0; li < nxi; li++) xi[li] = -1.0 + (PetscScalar)li * (2.0 / (PetscScalar)(nxi - 1)); 127b3bd94feSDave May 128b3bd94feSDave May for (i = i_start; i < i_start + m_f; i++) { 129b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 130e3fbd1f4SBarry Smith row = idx_f[(i - i_start_ghost)]; 131b3bd94feSDave May 132b3bd94feSDave May i_c = (i / ratio); /* coarse grid node to left of fine grid node */ 13308401ef6SPierre 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\ 1349371c9d4SSatish Balay i_start %" PetscInt_FMT " i_c %" PetscInt_FMT " i_start_ghost_c %" PetscInt_FMT, 1359371c9d4SSatish Balay i_start, i_c, i_start_ghost_c); 136b3bd94feSDave May 137b3bd94feSDave May /* remainders */ 138b3bd94feSDave May li = i - ratio * (i / ratio); 1398865f1eaSKarl Rupp if (i == mx - 1) li = nxi - 1; 140b3bd94feSDave May 141b3bd94feSDave May /* corners */ 142e3fbd1f4SBarry Smith col = (i_c - i_start_ghost_c); 143e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 144b3bd94feSDave May Ni[0] = 1.0; 145b3bd94feSDave May if ((li == 0) || (li == nxi - 1)) { 1469566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat, row, cols[0], Ni[0], INSERT_VALUES)); 147b3bd94feSDave May continue; 148b3bd94feSDave May } 149b3bd94feSDave May 150b3bd94feSDave May /* edges + interior */ 151b3bd94feSDave May /* remainders */ 1528865f1eaSKarl Rupp if (i == mx - 1) i_c--; 153b3bd94feSDave May 154e3fbd1f4SBarry Smith col = (i_c - i_start_ghost_c); 155e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 156e3fbd1f4SBarry Smith cols[1] = idx_c[col + 1]; 157b3bd94feSDave May 158b3bd94feSDave May Ni[0] = 0.5 * (1.0 - xi[li]); 159b3bd94feSDave May Ni[1] = 0.5 * (1.0 + xi[li]); 160b3bd94feSDave May for (n = 0; n < 2; n++) { 1618865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n]) < 1.0e-32) cols[n] = -1; 162b3bd94feSDave May } 1639566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, 2, cols, Ni, INSERT_VALUES)); 164b3bd94feSDave May } 1659566063dSJacob Faibussowitsch PetscCall(PetscFree(xi)); 166b3bd94feSDave May } 1679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 1689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 1699566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 1709566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 1719566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat, dof, A)); 1729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 1733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17447c6ae99SBarry Smith } 17547c6ae99SBarry Smith 17666976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac, DM daf, Mat *A) 177d71ae5a4SJacob Faibussowitsch { 1788ea3bf28SBarry Smith PetscInt i, i_start, m_f, Mx; 1798ea3bf28SBarry Smith const PetscInt *idx_f, *idx_c; 180e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 1818ea3bf28SBarry Smith PetscInt m_ghost, m_ghost_c; 18247c6ae99SBarry Smith PetscInt row, col, i_start_ghost, mx, m_c, nc, ratio; 18347c6ae99SBarry Smith PetscInt i_c, i_start_c, i_start_ghost_c, cols[2], dof; 18447c6ae99SBarry Smith PetscScalar v[2], x; 18547c6ae99SBarry Smith Mat mat; 186bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 187fdc842d1SBarry Smith MatType mattype; 18847c6ae99SBarry Smith 18947c6ae99SBarry Smith PetscFunctionBegin; 1909566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &bx, NULL, NULL, NULL)); 1919566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 192bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 19363a3b9bcSJacob Faibussowitsch PetscCheck(Mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be positive", Mx); 19447c6ae99SBarry Smith ratio = mx / Mx; 19563a3b9bcSJacob Faibussowitsch PetscCheck(ratio * Mx == mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mx/Mx must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 19647c6ae99SBarry Smith } else { 19763a3b9bcSJacob Faibussowitsch PetscCheck(Mx >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be greater than 1", Mx); 19847c6ae99SBarry Smith ratio = (mx - 1) / (Mx - 1); 1991dca8a05SBarry Smith PetscCheck(ratio * (Mx - 1) == mx - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 20047c6ae99SBarry Smith } 20147c6ae99SBarry Smith 2029566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, NULL, NULL, &m_f, NULL, NULL)); 2039566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, NULL, NULL, &m_ghost, NULL, NULL)); 2049566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 2059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 20647c6ae99SBarry Smith 2079566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, NULL, NULL, &m_c, NULL, NULL)); 2089566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac, &i_start_ghost_c, NULL, NULL, &m_ghost_c, NULL, NULL)); 2099566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 2109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 21147c6ae99SBarry Smith 21247c6ae99SBarry Smith /* create interpolation matrix */ 2139566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dac), &mat)); 214fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 215fdc842d1SBarry Smith /* 216fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 217fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 218fdc842d1SBarry Smith */ 21948a46eb9SPierre Jolivet if (dof > 1) PetscCall(MatBindToCPU(mat, PETSC_TRUE)); 220fdc842d1SBarry Smith #endif 2219566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, m_f, m_c, mx, Mx)); 2229566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype, &mattype)); 2239566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, mattype)); 2249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat, 2, NULL)); 2259566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat, 2, NULL, 0, NULL)); 22647c6ae99SBarry Smith 22747c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 22847c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 22947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 230e3fbd1f4SBarry Smith row = idx_f[(i - i_start_ghost)]; 23147c6ae99SBarry Smith 23247c6ae99SBarry Smith i_c = (i / ratio); /* coarse grid node to left of fine grid node */ 23347c6ae99SBarry Smith 23447c6ae99SBarry Smith /* 23547c6ae99SBarry Smith Only include those interpolation points that are truly 23647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 23747c6ae99SBarry Smith in x direction; since they have no right neighbor 23847c6ae99SBarry Smith */ 2396712e2f1SBarry Smith x = ((PetscReal)(i - i_c * ratio)) / ((PetscReal)ratio); 24047c6ae99SBarry Smith nc = 0; 24147c6ae99SBarry Smith /* one left and below; or we are right on it */ 242e3fbd1f4SBarry Smith col = (i_c - i_start_ghost_c); 243e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 24447c6ae99SBarry Smith v[nc++] = -x + 1.0; 24547c6ae99SBarry Smith /* one right? */ 24647c6ae99SBarry Smith if (i_c * ratio != i) { 247e3fbd1f4SBarry Smith cols[nc] = idx_c[col + 1]; 24847c6ae99SBarry Smith v[nc++] = x; 24947c6ae99SBarry Smith } 2509566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, nc, cols, v, INSERT_VALUES)); 25147c6ae99SBarry Smith } 2529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 2539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 2549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 2559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 2569566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat, dof, A)); 2579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 2589566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(5.0 * m_f)); 2593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26047c6ae99SBarry Smith } 26147c6ae99SBarry Smith 26266976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac, DM daf, Mat *A) 263d71ae5a4SJacob Faibussowitsch { 2648ea3bf28SBarry Smith PetscInt i, j, i_start, j_start, m_f, n_f, Mx, My, dof; 2658ea3bf28SBarry Smith const PetscInt *idx_c, *idx_f; 266e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 2678ea3bf28SBarry Smith PetscInt m_ghost, n_ghost, m_ghost_c, n_ghost_c, *dnz, *onz; 26847c6ae99SBarry Smith PetscInt row, col, i_start_ghost, j_start_ghost, cols[4], mx, m_c, my, nc, ratioi, ratioj; 26947c6ae99SBarry 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; 27047c6ae99SBarry Smith PetscMPIInt size_c, size_f, rank_f; 27147c6ae99SBarry Smith PetscScalar v[4], x, y; 27247c6ae99SBarry Smith Mat mat; 273bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 274fdc842d1SBarry Smith MatType mattype; 27547c6ae99SBarry Smith 27647c6ae99SBarry Smith PetscFunctionBegin; 2779566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, &My, NULL, NULL, NULL, NULL, NULL, NULL, &bx, &by, NULL, NULL)); 2789566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, &my, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 279bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 28063a3b9bcSJacob Faibussowitsch PetscCheck(Mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be positive", Mx); 28147c6ae99SBarry Smith ratioi = mx / Mx; 28263a3b9bcSJacob Faibussowitsch PetscCheck(ratioi * Mx == mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mx/Mx must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 28347c6ae99SBarry Smith } else { 28463a3b9bcSJacob Faibussowitsch PetscCheck(Mx >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be greater than 1", Mx); 28547c6ae99SBarry Smith ratioi = (mx - 1) / (Mx - 1); 2861dca8a05SBarry Smith PetscCheck(ratioi * (Mx - 1) == mx - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 28747c6ae99SBarry Smith } 288bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 28963a3b9bcSJacob Faibussowitsch PetscCheck(My, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of y coarse grid points %" PetscInt_FMT " must be positive", My); 29047c6ae99SBarry Smith ratioj = my / My; 29163a3b9bcSJacob Faibussowitsch PetscCheck(ratioj * My == my, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: my/My must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 29247c6ae99SBarry Smith } else { 29363a3b9bcSJacob Faibussowitsch PetscCheck(My >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of y coarse grid points %" PetscInt_FMT " must be greater than 1", My); 29447c6ae99SBarry Smith ratioj = (my - 1) / (My - 1); 2951dca8a05SBarry Smith PetscCheck(ratioj * (My - 1) == my - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (my - 1)/(My - 1) must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 29647c6ae99SBarry Smith } 29747c6ae99SBarry Smith 2989566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, &j_start, NULL, &m_f, &n_f, NULL)); 2999566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, &j_start_ghost, NULL, &m_ghost, &n_ghost, NULL)); 3009566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 3019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 30247c6ae99SBarry Smith 3039566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, &j_start_c, NULL, &m_c, &n_c, NULL)); 3049566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac, &i_start_ghost_c, &j_start_ghost_c, NULL, &m_ghost_c, &n_ghost_c, NULL)); 3059566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 3069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 30747c6ae99SBarry Smith 30847c6ae99SBarry Smith /* 309aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 31047c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 31147c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 31247c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 31347c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 31447c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 31547c6ae99SBarry Smith 31647c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 31747c6ae99SBarry Smith */ 3189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dac), &size_c)); 3199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)daf), &size_f)); 3209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)daf), &rank_f)); 32147c6ae99SBarry Smith col_scale = size_f / size_c; 32247c6ae99SBarry Smith col_shift = Mx * My * (rank_f / size_c); 32347c6ae99SBarry Smith 324d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)daf), m_f * n_f, col_scale * m_c * n_c, dnz, onz); 32547c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 32647c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 32747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 328e3fbd1f4SBarry Smith row = idx_f[(m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 32947c6ae99SBarry Smith 33047c6ae99SBarry Smith i_c = (i / ratioi); /* coarse grid node to left of fine grid node */ 33147c6ae99SBarry Smith j_c = (j / ratioj); /* coarse grid node below fine grid node */ 33247c6ae99SBarry Smith 33308401ef6SPierre 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\ 3349371c9d4SSatish Balay j_start %" PetscInt_FMT " j_c %" PetscInt_FMT " j_start_ghost_c %" PetscInt_FMT, 3359371c9d4SSatish Balay j_start, j_c, j_start_ghost_c); 33608401ef6SPierre 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\ 3379371c9d4SSatish Balay i_start %" PetscInt_FMT " i_c %" PetscInt_FMT " i_start_ghost_c %" PetscInt_FMT, 3389371c9d4SSatish Balay i_start, i_c, i_start_ghost_c); 33947c6ae99SBarry Smith 34047c6ae99SBarry Smith /* 34147c6ae99SBarry Smith Only include those interpolation points that are truly 34247c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 34347c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 34447c6ae99SBarry Smith */ 34547c6ae99SBarry Smith nc = 0; 34647c6ae99SBarry Smith /* one left and below; or we are right on it */ 347e3fbd1f4SBarry Smith col = (m_ghost_c * (j_c - j_start_ghost_c) + (i_c - i_start_ghost_c)); 348e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 34947c6ae99SBarry Smith /* one right and below */ 350e3fbd1f4SBarry Smith if (i_c * ratioi != i) cols[nc++] = col_shift + idx_c[col + 1]; 35147c6ae99SBarry Smith /* one left and above */ 352e3fbd1f4SBarry Smith if (j_c * ratioj != j) cols[nc++] = col_shift + idx_c[col + m_ghost_c]; 35347c6ae99SBarry Smith /* one right and above */ 354e3fbd1f4SBarry Smith if (i_c * ratioi != i && j_c * ratioj != j) cols[nc++] = col_shift + idx_c[col + (m_ghost_c + 1)]; 3559566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, nc, cols, dnz, onz)); 35647c6ae99SBarry Smith } 35747c6ae99SBarry Smith } 3589566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)daf), &mat)); 359fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 360fdc842d1SBarry Smith /* 361fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 362fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 363fdc842d1SBarry Smith */ 36448a46eb9SPierre Jolivet if (dof > 1) PetscCall(MatBindToCPU(mat, PETSC_TRUE)); 365fdc842d1SBarry Smith #endif 3669566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, m_f * n_f, col_scale * m_c * n_c, mx * my, col_scale * Mx * My)); 3679566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype, &mattype)); 3689566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, mattype)); 3699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat, 0, dnz)); 3709566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat, 0, dnz, 0, onz)); 371d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 37247c6ae99SBarry Smith 37347c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 37485afcc9aSBarry Smith if (!NEWVERSION) { 37547c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 37647c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 37747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 378e3fbd1f4SBarry Smith row = idx_f[(m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 37947c6ae99SBarry Smith 38047c6ae99SBarry Smith i_c = (i / ratioi); /* coarse grid node to left of fine grid node */ 38147c6ae99SBarry Smith j_c = (j / ratioj); /* coarse grid node below fine grid node */ 38247c6ae99SBarry Smith 38347c6ae99SBarry Smith /* 38447c6ae99SBarry Smith Only include those interpolation points that are truly 38547c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 38647c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 38747c6ae99SBarry Smith */ 3886712e2f1SBarry Smith x = ((PetscReal)(i - i_c * ratioi)) / ((PetscReal)ratioi); 3896712e2f1SBarry Smith y = ((PetscReal)(j - j_c * ratioj)) / ((PetscReal)ratioj); 390b3bd94feSDave May 39147c6ae99SBarry Smith nc = 0; 39247c6ae99SBarry Smith /* one left and below; or we are right on it */ 393e3fbd1f4SBarry Smith col = (m_ghost_c * (j_c - j_start_ghost_c) + (i_c - i_start_ghost_c)); 394e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 39547c6ae99SBarry Smith v[nc++] = x * y - x - y + 1.0; 39647c6ae99SBarry Smith /* one right and below */ 39747c6ae99SBarry Smith if (i_c * ratioi != i) { 398e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col + 1]; 39947c6ae99SBarry Smith v[nc++] = -x * y + x; 40047c6ae99SBarry Smith } 40147c6ae99SBarry Smith /* one left and above */ 40247c6ae99SBarry Smith if (j_c * ratioj != j) { 403e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col + m_ghost_c]; 40447c6ae99SBarry Smith v[nc++] = -x * y + y; 40547c6ae99SBarry Smith } 40647c6ae99SBarry Smith /* one right and above */ 40747c6ae99SBarry Smith if (j_c * ratioj != j && i_c * ratioi != i) { 408e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col + (m_ghost_c + 1)]; 40947c6ae99SBarry Smith v[nc++] = x * y; 41047c6ae99SBarry Smith } 4119566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, nc, cols, v, INSERT_VALUES)); 41247c6ae99SBarry Smith } 41347c6ae99SBarry Smith } 414b3bd94feSDave May 415b3bd94feSDave May } else { 416b3bd94feSDave May PetscScalar Ni[4]; 417b3bd94feSDave May PetscScalar *xi, *eta; 418b3bd94feSDave May PetscInt li, nxi, lj, neta; 419b3bd94feSDave May 420b3bd94feSDave May /* compute local coordinate arrays */ 421b3bd94feSDave May nxi = ratioi + 1; 422b3bd94feSDave May neta = ratioj + 1; 4239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nxi, &xi)); 4249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(neta, &eta)); 425ad540459SPierre Jolivet for (li = 0; li < nxi; li++) xi[li] = -1.0 + (PetscScalar)li * (2.0 / (PetscScalar)(nxi - 1)); 426ad540459SPierre Jolivet for (lj = 0; lj < neta; lj++) eta[lj] = -1.0 + (PetscScalar)lj * (2.0 / (PetscScalar)(neta - 1)); 427b3bd94feSDave May 428b3bd94feSDave May /* loop over local fine grid nodes setting interpolation for those*/ 429b3bd94feSDave May for (j = j_start; j < j_start + n_f; j++) { 430b3bd94feSDave May for (i = i_start; i < i_start + m_f; i++) { 431b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 432e3fbd1f4SBarry Smith row = idx_f[(m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 433b3bd94feSDave May 434b3bd94feSDave May i_c = (i / ratioi); /* coarse grid node to left of fine grid node */ 435b3bd94feSDave May j_c = (j / ratioj); /* coarse grid node below fine grid node */ 436b3bd94feSDave May 437b3bd94feSDave May /* remainders */ 438b3bd94feSDave May li = i - ratioi * (i / ratioi); 4398865f1eaSKarl Rupp if (i == mx - 1) li = nxi - 1; 440b3bd94feSDave May lj = j - ratioj * (j / ratioj); 4418865f1eaSKarl Rupp if (j == my - 1) lj = neta - 1; 442b3bd94feSDave May 443b3bd94feSDave May /* corners */ 444e3fbd1f4SBarry Smith col = (m_ghost_c * (j_c - j_start_ghost_c) + (i_c - i_start_ghost_c)); 445e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 446b3bd94feSDave May Ni[0] = 1.0; 447b3bd94feSDave May if ((li == 0) || (li == nxi - 1)) { 448b3bd94feSDave May if ((lj == 0) || (lj == neta - 1)) { 4499566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat, row, cols[0], Ni[0], INSERT_VALUES)); 450b3bd94feSDave May continue; 451b3bd94feSDave May } 452b3bd94feSDave May } 453b3bd94feSDave May 454b3bd94feSDave May /* edges + interior */ 455b3bd94feSDave May /* remainders */ 4568865f1eaSKarl Rupp if (i == mx - 1) i_c--; 4578865f1eaSKarl Rupp if (j == my - 1) j_c--; 458b3bd94feSDave May 459e3fbd1f4SBarry Smith col = (m_ghost_c * (j_c - j_start_ghost_c) + (i_c - i_start_ghost_c)); 460e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 461e3fbd1f4SBarry Smith cols[1] = col_shift + idx_c[col + 1]; /* right, below */ 462e3fbd1f4SBarry Smith cols[2] = col_shift + idx_c[col + m_ghost_c]; /* left, above */ 463e3fbd1f4SBarry Smith cols[3] = col_shift + idx_c[col + (m_ghost_c + 1)]; /* right, above */ 464b3bd94feSDave May 465b3bd94feSDave May Ni[0] = 0.25 * (1.0 - xi[li]) * (1.0 - eta[lj]); 466b3bd94feSDave May Ni[1] = 0.25 * (1.0 + xi[li]) * (1.0 - eta[lj]); 467b3bd94feSDave May Ni[2] = 0.25 * (1.0 - xi[li]) * (1.0 + eta[lj]); 468b3bd94feSDave May Ni[3] = 0.25 * (1.0 + xi[li]) * (1.0 + eta[lj]); 469b3bd94feSDave May 470b3bd94feSDave May nc = 0; 4718865f1eaSKarl Rupp if (PetscAbsScalar(Ni[0]) < 1.0e-32) cols[0] = -1; 4728865f1eaSKarl Rupp if (PetscAbsScalar(Ni[1]) < 1.0e-32) cols[1] = -1; 4738865f1eaSKarl Rupp if (PetscAbsScalar(Ni[2]) < 1.0e-32) cols[2] = -1; 4748865f1eaSKarl Rupp if (PetscAbsScalar(Ni[3]) < 1.0e-32) cols[3] = -1; 475b3bd94feSDave May 4769566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, 4, cols, Ni, INSERT_VALUES)); 477b3bd94feSDave May } 478b3bd94feSDave May } 4799566063dSJacob Faibussowitsch PetscCall(PetscFree(xi)); 4809566063dSJacob Faibussowitsch PetscCall(PetscFree(eta)); 481b3bd94feSDave May } 4829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 4839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 4849566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 4859566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 4869566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat, dof, A)); 4879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 4883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48947c6ae99SBarry Smith } 49047c6ae99SBarry Smith 49147c6ae99SBarry Smith /* 49247c6ae99SBarry Smith Contributed by Andrei Draganescu <aidraga@sandia.gov> 49347c6ae99SBarry Smith */ 49466976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac, DM daf, Mat *A) 495d71ae5a4SJacob Faibussowitsch { 4968ea3bf28SBarry Smith PetscInt i, j, i_start, j_start, m_f, n_f, Mx, My, dof; 4978ea3bf28SBarry Smith const PetscInt *idx_c, *idx_f; 498e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 4998ea3bf28SBarry Smith PetscInt m_ghost, n_ghost, m_ghost_c, n_ghost_c, *dnz, *onz; 50047c6ae99SBarry Smith PetscInt row, col, i_start_ghost, j_start_ghost, cols[4], mx, m_c, my, nc, ratioi, ratioj; 50147c6ae99SBarry 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; 50247c6ae99SBarry Smith PetscMPIInt size_c, size_f, rank_f; 50347c6ae99SBarry Smith PetscScalar v[4]; 50447c6ae99SBarry Smith Mat mat; 505bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 506fdc842d1SBarry Smith MatType mattype; 50747c6ae99SBarry Smith 50847c6ae99SBarry Smith PetscFunctionBegin; 5099566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, &My, NULL, NULL, NULL, NULL, NULL, NULL, &bx, &by, NULL, NULL)); 5109566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, &my, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 51163a3b9bcSJacob Faibussowitsch PetscCheck(Mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be positive", Mx); 51263a3b9bcSJacob Faibussowitsch PetscCheck(My, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of y coarse grid points %" PetscInt_FMT " must be positive", My); 51347c6ae99SBarry Smith ratioi = mx / Mx; 51447c6ae99SBarry Smith ratioj = my / My; 51508401ef6SPierre Jolivet PetscCheck(ratioi * Mx == mx, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Fine grid points must be multiple of coarse grid points in x"); 51608401ef6SPierre Jolivet PetscCheck(ratioj * My == my, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Fine grid points must be multiple of coarse grid points in y"); 51708401ef6SPierre Jolivet PetscCheck(ratioi == 2, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Coarsening factor in x must be 2"); 51808401ef6SPierre Jolivet PetscCheck(ratioj == 2, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Coarsening factor in y must be 2"); 51947c6ae99SBarry Smith 5209566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, &j_start, NULL, &m_f, &n_f, NULL)); 5219566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, &j_start_ghost, NULL, &m_ghost, &n_ghost, NULL)); 5229566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 5239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 52447c6ae99SBarry Smith 5259566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, &j_start_c, NULL, &m_c, &n_c, NULL)); 5269566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac, &i_start_ghost_c, &j_start_ghost_c, NULL, &m_ghost_c, &n_ghost_c, NULL)); 5279566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 5289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 52947c6ae99SBarry Smith 53047c6ae99SBarry Smith /* 531aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 53247c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 53347c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 53447c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 53547c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 53647c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 53747c6ae99SBarry Smith 53847c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 53947c6ae99SBarry Smith */ 5409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dac), &size_c)); 5419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)daf), &size_f)); 5429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)daf), &rank_f)); 54347c6ae99SBarry Smith col_scale = size_f / size_c; 54447c6ae99SBarry Smith col_shift = Mx * My * (rank_f / size_c); 54547c6ae99SBarry Smith 546d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)daf), m_f * n_f, col_scale * m_c * n_c, dnz, onz); 54747c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 54847c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 54947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 550e3fbd1f4SBarry Smith row = idx_f[(m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 55147c6ae99SBarry Smith 55247c6ae99SBarry Smith i_c = (i / ratioi); /* coarse grid node to left of fine grid node */ 55347c6ae99SBarry Smith j_c = (j / ratioj); /* coarse grid node below fine grid node */ 55447c6ae99SBarry Smith 55508401ef6SPierre 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\ 5569371c9d4SSatish Balay j_start %" PetscInt_FMT " j_c %" PetscInt_FMT " j_start_ghost_c %" PetscInt_FMT, 5579371c9d4SSatish Balay j_start, j_c, j_start_ghost_c); 55808401ef6SPierre 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\ 5599371c9d4SSatish Balay i_start %" PetscInt_FMT " i_c %" PetscInt_FMT " i_start_ghost_c %" PetscInt_FMT, 5609371c9d4SSatish Balay i_start, i_c, i_start_ghost_c); 56147c6ae99SBarry Smith 56247c6ae99SBarry Smith /* 56347c6ae99SBarry Smith Only include those interpolation points that are truly 56447c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 56547c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 56647c6ae99SBarry Smith */ 56747c6ae99SBarry Smith nc = 0; 56847c6ae99SBarry Smith /* one left and below; or we are right on it */ 569e3fbd1f4SBarry Smith col = (m_ghost_c * (j_c - j_start_ghost_c) + (i_c - i_start_ghost_c)); 570e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 5719566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, nc, cols, dnz, onz)); 57247c6ae99SBarry Smith } 57347c6ae99SBarry Smith } 5749566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)daf), &mat)); 575fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 576fdc842d1SBarry Smith /* 577fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 578fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 579fdc842d1SBarry Smith */ 58048a46eb9SPierre Jolivet if (dof > 1) PetscCall(MatBindToCPU(mat, PETSC_TRUE)); 581fdc842d1SBarry Smith #endif 5829566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, m_f * n_f, col_scale * m_c * n_c, mx * my, col_scale * Mx * My)); 5839566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype, &mattype)); 5849566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, mattype)); 5859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat, 0, dnz)); 5869566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat, 0, dnz, 0, onz)); 587d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 58847c6ae99SBarry Smith 58947c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 59047c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 59147c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 59247c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 593e3fbd1f4SBarry Smith row = idx_f[(m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 59447c6ae99SBarry Smith 59547c6ae99SBarry Smith i_c = (i / ratioi); /* coarse grid node to left of fine grid node */ 59647c6ae99SBarry Smith j_c = (j / ratioj); /* coarse grid node below fine grid node */ 59747c6ae99SBarry Smith nc = 0; 59847c6ae99SBarry Smith /* one left and below; or we are right on it */ 599e3fbd1f4SBarry Smith col = (m_ghost_c * (j_c - j_start_ghost_c) + (i_c - i_start_ghost_c)); 600e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 60147c6ae99SBarry Smith v[nc++] = 1.0; 60247c6ae99SBarry Smith 6039566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, nc, cols, v, INSERT_VALUES)); 60447c6ae99SBarry Smith } 60547c6ae99SBarry Smith } 6069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 6079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 6089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 6099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 6109566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat, dof, A)); 6119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 6129566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(13.0 * m_f * n_f)); 6133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61447c6ae99SBarry Smith } 61547c6ae99SBarry Smith 61647c6ae99SBarry Smith /* 61747c6ae99SBarry Smith Contributed by Jianming Yang <jianming-yang@uiowa.edu> 61847c6ae99SBarry Smith */ 61966976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac, DM daf, Mat *A) 620d71ae5a4SJacob Faibussowitsch { 6218ea3bf28SBarry Smith PetscInt i, j, l, i_start, j_start, l_start, m_f, n_f, p_f, Mx, My, Mz, dof; 6228ea3bf28SBarry Smith const PetscInt *idx_c, *idx_f; 623e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 6248ea3bf28SBarry Smith PetscInt m_ghost, n_ghost, p_ghost, m_ghost_c, n_ghost_c, p_ghost_c, nc, *dnz, *onz; 62547c6ae99SBarry 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; 62647c6ae99SBarry 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; 62747c6ae99SBarry Smith PetscMPIInt size_c, size_f, rank_f; 62847c6ae99SBarry Smith PetscScalar v[8]; 62947c6ae99SBarry Smith Mat mat; 630bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 631fdc842d1SBarry Smith MatType mattype; 63247c6ae99SBarry Smith 63347c6ae99SBarry Smith PetscFunctionBegin; 6349566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, &My, &Mz, NULL, NULL, NULL, NULL, NULL, &bx, &by, &bz, NULL)); 63563a3b9bcSJacob Faibussowitsch PetscCheck(Mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be positive", Mx); 63663a3b9bcSJacob Faibussowitsch PetscCheck(My, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of y coarse grid points %" PetscInt_FMT " must be positive", My); 63763a3b9bcSJacob Faibussowitsch PetscCheck(Mz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of z coarse grid points %" PetscInt_FMT " must be positive", Mz); 6389566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, &my, &mz, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 63947c6ae99SBarry Smith ratioi = mx / Mx; 64047c6ae99SBarry Smith ratioj = my / My; 64147c6ae99SBarry Smith ratiol = mz / Mz; 64208401ef6SPierre Jolivet PetscCheck(ratioi * Mx == mx, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Fine grid points must be multiple of coarse grid points in x"); 64308401ef6SPierre Jolivet PetscCheck(ratioj * My == my, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Fine grid points must be multiple of coarse grid points in y"); 64408401ef6SPierre Jolivet PetscCheck(ratiol * Mz == mz, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Fine grid points must be multiple of coarse grid points in z"); 6451dca8a05SBarry Smith PetscCheck(ratioi == 2 || ratioi == 1, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Coarsening factor in x must be 1 or 2"); 6461dca8a05SBarry Smith PetscCheck(ratioj == 2 || ratioj == 1, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Coarsening factor in y must be 1 or 2"); 6471dca8a05SBarry Smith PetscCheck(ratiol == 2 || ratiol == 1, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_WRONG, "Coarsening factor in z must be 1 or 2"); 64847c6ae99SBarry Smith 6499566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, &j_start, &l_start, &m_f, &n_f, &p_f)); 6509566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, &j_start_ghost, &l_start_ghost, &m_ghost, &n_ghost, &p_ghost)); 6519566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 6529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 65347c6ae99SBarry Smith 6549566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, &j_start_c, &l_start_c, &m_c, &n_c, &p_c)); 6559566063dSJacob 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)); 6569566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 6579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 658e3fbd1f4SBarry Smith 65947c6ae99SBarry Smith /* 660aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 66147c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 66247c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 66347c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 66447c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 66547c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 66647c6ae99SBarry Smith 66747c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 66847c6ae99SBarry Smith */ 6699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dac), &size_c)); 6709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)daf), &size_f)); 6719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)daf), &rank_f)); 67247c6ae99SBarry Smith col_scale = size_f / size_c; 67347c6ae99SBarry Smith col_shift = Mx * My * Mz * (rank_f / size_c); 67447c6ae99SBarry Smith 675d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)daf), m_f * n_f * p_f, col_scale * m_c * n_c * p_c, dnz, onz); 67647c6ae99SBarry Smith for (l = l_start; l < l_start + p_f; l++) { 67747c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 67847c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 67947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 680e3fbd1f4SBarry Smith row = idx_f[(m_ghost * n_ghost * (l - l_start_ghost) + m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 68147c6ae99SBarry Smith 68247c6ae99SBarry Smith i_c = (i / ratioi); /* coarse grid node to left of fine grid node */ 68347c6ae99SBarry Smith j_c = (j / ratioj); /* coarse grid node below fine grid node */ 68447c6ae99SBarry Smith l_c = (l / ratiol); 68547c6ae99SBarry Smith 68608401ef6SPierre 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\ 6879371c9d4SSatish Balay l_start %" PetscInt_FMT " l_c %" PetscInt_FMT " l_start_ghost_c %" PetscInt_FMT, 6889371c9d4SSatish Balay l_start, l_c, l_start_ghost_c); 68908401ef6SPierre 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\ 6909371c9d4SSatish Balay j_start %" PetscInt_FMT " j_c %" PetscInt_FMT " j_start_ghost_c %" PetscInt_FMT, 6919371c9d4SSatish Balay j_start, j_c, j_start_ghost_c); 69208401ef6SPierre 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\ 6939371c9d4SSatish Balay i_start %" PetscInt_FMT " i_c %" PetscInt_FMT " i_start_ghost_c %" PetscInt_FMT, 6949371c9d4SSatish Balay i_start, i_c, i_start_ghost_c); 69547c6ae99SBarry Smith 69647c6ae99SBarry Smith /* 69747c6ae99SBarry Smith Only include those interpolation points that are truly 69847c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 69947c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 70047c6ae99SBarry Smith */ 70147c6ae99SBarry Smith nc = 0; 70247c6ae99SBarry Smith /* one left and below; or we are right on it */ 703e3fbd1f4SBarry 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)); 704e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 7059566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, nc, cols, dnz, onz)); 70647c6ae99SBarry Smith } 70747c6ae99SBarry Smith } 70847c6ae99SBarry Smith } 7099566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)daf), &mat)); 710fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 711fdc842d1SBarry Smith /* 712fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 713fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 714fdc842d1SBarry Smith */ 71548a46eb9SPierre Jolivet if (dof > 1) PetscCall(MatBindToCPU(mat, PETSC_TRUE)); 716fdc842d1SBarry Smith #endif 7179566063dSJacob 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)); 7189566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype, &mattype)); 7199566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, mattype)); 7209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat, 0, dnz)); 7219566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat, 0, dnz, 0, onz)); 722d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 72347c6ae99SBarry Smith 72447c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 72547c6ae99SBarry Smith for (l = l_start; l < l_start + p_f; l++) { 72647c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 72747c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 72847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 729e3fbd1f4SBarry Smith row = idx_f[(m_ghost * n_ghost * (l - l_start_ghost) + m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 73047c6ae99SBarry Smith 73147c6ae99SBarry Smith i_c = (i / ratioi); /* coarse grid node to left of fine grid node */ 73247c6ae99SBarry Smith j_c = (j / ratioj); /* coarse grid node below fine grid node */ 73347c6ae99SBarry Smith l_c = (l / ratiol); 73447c6ae99SBarry Smith nc = 0; 73547c6ae99SBarry Smith /* one left and below; or we are right on it */ 736e3fbd1f4SBarry 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)); 737e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 73847c6ae99SBarry Smith v[nc++] = 1.0; 73947c6ae99SBarry Smith 7409566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, nc, cols, v, INSERT_VALUES)); 74147c6ae99SBarry Smith } 74247c6ae99SBarry Smith } 74347c6ae99SBarry Smith } 7449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 7459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 7469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 7479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 7489566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat, dof, A)); 7499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 7509566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(13.0 * m_f * n_f * p_f)); 7513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75247c6ae99SBarry Smith } 75347c6ae99SBarry Smith 75466976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac, DM daf, Mat *A) 755d71ae5a4SJacob Faibussowitsch { 7568ea3bf28SBarry Smith PetscInt i, j, i_start, j_start, m_f, n_f, Mx, My, dof, l; 7578ea3bf28SBarry Smith const PetscInt *idx_c, *idx_f; 758e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 7598ea3bf28SBarry Smith PetscInt m_ghost, n_ghost, m_ghost_c, n_ghost_c, Mz, mz; 76047c6ae99SBarry Smith PetscInt row, col, i_start_ghost, j_start_ghost, cols[8], mx, m_c, my, nc, ratioi, ratioj, ratiok; 76147c6ae99SBarry Smith PetscInt i_c, j_c, i_start_c, j_start_c, n_c, i_start_ghost_c, j_start_ghost_c; 76247c6ae99SBarry Smith PetscInt l_start, p_f, l_start_ghost, p_ghost, l_start_c, p_c; 76347c6ae99SBarry Smith PetscInt l_start_ghost_c, p_ghost_c, l_c, *dnz, *onz; 76447c6ae99SBarry Smith PetscScalar v[8], x, y, z; 76547c6ae99SBarry Smith Mat mat; 766bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 767fdc842d1SBarry Smith MatType mattype; 76847c6ae99SBarry Smith 76947c6ae99SBarry Smith PetscFunctionBegin; 7709566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, &My, &Mz, NULL, NULL, NULL, NULL, NULL, &bx, &by, &bz, NULL)); 7719566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, &my, &mz, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 77247c6ae99SBarry Smith if (mx == Mx) { 77347c6ae99SBarry Smith ratioi = 1; 774bff4a2f0SMatthew G. Knepley } else if (bx == DM_BOUNDARY_PERIODIC) { 77563a3b9bcSJacob Faibussowitsch PetscCheck(Mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be positive", Mx); 77647c6ae99SBarry Smith ratioi = mx / Mx; 77763a3b9bcSJacob Faibussowitsch PetscCheck(ratioi * Mx == mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mx/Mx must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 77847c6ae99SBarry Smith } else { 77963a3b9bcSJacob Faibussowitsch PetscCheck(Mx >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of x coarse grid points %" PetscInt_FMT " must be greater than 1", Mx); 78047c6ae99SBarry Smith ratioi = (mx - 1) / (Mx - 1); 7811dca8a05SBarry Smith PetscCheck(ratioi * (Mx - 1) == mx - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 78247c6ae99SBarry Smith } 78347c6ae99SBarry Smith if (my == My) { 78447c6ae99SBarry Smith ratioj = 1; 785bff4a2f0SMatthew G. Knepley } else if (by == DM_BOUNDARY_PERIODIC) { 78663a3b9bcSJacob Faibussowitsch PetscCheck(My, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of y coarse grid points %" PetscInt_FMT " must be positive", My); 78747c6ae99SBarry Smith ratioj = my / My; 78863a3b9bcSJacob Faibussowitsch PetscCheck(ratioj * My == my, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: my/My must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 78947c6ae99SBarry Smith } else { 79063a3b9bcSJacob Faibussowitsch PetscCheck(My >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of y coarse grid points %" PetscInt_FMT " must be greater than 1", My); 79147c6ae99SBarry Smith ratioj = (my - 1) / (My - 1); 7921dca8a05SBarry Smith PetscCheck(ratioj * (My - 1) == my - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (my - 1)/(My - 1) must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 79347c6ae99SBarry Smith } 79447c6ae99SBarry Smith if (mz == Mz) { 79547c6ae99SBarry Smith ratiok = 1; 796bff4a2f0SMatthew G. Knepley } else if (bz == DM_BOUNDARY_PERIODIC) { 79763a3b9bcSJacob Faibussowitsch PetscCheck(Mz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of z coarse grid points %" PetscInt_FMT " must be positive", Mz); 79847c6ae99SBarry Smith ratiok = mz / Mz; 79963a3b9bcSJacob Faibussowitsch PetscCheck(ratiok * Mz == mz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mz/Mz must be integer: mz %" PetscInt_FMT " Mz %" PetscInt_FMT, mz, Mz); 80047c6ae99SBarry Smith } else { 80163a3b9bcSJacob Faibussowitsch PetscCheck(Mz >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of z coarse grid points %" PetscInt_FMT " must be greater than 1", Mz); 80247c6ae99SBarry Smith ratiok = (mz - 1) / (Mz - 1); 8031dca8a05SBarry Smith PetscCheck(ratiok * (Mz - 1) == mz - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %" PetscInt_FMT " Mz %" PetscInt_FMT, mz, Mz); 80447c6ae99SBarry Smith } 80547c6ae99SBarry Smith 8069566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, &j_start, &l_start, &m_f, &n_f, &p_f)); 8079566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, &j_start_ghost, &l_start_ghost, &m_ghost, &n_ghost, &p_ghost)); 8089566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 8099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 81047c6ae99SBarry Smith 8119566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, &j_start_c, &l_start_c, &m_c, &n_c, &p_c)); 8129566063dSJacob 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)); 8139566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 8149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 81547c6ae99SBarry Smith 81647c6ae99SBarry Smith /* create interpolation matrix, determining exact preallocation */ 817d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)dac), m_f * n_f * p_f, m_c * n_c * p_c, dnz, onz); 81847c6ae99SBarry Smith /* loop over local fine grid nodes counting interpolating points */ 81947c6ae99SBarry Smith for (l = l_start; l < l_start + p_f; l++) { 82047c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 82147c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 82247c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 823e3fbd1f4SBarry Smith row = idx_f[(m_ghost * n_ghost * (l - l_start_ghost) + m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 82447c6ae99SBarry Smith i_c = (i / ratioi); 82547c6ae99SBarry Smith j_c = (j / ratioj); 82647c6ae99SBarry Smith l_c = (l / ratiok); 82708401ef6SPierre 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\ 8289371c9d4SSatish Balay l_start %" PetscInt_FMT " l_c %" PetscInt_FMT " l_start_ghost_c %" PetscInt_FMT, 8299371c9d4SSatish Balay l_start, l_c, l_start_ghost_c); 83008401ef6SPierre 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\ 8319371c9d4SSatish Balay j_start %" PetscInt_FMT " j_c %" PetscInt_FMT " j_start_ghost_c %" PetscInt_FMT, 8329371c9d4SSatish Balay j_start, j_c, j_start_ghost_c); 83308401ef6SPierre 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\ 8349371c9d4SSatish Balay i_start %" PetscInt_FMT " i_c %" PetscInt_FMT " i_start_ghost_c %" PetscInt_FMT, 8359371c9d4SSatish Balay i_start, i_c, i_start_ghost_c); 83647c6ae99SBarry Smith 83747c6ae99SBarry Smith /* 83847c6ae99SBarry Smith Only include those interpolation points that are truly 83947c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 84047c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 84147c6ae99SBarry Smith */ 84247c6ae99SBarry Smith nc = 0; 843e3fbd1f4SBarry 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)); 844e3fbd1f4SBarry Smith cols[nc++] = idx_c[col]; 845ad540459SPierre Jolivet if (i_c * ratioi != i) cols[nc++] = idx_c[col + 1]; 846ad540459SPierre Jolivet if (j_c * ratioj != j) cols[nc++] = idx_c[col + m_ghost_c]; 847ad540459SPierre Jolivet if (l_c * ratiok != l) cols[nc++] = idx_c[col + m_ghost_c * n_ghost_c]; 848ad540459SPierre Jolivet if (j_c * ratioj != j && i_c * ratioi != i) cols[nc++] = idx_c[col + (m_ghost_c + 1)]; 849ad540459SPierre Jolivet if (j_c * ratioj != j && l_c * ratiok != l) cols[nc++] = idx_c[col + (m_ghost_c * n_ghost_c + m_ghost_c)]; 850ad540459SPierre Jolivet if (i_c * ratioi != i && l_c * ratiok != l) cols[nc++] = idx_c[col + (m_ghost_c * n_ghost_c + 1)]; 851ad540459SPierre Jolivet if (i_c * ratioi != i && l_c * ratiok != l && j_c * ratioj != j) cols[nc++] = idx_c[col + (m_ghost_c * n_ghost_c + m_ghost_c + 1)]; 8529566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(row, nc, cols, dnz, onz)); 85347c6ae99SBarry Smith } 85447c6ae99SBarry Smith } 85547c6ae99SBarry Smith } 8569566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dac), &mat)); 857fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 858fdc842d1SBarry Smith /* 859fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 860fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 861fdc842d1SBarry Smith */ 86248a46eb9SPierre Jolivet if (dof > 1) PetscCall(MatBindToCPU(mat, PETSC_TRUE)); 863fdc842d1SBarry Smith #endif 8649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, m_f * n_f * p_f, m_c * n_c * p_c, mx * my * mz, Mx * My * Mz)); 8659566063dSJacob Faibussowitsch PetscCall(ConvertToAIJ(dac->mattype, &mattype)); 8669566063dSJacob Faibussowitsch PetscCall(MatSetType(mat, mattype)); 8679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(mat, 0, dnz)); 8689566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(mat, 0, dnz, 0, onz)); 869d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 87047c6ae99SBarry Smith 87147c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 8722adb9dcfSBarry Smith if (!NEWVERSION) { 87347c6ae99SBarry Smith for (l = l_start; l < l_start + p_f; l++) { 87447c6ae99SBarry Smith for (j = j_start; j < j_start + n_f; j++) { 87547c6ae99SBarry Smith for (i = i_start; i < i_start + m_f; i++) { 87647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 877e3fbd1f4SBarry Smith row = idx_f[(m_ghost * n_ghost * (l - l_start_ghost) + m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 87847c6ae99SBarry Smith 87947c6ae99SBarry Smith i_c = (i / ratioi); 88047c6ae99SBarry Smith j_c = (j / ratioj); 88147c6ae99SBarry Smith l_c = (l / ratiok); 88247c6ae99SBarry Smith 88347c6ae99SBarry Smith /* 88447c6ae99SBarry Smith Only include those interpolation points that are truly 88547c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 88647c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 88747c6ae99SBarry Smith */ 8886712e2f1SBarry Smith x = ((PetscReal)(i - i_c * ratioi)) / ((PetscReal)ratioi); 8896712e2f1SBarry Smith y = ((PetscReal)(j - j_c * ratioj)) / ((PetscReal)ratioj); 8906712e2f1SBarry Smith z = ((PetscReal)(l - l_c * ratiok)) / ((PetscReal)ratiok); 891b3bd94feSDave May 89247c6ae99SBarry Smith nc = 0; 89347c6ae99SBarry Smith /* one left and below; or we are right on it */ 894e3fbd1f4SBarry 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)); 89547c6ae99SBarry Smith 896e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 89747c6ae99SBarry Smith v[nc++] = .125 * (1. - (2.0 * x - 1.)) * (1. - (2.0 * y - 1.)) * (1. - (2.0 * z - 1.)); 89847c6ae99SBarry Smith 89947c6ae99SBarry Smith if (i_c * ratioi != i) { 900e3fbd1f4SBarry Smith cols[nc] = idx_c[col + 1]; 90147c6ae99SBarry Smith v[nc++] = .125 * (1. + (2.0 * x - 1.)) * (1. - (2.0 * y - 1.)) * (1. - (2.0 * z - 1.)); 90247c6ae99SBarry Smith } 90347c6ae99SBarry Smith 90447c6ae99SBarry Smith if (j_c * ratioj != j) { 905e3fbd1f4SBarry Smith cols[nc] = idx_c[col + m_ghost_c]; 90647c6ae99SBarry Smith v[nc++] = .125 * (1. - (2.0 * x - 1.)) * (1. + (2.0 * y - 1.)) * (1. - (2.0 * z - 1.)); 90747c6ae99SBarry Smith } 90847c6ae99SBarry Smith 90947c6ae99SBarry Smith if (l_c * ratiok != l) { 910e3fbd1f4SBarry Smith cols[nc] = idx_c[col + m_ghost_c * n_ghost_c]; 91147c6ae99SBarry Smith v[nc++] = .125 * (1. - (2.0 * x - 1.)) * (1. - (2.0 * y - 1.)) * (1. + (2.0 * z - 1.)); 91247c6ae99SBarry Smith } 91347c6ae99SBarry Smith 91447c6ae99SBarry Smith if (j_c * ratioj != j && i_c * ratioi != i) { 915e3fbd1f4SBarry Smith cols[nc] = idx_c[col + (m_ghost_c + 1)]; 91647c6ae99SBarry Smith v[nc++] = .125 * (1. + (2.0 * x - 1.)) * (1. + (2.0 * y - 1.)) * (1. - (2.0 * z - 1.)); 91747c6ae99SBarry Smith } 91847c6ae99SBarry Smith 91947c6ae99SBarry Smith if (j_c * ratioj != j && l_c * ratiok != l) { 920e3fbd1f4SBarry Smith cols[nc] = idx_c[col + (m_ghost_c * n_ghost_c + m_ghost_c)]; 92147c6ae99SBarry Smith v[nc++] = .125 * (1. - (2.0 * x - 1.)) * (1. + (2.0 * y - 1.)) * (1. + (2.0 * z - 1.)); 92247c6ae99SBarry Smith } 92347c6ae99SBarry Smith 92447c6ae99SBarry Smith if (i_c * ratioi != i && l_c * ratiok != l) { 925e3fbd1f4SBarry Smith cols[nc] = idx_c[col + (m_ghost_c * n_ghost_c + 1)]; 92647c6ae99SBarry Smith v[nc++] = .125 * (1. + (2.0 * x - 1.)) * (1. - (2.0 * y - 1.)) * (1. + (2.0 * z - 1.)); 92747c6ae99SBarry Smith } 92847c6ae99SBarry Smith 92947c6ae99SBarry Smith if (i_c * ratioi != i && l_c * ratiok != l && j_c * ratioj != j) { 930e3fbd1f4SBarry Smith cols[nc] = idx_c[col + (m_ghost_c * n_ghost_c + m_ghost_c + 1)]; 93147c6ae99SBarry Smith v[nc++] = .125 * (1. + (2.0 * x - 1.)) * (1. + (2.0 * y - 1.)) * (1. + (2.0 * z - 1.)); 93247c6ae99SBarry Smith } 9339566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, nc, cols, v, INSERT_VALUES)); 93447c6ae99SBarry Smith } 93547c6ae99SBarry Smith } 93647c6ae99SBarry Smith } 937b3bd94feSDave May 938b3bd94feSDave May } else { 939b3bd94feSDave May PetscScalar *xi, *eta, *zeta; 940b3bd94feSDave May PetscInt li, nxi, lj, neta, lk, nzeta, n; 941b3bd94feSDave May PetscScalar Ni[8]; 942b3bd94feSDave May 943b3bd94feSDave May /* compute local coordinate arrays */ 944b3bd94feSDave May nxi = ratioi + 1; 945b3bd94feSDave May neta = ratioj + 1; 946b3bd94feSDave May nzeta = ratiok + 1; 9479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nxi, &xi)); 9489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(neta, &eta)); 9499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzeta, &zeta)); 9508865f1eaSKarl Rupp for (li = 0; li < nxi; li++) xi[li] = -1.0 + (PetscScalar)li * (2.0 / (PetscScalar)(nxi - 1)); 9518865f1eaSKarl Rupp for (lj = 0; lj < neta; lj++) eta[lj] = -1.0 + (PetscScalar)lj * (2.0 / (PetscScalar)(neta - 1)); 9528865f1eaSKarl Rupp for (lk = 0; lk < nzeta; lk++) zeta[lk] = -1.0 + (PetscScalar)lk * (2.0 / (PetscScalar)(nzeta - 1)); 953b3bd94feSDave May 954b3bd94feSDave May for (l = l_start; l < l_start + p_f; l++) { 955b3bd94feSDave May for (j = j_start; j < j_start + n_f; j++) { 956b3bd94feSDave May for (i = i_start; i < i_start + m_f; i++) { 957b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 958e3fbd1f4SBarry Smith row = idx_f[(m_ghost * n_ghost * (l - l_start_ghost) + m_ghost * (j - j_start_ghost) + (i - i_start_ghost))]; 959b3bd94feSDave May 960b3bd94feSDave May i_c = (i / ratioi); 961b3bd94feSDave May j_c = (j / ratioj); 962b3bd94feSDave May l_c = (l / ratiok); 963b3bd94feSDave May 964b3bd94feSDave May /* remainders */ 965b3bd94feSDave May li = i - ratioi * (i / ratioi); 9668865f1eaSKarl Rupp if (i == mx - 1) li = nxi - 1; 967b3bd94feSDave May lj = j - ratioj * (j / ratioj); 9688865f1eaSKarl Rupp if (j == my - 1) lj = neta - 1; 969b3bd94feSDave May lk = l - ratiok * (l / ratiok); 9708865f1eaSKarl Rupp if (l == mz - 1) lk = nzeta - 1; 971b3bd94feSDave May 972b3bd94feSDave May /* corners */ 973e3fbd1f4SBarry 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)); 974e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 975b3bd94feSDave May Ni[0] = 1.0; 976b3bd94feSDave May if ((li == 0) || (li == nxi - 1)) { 977b3bd94feSDave May if ((lj == 0) || (lj == neta - 1)) { 978b3bd94feSDave May if ((lk == 0) || (lk == nzeta - 1)) { 9799566063dSJacob Faibussowitsch PetscCall(MatSetValue(mat, row, cols[0], Ni[0], INSERT_VALUES)); 980b3bd94feSDave May continue; 981b3bd94feSDave May } 982b3bd94feSDave May } 983b3bd94feSDave May } 984b3bd94feSDave May 985b3bd94feSDave May /* edges + interior */ 986b3bd94feSDave May /* remainders */ 9878865f1eaSKarl Rupp if (i == mx - 1) i_c--; 9888865f1eaSKarl Rupp if (j == my - 1) j_c--; 9898865f1eaSKarl Rupp if (l == mz - 1) l_c--; 990b3bd94feSDave May 991e3fbd1f4SBarry 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)); 992e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 993e3fbd1f4SBarry Smith cols[1] = idx_c[col + 1]; /* one right and below */ 994e3fbd1f4SBarry Smith cols[2] = idx_c[col + m_ghost_c]; /* one left and above */ 995e3fbd1f4SBarry Smith cols[3] = idx_c[col + (m_ghost_c + 1)]; /* one right and above */ 996b3bd94feSDave May 997e3fbd1f4SBarry Smith cols[4] = idx_c[col + m_ghost_c * n_ghost_c]; /* one left and below and front; or we are right on it */ 998e3fbd1f4SBarry Smith cols[5] = idx_c[col + (m_ghost_c * n_ghost_c + 1)]; /* one right and below, and front */ 999e3fbd1f4SBarry Smith cols[6] = idx_c[col + (m_ghost_c * n_ghost_c + m_ghost_c)]; /* one left and above and front*/ 1000e3fbd1f4SBarry Smith cols[7] = idx_c[col + (m_ghost_c * n_ghost_c + m_ghost_c + 1)]; /* one right and above and front */ 1001b3bd94feSDave May 1002b3bd94feSDave May Ni[0] = 0.125 * (1.0 - xi[li]) * (1.0 - eta[lj]) * (1.0 - zeta[lk]); 1003b3bd94feSDave May Ni[1] = 0.125 * (1.0 + xi[li]) * (1.0 - eta[lj]) * (1.0 - zeta[lk]); 1004b3bd94feSDave May Ni[2] = 0.125 * (1.0 - xi[li]) * (1.0 + eta[lj]) * (1.0 - zeta[lk]); 1005b3bd94feSDave May Ni[3] = 0.125 * (1.0 + xi[li]) * (1.0 + eta[lj]) * (1.0 - zeta[lk]); 1006b3bd94feSDave May 1007b3bd94feSDave May Ni[4] = 0.125 * (1.0 - xi[li]) * (1.0 - eta[lj]) * (1.0 + zeta[lk]); 1008b3bd94feSDave May Ni[5] = 0.125 * (1.0 + xi[li]) * (1.0 - eta[lj]) * (1.0 + zeta[lk]); 1009b3bd94feSDave May Ni[6] = 0.125 * (1.0 - xi[li]) * (1.0 + eta[lj]) * (1.0 + zeta[lk]); 1010b3bd94feSDave May Ni[7] = 0.125 * (1.0 + xi[li]) * (1.0 + eta[lj]) * (1.0 + zeta[lk]); 1011b3bd94feSDave May 1012b3bd94feSDave May for (n = 0; n < 8; n++) { 10138865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n]) < 1.0e-32) cols[n] = -1; 1014b3bd94feSDave May } 10159566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, 1, &row, 8, cols, Ni, INSERT_VALUES)); 1016b3bd94feSDave May } 1017b3bd94feSDave May } 1018b3bd94feSDave May } 10199566063dSJacob Faibussowitsch PetscCall(PetscFree(xi)); 10209566063dSJacob Faibussowitsch PetscCall(PetscFree(eta)); 10219566063dSJacob Faibussowitsch PetscCall(PetscFree(zeta)); 1022b3bd94feSDave May } 10239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 10249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 10259566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 10269566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 102747c6ae99SBarry Smith 10289566063dSJacob Faibussowitsch PetscCall(MatCreateMAIJ(mat, dof, A)); 10299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 10303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103147c6ae99SBarry Smith } 103247c6ae99SBarry Smith 1033d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_DA(DM dac, DM daf, Mat *A, Vec *scale) 1034d71ae5a4SJacob Faibussowitsch { 103547c6ae99SBarry Smith PetscInt dimc, Mc, Nc, Pc, mc, nc, pc, dofc, sc, dimf, Mf, Nf, Pf, mf, nf, pf, doff, sf; 1036bff4a2f0SMatthew G. Knepley DMBoundaryType bxc, byc, bzc, bxf, byf, bzf; 1037aa219208SBarry Smith DMDAStencilType stc, stf; 103847c6ae99SBarry Smith DM_DA *ddc = (DM_DA *)dac->data; 103947c6ae99SBarry Smith 104047c6ae99SBarry Smith PetscFunctionBegin; 104147c6ae99SBarry Smith PetscValidHeaderSpecific(dac, DM_CLASSID, 1); 104247c6ae99SBarry Smith PetscValidHeaderSpecific(daf, DM_CLASSID, 2); 10434f572ea9SToby Isaac PetscAssertPointer(A, 3); 10444f572ea9SToby Isaac if (scale) PetscAssertPointer(scale, 4); 104547c6ae99SBarry Smith 10469566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, &dimc, &Mc, &Nc, &Pc, &mc, &nc, &pc, &dofc, &sc, &bxc, &byc, &bzc, &stc)); 10479566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, &dimf, &Mf, &Nf, &Pf, &mf, &nf, &pf, &doff, &sf, &bxf, &byf, &bzf, &stf)); 104863a3b9bcSJacob Faibussowitsch PetscCheck(dimc == dimf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Dimensions of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, dimc, dimf); 104963a3b9bcSJacob Faibussowitsch PetscCheck(dofc == doff, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "DOF of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, dofc, doff); 105063a3b9bcSJacob Faibussowitsch PetscCheck(sc == sf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Stencil width of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, sc, sf); 10511dca8a05SBarry Smith PetscCheck(bxc == bxf && byc == byf && bzc == bzf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Boundary type different in two DMDAs"); 105208401ef6SPierre Jolivet PetscCheck(stc == stf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Stencil type different in two DMDAs"); 10531dca8a05SBarry Smith PetscCheck(Mc >= 2 || Mf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coarse grid requires at least 2 points in x direction"); 10541dca8a05SBarry Smith PetscCheck(dimc <= 1 || Nc >= 2 || Nf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coarse grid requires at least 2 points in y direction"); 10551dca8a05SBarry Smith PetscCheck(dimc <= 2 || Pc >= 2 || Pf <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coarse grid requires at least 2 points in z direction"); 105647c6ae99SBarry Smith 1057aa219208SBarry Smith if (ddc->interptype == DMDA_Q1) { 105847c6ae99SBarry Smith if (dimc == 1) { 10599566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_1D_Q1(dac, daf, A)); 106047c6ae99SBarry Smith } else if (dimc == 2) { 10619566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_2D_Q1(dac, daf, A)); 106247c6ae99SBarry Smith } else if (dimc == 3) { 10639566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_3D_Q1(dac, daf, A)); 106463a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)daf), PETSC_ERR_SUP, "No support for this DMDA dimension %" PetscInt_FMT " for interpolation type %d", dimc, (int)ddc->interptype); 1065aa219208SBarry Smith } else if (ddc->interptype == DMDA_Q0) { 106647c6ae99SBarry Smith if (dimc == 1) { 10679566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_1D_Q0(dac, daf, A)); 106847c6ae99SBarry Smith } else if (dimc == 2) { 10699566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_2D_Q0(dac, daf, A)); 107047c6ae99SBarry Smith } else if (dimc == 3) { 10719566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation_DA_3D_Q0(dac, daf, A)); 107263a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)daf), PETSC_ERR_SUP, "No support for this DMDA dimension %" PetscInt_FMT " for interpolation type %d", dimc, (int)ddc->interptype); 107347c6ae99SBarry Smith } 10741baa6e33SBarry Smith if (scale) PetscCall(DMCreateInterpolationScale((DM)dac, (DM)daf, *A, scale)); 10753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 107647c6ae99SBarry Smith } 107747c6ae99SBarry Smith 107866976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInjection_DA_1D(DM dac, DM daf, VecScatter *inject) 1079d71ae5a4SJacob Faibussowitsch { 10808ea3bf28SBarry Smith PetscInt i, i_start, m_f, Mx, dof; 10818ea3bf28SBarry Smith const PetscInt *idx_f; 1082e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f; 10838ea3bf28SBarry Smith PetscInt m_ghost, m_ghost_c; 10840bb2b966SJungho Lee PetscInt row, i_start_ghost, mx, m_c, nc, ratioi; 10850bb2b966SJungho Lee PetscInt i_start_c, i_start_ghost_c; 10860bb2b966SJungho Lee PetscInt *cols; 1087bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 10880bb2b966SJungho Lee Vec vecf, vecc; 10890bb2b966SJungho Lee IS isf; 10900bb2b966SJungho Lee 10910bb2b966SJungho Lee PetscFunctionBegin; 10929566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &bx, NULL, NULL, NULL)); 10939566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 1094bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 10950bb2b966SJungho Lee ratioi = mx / Mx; 109663a3b9bcSJacob Faibussowitsch PetscCheck(ratioi * Mx == mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mx/Mx must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 10970bb2b966SJungho Lee } else { 10980bb2b966SJungho Lee ratioi = (mx - 1) / (Mx - 1); 10991dca8a05SBarry Smith PetscCheck(ratioi * (Mx - 1) == mx - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 11000bb2b966SJungho Lee } 11010bb2b966SJungho Lee 11029566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, NULL, NULL, &m_f, NULL, NULL)); 11039566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, NULL, NULL, &m_ghost, NULL, NULL)); 11049566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 11059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 11060bb2b966SJungho Lee 11079566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, NULL, NULL, &m_c, NULL, NULL)); 11089566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac, &i_start_ghost_c, NULL, NULL, &m_ghost_c, NULL, NULL)); 11090bb2b966SJungho Lee 11100bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 11110bb2b966SJungho Lee nc = 0; 11129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m_f, &cols)); 11130bb2b966SJungho Lee 11140bb2b966SJungho Lee for (i = i_start_c; i < i_start_c + m_c; i++) { 11150bb2b966SJungho Lee PetscInt i_f = i * ratioi; 11160bb2b966SJungho Lee 11171dca8a05SBarry Smith PetscCheck(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 %" PetscInt_FMT " i_f %" PetscInt_FMT " fine ghost range [%" PetscInt_FMT ",%" PetscInt_FMT "]", i, i_f, i_start_ghost, i_start_ghost + m_ghost); 11188865f1eaSKarl Rupp 1119e3fbd1f4SBarry Smith row = idx_f[(i_f - i_start_ghost)]; 1120e3fbd1f4SBarry Smith cols[nc++] = row; 11210bb2b966SJungho Lee } 11220bb2b966SJungho Lee 11239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 11249566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)daf), dof, nc, cols, PETSC_OWN_POINTER, &isf)); 11259566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dac, &vecc)); 11269566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(daf, &vecf)); 11279566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vecf, isf, vecc, NULL, inject)); 11289566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dac, &vecc)); 11299566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(daf, &vecf)); 11309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isf)); 11313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11320bb2b966SJungho Lee } 11330bb2b966SJungho Lee 113466976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInjection_DA_2D(DM dac, DM daf, VecScatter *inject) 1135d71ae5a4SJacob Faibussowitsch { 11368ea3bf28SBarry Smith PetscInt i, j, i_start, j_start, m_f, n_f, Mx, My, dof; 11378ea3bf28SBarry Smith const PetscInt *idx_c, *idx_f; 1138e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 11398ea3bf28SBarry Smith PetscInt m_ghost, n_ghost, m_ghost_c, n_ghost_c; 114047c6ae99SBarry Smith PetscInt row, i_start_ghost, j_start_ghost, mx, m_c, my, nc, ratioi, ratioj; 1141076202ddSJed Brown PetscInt i_start_c, j_start_c, n_c, i_start_ghost_c, j_start_ghost_c; 114247c6ae99SBarry Smith PetscInt *cols; 1143bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by; 114447c6ae99SBarry Smith Vec vecf, vecc; 114547c6ae99SBarry Smith IS isf; 114647c6ae99SBarry Smith 114747c6ae99SBarry Smith PetscFunctionBegin; 11489566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, &My, NULL, NULL, NULL, NULL, NULL, NULL, &bx, &by, NULL, NULL)); 11499566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, &my, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 1150bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 115147c6ae99SBarry Smith ratioi = mx / Mx; 115263a3b9bcSJacob Faibussowitsch PetscCheck(ratioi * Mx == mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mx/Mx must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 115347c6ae99SBarry Smith } else { 115447c6ae99SBarry Smith ratioi = (mx - 1) / (Mx - 1); 11551dca8a05SBarry Smith PetscCheck(ratioi * (Mx - 1) == mx - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 115647c6ae99SBarry Smith } 1157bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 115847c6ae99SBarry Smith ratioj = my / My; 115963a3b9bcSJacob Faibussowitsch PetscCheck(ratioj * My == my, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: my/My must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 116047c6ae99SBarry Smith } else { 116147c6ae99SBarry Smith ratioj = (my - 1) / (My - 1); 11621dca8a05SBarry Smith PetscCheck(ratioj * (My - 1) == my - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (my - 1)/(My - 1) must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 116347c6ae99SBarry Smith } 116447c6ae99SBarry Smith 11659566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, &j_start, NULL, &m_f, &n_f, NULL)); 11669566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, &j_start_ghost, NULL, &m_ghost, &n_ghost, NULL)); 11679566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 11689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 116947c6ae99SBarry Smith 11709566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, &j_start_c, NULL, &m_c, &n_c, NULL)); 11719566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(dac, &i_start_ghost_c, &j_start_ghost_c, NULL, &m_ghost_c, &n_ghost_c, NULL)); 11729566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 11739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 117447c6ae99SBarry Smith 117547c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 117647c6ae99SBarry Smith nc = 0; 11779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_f * m_f, &cols)); 1178076202ddSJed Brown for (j = j_start_c; j < j_start_c + n_c; j++) { 1179076202ddSJed Brown for (i = i_start_c; i < i_start_c + m_c; i++) { 1180076202ddSJed Brown PetscInt i_f = i * ratioi, j_f = j * ratioj; 11811dca8a05SBarry Smith PetscCheck(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\ 11829371c9d4SSatish Balay j_c %" PetscInt_FMT " j_f %" PetscInt_FMT " fine ghost range [%" PetscInt_FMT ",%" PetscInt_FMT "]", 11839371c9d4SSatish Balay j, j_f, j_start_ghost, j_start_ghost + n_ghost); 11841dca8a05SBarry Smith PetscCheck(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\ 11859371c9d4SSatish Balay i_c %" PetscInt_FMT " i_f %" PetscInt_FMT " fine ghost range [%" PetscInt_FMT ",%" PetscInt_FMT "]", 11869371c9d4SSatish Balay i, i_f, i_start_ghost, i_start_ghost + m_ghost); 1187e3fbd1f4SBarry Smith row = idx_f[(m_ghost * (j_f - j_start_ghost) + (i_f - i_start_ghost))]; 1188e3fbd1f4SBarry Smith cols[nc++] = row; 118947c6ae99SBarry Smith } 119047c6ae99SBarry Smith } 11919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 11929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 119347c6ae99SBarry Smith 11949566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)daf), dof, nc, cols, PETSC_OWN_POINTER, &isf)); 11959566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dac, &vecc)); 11969566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(daf, &vecf)); 11979566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vecf, isf, vecc, NULL, inject)); 11989566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dac, &vecc)); 11999566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(daf, &vecf)); 12009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isf)); 12013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 120247c6ae99SBarry Smith } 120347c6ae99SBarry Smith 120466976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateInjection_DA_3D(DM dac, DM daf, VecScatter *inject) 1205d71ae5a4SJacob Faibussowitsch { 1206b1757049SJed Brown PetscInt i, j, k, i_start, j_start, k_start, m_f, n_f, p_f, Mx, My, Mz; 1207b1757049SJed Brown PetscInt m_ghost, n_ghost, p_ghost, m_ghost_c, n_ghost_c, p_ghost_c; 1208b1757049SJed Brown PetscInt i_start_ghost, j_start_ghost, k_start_ghost; 1209b1757049SJed Brown PetscInt mx, my, mz, ratioi, ratioj, ratiok; 1210b1757049SJed Brown PetscInt i_start_c, j_start_c, k_start_c; 1211b1757049SJed Brown PetscInt m_c, n_c, p_c; 1212b1757049SJed Brown PetscInt i_start_ghost_c, j_start_ghost_c, k_start_ghost_c; 1213b1757049SJed Brown PetscInt row, nc, dof; 12148ea3bf28SBarry Smith const PetscInt *idx_c, *idx_f; 1215e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f, ltog_c; 1216b1757049SJed Brown PetscInt *cols; 1217bff4a2f0SMatthew G. Knepley DMBoundaryType bx, by, bz; 1218b1757049SJed Brown Vec vecf, vecc; 1219b1757049SJed Brown IS isf; 1220b1757049SJed Brown 1221b1757049SJed Brown PetscFunctionBegin; 12229566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, NULL, &Mx, &My, &Mz, NULL, NULL, NULL, NULL, NULL, &bx, &by, &bz, NULL)); 12239566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, NULL, &mx, &my, &mz, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 1224b1757049SJed Brown 1225bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 1226b1757049SJed Brown ratioi = mx / Mx; 122763a3b9bcSJacob Faibussowitsch PetscCheck(ratioi * Mx == mx, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mx/Mx must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 1228b1757049SJed Brown } else { 1229b1757049SJed Brown ratioi = (mx - 1) / (Mx - 1); 12301dca8a05SBarry Smith PetscCheck(ratioi * (Mx - 1) == mx - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %" PetscInt_FMT " Mx %" PetscInt_FMT, mx, Mx); 1231b1757049SJed Brown } 1232bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 1233b1757049SJed Brown ratioj = my / My; 123463a3b9bcSJacob Faibussowitsch PetscCheck(ratioj * My == my, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: my/My must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 1235b1757049SJed Brown } else { 1236b1757049SJed Brown ratioj = (my - 1) / (My - 1); 12371dca8a05SBarry Smith PetscCheck(ratioj * (My - 1) == my - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (my - 1)/(My - 1) must be integer: my %" PetscInt_FMT " My %" PetscInt_FMT, my, My); 1238b1757049SJed Brown } 1239bff4a2f0SMatthew G. Knepley if (bz == DM_BOUNDARY_PERIODIC) { 1240b1757049SJed Brown ratiok = mz / Mz; 124163a3b9bcSJacob Faibussowitsch PetscCheck(ratiok * Mz == mz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: mz/Mz must be integer: mz %" PetscInt_FMT " My %" PetscInt_FMT, mz, Mz); 1242b1757049SJed Brown } else { 1243b1757049SJed Brown ratiok = (mz - 1) / (Mz - 1); 12441dca8a05SBarry Smith PetscCheck(ratiok * (Mz - 1) == mz - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %" PetscInt_FMT " Mz %" PetscInt_FMT, mz, Mz); 1245b1757049SJed Brown } 1246b1757049SJed Brown 12479566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, &j_start, &k_start, &m_f, &n_f, &p_f)); 12489566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, &j_start_ghost, &k_start_ghost, &m_ghost, &n_ghost, &p_ghost)); 12499566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <og_f)); 12509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_f, &idx_f)); 1251b1757049SJed Brown 12529566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, &j_start_c, &k_start_c, &m_c, &n_c, &p_c)); 12539566063dSJacob 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)); 12549566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <og_c)); 12559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(ltog_c, &idx_c)); 1256b1757049SJed Brown 1257b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1258b1757049SJed Brown nc = 0; 12599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_f * m_f * p_f, &cols)); 1260b1757049SJed Brown for (k = k_start_c; k < k_start_c + p_c; k++) { 1261b1757049SJed Brown for (j = j_start_c; j < j_start_c + n_c; j++) { 1262b1757049SJed Brown for (i = i_start_c; i < i_start_c + m_c; i++) { 1263b1757049SJed Brown PetscInt i_f = i * ratioi, j_f = j * ratioj, k_f = k * ratiok; 12649371c9d4SSatish Balay PetscCheck(k_f >= k_start_ghost && k_f < k_start_ghost + p_ghost, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, 12659371c9d4SSatish Balay "Processor's coarse DMDA must lie over fine DMDA " 12669371c9d4SSatish Balay "k_c %" PetscInt_FMT " k_f %" PetscInt_FMT " fine ghost range [%" PetscInt_FMT ",%" PetscInt_FMT "]", 12679371c9d4SSatish Balay k, k_f, k_start_ghost, k_start_ghost + p_ghost); 12689371c9d4SSatish Balay PetscCheck(j_f >= j_start_ghost && j_f < j_start_ghost + n_ghost, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, 12699371c9d4SSatish Balay "Processor's coarse DMDA must lie over fine DMDA " 12709371c9d4SSatish Balay "j_c %" PetscInt_FMT " j_f %" PetscInt_FMT " fine ghost range [%" PetscInt_FMT ",%" PetscInt_FMT "]", 12719371c9d4SSatish Balay j, j_f, j_start_ghost, j_start_ghost + n_ghost); 12729371c9d4SSatish Balay PetscCheck(i_f >= i_start_ghost && i_f < i_start_ghost + m_ghost, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, 12739371c9d4SSatish Balay "Processor's coarse DMDA must lie over fine DMDA " 12749371c9d4SSatish Balay "i_c %" PetscInt_FMT " i_f %" PetscInt_FMT " fine ghost range [%" PetscInt_FMT ",%" PetscInt_FMT "]", 12759371c9d4SSatish Balay i, i_f, i_start_ghost, i_start_ghost + m_ghost); 1276e3fbd1f4SBarry 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))]; 1277e3fbd1f4SBarry Smith cols[nc++] = row; 1278b1757049SJed Brown } 1279b1757049SJed Brown } 1280b1757049SJed Brown } 12819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_f, &idx_f)); 12829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(ltog_c, &idx_c)); 1283b1757049SJed Brown 12849566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)daf), dof, nc, cols, PETSC_OWN_POINTER, &isf)); 12859566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dac, &vecc)); 12869566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(daf, &vecf)); 12879566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vecf, isf, vecc, NULL, inject)); 12889566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dac, &vecc)); 12899566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(daf, &vecf)); 12909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isf)); 12913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1292b1757049SJed Brown } 1293b1757049SJed Brown 1294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_DA(DM dac, DM daf, Mat *mat) 1295d71ae5a4SJacob Faibussowitsch { 129647c6ae99SBarry Smith PetscInt dimc, Mc, Nc, Pc, mc, nc, pc, dofc, sc, dimf, Mf, Nf, Pf, mf, nf, pf, doff, sf; 1297bff4a2f0SMatthew G. Knepley DMBoundaryType bxc, byc, bzc, bxf, byf, bzf; 1298aa219208SBarry Smith DMDAStencilType stc, stf; 129960c16ac1SBarry Smith VecScatter inject = NULL; 130047c6ae99SBarry Smith 130147c6ae99SBarry Smith PetscFunctionBegin; 130247c6ae99SBarry Smith PetscValidHeaderSpecific(dac, DM_CLASSID, 1); 130347c6ae99SBarry Smith PetscValidHeaderSpecific(daf, DM_CLASSID, 2); 13044f572ea9SToby Isaac PetscAssertPointer(mat, 3); 130547c6ae99SBarry Smith 13069566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, &dimc, &Mc, &Nc, &Pc, &mc, &nc, &pc, &dofc, &sc, &bxc, &byc, &bzc, &stc)); 13079566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, &dimf, &Mf, &Nf, &Pf, &mf, &nf, &pf, &doff, &sf, &bxf, &byf, &bzf, &stf)); 130863a3b9bcSJacob Faibussowitsch PetscCheck(dimc == dimf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Dimensions of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, dimc, dimf); 130963a3b9bcSJacob Faibussowitsch PetscCheck(dofc == doff, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "DOF of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, dofc, doff); 131063a3b9bcSJacob Faibussowitsch PetscCheck(sc == sf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Stencil width of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, sc, sf); 13111dca8a05SBarry Smith PetscCheck(bxc == bxf && byc == byf && bzc == bzf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Boundary type different in two DMDAs"); 131208401ef6SPierre Jolivet PetscCheck(stc == stf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Stencil type different in two DMDAs"); 131308401ef6SPierre Jolivet PetscCheck(Mc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coarse grid requires at least 2 points in x direction"); 13141dca8a05SBarry Smith PetscCheck(dimc <= 1 || Nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coarse grid requires at least 2 points in y direction"); 13151dca8a05SBarry Smith PetscCheck(dimc <= 2 || Pc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coarse grid requires at least 2 points in z direction"); 131647c6ae99SBarry Smith 13170bb2b966SJungho Lee if (dimc == 1) { 13189566063dSJacob Faibussowitsch PetscCall(DMCreateInjection_DA_1D(dac, daf, &inject)); 13190bb2b966SJungho Lee } else if (dimc == 2) { 13209566063dSJacob Faibussowitsch PetscCall(DMCreateInjection_DA_2D(dac, daf, &inject)); 1321b1757049SJed Brown } else if (dimc == 3) { 13229566063dSJacob Faibussowitsch PetscCall(DMCreateInjection_DA_3D(dac, daf, &inject)); 132347c6ae99SBarry Smith } 13249566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)inject), inject, mat)); 13259566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&inject)); 13263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 132747c6ae99SBarry Smith } 132847c6ae99SBarry Smith 1329a4e35b19SJacob Faibussowitsch // PetscClangLinter pragma ignore: -fdoc-* 133097779f9aSLisandro Dalcin /*@ 133197779f9aSLisandro Dalcin DMCreateAggregates - Deprecated, see DMDACreateAggregates. 13326c877ef6SSatish Balay 13336c877ef6SSatish Balay Level: intermediate 133497779f9aSLisandro Dalcin @*/ 1335d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateAggregates(DM dac, DM daf, Mat *mat) 1336d71ae5a4SJacob Faibussowitsch { 1337a5bc1bf3SBarry Smith return DMDACreateAggregates(dac, daf, mat); 133897779f9aSLisandro Dalcin } 133997779f9aSLisandro Dalcin 134097779f9aSLisandro Dalcin /*@ 134197779f9aSLisandro Dalcin DMDACreateAggregates - Gets the aggregates that map between 1342dce8aebaSBarry Smith grids associated with two `DMDA` 134397779f9aSLisandro Dalcin 134420f4b53cSBarry Smith Collective 134597779f9aSLisandro Dalcin 134697779f9aSLisandro Dalcin Input Parameters: 134760225df5SJacob Faibussowitsch + dac - the coarse grid `DMDA` 134860225df5SJacob Faibussowitsch - daf - the fine grid `DMDA` 134997779f9aSLisandro Dalcin 13502fe279fdSBarry Smith Output Parameter: 135197779f9aSLisandro Dalcin . rest - the restriction matrix (transpose of the projection matrix) 135297779f9aSLisandro Dalcin 135397779f9aSLisandro Dalcin Level: intermediate 135497779f9aSLisandro Dalcin 1355dce8aebaSBarry Smith Note: 1356dce8aebaSBarry Smith This routine is not used by PETSc. 135797779f9aSLisandro Dalcin It is not clear what its use case is and it may be removed in a future release. 135897779f9aSLisandro Dalcin Users should contact petsc-maint@mcs.anl.gov if they plan to use it. 135997779f9aSLisandro Dalcin 1360*12b4a537SBarry Smith .seealso: [](sec_struct), `DMRefine()`, `DMCreateInjection()`, `DMCreateInterpolation()` 136197779f9aSLisandro Dalcin @*/ 1362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDACreateAggregates(DM dac, DM daf, Mat *rest) 1363d71ae5a4SJacob Faibussowitsch { 136447c6ae99SBarry Smith PetscInt dimc, Mc, Nc, Pc, mc, nc, pc, dofc, sc; 136547c6ae99SBarry Smith PetscInt dimf, Mf, Nf, Pf, mf, nf, pf, doff, sf; 1366bff4a2f0SMatthew G. Knepley DMBoundaryType bxc, byc, bzc, bxf, byf, bzf; 1367aa219208SBarry Smith DMDAStencilType stc, stf; 136847c6ae99SBarry Smith PetscInt i, j, l; 136947c6ae99SBarry Smith PetscInt i_start, j_start, l_start, m_f, n_f, p_f; 137047c6ae99SBarry Smith PetscInt i_start_ghost, j_start_ghost, l_start_ghost, m_ghost, n_ghost, p_ghost; 13718ea3bf28SBarry Smith const PetscInt *idx_f; 137247c6ae99SBarry Smith PetscInt i_c, j_c, l_c; 137347c6ae99SBarry Smith PetscInt i_start_c, j_start_c, l_start_c, m_c, n_c, p_c; 137447c6ae99SBarry Smith PetscInt i_start_ghost_c, j_start_ghost_c, l_start_ghost_c, m_ghost_c, n_ghost_c, p_ghost_c; 13758ea3bf28SBarry Smith const PetscInt *idx_c; 137647c6ae99SBarry Smith PetscInt d; 137747c6ae99SBarry Smith PetscInt a; 137847c6ae99SBarry Smith PetscInt max_agg_size; 137947c6ae99SBarry Smith PetscInt *fine_nodes; 138047c6ae99SBarry Smith PetscScalar *one_vec; 138147c6ae99SBarry Smith PetscInt fn_idx; 1382565245c5SBarry Smith ISLocalToGlobalMapping ltogmf, ltogmc; 138347c6ae99SBarry Smith 138447c6ae99SBarry Smith PetscFunctionBegin; 138597779f9aSLisandro Dalcin PetscValidHeaderSpecificType(dac, DM_CLASSID, 1, DMDA); 138697779f9aSLisandro Dalcin PetscValidHeaderSpecificType(daf, DM_CLASSID, 2, DMDA); 13874f572ea9SToby Isaac PetscAssertPointer(rest, 3); 138847c6ae99SBarry Smith 13899566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dac, &dimc, &Mc, &Nc, &Pc, &mc, &nc, &pc, &dofc, &sc, &bxc, &byc, &bzc, &stc)); 13909566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(daf, &dimf, &Mf, &Nf, &Pf, &mf, &nf, &pf, &doff, &sf, &bxf, &byf, &bzf, &stf)); 139163a3b9bcSJacob Faibussowitsch PetscCheck(dimc == dimf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Dimensions of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, dimc, dimf); 139263a3b9bcSJacob Faibussowitsch PetscCheck(dofc == doff, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "DOF of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, dofc, doff); 139363a3b9bcSJacob Faibussowitsch PetscCheck(sc == sf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Stencil width of DMDA do not match %" PetscInt_FMT " %" PetscInt_FMT, sc, sf); 13941dca8a05SBarry Smith PetscCheck(bxc == bxf && byc == byf && bzc == bzf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Boundary type different in two DMDAs"); 139508401ef6SPierre Jolivet PetscCheck(stc == stf, PetscObjectComm((PetscObject)daf), PETSC_ERR_ARG_INCOMP, "Stencil type different in two DMDAs"); 139647c6ae99SBarry Smith 139763a3b9bcSJacob Faibussowitsch PetscCheck(Mf >= Mc, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Coarse grid has more points than fine grid, Mc %" PetscInt_FMT ", Mf %" PetscInt_FMT, Mc, Mf); 139863a3b9bcSJacob Faibussowitsch PetscCheck(Nf >= Nc, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Coarse grid has more points than fine grid, Nc %" PetscInt_FMT ", Nf %" PetscInt_FMT, Nc, Nf); 139963a3b9bcSJacob Faibussowitsch PetscCheck(Pf >= Pc, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Coarse grid has more points than fine grid, Pc %" PetscInt_FMT ", Pf %" PetscInt_FMT, Pc, Pf); 140047c6ae99SBarry Smith 140147c6ae99SBarry Smith if (Pc < 0) Pc = 1; 140247c6ae99SBarry Smith if (Pf < 0) Pf = 1; 140347c6ae99SBarry Smith if (Nc < 0) Nc = 1; 140447c6ae99SBarry Smith if (Nf < 0) Nf = 1; 140547c6ae99SBarry Smith 14069566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(daf, &i_start, &j_start, &l_start, &m_f, &n_f, &p_f)); 14079566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(daf, &i_start_ghost, &j_start_ghost, &l_start_ghost, &m_ghost, &n_ghost, &p_ghost)); 1408565245c5SBarry Smith 14099566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(daf, <ogmf)); 14109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(ltogmf, &idx_f)); 141147c6ae99SBarry Smith 14129566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(dac, &i_start_c, &j_start_c, &l_start_c, &m_c, &n_c, &p_c)); 14139566063dSJacob 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)); 1414565245c5SBarry Smith 14159566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dac, <ogmc)); 14169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(ltogmc, &idx_c)); 141747c6ae99SBarry Smith 141847c6ae99SBarry Smith /* 141947c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 142047c6ae99SBarry Smith for dimension 1 and 2 respectively. 142147c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 1422da81f932SPierre Jolivet and r_y*j and r_y*(j+1) will be grouped into the same coarse grid aggregate. 142347c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 142447c6ae99SBarry Smith */ 142547c6ae99SBarry Smith 142647c6ae99SBarry Smith max_agg_size = (Mf / Mc + 1) * (Nf / Nc + 1) * (Pf / Pc + 1); 142747c6ae99SBarry Smith 142847c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 14299371c9d4SSatish Balay PetscCall(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, max_agg_size, NULL, max_agg_size, NULL, rest)); 143047c6ae99SBarry Smith 143147c6ae99SBarry Smith /* store nodes in the fine grid here */ 14329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(max_agg_size, &one_vec, max_agg_size, &fine_nodes)); 143347c6ae99SBarry Smith for (i = 0; i < max_agg_size; i++) one_vec[i] = 1.0; 143447c6ae99SBarry Smith 143547c6ae99SBarry Smith /* loop over all coarse nodes */ 143647c6ae99SBarry Smith for (l_c = l_start_c; l_c < l_start_c + p_c; l_c++) { 143747c6ae99SBarry Smith for (j_c = j_start_c; j_c < j_start_c + n_c; j_c++) { 143847c6ae99SBarry Smith for (i_c = i_start_c; i_c < i_start_c + m_c; i_c++) { 143947c6ae99SBarry Smith for (d = 0; d < dofc; d++) { 144047c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 144147c6ae99SBarry 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; 144247c6ae99SBarry Smith 144347c6ae99SBarry Smith fn_idx = 0; 144447c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 144547c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 144647c6ae99SBarry Smith (same for other dimensions) 144747c6ae99SBarry Smith */ 144847c6ae99SBarry Smith for (l = l_c * Pf / Pc; l < PetscMin((l_c + 1) * Pf / Pc, Pf); l++) { 144947c6ae99SBarry Smith for (j = j_c * Nf / Nc; j < PetscMin((j_c + 1) * Nf / Nc, Nf); j++) { 145047c6ae99SBarry Smith for (i = i_c * Mf / Mc; i < PetscMin((i_c + 1) * Mf / Mc, Mf); i++) { 145147c6ae99SBarry 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; 145247c6ae99SBarry Smith fn_idx++; 145347c6ae99SBarry Smith } 145447c6ae99SBarry Smith } 145547c6ae99SBarry Smith } 145647c6ae99SBarry Smith /* add all these points to one aggregate */ 14579566063dSJacob Faibussowitsch PetscCall(MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES)); 145847c6ae99SBarry Smith } 145947c6ae99SBarry Smith } 146047c6ae99SBarry Smith } 146147c6ae99SBarry Smith } 14629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogmf, &idx_f)); 14639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogmc, &idx_c)); 14649566063dSJacob Faibussowitsch PetscCall(PetscFree2(one_vec, fine_nodes)); 14659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY)); 14669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY)); 14673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 146847c6ae99SBarry Smith } 1469