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 49e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A) 5047c6ae99SBarry Smith { 5147c6ae99SBarry Smith PetscErrorCode ierr; 528ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 538ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 548ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 5547c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 5647c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 5785afcc9aSBarry Smith PetscScalar v[2],x; 5847c6ae99SBarry Smith Mat mat; 59bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 60e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 61e3fbd1f4SBarry Smith 6247c6ae99SBarry Smith 6347c6ae99SBarry Smith PetscFunctionBegin; 641321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 651321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 66bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 6747c6ae99SBarry Smith ratio = mx/Mx; 6847c6ae99SBarry 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); 6947c6ae99SBarry Smith } else { 7047c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 7147c6ae99SBarry 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); 7247c6ae99SBarry Smith } 7347c6ae99SBarry Smith 74aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 75aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 7645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 7745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 7847c6ae99SBarry Smith 79aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 80aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 8145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 8245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 8347c6ae99SBarry Smith 8447c6ae99SBarry Smith /* create interpolation matrix */ 85ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 8647c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 8747c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 880298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr); 890298fd71SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,NULL,1,NULL);CHKERRQ(ierr); 9047c6ae99SBarry Smith 9147c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 9285afcc9aSBarry Smith if (!NEWVERSION) { 93b3bd94feSDave May 9447c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 9547c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 96e3fbd1f4SBarry Smith row = idx_f[i-i_start_ghost]; 9747c6ae99SBarry Smith 9847c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 99aa219208SBarry 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\ 10047c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 10147c6ae99SBarry Smith 10247c6ae99SBarry Smith /* 10347c6ae99SBarry Smith Only include those interpolation points that are truly 10447c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 10547c6ae99SBarry Smith in x direction; since they have no right neighbor 10647c6ae99SBarry Smith */ 1076712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 10847c6ae99SBarry Smith nc = 0; 10947c6ae99SBarry Smith /* one left and below; or we are right on it */ 110e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 111e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 11247c6ae99SBarry Smith v[nc++] = -x + 1.0; 11347c6ae99SBarry Smith /* one right? */ 11447c6ae99SBarry Smith if (i_c*ratio != i) { 115e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 11647c6ae99SBarry Smith v[nc++] = x; 11747c6ae99SBarry Smith } 11847c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 11947c6ae99SBarry Smith } 120b3bd94feSDave May 121b3bd94feSDave May } else { 122b3bd94feSDave May PetscScalar *xi; 123b3bd94feSDave May PetscInt li,nxi,n; 124b3bd94feSDave May PetscScalar Ni[2]; 125b3bd94feSDave May 126b3bd94feSDave May /* compute local coordinate arrays */ 127b3bd94feSDave May nxi = ratio + 1; 128854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 129b3bd94feSDave May for (li=0; li<nxi; li++) { 13052218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 131b3bd94feSDave May } 132b3bd94feSDave May 133b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 134b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 135e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 136b3bd94feSDave May 137b3bd94feSDave May i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 138b3bd94feSDave 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\ 139b3bd94feSDave May i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 140b3bd94feSDave May 141b3bd94feSDave May /* remainders */ 142b3bd94feSDave May li = i - ratio * (i/ratio); 1438865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 144b3bd94feSDave May 145b3bd94feSDave May /* corners */ 146e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 147e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 148b3bd94feSDave May Ni[0] = 1.0; 149b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 150b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 151b3bd94feSDave May continue; 152b3bd94feSDave May } 153b3bd94feSDave May 154b3bd94feSDave May /* edges + interior */ 155b3bd94feSDave May /* remainders */ 1568865f1eaSKarl Rupp if (i==mx-1) i_c--; 157b3bd94feSDave May 158e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 159e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 160e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; 161b3bd94feSDave May 162b3bd94feSDave May Ni[0] = 0.5*(1.0-xi[li]); 163b3bd94feSDave May Ni[1] = 0.5*(1.0+xi[li]); 164b3bd94feSDave May for (n=0; n<2; n++) { 1658865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 166b3bd94feSDave May } 167b3bd94feSDave May ierr = MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 168b3bd94feSDave May } 169b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 170b3bd94feSDave May } 17145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 17245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 17347c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17447c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17547c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 176fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 17747c6ae99SBarry Smith PetscFunctionReturn(0); 17847c6ae99SBarry Smith } 17947c6ae99SBarry Smith 180e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A) 18147c6ae99SBarry Smith { 18247c6ae99SBarry Smith PetscErrorCode ierr; 1838ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx; 1848ea3bf28SBarry Smith const PetscInt *idx_f,*idx_c; 185e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1868ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 18747c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 18847c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 18947c6ae99SBarry Smith PetscScalar v[2],x; 19047c6ae99SBarry Smith Mat mat; 191bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 19247c6ae99SBarry Smith 19347c6ae99SBarry Smith PetscFunctionBegin; 1941321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 1951321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 196bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 19747c6ae99SBarry Smith ratio = mx/Mx; 19847c6ae99SBarry 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); 19947c6ae99SBarry Smith } else { 20047c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 20147c6ae99SBarry 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); 20247c6ae99SBarry Smith } 20347c6ae99SBarry Smith 204aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 205aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 20645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 20745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 20847c6ae99SBarry Smith 209aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 210aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 21145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 21245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 21347c6ae99SBarry Smith 21447c6ae99SBarry Smith /* create interpolation matrix */ 215ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 21647c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 21747c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 2180298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,NULL);CHKERRQ(ierr); 2190298fd71SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,NULL,0,NULL);CHKERRQ(ierr); 22047c6ae99SBarry Smith 22147c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 22247c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 22347c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 224e3fbd1f4SBarry Smith row = idx_f[(i-i_start_ghost)]; 22547c6ae99SBarry Smith 22647c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 22747c6ae99SBarry Smith 22847c6ae99SBarry Smith /* 22947c6ae99SBarry Smith Only include those interpolation points that are truly 23047c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 23147c6ae99SBarry Smith in x direction; since they have no right neighbor 23247c6ae99SBarry Smith */ 2336712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratio))/((PetscReal)ratio); 23447c6ae99SBarry Smith nc = 0; 23547c6ae99SBarry Smith /* one left and below; or we are right on it */ 236e3fbd1f4SBarry Smith col = (i_c-i_start_ghost_c); 237e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 23847c6ae99SBarry Smith v[nc++] = -x + 1.0; 23947c6ae99SBarry Smith /* one right? */ 24047c6ae99SBarry Smith if (i_c*ratio != i) { 241e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 24247c6ae99SBarry Smith v[nc++] = x; 24347c6ae99SBarry Smith } 24447c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 24547c6ae99SBarry Smith } 24645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 24745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 24847c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 24947c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 25047c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 251fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 25247c6ae99SBarry Smith ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr); 25347c6ae99SBarry Smith PetscFunctionReturn(0); 25447c6ae99SBarry Smith } 25547c6ae99SBarry Smith 256e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A) 25747c6ae99SBarry Smith { 25847c6ae99SBarry Smith PetscErrorCode ierr; 2598ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 2608ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 261e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 2628ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 26347c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 26447c6ae99SBarry 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; 26547c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 26647c6ae99SBarry Smith PetscScalar v[4],x,y; 26747c6ae99SBarry Smith Mat mat; 268bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 26947c6ae99SBarry Smith 27047c6ae99SBarry Smith PetscFunctionBegin; 2711321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 2721321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 273bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 27447c6ae99SBarry Smith ratioi = mx/Mx; 27547c6ae99SBarry 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); 27647c6ae99SBarry Smith } else { 27747c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 27847c6ae99SBarry 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); 27947c6ae99SBarry Smith } 280bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 28147c6ae99SBarry Smith ratioj = my/My; 28247c6ae99SBarry 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); 28347c6ae99SBarry Smith } else { 28447c6ae99SBarry Smith ratioj = (my-1)/(My-1); 28547c6ae99SBarry 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); 28647c6ae99SBarry Smith } 28747c6ae99SBarry Smith 28847c6ae99SBarry Smith 289aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 290aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 29145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 29245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 29347c6ae99SBarry Smith 294aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 295aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 29645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 29745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 29847c6ae99SBarry Smith 29947c6ae99SBarry Smith /* 300aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 30147c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 30247c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 30347c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 30447c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 30547c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 30647c6ae99SBarry Smith 30747c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 30847c6ae99SBarry Smith */ 309ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 310ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 311ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr); 31247c6ae99SBarry Smith col_scale = size_f/size_c; 31347c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 31447c6ae99SBarry Smith 315ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 31647c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 31747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 31847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 319e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 32047c6ae99SBarry Smith 32147c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 32247c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 32347c6ae99SBarry Smith 324aa219208SBarry 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\ 32547c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 326aa219208SBarry 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\ 32747c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 32847c6ae99SBarry Smith 32947c6ae99SBarry Smith /* 33047c6ae99SBarry Smith Only include those interpolation points that are truly 33147c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 33247c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 33347c6ae99SBarry Smith */ 33447c6ae99SBarry Smith nc = 0; 33547c6ae99SBarry Smith /* one left and below; or we are right on it */ 336e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 337e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 33847c6ae99SBarry Smith /* one right and below */ 339e3fbd1f4SBarry Smith if (i_c*ratioi != i) cols[nc++] = col_shift + idx_c[col+1]; 34047c6ae99SBarry Smith /* one left and above */ 341e3fbd1f4SBarry Smith if (j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+m_ghost_c]; 34247c6ae99SBarry Smith /* one right and above */ 343e3fbd1f4SBarry Smith if (i_c*ratioi != i && j_c*ratioj != j) cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)]; 34447c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 34547c6ae99SBarry Smith } 34647c6ae99SBarry Smith } 347ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 34847c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 34947c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 35047c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 35147c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 35247c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 35347c6ae99SBarry Smith 35447c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 35585afcc9aSBarry Smith if (!NEWVERSION) { 356b3bd94feSDave May 35747c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 35847c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 35947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 360e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 36147c6ae99SBarry Smith 36247c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 36347c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 36447c6ae99SBarry Smith 36547c6ae99SBarry Smith /* 36647c6ae99SBarry Smith Only include those interpolation points that are truly 36747c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 36847c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 36947c6ae99SBarry Smith */ 3706712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 3716712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 372b3bd94feSDave May 37347c6ae99SBarry Smith nc = 0; 37447c6ae99SBarry Smith /* one left and below; or we are right on it */ 375e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 376e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 37747c6ae99SBarry Smith v[nc++] = x*y - x - y + 1.0; 37847c6ae99SBarry Smith /* one right and below */ 37947c6ae99SBarry Smith if (i_c*ratioi != i) { 380e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+1]; 38147c6ae99SBarry Smith v[nc++] = -x*y + x; 38247c6ae99SBarry Smith } 38347c6ae99SBarry Smith /* one left and above */ 38447c6ae99SBarry Smith if (j_c*ratioj != j) { 385e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+m_ghost_c]; 38647c6ae99SBarry Smith v[nc++] = -x*y + y; 38747c6ae99SBarry Smith } 38847c6ae99SBarry Smith /* one right and above */ 38947c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 390e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)]; 39147c6ae99SBarry Smith v[nc++] = x*y; 39247c6ae99SBarry Smith } 39347c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 39447c6ae99SBarry Smith } 39547c6ae99SBarry Smith } 396b3bd94feSDave May 397b3bd94feSDave May } else { 398b3bd94feSDave May PetscScalar Ni[4]; 399b3bd94feSDave May PetscScalar *xi,*eta; 400b3bd94feSDave May PetscInt li,nxi,lj,neta; 401b3bd94feSDave May 402b3bd94feSDave May /* compute local coordinate arrays */ 403b3bd94feSDave May nxi = ratioi + 1; 404b3bd94feSDave May neta = ratioj + 1; 405854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 406854ce69bSBarry Smith ierr = PetscMalloc1(neta,&eta);CHKERRQ(ierr); 407b3bd94feSDave May for (li=0; li<nxi; li++) { 40852218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 409b3bd94feSDave May } 410b3bd94feSDave May for (lj=0; lj<neta; lj++) { 41152218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 412b3bd94feSDave May } 413b3bd94feSDave May 414b3bd94feSDave May /* loop over local fine grid nodes setting interpolation for those*/ 415b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 416b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 417b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 418e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 419b3bd94feSDave May 420b3bd94feSDave May i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 421b3bd94feSDave May j_c = (j/ratioj); /* coarse grid node below fine grid node */ 422b3bd94feSDave May 423b3bd94feSDave May /* remainders */ 424b3bd94feSDave May li = i - ratioi * (i/ratioi); 4258865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 426b3bd94feSDave May lj = j - ratioj * (j/ratioj); 4278865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 428b3bd94feSDave May 429b3bd94feSDave May /* corners */ 430e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 431e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 432b3bd94feSDave May Ni[0] = 1.0; 433b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 434b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 435b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 436b3bd94feSDave May continue; 437b3bd94feSDave May } 438b3bd94feSDave May } 439b3bd94feSDave May 440b3bd94feSDave May /* edges + interior */ 441b3bd94feSDave May /* remainders */ 4428865f1eaSKarl Rupp if (i==mx-1) i_c--; 4438865f1eaSKarl Rupp if (j==my-1) j_c--; 444b3bd94feSDave May 445e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 446e3fbd1f4SBarry Smith cols[0] = col_shift + idx_c[col]; /* left, below */ 447e3fbd1f4SBarry Smith cols[1] = col_shift + idx_c[col+1]; /* right, below */ 448e3fbd1f4SBarry Smith cols[2] = col_shift + idx_c[col+m_ghost_c]; /* left, above */ 449e3fbd1f4SBarry Smith cols[3] = col_shift + idx_c[col+(m_ghost_c+1)]; /* right, above */ 450b3bd94feSDave May 451b3bd94feSDave May Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]); 452b3bd94feSDave May Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]); 453b3bd94feSDave May Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]); 454b3bd94feSDave May Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]); 455b3bd94feSDave May 456b3bd94feSDave May nc = 0; 4578865f1eaSKarl Rupp if (PetscAbsScalar(Ni[0])<1.0e-32) cols[0]=-1; 4588865f1eaSKarl Rupp if (PetscAbsScalar(Ni[1])<1.0e-32) cols[1]=-1; 4598865f1eaSKarl Rupp if (PetscAbsScalar(Ni[2])<1.0e-32) cols[2]=-1; 4608865f1eaSKarl Rupp if (PetscAbsScalar(Ni[3])<1.0e-32) cols[3]=-1; 461b3bd94feSDave May 462b3bd94feSDave May ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 463b3bd94feSDave May } 464b3bd94feSDave May } 465b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 466b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 467b3bd94feSDave May } 46845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 46945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 47047c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 47147c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 47247c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 473fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 47447c6ae99SBarry Smith PetscFunctionReturn(0); 47547c6ae99SBarry Smith } 47647c6ae99SBarry Smith 47747c6ae99SBarry Smith /* 47847c6ae99SBarry Smith Contributed by Andrei Draganescu <aidraga@sandia.gov> 47947c6ae99SBarry Smith */ 480e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A) 48147c6ae99SBarry Smith { 48247c6ae99SBarry Smith PetscErrorCode ierr; 4838ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 4848ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 485e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 4868ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,*dnz,*onz; 48747c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 48847c6ae99SBarry 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; 48947c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 49047c6ae99SBarry Smith PetscScalar v[4]; 49147c6ae99SBarry Smith Mat mat; 492bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 49347c6ae99SBarry Smith 49447c6ae99SBarry Smith PetscFunctionBegin; 4951321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 4961321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 49747c6ae99SBarry Smith ratioi = mx/Mx; 49847c6ae99SBarry Smith ratioj = my/My; 499ce94432eSBarry 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"); 500ce94432eSBarry 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"); 501ce94432eSBarry Smith if (ratioi != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2"); 502ce94432eSBarry Smith if (ratioj != 2) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2"); 50347c6ae99SBarry Smith 504aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 505aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 50645b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 50745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 50847c6ae99SBarry Smith 509aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 510aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 51145b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 51245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 51347c6ae99SBarry Smith 51447c6ae99SBarry Smith /* 515aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 51647c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 51747c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 51847c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 51947c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 52047c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 52147c6ae99SBarry Smith 52247c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 52347c6ae99SBarry Smith */ 524ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 525ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 526ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr); 52747c6ae99SBarry Smith col_scale = size_f/size_c; 52847c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 52947c6ae99SBarry Smith 530ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 53147c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 53247c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 53347c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 534e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 53547c6ae99SBarry Smith 53647c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 53747c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 53847c6ae99SBarry Smith 539aa219208SBarry 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\ 54047c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 541aa219208SBarry 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\ 54247c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 54347c6ae99SBarry Smith 54447c6ae99SBarry Smith /* 54547c6ae99SBarry Smith Only include those interpolation points that are truly 54647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 54747c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 54847c6ae99SBarry Smith */ 54947c6ae99SBarry Smith nc = 0; 55047c6ae99SBarry Smith /* one left and below; or we are right on it */ 551e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 552e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 55347c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 55447c6ae99SBarry Smith } 55547c6ae99SBarry Smith } 556ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 55747c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 55847c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 55947c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 56047c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 56147c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 56247c6ae99SBarry Smith 56347c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 56447c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 56547c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 56647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 567e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 56847c6ae99SBarry Smith 56947c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 57047c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 57147c6ae99SBarry Smith nc = 0; 57247c6ae99SBarry Smith /* one left and below; or we are right on it */ 573e3fbd1f4SBarry Smith col = (m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 574e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 57547c6ae99SBarry Smith v[nc++] = 1.0; 57647c6ae99SBarry Smith 57747c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 57847c6ae99SBarry Smith } 57947c6ae99SBarry Smith } 58045b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 58145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 58247c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 58347c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 58447c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 585fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 58647c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr); 58747c6ae99SBarry Smith PetscFunctionReturn(0); 58847c6ae99SBarry Smith } 58947c6ae99SBarry Smith 59047c6ae99SBarry Smith /* 59147c6ae99SBarry Smith Contributed by Jianming Yang <jianming-yang@uiowa.edu> 59247c6ae99SBarry Smith */ 593e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A) 59447c6ae99SBarry Smith { 59547c6ae99SBarry Smith PetscErrorCode ierr; 5968ea3bf28SBarry Smith PetscInt i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,dof; 5978ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 598e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 5998ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz; 60047c6ae99SBarry 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; 60147c6ae99SBarry 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; 60247c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 60347c6ae99SBarry Smith PetscScalar v[8]; 60447c6ae99SBarry Smith Mat mat; 605bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 60647c6ae99SBarry Smith 60747c6ae99SBarry Smith PetscFunctionBegin; 6081321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 6091321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 61047c6ae99SBarry Smith ratioi = mx/Mx; 61147c6ae99SBarry Smith ratioj = my/My; 61247c6ae99SBarry Smith ratiol = mz/Mz; 613ce94432eSBarry 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"); 614ce94432eSBarry 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"); 615ce94432eSBarry 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"); 616ce94432eSBarry Smith if (ratioi != 2 && ratioi != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2"); 617ce94432eSBarry Smith if (ratioj != 2 && ratioj != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2"); 618ce94432eSBarry Smith if (ratiol != 2 && ratiol != 1) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2"); 61947c6ae99SBarry Smith 620aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 621aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 62245b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 62345b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 62447c6ae99SBarry Smith 625aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 626aa219208SBarry 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); 62745b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 62845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 629e3fbd1f4SBarry Smith 63047c6ae99SBarry Smith /* 631aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 63247c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 63347c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 63447c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 63547c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 63647c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 63747c6ae99SBarry Smith 63847c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 63947c6ae99SBarry Smith */ 640ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dac),&size_c);CHKERRQ(ierr); 641ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)daf),&size_f);CHKERRQ(ierr); 642ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)daf),&rank_f);CHKERRQ(ierr); 64347c6ae99SBarry Smith col_scale = size_f/size_c; 64447c6ae99SBarry Smith col_shift = Mx*My*Mz*(rank_f/size_c); 64547c6ae99SBarry Smith 646ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)daf),m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 64747c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 64847c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 64947c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 65047c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 651e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 65247c6ae99SBarry Smith 65347c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 65447c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 65547c6ae99SBarry Smith l_c = (l/ratiol); 65647c6ae99SBarry Smith 657aa219208SBarry 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\ 65847c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 659aa219208SBarry 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\ 66047c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 661aa219208SBarry 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\ 66247c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 66347c6ae99SBarry Smith 66447c6ae99SBarry Smith /* 66547c6ae99SBarry Smith Only include those interpolation points that are truly 66647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 66747c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 66847c6ae99SBarry Smith */ 66947c6ae99SBarry Smith nc = 0; 67047c6ae99SBarry Smith /* one left and below; or we are right on it */ 671e3fbd1f4SBarry 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)); 672e3fbd1f4SBarry Smith cols[nc++] = col_shift + idx_c[col]; 67347c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 67447c6ae99SBarry Smith } 67547c6ae99SBarry Smith } 67647c6ae99SBarry Smith } 677ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)daf),&mat);CHKERRQ(ierr); 67847c6ae99SBarry 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); 67947c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 68047c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 68147c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 68247c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 68347c6ae99SBarry Smith 68447c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 68547c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 68647c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 68747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 68847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 689e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 69047c6ae99SBarry Smith 69147c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 69247c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 69347c6ae99SBarry Smith l_c = (l/ratiol); 69447c6ae99SBarry Smith nc = 0; 69547c6ae99SBarry Smith /* one left and below; or we are right on it */ 696e3fbd1f4SBarry 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)); 697e3fbd1f4SBarry Smith cols[nc] = col_shift + idx_c[col]; 69847c6ae99SBarry Smith v[nc++] = 1.0; 69947c6ae99SBarry Smith 70047c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 70147c6ae99SBarry Smith } 70247c6ae99SBarry Smith } 70347c6ae99SBarry Smith } 70445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 70545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 70647c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 70747c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 70847c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 709fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 71047c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr); 71147c6ae99SBarry Smith PetscFunctionReturn(0); 71247c6ae99SBarry Smith } 71347c6ae99SBarry Smith 714e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A) 71547c6ae99SBarry Smith { 71647c6ae99SBarry Smith PetscErrorCode ierr; 7178ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof,l; 7188ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 719e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 7208ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c,Mz,mz; 72147c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok; 72247c6ae99SBarry Smith PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 72347c6ae99SBarry Smith PetscInt l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c; 72447c6ae99SBarry Smith PetscInt l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz; 72547c6ae99SBarry Smith PetscScalar v[8],x,y,z; 72647c6ae99SBarry Smith Mat mat; 727bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 72847c6ae99SBarry Smith 72947c6ae99SBarry Smith PetscFunctionBegin; 7301321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 7311321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 73247c6ae99SBarry Smith if (mx == Mx) { 73347c6ae99SBarry Smith ratioi = 1; 734bff4a2f0SMatthew G. Knepley } else if (bx == DM_BOUNDARY_PERIODIC) { 73547c6ae99SBarry Smith ratioi = mx/Mx; 73647c6ae99SBarry 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); 73747c6ae99SBarry Smith } else { 73847c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 73947c6ae99SBarry 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); 74047c6ae99SBarry Smith } 74147c6ae99SBarry Smith if (my == My) { 74247c6ae99SBarry Smith ratioj = 1; 743bff4a2f0SMatthew G. Knepley } else if (by == DM_BOUNDARY_PERIODIC) { 74447c6ae99SBarry Smith ratioj = my/My; 74547c6ae99SBarry 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); 74647c6ae99SBarry Smith } else { 74747c6ae99SBarry Smith ratioj = (my-1)/(My-1); 74847c6ae99SBarry 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); 74947c6ae99SBarry Smith } 75047c6ae99SBarry Smith if (mz == Mz) { 75147c6ae99SBarry Smith ratiok = 1; 752bff4a2f0SMatthew G. Knepley } else if (bz == DM_BOUNDARY_PERIODIC) { 75347c6ae99SBarry Smith ratiok = mz/Mz; 75447c6ae99SBarry 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); 75547c6ae99SBarry Smith } else { 75647c6ae99SBarry Smith ratiok = (mz-1)/(Mz-1); 75747c6ae99SBarry 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); 75847c6ae99SBarry Smith } 75947c6ae99SBarry Smith 760aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 761aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 76245b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 76345b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 76447c6ae99SBarry Smith 765aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 766aa219208SBarry 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); 76745b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 76845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 76947c6ae99SBarry Smith 77047c6ae99SBarry Smith /* create interpolation matrix, determining exact preallocation */ 771ce94432eSBarry Smith ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)dac),m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 77247c6ae99SBarry Smith /* loop over local fine grid nodes counting interpolating points */ 77347c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 77447c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 77547c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 77647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 777e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 77847c6ae99SBarry Smith i_c = (i/ratioi); 77947c6ae99SBarry Smith j_c = (j/ratioj); 78047c6ae99SBarry Smith l_c = (l/ratiok); 781aa219208SBarry 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\ 78247c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 783aa219208SBarry 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\ 78447c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 785aa219208SBarry 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\ 78647c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 78747c6ae99SBarry Smith 78847c6ae99SBarry Smith /* 78947c6ae99SBarry Smith Only include those interpolation points that are truly 79047c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 79147c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 79247c6ae99SBarry Smith */ 79347c6ae99SBarry Smith nc = 0; 794e3fbd1f4SBarry 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)); 795e3fbd1f4SBarry Smith cols[nc++] = idx_c[col]; 79647c6ae99SBarry Smith if (i_c*ratioi != i) { 797e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+1]; 79847c6ae99SBarry Smith } 79947c6ae99SBarry Smith if (j_c*ratioj != j) { 800e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c]; 80147c6ae99SBarry Smith } 80247c6ae99SBarry Smith if (l_c*ratiok != l) { 803e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c]; 80447c6ae99SBarry Smith } 80547c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 806e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c+1)]; 80747c6ae99SBarry Smith } 80847c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 809e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 81047c6ae99SBarry Smith } 81147c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 812e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 81347c6ae99SBarry Smith } 81447c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 815e3fbd1f4SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 81647c6ae99SBarry Smith } 81747c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 81847c6ae99SBarry Smith } 81947c6ae99SBarry Smith } 82047c6ae99SBarry Smith } 821ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dac),&mat);CHKERRQ(ierr); 82247c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr); 82347c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 82447c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 82547c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 82647c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 82747c6ae99SBarry Smith 82847c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 8292adb9dcfSBarry Smith if (!NEWVERSION) { 830b3bd94feSDave May 83147c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 83247c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 83347c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 83447c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 835e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 83647c6ae99SBarry Smith 83747c6ae99SBarry Smith i_c = (i/ratioi); 83847c6ae99SBarry Smith j_c = (j/ratioj); 83947c6ae99SBarry Smith l_c = (l/ratiok); 84047c6ae99SBarry Smith 84147c6ae99SBarry Smith /* 84247c6ae99SBarry Smith Only include those interpolation points that are truly 84347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 84447c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 84547c6ae99SBarry Smith */ 8466712e2f1SBarry Smith x = ((PetscReal)(i - i_c*ratioi))/((PetscReal)ratioi); 8476712e2f1SBarry Smith y = ((PetscReal)(j - j_c*ratioj))/((PetscReal)ratioj); 8486712e2f1SBarry Smith z = ((PetscReal)(l - l_c*ratiok))/((PetscReal)ratiok); 849b3bd94feSDave May 85047c6ae99SBarry Smith nc = 0; 85147c6ae99SBarry Smith /* one left and below; or we are right on it */ 852e3fbd1f4SBarry 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)); 85347c6ae99SBarry Smith 854e3fbd1f4SBarry Smith cols[nc] = idx_c[col]; 85547c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 85647c6ae99SBarry Smith 85747c6ae99SBarry Smith if (i_c*ratioi != i) { 858e3fbd1f4SBarry Smith cols[nc] = idx_c[col+1]; 85947c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 86047c6ae99SBarry Smith } 86147c6ae99SBarry Smith 86247c6ae99SBarry Smith if (j_c*ratioj != j) { 863e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c]; 86447c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 86547c6ae99SBarry Smith } 86647c6ae99SBarry Smith 86747c6ae99SBarry Smith if (l_c*ratiok != l) { 868e3fbd1f4SBarry Smith cols[nc] = idx_c[col+m_ghost_c*n_ghost_c]; 86947c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 87047c6ae99SBarry Smith } 87147c6ae99SBarry Smith 87247c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 873e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c+1)]; 87447c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 87547c6ae99SBarry Smith } 87647c6ae99SBarry Smith 87747c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 878e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; 87947c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 88047c6ae99SBarry Smith } 88147c6ae99SBarry Smith 88247c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 883e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; 88447c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 88547c6ae99SBarry Smith } 88647c6ae99SBarry Smith 88747c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 888e3fbd1f4SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; 88947c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 89047c6ae99SBarry Smith } 89147c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 89247c6ae99SBarry Smith } 89347c6ae99SBarry Smith } 89447c6ae99SBarry Smith } 895b3bd94feSDave May 896b3bd94feSDave May } else { 897b3bd94feSDave May PetscScalar *xi,*eta,*zeta; 898b3bd94feSDave May PetscInt li,nxi,lj,neta,lk,nzeta,n; 899b3bd94feSDave May PetscScalar Ni[8]; 900b3bd94feSDave May 901b3bd94feSDave May /* compute local coordinate arrays */ 902b3bd94feSDave May nxi = ratioi + 1; 903b3bd94feSDave May neta = ratioj + 1; 904b3bd94feSDave May nzeta = ratiok + 1; 905854ce69bSBarry Smith ierr = PetscMalloc1(nxi,&xi);CHKERRQ(ierr); 906854ce69bSBarry Smith ierr = PetscMalloc1(neta,&eta);CHKERRQ(ierr); 907854ce69bSBarry Smith ierr = PetscMalloc1(nzeta,&zeta);CHKERRQ(ierr); 9088865f1eaSKarl Rupp for (li=0; li<nxi; li++) xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 9098865f1eaSKarl Rupp for (lj=0; lj<neta; lj++) eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 9108865f1eaSKarl Rupp for (lk=0; lk<nzeta; lk++) zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1)); 911b3bd94feSDave May 912b3bd94feSDave May for (l=l_start; l<l_start+p_f; l++) { 913b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 914b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 915b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 916e3fbd1f4SBarry Smith row = idx_f[(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]; 917b3bd94feSDave May 918b3bd94feSDave May i_c = (i/ratioi); 919b3bd94feSDave May j_c = (j/ratioj); 920b3bd94feSDave May l_c = (l/ratiok); 921b3bd94feSDave May 922b3bd94feSDave May /* remainders */ 923b3bd94feSDave May li = i - ratioi * (i/ratioi); 9248865f1eaSKarl Rupp if (i==mx-1) li = nxi-1; 925b3bd94feSDave May lj = j - ratioj * (j/ratioj); 9268865f1eaSKarl Rupp if (j==my-1) lj = neta-1; 927b3bd94feSDave May lk = l - ratiok * (l/ratiok); 9288865f1eaSKarl Rupp if (l==mz-1) lk = nzeta-1; 929b3bd94feSDave May 930b3bd94feSDave May /* corners */ 931e3fbd1f4SBarry 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)); 932e3fbd1f4SBarry Smith cols[0] = idx_c[col]; 933b3bd94feSDave May Ni[0] = 1.0; 934b3bd94feSDave May if ((li==0) || (li==nxi-1)) { 935b3bd94feSDave May if ((lj==0) || (lj==neta-1)) { 936b3bd94feSDave May if ((lk==0) || (lk==nzeta-1)) { 937b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 938b3bd94feSDave May continue; 939b3bd94feSDave May } 940b3bd94feSDave May } 941b3bd94feSDave May } 942b3bd94feSDave May 943b3bd94feSDave May /* edges + interior */ 944b3bd94feSDave May /* remainders */ 9458865f1eaSKarl Rupp if (i==mx-1) i_c--; 9468865f1eaSKarl Rupp if (j==my-1) j_c--; 9478865f1eaSKarl Rupp if (l==mz-1) l_c--; 948b3bd94feSDave May 949e3fbd1f4SBarry 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)); 950e3fbd1f4SBarry Smith cols[0] = idx_c[col]; /* one left and below; or we are right on it */ 951e3fbd1f4SBarry Smith cols[1] = idx_c[col+1]; /* one right and below */ 952e3fbd1f4SBarry Smith cols[2] = idx_c[col+m_ghost_c]; /* one left and above */ 953e3fbd1f4SBarry Smith cols[3] = idx_c[col+(m_ghost_c+1)]; /* one right and above */ 954b3bd94feSDave May 955e3fbd1f4SBarry Smith cols[4] = idx_c[col+m_ghost_c*n_ghost_c]; /* one left and below and front; or we are right on it */ 956e3fbd1f4SBarry Smith cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)]; /* one right and below, and front */ 957e3fbd1f4SBarry Smith cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)]; /* one left and above and front*/ 958e3fbd1f4SBarry Smith cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)]; /* one right and above and front */ 959b3bd94feSDave May 960b3bd94feSDave May Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 961b3bd94feSDave May Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 962b3bd94feSDave May Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 963b3bd94feSDave May Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 964b3bd94feSDave May 965b3bd94feSDave May Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 966b3bd94feSDave May Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 967b3bd94feSDave May Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 968b3bd94feSDave May Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 969b3bd94feSDave May 970b3bd94feSDave May for (n=0; n<8; n++) { 9718865f1eaSKarl Rupp if (PetscAbsScalar(Ni[n])<1.0e-32) cols[n]=-1; 972b3bd94feSDave May } 973b3bd94feSDave May ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 974b3bd94feSDave May 975b3bd94feSDave May } 976b3bd94feSDave May } 977b3bd94feSDave May } 978b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 979b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 980b3bd94feSDave May ierr = PetscFree(zeta);CHKERRQ(ierr); 981b3bd94feSDave May } 98245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 98345b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 98447c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 98547c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 98647c6ae99SBarry Smith 98747c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 988fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 98947c6ae99SBarry Smith PetscFunctionReturn(0); 99047c6ae99SBarry Smith } 99147c6ae99SBarry Smith 992e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale) 99347c6ae99SBarry Smith { 99447c6ae99SBarry Smith PetscErrorCode ierr; 99547c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 996bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 997aa219208SBarry Smith DMDAStencilType stc,stf; 99847c6ae99SBarry Smith DM_DA *ddc = (DM_DA*)dac->data; 99947c6ae99SBarry Smith 100047c6ae99SBarry Smith PetscFunctionBegin; 100147c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 100247c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 100347c6ae99SBarry Smith PetscValidPointer(A,3); 100447c6ae99SBarry Smith if (scale) PetscValidPointer(scale,4); 100547c6ae99SBarry Smith 10061321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 10071321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1008*13903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1009*13903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1010*13903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 1011*13903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1012*13903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 101347c6ae99SBarry Smith if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 101447c6ae99SBarry 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"); 101547c6ae99SBarry 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"); 101647c6ae99SBarry Smith 1017aa219208SBarry Smith if (ddc->interptype == DMDA_Q1) { 101847c6ae99SBarry Smith if (dimc == 1) { 1019e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr); 102047c6ae99SBarry Smith } else if (dimc == 2) { 1021e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr); 102247c6ae99SBarry Smith } else if (dimc == 3) { 1023e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr); 1024ce94432eSBarry Smith } else SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 1025aa219208SBarry Smith } else if (ddc->interptype == DMDA_Q0) { 102647c6ae99SBarry Smith if (dimc == 1) { 1027e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr); 102847c6ae99SBarry Smith } else if (dimc == 2) { 1029e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr); 103047c6ae99SBarry Smith } else if (dimc == 3) { 1031e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr); 1032ce94432eSBarry Smith } else SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 103347c6ae99SBarry Smith } 103447c6ae99SBarry Smith if (scale) { 1035e727c939SJed Brown ierr = DMCreateInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr); 103647c6ae99SBarry Smith } 103747c6ae99SBarry Smith PetscFunctionReturn(0); 103847c6ae99SBarry Smith } 103947c6ae99SBarry Smith 1040e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_1D(DM dac,DM daf,VecScatter *inject) 10410bb2b966SJungho Lee { 10420bb2b966SJungho Lee PetscErrorCode ierr; 10438ea3bf28SBarry Smith PetscInt i,i_start,m_f,Mx,dof; 10448ea3bf28SBarry Smith const PetscInt *idx_f; 1045e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f; 10468ea3bf28SBarry Smith PetscInt m_ghost,m_ghost_c; 10470bb2b966SJungho Lee PetscInt row,i_start_ghost,mx,m_c,nc,ratioi; 10480bb2b966SJungho Lee PetscInt i_start_c,i_start_ghost_c; 10490bb2b966SJungho Lee PetscInt *cols; 1050bff4a2f0SMatthew G. Knepley DMBoundaryType bx; 10510bb2b966SJungho Lee Vec vecf,vecc; 10520bb2b966SJungho Lee IS isf; 10530bb2b966SJungho Lee 10540bb2b966SJungho Lee PetscFunctionBegin; 10550bb2b966SJungho Lee ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 10560bb2b966SJungho Lee ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1057bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 10580bb2b966SJungho Lee ratioi = mx/Mx; 10590bb2b966SJungho 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); 10600bb2b966SJungho Lee } else { 10610bb2b966SJungho Lee ratioi = (mx-1)/(Mx-1); 10620bb2b966SJungho 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); 10630bb2b966SJungho Lee } 10640bb2b966SJungho Lee 10650bb2b966SJungho Lee ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 10660bb2b966SJungho Lee ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 106745b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 106845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 10690bb2b966SJungho Lee 10700bb2b966SJungho Lee ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 10710bb2b966SJungho Lee ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 10720bb2b966SJungho Lee 10730bb2b966SJungho Lee 10740bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 10750bb2b966SJungho Lee nc = 0; 1076785e854fSJed Brown ierr = PetscMalloc1(m_f,&cols);CHKERRQ(ierr); 10770bb2b966SJungho Lee 10780bb2b966SJungho Lee 10790bb2b966SJungho Lee for (i=i_start_c; i<i_start_c+m_c; i++) { 10800bb2b966SJungho Lee PetscInt i_f = i*ratioi; 10810bb2b966SJungho Lee 10828865f1eaSKarl 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); 10838865f1eaSKarl Rupp 1084e3fbd1f4SBarry Smith row = idx_f[(i_f-i_start_ghost)]; 1085e3fbd1f4SBarry Smith cols[nc++] = row; 10860bb2b966SJungho Lee } 10870bb2b966SJungho Lee 108845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1089ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 10900bb2b966SJungho Lee ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 10910bb2b966SJungho Lee ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 10920298fd71SBarry Smith ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 10930bb2b966SJungho Lee ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 10940bb2b966SJungho Lee ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 10950bb2b966SJungho Lee ierr = ISDestroy(&isf);CHKERRQ(ierr); 10960bb2b966SJungho Lee PetscFunctionReturn(0); 10970bb2b966SJungho Lee } 10980bb2b966SJungho Lee 1099e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject) 110047c6ae99SBarry Smith { 110147c6ae99SBarry Smith PetscErrorCode ierr; 11028ea3bf28SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,dof; 11038ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1104e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 11058ea3bf28SBarry Smith PetscInt m_ghost,n_ghost,m_ghost_c,n_ghost_c; 110647c6ae99SBarry Smith PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; 1107076202ddSJed Brown PetscInt i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 110847c6ae99SBarry Smith PetscInt *cols; 1109bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by; 111047c6ae99SBarry Smith Vec vecf,vecc; 111147c6ae99SBarry Smith IS isf; 111247c6ae99SBarry Smith 111347c6ae99SBarry Smith PetscFunctionBegin; 11141321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 11151321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1116bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 111747c6ae99SBarry Smith ratioi = mx/Mx; 111847c6ae99SBarry 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); 111947c6ae99SBarry Smith } else { 112047c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 112147c6ae99SBarry 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); 112247c6ae99SBarry Smith } 1123bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 112447c6ae99SBarry Smith ratioj = my/My; 112547c6ae99SBarry 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); 112647c6ae99SBarry Smith } else { 112747c6ae99SBarry Smith ratioj = (my-1)/(My-1); 112847c6ae99SBarry 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); 112947c6ae99SBarry Smith } 113047c6ae99SBarry Smith 1131aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 1132aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 113345b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 113445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 113547c6ae99SBarry Smith 1136aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 1137aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 113845b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 113945b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 114047c6ae99SBarry Smith 114147c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 114247c6ae99SBarry Smith nc = 0; 1143785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f,&cols);CHKERRQ(ierr); 1144076202ddSJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1145076202ddSJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1146076202ddSJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj; 1147076202ddSJed 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\ 1148076202ddSJed Brown j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1149076202ddSJed 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\ 1150076202ddSJed Brown i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1151e3fbd1f4SBarry Smith row = idx_f[(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 1152e3fbd1f4SBarry Smith cols[nc++] = row; 115347c6ae99SBarry Smith } 115447c6ae99SBarry Smith } 115545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 115645b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 115747c6ae99SBarry Smith 1158ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 11599a42bb27SBarry Smith ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 11609a42bb27SBarry Smith ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 11610298fd71SBarry Smith ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 11629a42bb27SBarry Smith ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 11639a42bb27SBarry Smith ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1164fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 116547c6ae99SBarry Smith PetscFunctionReturn(0); 116647c6ae99SBarry Smith } 116747c6ae99SBarry Smith 1168e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject) 1169b1757049SJed Brown { 1170b1757049SJed Brown PetscErrorCode ierr; 1171b1757049SJed Brown PetscInt i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz; 1172b1757049SJed Brown PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c; 1173b1757049SJed Brown PetscInt i_start_ghost,j_start_ghost,k_start_ghost; 1174b1757049SJed Brown PetscInt mx,my,mz,ratioi,ratioj,ratiok; 1175b1757049SJed Brown PetscInt i_start_c,j_start_c,k_start_c; 1176b1757049SJed Brown PetscInt m_c,n_c,p_c; 1177b1757049SJed Brown PetscInt i_start_ghost_c,j_start_ghost_c,k_start_ghost_c; 1178b1757049SJed Brown PetscInt row,nc,dof; 11798ea3bf28SBarry Smith const PetscInt *idx_c,*idx_f; 1180e3fbd1f4SBarry Smith ISLocalToGlobalMapping ltog_f,ltog_c; 1181b1757049SJed Brown PetscInt *cols; 1182bff4a2f0SMatthew G. Knepley DMBoundaryType bx,by,bz; 1183b1757049SJed Brown Vec vecf,vecc; 1184b1757049SJed Brown IS isf; 1185b1757049SJed Brown 1186b1757049SJed Brown PetscFunctionBegin; 11871321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 11881321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1189b1757049SJed Brown 1190bff4a2f0SMatthew G. Knepley if (bx == DM_BOUNDARY_PERIODIC) { 1191b1757049SJed Brown ratioi = mx/Mx; 1192b1757049SJed 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); 1193b1757049SJed Brown } else { 1194b1757049SJed Brown ratioi = (mx-1)/(Mx-1); 1195b1757049SJed 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); 1196b1757049SJed Brown } 1197bff4a2f0SMatthew G. Knepley if (by == DM_BOUNDARY_PERIODIC) { 1198b1757049SJed Brown ratioj = my/My; 1199b1757049SJed 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); 1200b1757049SJed Brown } else { 1201b1757049SJed Brown ratioj = (my-1)/(My-1); 1202b1757049SJed 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); 1203b1757049SJed Brown } 1204bff4a2f0SMatthew G. Knepley if (bz == DM_BOUNDARY_PERIODIC) { 1205b1757049SJed Brown ratiok = mz/Mz; 1206b1757049SJed 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); 1207b1757049SJed Brown } else { 1208b1757049SJed Brown ratiok = (mz-1)/(Mz-1); 1209b1757049SJed 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); 1210b1757049SJed Brown } 1211b1757049SJed Brown 1212b1757049SJed Brown ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1213b1757049SJed Brown ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 121445b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<og_f);CHKERRQ(ierr); 121545b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 1216b1757049SJed Brown 1217b1757049SJed Brown ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1218b1757049SJed 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); 121945b6f7e9SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<og_c);CHKERRQ(ierr); 122045b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1221b1757049SJed Brown 1222b1757049SJed Brown 1223b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1224b1757049SJed Brown nc = 0; 1225785e854fSJed Brown ierr = PetscMalloc1(n_f*m_f*p_f,&cols);CHKERRQ(ierr); 1226b1757049SJed Brown for (k=k_start_c; k<k_start_c+p_c; k++) { 1227b1757049SJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1228b1757049SJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1229b1757049SJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok; 1230b1757049SJed 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 " 1231b1757049SJed Brown "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost); 1232b1757049SJed 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 " 1233b1757049SJed Brown "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1234b1757049SJed 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 " 1235b1757049SJed Brown "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1236e3fbd1f4SBarry 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))]; 1237e3fbd1f4SBarry Smith cols[nc++] = row; 1238b1757049SJed Brown } 1239b1757049SJed Brown } 1240b1757049SJed Brown } 124145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_f,&idx_f);CHKERRQ(ierr); 124245b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockIndices(ltog_c,&idx_c);CHKERRQ(ierr); 1243b1757049SJed Brown 1244ce94432eSBarry Smith ierr = ISCreateBlock(PetscObjectComm((PetscObject)daf),dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 1245b1757049SJed Brown ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 1246b1757049SJed Brown ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 12470298fd71SBarry Smith ierr = VecScatterCreate(vecf,isf,vecc,NULL,inject);CHKERRQ(ierr); 1248b1757049SJed Brown ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 1249b1757049SJed Brown ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1250fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 1251b1757049SJed Brown PetscFunctionReturn(0); 1252b1757049SJed Brown } 1253b1757049SJed Brown 12546dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_DA(DM dac,DM daf,Mat *mat) 125547c6ae99SBarry Smith { 125647c6ae99SBarry Smith PetscErrorCode ierr; 125747c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1258bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1259aa219208SBarry Smith DMDAStencilType stc,stf; 126060c16ac1SBarry Smith VecScatter inject = NULL; 126147c6ae99SBarry Smith 126247c6ae99SBarry Smith PetscFunctionBegin; 126347c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 126447c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 12656dbf9973SLawrence Mitchell PetscValidPointer(mat,3); 126647c6ae99SBarry Smith 12671321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 12681321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1269*13903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1270*13903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1271*13903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 1272*13903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1273*13903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 127447c6ae99SBarry Smith if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 127547c6ae99SBarry Smith if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 127647c6ae99SBarry Smith if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 127747c6ae99SBarry Smith 12780bb2b966SJungho Lee if (dimc == 1) { 12796dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_1D(dac,daf,&inject);CHKERRQ(ierr); 12800bb2b966SJungho Lee } else if (dimc == 2) { 12816dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_2D(dac,daf,&inject);CHKERRQ(ierr); 1282b1757049SJed Brown } else if (dimc == 3) { 12836dbf9973SLawrence Mitchell ierr = DMCreateInjection_DA_3D(dac,daf,&inject);CHKERRQ(ierr); 128447c6ae99SBarry Smith } 12856dbf9973SLawrence Mitchell ierr = MatCreateScatter(PetscObjectComm((PetscObject)inject), inject, mat);CHKERRQ(ierr); 12866dbf9973SLawrence Mitchell ierr = VecScatterDestroy(&inject);CHKERRQ(ierr); 128747c6ae99SBarry Smith PetscFunctionReturn(0); 128847c6ae99SBarry Smith } 128947c6ae99SBarry Smith 1290e727c939SJed Brown PetscErrorCode DMCreateAggregates_DA(DM dac,DM daf,Mat *rest) 129147c6ae99SBarry Smith { 129247c6ae99SBarry Smith PetscErrorCode ierr; 129347c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc; 129447c6ae99SBarry Smith PetscInt dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 1295bff4a2f0SMatthew G. Knepley DMBoundaryType bxc,byc,bzc,bxf,byf,bzf; 1296aa219208SBarry Smith DMDAStencilType stc,stf; 129747c6ae99SBarry Smith PetscInt i,j,l; 129847c6ae99SBarry Smith PetscInt i_start,j_start,l_start, m_f,n_f,p_f; 129947c6ae99SBarry Smith PetscInt i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost; 13008ea3bf28SBarry Smith const PetscInt *idx_f; 130147c6ae99SBarry Smith PetscInt i_c,j_c,l_c; 130247c6ae99SBarry Smith PetscInt i_start_c,j_start_c,l_start_c, m_c,n_c,p_c; 130347c6ae99SBarry Smith PetscInt i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c; 13048ea3bf28SBarry Smith const PetscInt *idx_c; 130547c6ae99SBarry Smith PetscInt d; 130647c6ae99SBarry Smith PetscInt a; 130747c6ae99SBarry Smith PetscInt max_agg_size; 130847c6ae99SBarry Smith PetscInt *fine_nodes; 130947c6ae99SBarry Smith PetscScalar *one_vec; 131047c6ae99SBarry Smith PetscInt fn_idx; 1311565245c5SBarry Smith ISLocalToGlobalMapping ltogmf,ltogmc; 131247c6ae99SBarry Smith 131347c6ae99SBarry Smith PetscFunctionBegin; 131447c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 131547c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 131647c6ae99SBarry Smith PetscValidPointer(rest,3); 131747c6ae99SBarry Smith 13181321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 13191321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1320*13903a91SSatish Balay if (dimc != dimf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf); 1321*13903a91SSatish Balay if (dofc != doff) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff); 1322*13903a91SSatish Balay if (sc != sf) SETERRQ2(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf); 1323*13903a91SSatish Balay if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs"); 1324*13903a91SSatish Balay if (stc != stf) SETERRQ(PetscObjectComm((PetscObject)daf),PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs"); 132547c6ae99SBarry Smith 132647c6ae99SBarry 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); 132747c6ae99SBarry 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); 132847c6ae99SBarry 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); 132947c6ae99SBarry Smith 133047c6ae99SBarry Smith if (Pc < 0) Pc = 1; 133147c6ae99SBarry Smith if (Pf < 0) Pf = 1; 133247c6ae99SBarry Smith if (Nc < 0) Nc = 1; 133347c6ae99SBarry Smith if (Nf < 0) Nf = 1; 133447c6ae99SBarry Smith 1335aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1336aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1337565245c5SBarry Smith 1338565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(daf,<ogmf);CHKERRQ(ierr); 1339565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmf,&idx_f);CHKERRQ(ierr); 134047c6ae99SBarry Smith 1341aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1342aa219208SBarry 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); 1343565245c5SBarry Smith 1344565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(dac,<ogmc);CHKERRQ(ierr); 1345565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltogmc,&idx_c);CHKERRQ(ierr); 134647c6ae99SBarry Smith 134747c6ae99SBarry Smith /* 134847c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 134947c6ae99SBarry Smith for dimension 1 and 2 respectively. 135047c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 135147c6ae99SBarry Smith and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate. 135247c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 135347c6ae99SBarry Smith */ 135447c6ae99SBarry Smith 135547c6ae99SBarry Smith max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1); 135647c6ae99SBarry Smith 135747c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 1358ce94432eSBarry 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, 13590298fd71SBarry Smith max_agg_size, NULL, max_agg_size, NULL, rest);CHKERRQ(ierr); 136047c6ae99SBarry Smith 136147c6ae99SBarry Smith /* store nodes in the fine grid here */ 1362dcca6d9dSJed Brown ierr = PetscMalloc2(max_agg_size, &one_vec,max_agg_size, &fine_nodes);CHKERRQ(ierr); 136347c6ae99SBarry Smith for (i=0; i<max_agg_size; i++) one_vec[i] = 1.0; 136447c6ae99SBarry Smith 136547c6ae99SBarry Smith /* loop over all coarse nodes */ 136647c6ae99SBarry Smith for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) { 136747c6ae99SBarry Smith for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) { 136847c6ae99SBarry Smith for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) { 136947c6ae99SBarry Smith for (d=0; d<dofc; d++) { 137047c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 137147c6ae99SBarry 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; 137247c6ae99SBarry Smith 137347c6ae99SBarry Smith fn_idx = 0; 137447c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 137547c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 137647c6ae99SBarry Smith (same for other dimensions) 137747c6ae99SBarry Smith */ 137847c6ae99SBarry Smith for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) { 137947c6ae99SBarry Smith for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) { 138047c6ae99SBarry Smith for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) { 138147c6ae99SBarry 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; 138247c6ae99SBarry Smith fn_idx++; 138347c6ae99SBarry Smith } 138447c6ae99SBarry Smith } 138547c6ae99SBarry Smith } 138647c6ae99SBarry Smith /* add all these points to one aggregate */ 138747c6ae99SBarry Smith ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr); 138847c6ae99SBarry Smith } 138947c6ae99SBarry Smith } 139047c6ae99SBarry Smith } 139147c6ae99SBarry Smith } 1392565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmf,&idx_f);CHKERRQ(ierr); 1393565245c5SBarry Smith ierr = ISLocalToGlobalMappingRestoreIndices(ltogmc,&idx_c);CHKERRQ(ierr); 139447c6ae99SBarry Smith ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr); 139547c6ae99SBarry Smith ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 139647c6ae99SBarry Smith ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 139747c6ae99SBarry Smith PetscFunctionReturn(0); 139847c6ae99SBarry Smith } 1399