147c6ae99SBarry Smith 247c6ae99SBarry Smith /* 3aa219208SBarry Smith Code for interpolating between grids represented by DMDAs 447c6ae99SBarry Smith */ 547c6ae99SBarry Smith 6d52bd9f3SBarry Smith /* 7d52bd9f3SBarry Smith For linear elements there are two branches of code to compute the interpolation. They should compute the same results but may not. The "new version" does 8d52bd9f3SBarry Smith not work for periodic domains, the old does. Change NEWVERSION to 1 to compile in the new version. Eventually when we are sure the two produce identical results 92adb9dcfSBarry Smith we will remove/merge the new version. Based on current tests, these both produce the same results. We are leaving NEWVERSION for now in the code since some 102adb9dcfSBarry Smith consider it cleaner, but old version is turned on since it handles periodic case. 11d52bd9f3SBarry Smith */ 129314d695SBarry Smith #define NEWVERSION 0 1385afcc9aSBarry Smith 14af0996ceSBarry Smith #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/ 1547c6ae99SBarry Smith 1647c6ae99SBarry Smith /*@ 17e727c939SJed Brown DMCreateInterpolationScale - Forms L = R*1/diag(R*1) - L.*v is like a coarse grid average of the 1847c6ae99SBarry Smith nearby fine grid points. 1947c6ae99SBarry Smith 2047c6ae99SBarry Smith Input Parameters: 2147c6ae99SBarry Smith + dac - DM that defines a coarse mesh 2247c6ae99SBarry Smith . daf - DM that defines a fine mesh 2347c6ae99SBarry Smith - mat - the restriction (or interpolation operator) from fine to coarse 2447c6ae99SBarry Smith 2547c6ae99SBarry Smith Output Parameter: 2647c6ae99SBarry Smith . scale - the scaled vector 2747c6ae99SBarry Smith 2847c6ae99SBarry Smith Level: developer 2947c6ae99SBarry Smith 30e727c939SJed Brown .seealso: DMCreateInterpolation() 3147c6ae99SBarry Smith 3247c6ae99SBarry Smith @*/ 33e727c939SJed Brown PetscErrorCode DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale) 3447c6ae99SBarry Smith { 3547c6ae99SBarry Smith PetscErrorCode ierr; 3647c6ae99SBarry Smith Vec fine; 3747c6ae99SBarry Smith PetscScalar one = 1.0; 3847c6ae99SBarry Smith 3947c6ae99SBarry Smith PetscFunctionBegin; 4047c6ae99SBarry Smith ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr); 4147c6ae99SBarry Smith ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr); 4247c6ae99SBarry Smith ierr = VecSet(fine,one);CHKERRQ(ierr); 4347c6ae99SBarry Smith ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr); 44fcfd50ebSBarry Smith ierr = VecDestroy(&fine);CHKERRQ(ierr); 4547c6ae99SBarry Smith ierr = VecReciprocal(*scale);CHKERRQ(ierr); 4647c6ae99SBarry Smith PetscFunctionReturn(0); 4747c6ae99SBarry Smith } 4847c6ae99SBarry Smith 49*fdc842d1SBarry Smith /* 50*fdc842d1SBarry Smith Since the interpolation uses MATMAIJ for dof > 0 we convert request for non-MATAIJ baseded matrices to MATAIJ. 51*fdc842d1SBarry Smith This is a bit of a hack, the reason for it is partially because -dm_mat_type defines the 52*fdc842d1SBarry Smith matrix type for both the operator matrices and the interpolation matrices so that users 53*fdc842d1SBarry Smith can select matrix types of base MATAIJ for accelerators 54*fdc842d1SBarry Smith */ 55*fdc842d1SBarry Smith static PetscErrorCode ConvertToAIJ(MatType intype,MatType *outtype) 56*fdc842d1SBarry Smith { 57*fdc842d1SBarry Smith PetscErrorCode ierr; 58*fdc842d1SBarry Smith PetscInt i; 59*fdc842d1SBarry Smith char const *types[3] = {MATAIJ,MATSEQAIJ,MATMPIAIJ}; 60*fdc842d1SBarry Smith PetscBool flg; 61*fdc842d1SBarry Smith 62*fdc842d1SBarry Smith PetscFunctionBegin; 63*fdc842d1SBarry Smith for (i=0; i<3; i++) { 64*fdc842d1SBarry Smith ierr = PetscStrbeginswith(intype,types[i],&flg);CHKERRQ(ierr); 65*fdc842d1SBarry Smith if (flg) { 66*fdc842d1SBarry Smith *outtype = intype; 67*fdc842d1SBarry Smith PetscFunctionReturn(0); 68*fdc842d1SBarry Smith } 69*fdc842d1SBarry Smith } 70*fdc842d1SBarry Smith *outtype = MATAIJ; 71*fdc842d1SBarry Smith PetscFunctionReturn(0); 72*fdc842d1SBarry Smith } 73*fdc842d1SBarry Smith 74e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A) 7547c6ae99SBarry Smith { 7647c6ae99SBarry Smith PetscErrorCode ierr; 778ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 788ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 798ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 8047c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 8147c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 8285afcc9aSBarry Smith PetscScalar v[2],x; 8347c6ae99SBarry Smith Mat mat; 84bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 85e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 86*fdc842d1SBarry Smith MatType mattype; 8747c6ae99SBarry Smith 8847c6ae99SBarry Smith PetscFunctionBegin; 891321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 901321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 91bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 9247c6ae99SBarry Smith ratio = mx/Mx; 9347c6ae99SBarry Smith if (ratio*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 9447c6ae99SBarry Smith } else { 9547c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 9647c6ae99SBarry Smith if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 9747c6ae99SBarry Smith } 9847c6ae99SBarry Smith 99aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 100aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 10145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 10245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 10347c6ae99SBarry Smith 104aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 105aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 10645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 10745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 10847c6ae99SBarry Smith 10947c6ae99SBarry Smith /* create interpolation matrix */ 110ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 111*fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 112*fdc842d1SBarry Smith /* 113*fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 114*fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 115*fdc842d1SBarry Smith */ 116*fdc842d1SBarry Smith if (dof > 1) { 117*fdc842d1SBarry Smith ierr = MatPinToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 118*fdc842d1SBarry Smith } 119*fdc842d1SBarry Smith #endif 12047c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 121*fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 122*fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 1230298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr); 1240298fd71SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,NULL,1,NULL);CHKERRQ(ierr); 12547c6ae99SBarry Smith 12647c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 12785afcc9aSBarry Smith if (!NEWVERSION) { 128b3bd94feSDave May 12947c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 13047c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 131e3fbd1f4SBarry Smith row = idx_f[i-i_start_ghost]; 13247c6ae99SBarry Smith 13347c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 134aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 13547c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 13647c6ae99SBarry Smith 13747c6ae99SBarry Smith /* 13847c6ae99SBarry Smith Only include those interpolation points that are truly 13947c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 14047c6ae99SBarry Smith in x direction; since they have no right neighbor 14147c6ae99SBarry Smith */ 1426712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 14347c6ae99SBarry Smith nc = 0; 14447c6ae99SBarry Smith /* one left and below; or we are right on it */ 145e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 146e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 14747c6ae99SBarry Smith v[nc++] = -x + 1.0; 14847c6ae99SBarry Smith /* one right? */ 14947c6ae99SBarry Smith if (i_c*ratio != i) { 150e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 15147c6ae99SBarry Smith v[nc++] = x; 15247c6ae99SBarry Smith } 15347c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 15447c6ae99SBarry Smith } 155b3bd94feSDave May 156b3bd94feSDave May } else { 157b3bd94feSDave May PetscScalar *xi; 158b3bd94feSDave May PetscInt li,nxi,n; 159b3bd94feSDave May PetscScalar Ni[2]; 160b3bd94feSDave May 161b3bd94feSDave May /* compute local coordinate arrays */ 162b3bd94feSDave May nxi = ratio + 1; 163854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 164b3bd94feSDave May for (li=0; li<nxi; li++) { 16552218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 166b3bd94feSDave May } 167b3bd94feSDave May 168b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 169b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 170e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 171b3bd94feSDave May 172b3bd94feSDave May i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 173b3bd94feSDave May if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 174b3bd94feSDave May i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 175b3bd94feSDave May 176b3bd94feSDave May /* remainders */ 177b3bd94feSDave May li = i - ratio * (i/ratio); 1788865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 179b3bd94feSDave May 180b3bd94feSDave May /* corners */ 181e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 182e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 183b3bd94feSDave May Ni[0] = 1.0; 184b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 185b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 186b3bd94feSDave May continue; 187b3bd94feSDave May } 188b3bd94feSDave May 189b3bd94feSDave May /* edges + interior */ 190b3bd94feSDave May /* remainders */ 1918865f1eaSKarl Rupp if (i==mx-1) i_c--; 192b3bd94feSDave May 193e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 194e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 195e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; 196b3bd94feSDave May 197b3bd94feSDave May Ni[0] = 0.5*(1.0-xi[li]); 198b3bd94feSDave May Ni[1] = 0.5*(1.0+xi[li]); 199b3bd94feSDave May for (n=0; n<2; n++) { 2008865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 201b3bd94feSDave May } 202b3bd94feSDave May ierr = MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 203b3bd94feSDave May } 204b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 205b3bd94feSDave May } 20645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 20745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 20847c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 20947c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 21047c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 211fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 21247c6ae99SBarry Smith PetscFunctionReturn(0); 21347c6ae99SBarry Smith } 21447c6ae99SBarry Smith 215e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A) 21647c6ae99SBarry Smith { 21747c6ae99SBarry Smith PetscErrorCode ierr; 2188ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 2198ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 220e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 2218ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 22247c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 22347c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 22447c6ae99SBarry Smith PetscScalar v[2],x; 22547c6ae99SBarry Smith Mat mat; 226bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 227*fdc842d1SBarry Smith MatType mattype; 22847c6ae99SBarry Smith 22947c6ae99SBarry Smith PetscFunctionBegin; 2301321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 2311321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 232bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 2333a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 23447c6ae99SBarry Smith ratio = mx/Mx; 23547c6ae99SBarry Smith if (ratio*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 23647c6ae99SBarry Smith } else { 2373a586487SStefano Zampini if (Mx < 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 23847c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 23947c6ae99SBarry Smith if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 24047c6ae99SBarry Smith } 24147c6ae99SBarry Smith 242aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 243aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 24445b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 24545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 24647c6ae99SBarry Smith 247aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 248aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 24945b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 25045b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 25147c6ae99SBarry Smith 25247c6ae99SBarry Smith /* create interpolation matrix */ 253ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 254*fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 255*fdc842d1SBarry Smith /* 256*fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 257*fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 258*fdc842d1SBarry Smith */ 259*fdc842d1SBarry Smith if (dof > 1) { 260*fdc842d1SBarry Smith ierr = MatPinToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 261*fdc842d1SBarry Smith } 262*fdc842d1SBarry Smith #endif 26347c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 264*fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 265*fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 2660298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr); 2670298fd71SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,NULL,0,NULL);CHKERRQ(ierr); 26847c6ae99SBarry Smith 26947c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 27047c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 27147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 272e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 27347c6ae99SBarry Smith 27447c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 27547c6ae99SBarry Smith 27647c6ae99SBarry Smith /* 27747c6ae99SBarry Smith Only include those interpolation points that are truly 27847c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 27947c6ae99SBarry Smith in x direction; since they have no right neighbor 28047c6ae99SBarry Smith */ 2816712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 28247c6ae99SBarry Smith nc = 0; 28347c6ae99SBarry Smith /* one left and below; or we are right on it */ 284e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 285e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 28647c6ae99SBarry Smith v[nc++] = -x + 1.0; 28747c6ae99SBarry Smith /* one right? */ 28847c6ae99SBarry Smith if (i_c*ratio != i) { 289e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 29047c6ae99SBarry Smith v[nc++] = x; 29147c6ae99SBarry Smith } 29247c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 29347c6ae99SBarry Smith } 29445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 29545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 29647c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 29747c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 29847c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 299fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 30047c6ae99SBarry Smith ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr); 30147c6ae99SBarry Smith PetscFunctionReturn(0); 30247c6ae99SBarry Smith } 30347c6ae99SBarry Smith 304e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A) 30547c6ae99SBarry Smith { 30647c6ae99SBarry Smith PetscErrorCode ierr; 3078ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 3088ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 309e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 3108ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 31147c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 31247c6ae99SBarry 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; 31347c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 31447c6ae99SBarry Smith PetscScalar v[4],x,y; 31547c6ae99SBarry Smith Mat mat; 316bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 317*fdc842d1SBarry Smith MatType mattype; 31847c6ae99SBarry Smith 31947c6ae99SBarry Smith PetscFunctionBegin; 3201321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 3211321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 322bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 3233a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 32447c6ae99SBarry Smith ratioi = mx/Mx; 32547c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 32647c6ae99SBarry Smith } else { 3273a586487SStefano Zampini if (Mx < 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 32847c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 32947c6ae99SBarry Smith if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 33047c6ae99SBarry Smith } 331bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 3323a586487SStefano Zampini if (!My) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 33347c6ae99SBarry Smith ratioj = my/My; 33447c6ae99SBarry Smith if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 33547c6ae99SBarry Smith } else { 3363a586487SStefano Zampini if (My < 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be greater than 1",My); 33747c6ae99SBarry Smith ratioj = (my-1)/(My-1); 33847c6ae99SBarry Smith if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 33947c6ae99SBarry Smith } 34047c6ae99SBarry Smith 341aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 342aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 34345b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 34445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 34547c6ae99SBarry Smith 346aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 347aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 34845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 34945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 35047c6ae99SBarry Smith 35147c6ae99SBarry Smith /* 352aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 35347c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 35447c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 35547c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 35647c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 35747c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 35847c6ae99SBarry Smith 35947c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 36047c6ae99SBarry Smith */ 361ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 362ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 363ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr); 36447c6ae99SBarry Smith col_scale = size_f/size_c; 36547c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 36647c6ae99SBarry Smith 367ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 36847c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 36947c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 37047c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 371e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 37247c6ae99SBarry Smith 37347c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 37447c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 37547c6ae99SBarry Smith 376aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 37747c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 378aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 37947c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 38047c6ae99SBarry Smith 38147c6ae99SBarry Smith /* 38247c6ae99SBarry Smith Only include those interpolation points that are truly 38347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 38447c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 38547c6ae99SBarry Smith */ 38647c6ae99SBarry Smith nc = 0; 38747c6ae99SBarry Smith /* one left and below; or we are right on it */ 388e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 389e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 39047c6ae99SBarry Smith /* one right and below */ 391e3fbd1f4SBarry Smith if (i_c*ratioi != i) cols[nc++] = col_shift + idx_c[col+1]; 39247c6ae99SBarry Smith /* one left and above */ 393e3fbd1f4SBarry Smith if (j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+m_ghost_c]; 39447c6ae99SBarry Smith /* one right and above */ 395e3fbd1f4SBarry Smith if (i_c*ratioi != i && j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)]; 39647c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 39747c6ae99SBarry Smith } 39847c6ae99SBarry Smith } 399ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 400*fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 401*fdc842d1SBarry Smith /* 402*fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 403*fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 404*fdc842d1SBarry Smith */ 405*fdc842d1SBarry Smith if (dof > 1) { 406*fdc842d1SBarry Smith ierr = MatPinToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 407*fdc842d1SBarry Smith } 408*fdc842d1SBarry Smith #endif 40947c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 410*fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 411*fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 41247c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 41347c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 41447c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 41547c6ae99SBarry Smith 41647c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 41785afcc9aSBarry Smith if (!NEWVERSION) { 418b3bd94feSDave May 41947c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 42047c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 42147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 422e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 42347c6ae99SBarry Smith 42447c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 42547c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 42647c6ae99SBarry Smith 42747c6ae99SBarry Smith /* 42847c6ae99SBarry Smith Only include those interpolation points that are truly 42947c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 43047c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 43147c6ae99SBarry Smith */ 4326712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 4336712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 434b3bd94feSDave May 43547c6ae99SBarry Smith nc = 0; 43647c6ae99SBarry Smith /* one left and below; or we are right on it */ 437e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 438e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 43947c6ae99SBarry Smith v[nc++] = x*y - x - y + 1.0; 44047c6ae99SBarry Smith /* one right and below */ 44147c6ae99SBarry Smith if (i_c*ratioi != i) { 442e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+1]; 44347c6ae99SBarry Smith v[nc++] = -x*y + x; 44447c6ae99SBarry Smith } 44547c6ae99SBarry Smith /* one left and above */ 44647c6ae99SBarry Smith if (j_c*ratioj != j) { 447e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+m_ghost_c]; 44847c6ae99SBarry Smith v[nc++] = -x*y + y; 44947c6ae99SBarry Smith } 45047c6ae99SBarry Smith /* one right and above */ 45147c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 452e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)]; 45347c6ae99SBarry Smith v[nc++] = x*y; 45447c6ae99SBarry Smith } 45547c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 45647c6ae99SBarry Smith } 45747c6ae99SBarry Smith } 458b3bd94feSDave May 459b3bd94feSDave May } else { 460b3bd94feSDave May PetscScalar Ni[4]; 461b3bd94feSDave May PetscScalar *xi,*eta; 462b3bd94feSDave May PetscInt li,nxi,lj,neta; 463b3bd94feSDave May 464b3bd94feSDave May /* compute local coordinate arrays */ 465b3bd94feSDave May nxi = ratioi + 1; 466b3bd94feSDave May neta = ratioj + 1; 467854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 468854ce69bSBarry Smith ierr = PetscMalloc1(neta,&eta);CHKERRQ(ierr); 469b3bd94feSDave May for (li=0; li<nxi; li++) { 47052218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 471b3bd94feSDave May } 472b3bd94feSDave May for (lj=0; lj<neta; lj++) { 47352218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 474b3bd94feSDave May } 475b3bd94feSDave May 476b3bd94feSDave May /* loop over local fine grid nodes setting interpolation for those*/ 477b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 478b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 479b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 480e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 481b3bd94feSDave May 482b3bd94feSDave May i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 483b3bd94feSDave May j_c = (j/ratioj); /* coarse grid node below fine grid node */ 484b3bd94feSDave May 485b3bd94feSDave May /* remainders */ 486b3bd94feSDave May li = i - ratioi * (i/ratioi); 4878865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 488b3bd94feSDave May lj = j - ratioj * (j/ratioj); 4898865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 490b3bd94feSDave May 491b3bd94feSDave May /* corners */ 492e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 493e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 494b3bd94feSDave May Ni[0] = 1.0; 495b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 496b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 497b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 498b3bd94feSDave May continue; 499b3bd94feSDave May } 500b3bd94feSDave May } 501b3bd94feSDave May 502b3bd94feSDave May /* edges + interior */ 503b3bd94feSDave May /* remainders */ 5048865f1eaSKarl Rupp if (i==mx-1) i_c--; 5058865f1eaSKarl Rupp if (j==my-1) j_c--; 506b3bd94feSDave May 507e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 508e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 509e3fbd1f4SBarry Smith cols[1] = col_shift + idx_c[col+1]; /* right, below */ 510e3fbd1f4SBarry Smith cols[2] = col_shift + idx_c[col+m_ghost_c]; /* left, above */ 511e3fbd1f4SBarry Smith cols[3] = col_shift + idx_c[col+(m_ghost_c+1)]; /* right, above */ 512b3bd94feSDave May 513b3bd94feSDave May Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]); 514b3bd94feSDave May Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]); 515b3bd94feSDave May Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]); 516b3bd94feSDave May Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]); 517b3bd94feSDave May 518b3bd94feSDave May nc = 0; 5198865f1eaSKarl Rupp if (PetscAbsScalar(Ni[0])<1.0e-32) cols[0]=-1; 5208865f1eaSKarl Rupp if (PetscAbsScalar(Ni[1])<1.0e-32) cols[1]=-1; 5218865f1eaSKarl Rupp if (PetscAbsScalar(Ni[2])<1.0e-32) cols[2]=-1; 5228865f1eaSKarl Rupp if (PetscAbsScalar(Ni[3])<1.0e-32) cols[3]=-1; 523b3bd94feSDave May 524b3bd94feSDave May ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 525b3bd94feSDave May } 526b3bd94feSDave May } 527b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 528b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 529b3bd94feSDave May } 53045b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 53145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 53247c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 53347c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 53447c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 535fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 53647c6ae99SBarry Smith PetscFunctionReturn(0); 53747c6ae99SBarry Smith } 53847c6ae99SBarry Smith 53947c6ae99SBarry Smith /* 54047c6ae99SBarry Smith Contributed by Andrei Draganescu <aidraga@sandia.gov> 54147c6ae99SBarry Smith */ 542e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A) 54347c6ae99SBarry Smith { 54447c6ae99SBarry Smith PetscErrorCode ierr; 5458ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 5468ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 547e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 5488ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 54947c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 55047c6ae99SBarry 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; 55147c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 55247c6ae99SBarry Smith PetscScalar v[4]; 55347c6ae99SBarry Smith Mat mat; 554bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 555*fdc842d1SBarry Smith MatType mattype; 55647c6ae99SBarry Smith 55747c6ae99SBarry Smith PetscFunctionBegin; 5581321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 5591321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 5603a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 5613a586487SStefano Zampini if (!My) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 56247c6ae99SBarry Smith ratioi = mx/Mx; 56347c6ae99SBarry Smith ratioj = my/My; 564ce94432eSBarry Smith if (ratioi*Mx != mx) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 565ce94432eSBarry Smith if (ratioj*My != my) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 566ce94432eSBarry Smith if (ratioi != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2"); 567ce94432eSBarry Smith if (ratioj != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2"); 56847c6ae99SBarry Smith 569aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 570aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 57145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 57245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 57347c6ae99SBarry Smith 574aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 575aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 57645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 57745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 57847c6ae99SBarry Smith 57947c6ae99SBarry Smith /* 580aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 58147c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 58247c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 58347c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 58447c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 58547c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 58647c6ae99SBarry Smith 58747c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 58847c6ae99SBarry Smith */ 589ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 590ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 591ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr); 59247c6ae99SBarry Smith col_scale = size_f/size_c; 59347c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 59447c6ae99SBarry Smith 595ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 59647c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 59747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 59847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 599e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 60047c6ae99SBarry Smith 60147c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 60247c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 60347c6ae99SBarry Smith 604aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 60547c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 606aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 60747c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 60847c6ae99SBarry Smith 60947c6ae99SBarry Smith /* 61047c6ae99SBarry Smith Only include those interpolation points that are truly 61147c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 61247c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 61347c6ae99SBarry Smith */ 61447c6ae99SBarry Smith nc = 0; 61547c6ae99SBarry Smith /* one left and below; or we are right on it */ 616e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 617e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 61847c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 61947c6ae99SBarry Smith } 62047c6ae99SBarry Smith } 621ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 622*fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 623*fdc842d1SBarry Smith /* 624*fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 625*fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 626*fdc842d1SBarry Smith */ 627*fdc842d1SBarry Smith if (dof > 1) { 628*fdc842d1SBarry Smith ierr = MatPinToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 629*fdc842d1SBarry Smith } 630*fdc842d1SBarry Smith #endif 63147c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 632*fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 633*fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 63447c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 63547c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 63647c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 63747c6ae99SBarry Smith 63847c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 63947c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 64047c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 64147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 642e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 64347c6ae99SBarry Smith 64447c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 64547c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 64647c6ae99SBarry Smith nc = 0; 64747c6ae99SBarry Smith /* one left and below; or we are right on it */ 648e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 649e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 65047c6ae99SBarry Smith v[nc++] = 1.0; 65147c6ae99SBarry Smith 65247c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 65347c6ae99SBarry Smith } 65447c6ae99SBarry Smith } 65545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 65645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 65747c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 65847c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 65947c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 660fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 66147c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr); 66247c6ae99SBarry Smith PetscFunctionReturn(0); 66347c6ae99SBarry Smith } 66447c6ae99SBarry Smith 66547c6ae99SBarry Smith /* 66647c6ae99SBarry Smith Contributed by Jianming Yang <jianming-yang@uiowa.edu> 66747c6ae99SBarry Smith */ 668e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A) 66947c6ae99SBarry Smith { 67047c6ae99SBarry Smith PetscErrorCode ierr; 6718ea3bf28SBarry Smith PetscInt i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,dof; 6728ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 673e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 6748ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz; 67547c6ae99SBarry 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; 67647c6ae99SBarry 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; 67747c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 67847c6ae99SBarry Smith PetscScalar v[8]; 67947c6ae99SBarry Smith Mat mat; 680bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 681*fdc842d1SBarry Smith MatType mattype; 68247c6ae99SBarry Smith 68347c6ae99SBarry Smith PetscFunctionBegin; 6841321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 6853a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 6863a586487SStefano Zampini if (!My) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 6873a586487SStefano Zampini if (!Mz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 6881321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 68947c6ae99SBarry Smith ratioi = mx/Mx; 69047c6ae99SBarry Smith ratioj = my/My; 69147c6ae99SBarry Smith ratiol = mz/Mz; 692ce94432eSBarry Smith if (ratioi*Mx != mx) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 693ce94432eSBarry Smith if (ratioj*My != my) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 694ce94432eSBarry Smith if (ratiol*Mz != mz) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z"); 695ce94432eSBarry Smith if (ratioi != 2 && ratioi != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2"); 696ce94432eSBarry Smith if (ratioj != 2 && ratioj != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2"); 697ce94432eSBarry Smith if (ratiol != 2 && ratiol != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2"); 69847c6ae99SBarry Smith 699aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 700aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 70145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 70245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 70347c6ae99SBarry Smith 704aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 705aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr); 70645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 70745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 708e3fbd1f4SBarry Smith 70947c6ae99SBarry Smith /* 710aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 71147c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 71247c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 71347c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 71447c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 71547c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 71647c6ae99SBarry Smith 71747c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 71847c6ae99SBarry Smith */ 719ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 720ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 721ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr); 72247c6ae99SBarry Smith col_scale = size_f/size_c; 72347c6ae99SBarry Smith col_shift = Mx*My*Mz*(rank_f/size_c); 72447c6ae99SBarry Smith 725ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 72647c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 72747c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 72847c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 72947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 730e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 73147c6ae99SBarry Smith 73247c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 73347c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 73447c6ae99SBarry Smith l_c = (l/ratiol); 73547c6ae99SBarry Smith 736aa219208SBarry Smith if (l_c < l_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 73747c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 738aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 73947c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 740aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 74147c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 74247c6ae99SBarry Smith 74347c6ae99SBarry Smith /* 74447c6ae99SBarry Smith Only include those interpolation points that are truly 74547c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 74647c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 74747c6ae99SBarry Smith */ 74847c6ae99SBarry Smith nc = 0; 74947c6ae99SBarry Smith /* one left and below; or we are right on it */ 750e3fbd1f4SBarry 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)); 751e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 75247c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 75347c6ae99SBarry Smith } 75447c6ae99SBarry Smith } 75547c6ae99SBarry Smith } 756ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 757*fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 758*fdc842d1SBarry Smith /* 759*fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 760*fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 761*fdc842d1SBarry Smith */ 762*fdc842d1SBarry Smith if (dof > 1) { 763*fdc842d1SBarry Smith ierr = MatPinToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 764*fdc842d1SBarry Smith } 765*fdc842d1SBarry Smith #endif 76647c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f*p_f,col_scale*m_c*n_c*p_c,mx*my*mz,col_scale*Mx*My*Mz);CHKERRQ(ierr); 767*fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 768*fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 76947c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 77047c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 77147c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 77247c6ae99SBarry Smith 77347c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 77447c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 77547c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 77647c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 77747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 778e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 77947c6ae99SBarry Smith 78047c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 78147c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 78247c6ae99SBarry Smith l_c = (l/ratiol); 78347c6ae99SBarry Smith nc = 0; 78447c6ae99SBarry Smith /* one left and below; or we are right on it */ 785e3fbd1f4SBarry 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)); 786e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 78747c6ae99SBarry Smith v[nc++] = 1.0; 78847c6ae99SBarry Smith 78947c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 79047c6ae99SBarry Smith } 79147c6ae99SBarry Smith } 79247c6ae99SBarry Smith } 79345b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 79445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 79547c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 79647c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 79747c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 798fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 79947c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr); 80047c6ae99SBarry Smith PetscFunctionReturn(0); 80147c6ae99SBarry Smith } 80247c6ae99SBarry Smith 803e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A) 80447c6ae99SBarry Smith { 80547c6ae99SBarry Smith PetscErrorCode ierr; 8068ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof,l; 8078ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 808e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 8098ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,Mz,mz; 81047c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok; 81147c6ae99SBarry Smith PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 81247c6ae99SBarry Smith PetscInt l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c; 81347c6ae99SBarry Smith PetscInt l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz; 81447c6ae99SBarry Smith PetscScalar v[8],x,y,z; 81547c6ae99SBarry Smith Mat mat; 816bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 817*fdc842d1SBarry Smith MatType mattype; 81847c6ae99SBarry Smith 81947c6ae99SBarry Smith PetscFunctionBegin; 8201321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 8211321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 82247c6ae99SBarry Smith if (mx == Mx) { 82347c6ae99SBarry Smith ratioi = 1; 824bff4a2f0SMatthew G. Knepley } else if (bx == DM_BOUNDARY_PERIODIC) { 8253a586487SStefano Zampini if (!Mx) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be positive",Mx); 82647c6ae99SBarry Smith ratioi = mx/Mx; 82747c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 82847c6ae99SBarry Smith } else { 8293a586487SStefano Zampini if (Mx < 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of x coarse grid points %D must be greater than 1",Mx); 83047c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 83147c6ae99SBarry Smith if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 83247c6ae99SBarry Smith } 83347c6ae99SBarry Smith if (my == My) { 83447c6ae99SBarry Smith ratioj = 1; 835bff4a2f0SMatthew G. Knepley } else if (by == DM_BOUNDARY_PERIODIC) { 8363a586487SStefano Zampini if (!My) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be positive",My); 83747c6ae99SBarry Smith ratioj = my/My; 83847c6ae99SBarry Smith if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 83947c6ae99SBarry Smith } else { 8403a586487SStefano Zampini if (My < 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of y coarse grid points %D must be greater than 1",My); 84147c6ae99SBarry Smith ratioj = (my-1)/(My-1); 84247c6ae99SBarry Smith if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 84347c6ae99SBarry Smith } 84447c6ae99SBarry Smith if (mz == Mz) { 84547c6ae99SBarry Smith ratiok = 1; 846bff4a2f0SMatthew G. Knepley } else if (bz == DM_BOUNDARY_PERIODIC) { 8473a586487SStefano Zampini if (!Mz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be positive",Mz); 84847c6ae99SBarry Smith ratiok = mz/Mz; 84947c6ae99SBarry Smith if (ratiok*Mz != mz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D Mz %D",mz,Mz); 85047c6ae99SBarry Smith } else { 8513a586487SStefano Zampini if (Mz < 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of z coarse grid points %D must be greater than 1",Mz); 85247c6ae99SBarry Smith ratiok = (mz-1)/(Mz-1); 85347c6ae99SBarry Smith if (ratiok*(Mz-1) != mz-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 85447c6ae99SBarry Smith } 85547c6ae99SBarry Smith 856aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 857aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 85845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 85945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 86047c6ae99SBarry Smith 861aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 862aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr); 86345b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 86445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 86547c6ae99SBarry Smith 86647c6ae99SBarry Smith /* create interpolation matrix, determining exact preallocation */ 867ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)dac),m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 86847c6ae99SBarry Smith /* loop over local fine grid nodes counting interpolating points */ 86947c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 87047c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 87147c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 87247c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 873e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 87447c6ae99SBarry Smith i_c = (i/ratioi); 87547c6ae99SBarry Smith j_c = (j/ratioj); 87647c6ae99SBarry Smith l_c = (l/ratiok); 877aa219208SBarry Smith if (l_c < l_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 87847c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 879aa219208SBarry Smith if (j_c < j_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 88047c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 881aa219208SBarry Smith if (i_c < i_start_ghost_c) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 88247c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 88347c6ae99SBarry Smith 88447c6ae99SBarry Smith /* 88547c6ae99SBarry Smith Only include those interpolation points that are truly 88647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 88747c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 88847c6ae99SBarry Smith */ 88947c6ae99SBarry Smith nc = 0; 890e3fbd1f4SBarry 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)); 891e3fbd1f4SBarry Smith cols[nc++] = idx_c[col]; 89247c6ae99SBarry Smith if (i_c*ratioi != i) { 893e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+1]; 89447c6ae99SBarry Smith } 89547c6ae99SBarry Smith if (j_c*ratioj != j) { 896e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c]; 89747c6ae99SBarry Smith } 89847c6ae99SBarry Smith if (l_c*ratiok != l) { 899e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c]; 90047c6ae99SBarry Smith } 90147c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 902e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c+1)]; 90347c6ae99SBarry Smith } 90447c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 905e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 90647c6ae99SBarry Smith } 90747c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 908e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 90947c6ae99SBarry Smith } 91047c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 911e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 91247c6ae99SBarry Smith } 91347c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 91447c6ae99SBarry Smith } 91547c6ae99SBarry Smith } 91647c6ae99SBarry Smith } 917ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 918*fdc842d1SBarry Smith #if defined(PETSC_HAVE_CUDA) 919*fdc842d1SBarry Smith /* 920*fdc842d1SBarry Smith Temporary hack: Since the MAIJ matrix must be converted to AIJ before being used by the GPU 921*fdc842d1SBarry Smith we don't want the original unconverted matrix copied to the GPU 922*fdc842d1SBarry Smith */ 923*fdc842d1SBarry Smith if (dof > 1) { 924*fdc842d1SBarry Smith ierr = MatPinToCPU(mat,PETSC_TRUE);CHKERRQ(ierr); 925*fdc842d1SBarry Smith } 926*fdc842d1SBarry Smith #endif 92747c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr); 928*fdc842d1SBarry Smith ierr = ConvertToAIJ(dac->mattype,&mattype);CHKERRQ(ierr); 929*fdc842d1SBarry Smith ierr = MatSetType(mat,mattype);CHKERRQ(ierr); 93047c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 93147c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 93247c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 93347c6ae99SBarry Smith 93447c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 9352adb9dcfSBarry Smith if (!NEWVERSION) { 936b3bd94feSDave May 93747c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 93847c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 93947c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 94047c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 941e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 94247c6ae99SBarry Smith 94347c6ae99SBarry Smith i_c = (i/ratioi); 94447c6ae99SBarry Smith j_c = (j/ratioj); 94547c6ae99SBarry Smith l_c = (l/ratiok); 94647c6ae99SBarry Smith 94747c6ae99SBarry Smith /* 94847c6ae99SBarry Smith Only include those interpolation points that are truly 94947c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 95047c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 95147c6ae99SBarry Smith */ 9526712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 9536712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 9546712e2f1SBarry Smith z = ((PetscReal)(l - l_c*ratiok))/((PetscReal)ratiok); 955b3bd94feSDave May 95647c6ae99SBarry Smith nc = 0; 95747c6ae99SBarry Smith /* one left and below; or we are right on it */ 958e3fbd1f4SBarry 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)); 95947c6ae99SBarry Smith 960e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 96147c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 96247c6ae99SBarry Smith 96347c6ae99SBarry Smith if (i_c*ratioi != i) { 964e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 96547c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 96647c6ae99SBarry Smith } 96747c6ae99SBarry Smith 96847c6ae99SBarry Smith if (j_c*ratioj != j) { 969e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c]; 97047c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 97147c6ae99SBarry Smith } 97247c6ae99SBarry Smith 97347c6ae99SBarry Smith if (l_c*ratiok != l) { 974e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c*n_ghost_c]; 97547c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 97647c6ae99SBarry Smith } 97747c6ae99SBarry Smith 97847c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 979e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c+1)]; 98047c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 98147c6ae99SBarry Smith } 98247c6ae99SBarry Smith 98347c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 984e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 98547c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 98647c6ae99SBarry Smith } 98747c6ae99SBarry Smith 98847c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 989e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 99047c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 99147c6ae99SBarry Smith } 99247c6ae99SBarry Smith 99347c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 994e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 99547c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 99647c6ae99SBarry Smith } 99747c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 99847c6ae99SBarry Smith } 99947c6ae99SBarry Smith } 100047c6ae99SBarry Smith } 1001b3bd94feSDave May 1002b3bd94feSDave May } else { 1003b3bd94feSDave May PetscScalar *xi,*eta,*zeta; 1004b3bd94feSDave May PetscInt li,nxi,lj,neta,lk,nzeta,n; 1005b3bd94feSDave May PetscScalar Ni[8]; 1006b3bd94feSDave May 1007b3bd94feSDave May /* compute local coordinate arrays */ 1008b3bd94feSDave May nxi = ratioi + 1; 1009b3bd94feSDave May neta = ratioj + 1; 1010b3bd94feSDave May nzeta = ratiok + 1; 1011854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 1012854ce69bSBarry Smith ierr = PetscMalloc1(neta,&eta);CHKERRQ(ierr); 1013854ce69bSBarry Smith ierr = PetscMalloc1(nzeta,&zeta);CHKERRQ(ierr); 10148865f1eaSKarl Rupp for (li=0; li<nxi; li++) xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 10158865f1eaSKarl Rupp for (lj=0; lj<neta; lj++) eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 10168865f1eaSKarl Rupp for (lk=0; lk<nzeta; lk++) zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1)); 1017b3bd94feSDave May 1018b3bd94feSDave May for (l=l_start; l<l_start+p_f; l++) { 1019b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 1020b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 1021b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 1022e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 1023b3bd94feSDave May 1024b3bd94feSDave May i_c = (i/ratioi); 1025b3bd94feSDave May j_c = (j/ratioj); 1026b3bd94feSDave May l_c = (l/ratiok); 1027b3bd94feSDave May 1028b3bd94feSDave May /* remainders */ 1029b3bd94feSDave May li = i - ratioi * (i/ratioi); 10308865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 1031b3bd94feSDave May lj = j - ratioj * (j/ratioj); 10328865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 1033b3bd94feSDave May lk = l - ratiok * (l/ratiok); 10348865f1eaSKarl Rupp if (l==mz-1) lk = nzeta-1; 1035b3bd94feSDave May 1036b3bd94feSDave May /* corners */ 1037e3fbd1f4SBarry 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)); 1038e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 1039b3bd94feSDave May Ni[0] = 1.0; 1040b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 1041b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 1042b3bd94feSDave May if ((lk==0) || (lk==nzeta-1)) { 1043b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 1044b3bd94feSDave May continue; 1045b3bd94feSDave May } 1046b3bd94feSDave May } 1047b3bd94feSDave May } 1048b3bd94feSDave May 1049b3bd94feSDave May /* edges + interior */ 1050b3bd94feSDave May /* remainders */ 10518865f1eaSKarl Rupp if (i==mx-1) i_c--; 10528865f1eaSKarl Rupp if (j==my-1) j_c--; 10538865f1eaSKarl Rupp if (l==mz-1) l_c--; 1054b3bd94feSDave May 1055e3fbd1f4SBarry 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)); 1056e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 1057e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; /* one right and below */ 1058e3fbd1f4SBarry Smith cols[2] = idx_c[col+m_ghost_c]; /* one left and above */ 1059e3fbd1f4SBarry Smith cols[3] = idx_c[col+(m_ghost_c+1)]; /* one right and above */ 1060b3bd94feSDave May 1061e3fbd1f4SBarry Smith cols[4] = idx_c[col+m_ghost_c*n_ghost_c]; /* one left and below and front; or we are right on it */ 1062e3fbd1f4SBarry Smith cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; /* one right and below, and front */ 1063e3fbd1f4SBarry Smith cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; /* one left and above and front*/ 1064e3fbd1f4SBarry Smith cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; /* one right and above and front */ 1065b3bd94feSDave May 1066b3bd94feSDave May Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 1067b3bd94feSDave May Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 1068b3bd94feSDave May Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 1069b3bd94feSDave May Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 1070b3bd94feSDave May 1071b3bd94feSDave May Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 1072b3bd94feSDave May Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 1073b3bd94feSDave May Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 1074b3bd94feSDave May Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 1075b3bd94feSDave May 1076b3bd94feSDave May for (n=0; n<8; n++) { 10778865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 1078b3bd94feSDave May } 1079b3bd94feSDave May ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 1080b3bd94feSDave May 1081b3bd94feSDave May } 1082b3bd94feSDave May } 1083b3bd94feSDave May } 1084b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 1085b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 1086b3bd94feSDave May ierr = PetscFree(zeta);CHKERRQ(ierr); 1087b3bd94feSDave May } 108845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 108945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 109047c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 109147c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 109247c6ae99SBarry Smith 109347c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 1094fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 109547c6ae99SBarry Smith PetscFunctionReturn(0); 109647c6ae99SBarry Smith } 109747c6ae99SBarry Smith 1098e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale) 109947c6ae99SBarry Smith { 110047c6ae99SBarry Smith PetscErrorCode ierr; 110147c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1102bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1103aa219208SBarry Smith DMDAStencilType stc,stf; 110447c6ae99SBarry Smith DM_DA *ddc = (DM_DA*)dac->data; 110547c6ae99SBarry Smith 110647c6ae99SBarry Smith PetscFunctionBegin; 110747c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 110847c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 110947c6ae99SBarry Smith PetscValidPointer(A,3); 111047c6ae99SBarry Smith if (scale) PetscValidPointer(scale,4); 111147c6ae99SBarry Smith 11121321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 11131321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 111413903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 111513903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 111613903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 111713903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 111813903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 111947c6ae99SBarry Smith if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 112047c6ae99SBarry Smith if (dimc > 1 && Nc < 2 && Nf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 112147c6ae99SBarry Smith if (dimc > 2 && Pc < 2 && Pf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 112247c6ae99SBarry Smith 1123aa219208SBarry Smith if (ddc->interptype == DMDA_Q1) { 112447c6ae99SBarry Smith if (dimc == 1) { 1125e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr); 112647c6ae99SBarry Smith } else if (dimc == 2) { 1127e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr); 112847c6ae99SBarry Smith } else if (dimc == 3) { 1129e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr); 1130ce94432eSBarry Smith } else SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 1131aa219208SBarry Smith } else if (ddc->interptype == DMDA_Q0) { 113247c6ae99SBarry Smith if (dimc == 1) { 1133e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr); 113447c6ae99SBarry Smith } else if (dimc == 2) { 1135e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr); 113647c6ae99SBarry Smith } else if (dimc == 3) { 1137e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr); 1138ce94432eSBarry Smith } else SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 113947c6ae99SBarry Smith } 114047c6ae99SBarry Smith if (scale) { 1141e727c939SJed Brown ierr = DMCreateInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr); 114247c6ae99SBarry Smith } 114347c6ae99SBarry Smith PetscFunctionReturn(0); 114447c6ae99SBarry Smith } 114547c6ae99SBarry Smith 1146e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_1D(DM dac,DM daf,VecScatter *inject) 11470bb2b966SJungho Lee { 11480bb2b966SJungho Lee PetscErrorCode ierr; 11498ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx,dof; 11508ea3bf28SBarry Smith const PetscInt *idx_f; 1151e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f; 11528ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 11530bb2b966SJungho Lee PetscInt row,i_start_ghost,mx,m_c,nc,ratioi; 11540bb2b966SJungho Lee PetscInt i_start_c,i_start_ghost_c; 11550bb2b966SJungho Lee PetscInt *cols; 1156bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 11570bb2b966SJungho Lee Vec vecf,vecc; 11580bb2b966SJungho Lee IS isf; 11590bb2b966SJungho Lee 11600bb2b966SJungho Lee PetscFunctionBegin; 11610bb2b966SJungho Lee ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 11620bb2b966SJungho Lee ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1163bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 11640bb2b966SJungho Lee ratioi = mx/Mx; 11650bb2b966SJungho Lee if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 11660bb2b966SJungho Lee } else { 11670bb2b966SJungho Lee ratioi = (mx-1)/(Mx-1); 11680bb2b966SJungho Lee if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 11690bb2b966SJungho Lee } 11700bb2b966SJungho Lee 11710bb2b966SJungho Lee ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 11720bb2b966SJungho Lee ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 117345b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 117445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 11750bb2b966SJungho Lee 11760bb2b966SJungho Lee ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 11770bb2b966SJungho Lee ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 11780bb2b966SJungho Lee 11790bb2b966SJungho Lee 11800bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 11810bb2b966SJungho Lee nc = 0; 1182785e854fSJed Brown ierr = PetscMalloc1(m_f,&cols);CHKERRQ(ierr); 11830bb2b966SJungho Lee 11840bb2b966SJungho Lee 11850bb2b966SJungho Lee for (i=i_start_c; i<i_start_c+m_c; i++) { 11860bb2b966SJungho Lee PetscInt i_f = i*ratioi; 11870bb2b966SJungho Lee 11888865f1eaSKarl Rupp if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\ni_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 11898865f1eaSKarl Rupp 1190e3fbd1f4SBarry Smith row = idx_f[(i_f-i_start_ghost)]; 1191e3fbd1f4SBarry Smith cols[nc++] = row; 11920bb2b966SJungho Lee } 11930bb2b966SJungho Lee 119445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1195ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 11960bb2b966SJungho Lee ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 11970bb2b966SJungho Lee ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 11989448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 11990bb2b966SJungho Lee ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 12000bb2b966SJungho Lee ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 12010bb2b966SJungho Lee ierr = ISDestroy(&isf);CHKERRQ(ierr); 12020bb2b966SJungho Lee PetscFunctionReturn(0); 12030bb2b966SJungho Lee } 12040bb2b966SJungho Lee 1205e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject) 120647c6ae99SBarry Smith { 120747c6ae99SBarry Smith PetscErrorCode ierr; 12088ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 12098ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1210e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 12118ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c; 121247c6ae99SBarry Smith PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; 1213076202ddSJed Brown PetscInt i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 121447c6ae99SBarry Smith PetscInt *cols; 1215bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 121647c6ae99SBarry Smith Vec vecf,vecc; 121747c6ae99SBarry Smith IS isf; 121847c6ae99SBarry Smith 121947c6ae99SBarry Smith PetscFunctionBegin; 12201321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 12211321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1222bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 122347c6ae99SBarry Smith ratioi = mx/Mx; 122447c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 122547c6ae99SBarry Smith } else { 122647c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 122747c6ae99SBarry Smith if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 122847c6ae99SBarry Smith } 1229bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 123047c6ae99SBarry Smith ratioj = my/My; 123147c6ae99SBarry Smith if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 123247c6ae99SBarry Smith } else { 123347c6ae99SBarry Smith ratioj = (my-1)/(My-1); 123447c6ae99SBarry Smith if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 123547c6ae99SBarry Smith } 123647c6ae99SBarry Smith 1237aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 1238aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 123945b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 124045b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 124147c6ae99SBarry Smith 1242aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 1243aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 124445b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 124545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 124647c6ae99SBarry Smith 124747c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 124847c6ae99SBarry Smith nc = 0; 1249785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f,&cols);CHKERRQ(ierr); 1250076202ddSJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1251076202ddSJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1252076202ddSJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj; 1253076202ddSJed Brown if (j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1254076202ddSJed Brown j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1255076202ddSJed Brown if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA\n\ 1256076202ddSJed Brown i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1257e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 1258e3fbd1f4SBarry Smith cols[nc++] = row; 125947c6ae99SBarry Smith } 126047c6ae99SBarry Smith } 126145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 126245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 126347c6ae99SBarry Smith 1264ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 12659a42bb27SBarry Smith ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 12669a42bb27SBarry Smith ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 12679448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 12689a42bb27SBarry Smith ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 12699a42bb27SBarry Smith ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1270fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 127147c6ae99SBarry Smith PetscFunctionReturn(0); 127247c6ae99SBarry Smith } 127347c6ae99SBarry Smith 1274e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject) 1275b1757049SJed Brown { 1276b1757049SJed Brown PetscErrorCode ierr; 1277b1757049SJed Brown PetscInt i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz; 1278b1757049SJed Brown PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c; 1279b1757049SJed Brown PetscInt i_start_ghost,j_start_ghost,k_start_ghost; 1280b1757049SJed Brown PetscInt mx,my,mz,ratioi,ratioj,ratiok; 1281b1757049SJed Brown PetscInt i_start_c,j_start_c,k_start_c; 1282b1757049SJed Brown PetscInt m_c,n_c,p_c; 1283b1757049SJed Brown PetscInt i_start_ghost_c,j_start_ghost_c,k_start_ghost_c; 1284b1757049SJed Brown PetscInt row,nc,dof; 12858ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1286e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1287b1757049SJed Brown PetscInt *cols; 1288bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 1289b1757049SJed Brown Vec vecf,vecc; 1290b1757049SJed Brown IS isf; 1291b1757049SJed Brown 1292b1757049SJed Brown PetscFunctionBegin; 12931321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 12941321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1295b1757049SJed Brown 1296bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 1297b1757049SJed Brown ratioi = mx/Mx; 1298b1757049SJed Brown if (ratioi*Mx != mx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); 1299b1757049SJed Brown } else { 1300b1757049SJed Brown ratioi = (mx-1)/(Mx-1); 1301b1757049SJed Brown if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); 1302b1757049SJed Brown } 1303bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 1304b1757049SJed Brown ratioj = my/My; 1305b1757049SJed Brown if (ratioj*My != my) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); 1306b1757049SJed Brown } else { 1307b1757049SJed Brown ratioj = (my-1)/(My-1); 1308b1757049SJed Brown if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); 1309b1757049SJed Brown } 1310bff4a2f0SMatthew G. Knepley if (bz == DM_BOUNDARY_PERIODIC) { 1311b1757049SJed Brown ratiok = mz/Mz; 1312b1757049SJed Brown if (ratiok*Mz != mz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D My %D",mz,Mz); 1313b1757049SJed Brown } else { 1314b1757049SJed Brown ratiok = (mz-1)/(Mz-1); 1315b1757049SJed Brown if (ratiok*(Mz-1) != mz-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); 1316b1757049SJed Brown } 1317b1757049SJed Brown 1318b1757049SJed Brown ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1319b1757049SJed Brown ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 132045b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 132145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1322b1757049SJed Brown 1323b1757049SJed Brown ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1324b1757049SJed Brown ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&k_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr); 132545b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 132645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1327b1757049SJed Brown 1328b1757049SJed Brown 1329b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1330b1757049SJed Brown nc = 0; 1331785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f*p_f,&cols);CHKERRQ(ierr); 1332b1757049SJed Brown for (k=k_start_c; k<k_start_c+p_c; k++) { 1333b1757049SJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1334b1757049SJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1335b1757049SJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok; 1336b1757049SJed Brown if (k_f < k_start_ghost || k_f >= k_start_ghost+p_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1337b1757049SJed Brown "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost); 1338b1757049SJed Brown if (j_f < j_start_ghost || j_f >= j_start_ghost+n_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1339b1757049SJed Brown "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1340b1757049SJed Brown if (i_f < i_start_ghost || i_f >= i_start_ghost+m_ghost) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Processor's coarse DMDA must lie over fine DMDA " 1341b1757049SJed Brown "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1342e3fbd1f4SBarry 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))]; 1343e3fbd1f4SBarry Smith cols[nc++] = row; 1344b1757049SJed Brown } 1345b1757049SJed Brown } 1346b1757049SJed Brown } 134745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 134845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1349b1757049SJed Brown 1350ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 1351b1757049SJed Brown ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 1352b1757049SJed Brown ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 13539448b7f1SJunchao Zhang ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 1354b1757049SJed Brown ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 1355b1757049SJed Brown ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1356fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 1357b1757049SJed Brown PetscFunctionReturn(0); 1358b1757049SJed Brown } 1359b1757049SJed Brown 13606dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_DA(DM dac,DM daf,Mat *mat) 136147c6ae99SBarry Smith { 136247c6ae99SBarry Smith PetscErrorCode ierr; 136347c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1364bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1365aa219208SBarry Smith DMDAStencilType stc,stf; 136660c16ac1SBarry Smith VecScatter inject = NULL; 136747c6ae99SBarry Smith 136847c6ae99SBarry Smith PetscFunctionBegin; 136947c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 137047c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 13716dbf9973SLawrence Mitchell PetscValidPointer(mat,3); 137247c6ae99SBarry Smith 13731321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 13741321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 137513903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 137613903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 137713903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 137813903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 137913903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 138047c6ae99SBarry Smith if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 138147c6ae99SBarry Smith if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 138247c6ae99SBarry Smith if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 138347c6ae99SBarry Smith 13840bb2b966SJungho Lee if (dimc == 1) { 13856dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_1D(dac,daf,&inject);CHKERRQ(ierr); 13860bb2b966SJungho Lee } else if (dimc == 2) { 13876dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_2D(dac,daf,&inject);CHKERRQ(ierr); 1388b1757049SJed Brown } else if (dimc == 3) { 13896dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_3D(dac,daf,&inject);CHKERRQ(ierr); 139047c6ae99SBarry Smith } 13916dbf9973SLawrence Mitchell ierr = MatCreateScatter(PetscObjectComm((PetscObject)inject), inject, mat);CHKERRQ(ierr); 13926dbf9973SLawrence Mitchell ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 139347c6ae99SBarry Smith PetscFunctionReturn(0); 139447c6ae99SBarry Smith } 139547c6ae99SBarry Smith 1396e727c939SJed Brown PetscErrorCode DMCreateAggregates_DA(DM dac,DM daf,Mat *rest) 139747c6ae99SBarry Smith { 139847c6ae99SBarry Smith PetscErrorCode ierr; 139947c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc; 140047c6ae99SBarry Smith PetscInt dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1401bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1402aa219208SBarry Smith DMDAStencilType stc,stf; 140347c6ae99SBarry Smith PetscInt i,j,l; 140447c6ae99SBarry Smith PetscInt i_start,j_start,l_start, m_f,n_f,p_f; 140547c6ae99SBarry Smith PetscInt i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost; 14068ea3bf28SBarry Smith const PetscInt *idx_f; 140747c6ae99SBarry Smith PetscInt i_c,j_c,l_c; 140847c6ae99SBarry Smith PetscInt i_start_c,j_start_c,l_start_c, m_c,n_c,p_c; 140947c6ae99SBarry Smith PetscInt i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c; 14108ea3bf28SBarry Smith const PetscInt *idx_c; 141147c6ae99SBarry Smith PetscInt d; 141247c6ae99SBarry Smith PetscInt a; 141347c6ae99SBarry Smith PetscInt max_agg_size; 141447c6ae99SBarry Smith PetscInt *fine_nodes; 141547c6ae99SBarry Smith PetscScalar *one_vec; 141647c6ae99SBarry Smith PetscInt fn_idx; 1417565245c5SBarry Smith ISLocalToGlobalMapping ltogmf,ltogmc; 141847c6ae99SBarry Smith 141947c6ae99SBarry Smith PetscFunctionBegin; 142047c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 142147c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 142247c6ae99SBarry Smith PetscValidPointer(rest,3); 142347c6ae99SBarry Smith 14241321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 14251321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 142613903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 142713903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 142813903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 142913903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 143013903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 143147c6ae99SBarry Smith 143247c6ae99SBarry Smith if (Mf < Mc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Mc %D, Mf %D", Mc, Mf); 143347c6ae99SBarry Smith if (Nf < Nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Nc %D, Nf %D", Nc, Nf); 143447c6ae99SBarry Smith if (Pf < Pc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Coarse grid has more points than fine grid, Pc %D, Pf %D", Pc, Pf); 143547c6ae99SBarry Smith 143647c6ae99SBarry Smith if (Pc < 0) Pc = 1; 143747c6ae99SBarry Smith if (Pf < 0) Pf = 1; 143847c6ae99SBarry Smith if (Nc < 0) Nc = 1; 143947c6ae99SBarry Smith if (Nf < 0) Nf = 1; 144047c6ae99SBarry Smith 1441aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1442aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1443565245c5SBarry Smith 1444565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<ogmf);CHKERRQ(ierr); 1445565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmf,&idx_f);CHKERRQ(ierr); 144647c6ae99SBarry Smith 1447aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1448aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr); 1449565245c5SBarry Smith 1450565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<ogmc);CHKERRQ(ierr); 1451565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmc,&idx_c);CHKERRQ(ierr); 145247c6ae99SBarry Smith 145347c6ae99SBarry Smith /* 145447c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 145547c6ae99SBarry Smith for dimension 1 and 2 respectively. 145647c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 145747c6ae99SBarry Smith and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate. 145847c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 145947c6ae99SBarry Smith */ 146047c6ae99SBarry Smith 146147c6ae99SBarry Smith max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1); 146247c6ae99SBarry Smith 146347c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 1464ce94432eSBarry Smith ierr = MatCreateAIJ(PetscObjectComm((PetscObject)daf), m_c*n_c*p_c*dofc, m_f*n_f*p_f*doff, Mc*Nc*Pc*dofc, Mf*Nf*Pf*doff, 14650298fd71SBarry Smith max_agg_size, NULL, max_agg_size, NULL, rest);CHKERRQ(ierr); 146647c6ae99SBarry Smith 146747c6ae99SBarry Smith /* store nodes in the fine grid here */ 1468dcca6d9dSJed Brown ierr = PetscMalloc2(max_agg_size, &one_vec,max_agg_size, &fine_nodes);CHKERRQ(ierr); 146947c6ae99SBarry Smith for (i=0; i<max_agg_size; i++) one_vec[i] = 1.0; 147047c6ae99SBarry Smith 147147c6ae99SBarry Smith /* loop over all coarse nodes */ 147247c6ae99SBarry Smith for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) { 147347c6ae99SBarry Smith for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) { 147447c6ae99SBarry Smith for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) { 147547c6ae99SBarry Smith for (d=0; d<dofc; d++) { 147647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 147747c6ae99SBarry 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; 147847c6ae99SBarry Smith 147947c6ae99SBarry Smith fn_idx = 0; 148047c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 148147c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 148247c6ae99SBarry Smith (same for other dimensions) 148347c6ae99SBarry Smith */ 148447c6ae99SBarry Smith for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) { 148547c6ae99SBarry Smith for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) { 148647c6ae99SBarry Smith for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) { 148747c6ae99SBarry 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; 148847c6ae99SBarry Smith fn_idx++; 148947c6ae99SBarry Smith } 149047c6ae99SBarry Smith } 149147c6ae99SBarry Smith } 149247c6ae99SBarry Smith /* add all these points to one aggregate */ 149347c6ae99SBarry Smith ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr); 149447c6ae99SBarry Smith } 149547c6ae99SBarry Smith } 149647c6ae99SBarry Smith } 149747c6ae99SBarry Smith } 1498565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmf,&idx_f);CHKERRQ(ierr); 1499565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmc,&idx_c);CHKERRQ(ierr); 150047c6ae99SBarry Smith ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr); 150147c6ae99SBarry Smith ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 150247c6ae99SBarry Smith ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 150347c6ae99SBarry Smith PetscFunctionReturn(0); 150447c6ae99SBarry Smith } 1505