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 14c6db04a5SJed Brown #include <private/daimpl.h> /*I "petscdmda.h" I*/ 1547c6ae99SBarry Smith 1647c6ae99SBarry Smith #undef __FUNCT__ 17e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolationScale" 1847c6ae99SBarry Smith /*@ 19e727c939SJed Brown DMCreateInterpolationScale - Forms L = R*1/diag(R*1) - L.*v is like a coarse grid average of the 2047c6ae99SBarry Smith nearby fine grid points. 2147c6ae99SBarry Smith 2247c6ae99SBarry Smith Input Parameters: 2347c6ae99SBarry Smith + dac - DM that defines a coarse mesh 2447c6ae99SBarry Smith . daf - DM that defines a fine mesh 2547c6ae99SBarry Smith - mat - the restriction (or interpolation operator) from fine to coarse 2647c6ae99SBarry Smith 2747c6ae99SBarry Smith Output Parameter: 2847c6ae99SBarry Smith . scale - the scaled vector 2947c6ae99SBarry Smith 3047c6ae99SBarry Smith Level: developer 3147c6ae99SBarry Smith 32e727c939SJed Brown .seealso: DMCreateInterpolation() 3347c6ae99SBarry Smith 3447c6ae99SBarry Smith @*/ 35e727c939SJed Brown PetscErrorCode DMCreateInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale) 3647c6ae99SBarry Smith { 3747c6ae99SBarry Smith PetscErrorCode ierr; 3847c6ae99SBarry Smith Vec fine; 3947c6ae99SBarry Smith PetscScalar one = 1.0; 4047c6ae99SBarry Smith 4147c6ae99SBarry Smith PetscFunctionBegin; 4247c6ae99SBarry Smith ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr); 4347c6ae99SBarry Smith ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr); 4447c6ae99SBarry Smith ierr = VecSet(fine,one);CHKERRQ(ierr); 4547c6ae99SBarry Smith ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr); 46fcfd50ebSBarry Smith ierr = VecDestroy(&fine);CHKERRQ(ierr); 4747c6ae99SBarry Smith ierr = VecReciprocal(*scale);CHKERRQ(ierr); 4847c6ae99SBarry Smith PetscFunctionReturn(0); 4947c6ae99SBarry Smith } 5047c6ae99SBarry Smith 5147c6ae99SBarry Smith #undef __FUNCT__ 52e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_1D_Q1" 53e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A) 5447c6ae99SBarry Smith { 5547c6ae99SBarry Smith PetscErrorCode ierr; 5647c6ae99SBarry Smith PetscInt i,i_start,m_f,Mx,*idx_f; 5747c6ae99SBarry Smith PetscInt m_ghost,*idx_c,m_ghost_c; 5847c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 5947c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 6085afcc9aSBarry Smith PetscScalar v[2],x; 6147c6ae99SBarry Smith Mat mat; 621321219cSEthan Coon DMDABoundaryType bx; 6347c6ae99SBarry Smith 6447c6ae99SBarry Smith PetscFunctionBegin; 651321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 661321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 671321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 6847c6ae99SBarry Smith ratio = mx/Mx; 6947c6ae99SBarry 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); 7047c6ae99SBarry Smith } else { 7147c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 7247c6ae99SBarry 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); 7347c6ae99SBarry Smith } 7447c6ae99SBarry Smith 75aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 76aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 77aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&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); 81aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 8247c6ae99SBarry Smith 8347c6ae99SBarry Smith /* create interpolation matrix */ 8447c6ae99SBarry Smith ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr); 8547c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 8647c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 8747c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr); 88*b7f7bd40SJed Brown ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,1,PETSC_NULL);CHKERRQ(ierr); 8947c6ae99SBarry Smith 9047c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 9185afcc9aSBarry Smith if (!NEWVERSION) { 92b3bd94feSDave May 9347c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 9447c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 9547c6ae99SBarry Smith row = idx_f[dof*(i-i_start_ghost)]/dof; 9647c6ae99SBarry Smith 9747c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 98aa219208SBarry 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\ 9947c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 10047c6ae99SBarry Smith 10147c6ae99SBarry Smith /* 10247c6ae99SBarry Smith Only include those interpolation points that are truly 10347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 10447c6ae99SBarry Smith in x direction; since they have no right neighbor 10547c6ae99SBarry Smith */ 10647c6ae99SBarry Smith x = ((double)(i - i_c*ratio))/((double)ratio); 10747c6ae99SBarry Smith nc = 0; 10847c6ae99SBarry Smith /* one left and below; or we are right on it */ 10947c6ae99SBarry Smith col = dof*(i_c-i_start_ghost_c); 11047c6ae99SBarry Smith cols[nc] = idx_c[col]/dof; 11147c6ae99SBarry Smith v[nc++] = - x + 1.0; 11247c6ae99SBarry Smith /* one right? */ 11347c6ae99SBarry Smith if (i_c*ratio != i) { 11447c6ae99SBarry Smith cols[nc] = idx_c[col+dof]/dof; 11547c6ae99SBarry Smith v[nc++] = x; 11647c6ae99SBarry Smith } 11747c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 11847c6ae99SBarry Smith } 119b3bd94feSDave May 120b3bd94feSDave May } else { 121b3bd94feSDave May PetscScalar *xi; 122b3bd94feSDave May PetscInt li,nxi,n; 123b3bd94feSDave May PetscScalar Ni[2]; 124b3bd94feSDave May 125b3bd94feSDave May /* compute local coordinate arrays */ 126b3bd94feSDave May nxi = ratio + 1; 127b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr); 128b3bd94feSDave May for (li=0; li<nxi; li++) { 12952218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 130b3bd94feSDave May } 131b3bd94feSDave May 132b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 133b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 134b3bd94feSDave May row = idx_f[dof*(i-i_start_ghost)]/dof; 135b3bd94feSDave May 136b3bd94feSDave May i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 137b3bd94feSDave 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\ 138b3bd94feSDave May i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 139b3bd94feSDave May 140b3bd94feSDave May /* remainders */ 141b3bd94feSDave May li = i - ratio * (i/ratio); 142b3bd94feSDave May if (i==mx-1){ li = nxi-1; } 143b3bd94feSDave May 144b3bd94feSDave May /* corners */ 145b3bd94feSDave May col = dof*(i_c-i_start_ghost_c); 146b3bd94feSDave May cols[0] = idx_c[col]/dof; 147b3bd94feSDave May Ni[0] = 1.0; 148b3bd94feSDave May if ( (li==0) || (li==nxi-1) ) { 149b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 150b3bd94feSDave May continue; 151b3bd94feSDave May } 152b3bd94feSDave May 153b3bd94feSDave May /* edges + interior */ 154b3bd94feSDave May /* remainders */ 155b3bd94feSDave May if (i==mx-1){ i_c--; } 156b3bd94feSDave May 157b3bd94feSDave May col = dof*(i_c-i_start_ghost_c); 158b3bd94feSDave May cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */ 159b3bd94feSDave May cols[1] = idx_c[col+dof]/dof; 160b3bd94feSDave May 161b3bd94feSDave May Ni[0] = 0.5*(1.0-xi[li]); 162b3bd94feSDave May Ni[1] = 0.5*(1.0+xi[li]); 163b3bd94feSDave May for (n=0; n<2; n++) { 164b3bd94feSDave May if( PetscAbsScalar(Ni[n])<1.0e-32) { cols[n]=-1; } 165b3bd94feSDave May } 166b3bd94feSDave May ierr = MatSetValues(mat,1,&row,2,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 167b3bd94feSDave May } 168b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 169b3bd94feSDave May } 17047c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17147c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17247c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 173fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 17447c6ae99SBarry Smith PetscFunctionReturn(0); 17547c6ae99SBarry Smith } 17647c6ae99SBarry Smith 17747c6ae99SBarry Smith #undef __FUNCT__ 178e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_1D_Q0" 179e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A) 18047c6ae99SBarry Smith { 18147c6ae99SBarry Smith PetscErrorCode ierr; 18247c6ae99SBarry Smith PetscInt i,i_start,m_f,Mx,*idx_f; 18347c6ae99SBarry Smith PetscInt m_ghost,*idx_c,m_ghost_c; 18447c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 18547c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 18647c6ae99SBarry Smith PetscScalar v[2],x; 18747c6ae99SBarry Smith Mat mat; 1881321219cSEthan Coon DMDABoundaryType bx; 18947c6ae99SBarry Smith 19047c6ae99SBarry Smith PetscFunctionBegin; 1911321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 1921321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1931321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 19447c6ae99SBarry Smith ratio = mx/Mx; 19547c6ae99SBarry 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); 19647c6ae99SBarry Smith } else { 19747c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 19847c6ae99SBarry 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); 19947c6ae99SBarry Smith } 20047c6ae99SBarry Smith 201aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 202aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 203aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 20447c6ae99SBarry Smith 205aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 206aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 207aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 20847c6ae99SBarry Smith 20947c6ae99SBarry Smith /* create interpolation matrix */ 21047c6ae99SBarry Smith ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr); 21147c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 21247c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 21347c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr); 21447c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 21547c6ae99SBarry Smith 21647c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 21747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 21847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 21947c6ae99SBarry Smith row = idx_f[dof*(i-i_start_ghost)]/dof; 22047c6ae99SBarry Smith 22147c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 22247c6ae99SBarry Smith 22347c6ae99SBarry Smith /* 22447c6ae99SBarry Smith Only include those interpolation points that are truly 22547c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 22647c6ae99SBarry Smith in x direction; since they have no right neighbor 22747c6ae99SBarry Smith */ 22847c6ae99SBarry Smith x = ((double)(i - i_c*ratio))/((double)ratio); 22947c6ae99SBarry Smith nc = 0; 23047c6ae99SBarry Smith /* one left and below; or we are right on it */ 23147c6ae99SBarry Smith col = dof*(i_c-i_start_ghost_c); 23247c6ae99SBarry Smith cols[nc] = idx_c[col]/dof; 23347c6ae99SBarry Smith v[nc++] = - x + 1.0; 23447c6ae99SBarry Smith /* one right? */ 23547c6ae99SBarry Smith if (i_c*ratio != i) { 23647c6ae99SBarry Smith cols[nc] = idx_c[col+dof]/dof; 23747c6ae99SBarry Smith v[nc++] = x; 23847c6ae99SBarry Smith } 23947c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 24047c6ae99SBarry Smith } 24147c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 24247c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 24347c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 244fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 24547c6ae99SBarry Smith ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr); 24647c6ae99SBarry Smith PetscFunctionReturn(0); 24747c6ae99SBarry Smith } 24847c6ae99SBarry Smith 24947c6ae99SBarry Smith #undef __FUNCT__ 250e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_2D_Q1" 251e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A) 25247c6ae99SBarry Smith { 25347c6ae99SBarry Smith PetscErrorCode ierr; 25447c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof; 25547c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz; 25647c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 25747c6ae99SBarry 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; 25847c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 25947c6ae99SBarry Smith PetscScalar v[4],x,y; 26047c6ae99SBarry Smith Mat mat; 2611321219cSEthan Coon DMDABoundaryType bx,by; 26247c6ae99SBarry Smith 26347c6ae99SBarry Smith PetscFunctionBegin; 2641321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 2651321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 2661321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 26747c6ae99SBarry Smith ratioi = mx/Mx; 26847c6ae99SBarry 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); 26947c6ae99SBarry Smith } else { 27047c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 27147c6ae99SBarry 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); 27247c6ae99SBarry Smith } 2731321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC){ 27447c6ae99SBarry Smith ratioj = my/My; 27547c6ae99SBarry 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); 27647c6ae99SBarry Smith } else { 27747c6ae99SBarry Smith ratioj = (my-1)/(My-1); 27847c6ae99SBarry 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); 27947c6ae99SBarry Smith } 28047c6ae99SBarry Smith 28147c6ae99SBarry Smith 282aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 283aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 284aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 28547c6ae99SBarry Smith 286aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 287aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 288aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 28947c6ae99SBarry Smith 29047c6ae99SBarry Smith /* 291aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 29247c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 29347c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 29447c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 29547c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 29647c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 29747c6ae99SBarry Smith 29847c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 29947c6ae99SBarry Smith */ 30047c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr); 30147c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr); 30247c6ae99SBarry Smith ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr); 30347c6ae99SBarry Smith col_scale = size_f/size_c; 30447c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 30547c6ae99SBarry Smith 30647c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 30747c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 30847c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 30947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 31047c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 31147c6ae99SBarry Smith 31247c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 31347c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 31447c6ae99SBarry Smith 315aa219208SBarry 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\ 31647c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 317aa219208SBarry 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\ 31847c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 31947c6ae99SBarry Smith 32047c6ae99SBarry Smith /* 32147c6ae99SBarry Smith Only include those interpolation points that are truly 32247c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 32347c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 32447c6ae99SBarry Smith */ 32547c6ae99SBarry Smith nc = 0; 32647c6ae99SBarry Smith /* one left and below; or we are right on it */ 32747c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 32847c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col]/dof; 32947c6ae99SBarry Smith /* one right and below */ 33047c6ae99SBarry Smith if (i_c*ratioi != i) { 33147c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col+dof]/dof; 33247c6ae99SBarry Smith } 33347c6ae99SBarry Smith /* one left and above */ 33447c6ae99SBarry Smith if (j_c*ratioj != j) { 33547c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col+m_ghost_c*dof]/dof; 33647c6ae99SBarry Smith } 33747c6ae99SBarry Smith /* one right and above */ 3380c82216cSJed Brown if (i_c*ratioi != i && j_c*ratioj != j) { 33947c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; 34047c6ae99SBarry Smith } 34147c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 34247c6ae99SBarry Smith } 34347c6ae99SBarry Smith } 34447c6ae99SBarry Smith ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr); 34547c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 34647c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 34747c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 34847c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 34947c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 35047c6ae99SBarry Smith 35147c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 35285afcc9aSBarry Smith if (!NEWVERSION) { 353b3bd94feSDave May 35447c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 35547c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 35647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 35747c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 35847c6ae99SBarry Smith 35947c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 36047c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 36147c6ae99SBarry Smith 36247c6ae99SBarry Smith /* 36347c6ae99SBarry Smith Only include those interpolation points that are truly 36447c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 36547c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 36647c6ae99SBarry Smith */ 36747c6ae99SBarry Smith x = ((double)(i - i_c*ratioi))/((double)ratioi); 36847c6ae99SBarry Smith y = ((double)(j - j_c*ratioj))/((double)ratioj); 369b3bd94feSDave May 37047c6ae99SBarry Smith nc = 0; 37147c6ae99SBarry Smith /* one left and below; or we are right on it */ 37247c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 37347c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col]/dof; 37447c6ae99SBarry Smith v[nc++] = x*y - x - y + 1.0; 37547c6ae99SBarry Smith /* one right and below */ 37647c6ae99SBarry Smith if (i_c*ratioi != i) { 37747c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col+dof]/dof; 37847c6ae99SBarry Smith v[nc++] = -x*y + x; 37947c6ae99SBarry Smith } 38047c6ae99SBarry Smith /* one left and above */ 38147c6ae99SBarry Smith if (j_c*ratioj != j) { 38247c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col+m_ghost_c*dof]/dof; 38347c6ae99SBarry Smith v[nc++] = -x*y + y; 38447c6ae99SBarry Smith } 38547c6ae99SBarry Smith /* one right and above */ 38647c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 38747c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; 38847c6ae99SBarry Smith v[nc++] = x*y; 38947c6ae99SBarry Smith } 39047c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 39147c6ae99SBarry Smith } 39247c6ae99SBarry Smith } 393b3bd94feSDave May 394b3bd94feSDave May } else { 395b3bd94feSDave May PetscScalar Ni[4]; 396b3bd94feSDave May PetscScalar *xi,*eta; 397b3bd94feSDave May PetscInt li,nxi,lj,neta; 398b3bd94feSDave May 399b3bd94feSDave May /* compute local coordinate arrays */ 400b3bd94feSDave May nxi = ratioi + 1; 401b3bd94feSDave May neta = ratioj + 1; 402b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr); 403b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr); 404b3bd94feSDave May for (li=0; li<nxi; li++) { 40552218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 406b3bd94feSDave May } 407b3bd94feSDave May for (lj=0; lj<neta; lj++) { 40852218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 409b3bd94feSDave May } 410b3bd94feSDave May 411b3bd94feSDave May /* loop over local fine grid nodes setting interpolation for those*/ 412b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 413b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 414b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 415b3bd94feSDave May row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 416b3bd94feSDave May 417b3bd94feSDave May i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 418b3bd94feSDave May j_c = (j/ratioj); /* coarse grid node below fine grid node */ 419b3bd94feSDave May 420b3bd94feSDave May /* remainders */ 421b3bd94feSDave May li = i - ratioi * (i/ratioi); 422b3bd94feSDave May if (i==mx-1){ li = nxi-1; } 423b3bd94feSDave May lj = j - ratioj * (j/ratioj); 424b3bd94feSDave May if (j==my-1){ lj = neta-1; } 425b3bd94feSDave May 426b3bd94feSDave May /* corners */ 427b3bd94feSDave May col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 428b3bd94feSDave May cols[0] = col_shift + idx_c[col]/dof; /* left, below */ 429b3bd94feSDave May Ni[0] = 1.0; 430b3bd94feSDave May if ( (li==0) || (li==nxi-1) ) { 431b3bd94feSDave May if ( (lj==0) || (lj==neta-1) ) { 432b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 433b3bd94feSDave May continue; 434b3bd94feSDave May } 435b3bd94feSDave May } 436b3bd94feSDave May 437b3bd94feSDave May /* edges + interior */ 438b3bd94feSDave May /* remainders */ 439b3bd94feSDave May if (i==mx-1){ i_c--; } 440b3bd94feSDave May if (j==my-1){ j_c--; } 441b3bd94feSDave May 442b3bd94feSDave May col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 443b3bd94feSDave May cols[0] = col_shift + idx_c[col]/dof; /* left, below */ 444b3bd94feSDave May cols[1] = col_shift + idx_c[col+dof]/dof; /* right, below */ 445b3bd94feSDave May cols[2] = col_shift + idx_c[col+m_ghost_c*dof]/dof; /* left, above */ 446b3bd94feSDave May cols[3] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; /* right, above */ 447b3bd94feSDave May 448b3bd94feSDave May Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]); 449b3bd94feSDave May Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]); 450b3bd94feSDave May Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]); 451b3bd94feSDave May Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]); 452b3bd94feSDave May 453b3bd94feSDave May nc = 0; 454b3bd94feSDave May if( PetscAbsScalar(Ni[0])<1.0e-32) { cols[0]=-1; } 455b3bd94feSDave May if( PetscAbsScalar(Ni[1])<1.0e-32) { cols[1]=-1; } 456b3bd94feSDave May if( PetscAbsScalar(Ni[2])<1.0e-32) { cols[2]=-1; } 457b3bd94feSDave May if( PetscAbsScalar(Ni[3])<1.0e-32) { cols[3]=-1; } 458b3bd94feSDave May 459b3bd94feSDave May ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 460b3bd94feSDave May } 461b3bd94feSDave May } 462b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 463b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 464b3bd94feSDave May } 46547c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 46647c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 46747c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 468fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 46947c6ae99SBarry Smith PetscFunctionReturn(0); 47047c6ae99SBarry Smith } 47147c6ae99SBarry Smith 47247c6ae99SBarry Smith /* 47347c6ae99SBarry Smith Contributed by Andrei Draganescu <aidraga@sandia.gov> 47447c6ae99SBarry Smith */ 47547c6ae99SBarry Smith #undef __FUNCT__ 476e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_2D_Q0" 477e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A) 47847c6ae99SBarry Smith { 47947c6ae99SBarry Smith PetscErrorCode ierr; 48047c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof; 48147c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz; 48247c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 48347c6ae99SBarry 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; 48447c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 48547c6ae99SBarry Smith PetscScalar v[4]; 48647c6ae99SBarry Smith Mat mat; 4871321219cSEthan Coon DMDABoundaryType bx,by; 48847c6ae99SBarry Smith 48947c6ae99SBarry Smith PetscFunctionBegin; 4901321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 4911321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 4921321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x"); 4931321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y"); 49447c6ae99SBarry Smith ratioi = mx/Mx; 49547c6ae99SBarry Smith ratioj = my/My; 49647c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 49747c6ae99SBarry Smith if (ratioj*My != my) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 49847c6ae99SBarry Smith if (ratioi != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2"); 49947c6ae99SBarry Smith if (ratioj != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2"); 50047c6ae99SBarry Smith 501aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 502aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 503aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 50447c6ae99SBarry Smith 505aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 506aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 507aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 50847c6ae99SBarry Smith 50947c6ae99SBarry Smith /* 510aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 51147c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 51247c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 51347c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 51447c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 51547c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 51647c6ae99SBarry Smith 51747c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 51847c6ae99SBarry Smith */ 51947c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr); 52047c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr); 52147c6ae99SBarry Smith ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr); 52247c6ae99SBarry Smith col_scale = size_f/size_c; 52347c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 52447c6ae99SBarry Smith 52547c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 52647c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 52747c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 52847c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 52947c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 53047c6ae99SBarry Smith 53147c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 53247c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 53347c6ae99SBarry Smith 534aa219208SBarry 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\ 53547c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 536aa219208SBarry 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\ 53747c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 53847c6ae99SBarry Smith 53947c6ae99SBarry Smith /* 54047c6ae99SBarry Smith Only include those interpolation points that are truly 54147c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 54247c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 54347c6ae99SBarry Smith */ 54447c6ae99SBarry Smith nc = 0; 54547c6ae99SBarry Smith /* one left and below; or we are right on it */ 54647c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 54747c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col]/dof; 54847c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 54947c6ae99SBarry Smith } 55047c6ae99SBarry Smith } 55147c6ae99SBarry Smith ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr); 55247c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 55347c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 55447c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 55547c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 55647c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 55747c6ae99SBarry Smith 55847c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 55947c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 56047c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 56147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 56247c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 56347c6ae99SBarry Smith 56447c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 56547c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 56647c6ae99SBarry Smith nc = 0; 56747c6ae99SBarry Smith /* one left and below; or we are right on it */ 56847c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 56947c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col]/dof; 57047c6ae99SBarry Smith v[nc++] = 1.0; 57147c6ae99SBarry Smith 57247c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 57347c6ae99SBarry Smith } 57447c6ae99SBarry Smith } 57547c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57647c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57747c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 578fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 57947c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr); 58047c6ae99SBarry Smith PetscFunctionReturn(0); 58147c6ae99SBarry Smith } 58247c6ae99SBarry Smith 58347c6ae99SBarry Smith /* 58447c6ae99SBarry Smith Contributed by Jianming Yang <jianming-yang@uiowa.edu> 58547c6ae99SBarry Smith */ 58647c6ae99SBarry Smith #undef __FUNCT__ 587e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_3D_Q0" 588e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A) 58947c6ae99SBarry Smith { 59047c6ae99SBarry Smith PetscErrorCode ierr; 59147c6ae99SBarry Smith PetscInt i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,*idx_f,dof; 59247c6ae99SBarry Smith PetscInt m_ghost,n_ghost,p_ghost,*idx_c,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz; 59347c6ae99SBarry 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; 59447c6ae99SBarry 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; 59547c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 59647c6ae99SBarry Smith PetscScalar v[8]; 59747c6ae99SBarry Smith Mat mat; 5981321219cSEthan Coon DMDABoundaryType bx,by,bz; 59947c6ae99SBarry Smith 60047c6ae99SBarry Smith PetscFunctionBegin; 6011321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 6021321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 6031321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x"); 6041321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y"); 6051321219cSEthan Coon if (bz == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in z"); 60647c6ae99SBarry Smith ratioi = mx/Mx; 60747c6ae99SBarry Smith ratioj = my/My; 60847c6ae99SBarry Smith ratiol = mz/Mz; 60947c6ae99SBarry Smith if (ratioi*Mx != mx) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in x"); 61047c6ae99SBarry Smith if (ratioj*My != my) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in y"); 61147c6ae99SBarry Smith if (ratiol*Mz != mz) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Fine grid points must be multiple of coarse grid points in z"); 61247c6ae99SBarry Smith if (ratioi != 2 && ratioi != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2"); 61347c6ae99SBarry Smith if (ratioj != 2 && ratioj != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2"); 61447c6ae99SBarry Smith if (ratiol != 2 && ratiol != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2"); 61547c6ae99SBarry Smith 616aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 617aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 618aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 61947c6ae99SBarry Smith 620aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 621aa219208SBarry 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); 622aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 62347c6ae99SBarry Smith /* 624aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 62547c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 62647c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 62747c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 62847c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 62947c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 63047c6ae99SBarry Smith 63147c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 63247c6ae99SBarry Smith */ 63347c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr); 63447c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr); 63547c6ae99SBarry Smith ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr); 63647c6ae99SBarry Smith col_scale = size_f/size_c; 63747c6ae99SBarry Smith col_shift = Mx*My*Mz*(rank_f/size_c); 63847c6ae99SBarry Smith 63947c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 64047c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 64147c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 64247c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 64347c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 64447c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 64547c6ae99SBarry Smith 64647c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 64747c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 64847c6ae99SBarry Smith l_c = (l/ratiol); 64947c6ae99SBarry Smith 650aa219208SBarry 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\ 65147c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 652aa219208SBarry 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\ 65347c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 654aa219208SBarry 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\ 65547c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 65647c6ae99SBarry Smith 65747c6ae99SBarry Smith /* 65847c6ae99SBarry Smith Only include those interpolation points that are truly 65947c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 66047c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 66147c6ae99SBarry Smith */ 66247c6ae99SBarry Smith nc = 0; 66347c6ae99SBarry Smith /* one left and below; or we are right on it */ 66447c6ae99SBarry Smith col = dof*(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)); 66547c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col]/dof; 66647c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 66747c6ae99SBarry Smith } 66847c6ae99SBarry Smith } 66947c6ae99SBarry Smith } 67047c6ae99SBarry Smith ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr); 67147c6ae99SBarry 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); 67247c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 67347c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 67447c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 67547c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 67647c6ae99SBarry Smith 67747c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 67847c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 67947c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 68047c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 68147c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 68247c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 68347c6ae99SBarry Smith 68447c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 68547c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 68647c6ae99SBarry Smith l_c = (l/ratiol); 68747c6ae99SBarry Smith nc = 0; 68847c6ae99SBarry Smith /* one left and below; or we are right on it */ 68947c6ae99SBarry Smith col = dof*(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)); 69047c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col]/dof; 69147c6ae99SBarry Smith v[nc++] = 1.0; 69247c6ae99SBarry Smith 69347c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 69447c6ae99SBarry Smith } 69547c6ae99SBarry Smith } 69647c6ae99SBarry Smith } 69747c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 69847c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 69947c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 700fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 70147c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr); 70247c6ae99SBarry Smith PetscFunctionReturn(0); 70347c6ae99SBarry Smith } 70447c6ae99SBarry Smith 70547c6ae99SBarry Smith #undef __FUNCT__ 706e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA_3D_Q1" 707e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A) 70847c6ae99SBarry Smith { 70947c6ae99SBarry Smith PetscErrorCode ierr; 71047c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof,l; 71147c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,Mz,mz; 71247c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok; 71347c6ae99SBarry Smith PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 71447c6ae99SBarry Smith PetscInt l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c; 71547c6ae99SBarry Smith PetscInt l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz; 71647c6ae99SBarry Smith PetscScalar v[8],x,y,z; 71747c6ae99SBarry Smith Mat mat; 7181321219cSEthan Coon DMDABoundaryType bx,by,bz; 71947c6ae99SBarry Smith 72047c6ae99SBarry Smith PetscFunctionBegin; 7211321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 7221321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 72347c6ae99SBarry Smith if (mx == Mx) { 72447c6ae99SBarry Smith ratioi = 1; 7251321219cSEthan Coon } else if (bx == DMDA_BOUNDARY_PERIODIC) { 72647c6ae99SBarry Smith ratioi = mx/Mx; 72747c6ae99SBarry 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); 72847c6ae99SBarry Smith } else { 72947c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 73047c6ae99SBarry 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); 73147c6ae99SBarry Smith } 73247c6ae99SBarry Smith if (my == My) { 73347c6ae99SBarry Smith ratioj = 1; 7341321219cSEthan Coon } else if (by == DMDA_BOUNDARY_PERIODIC) { 73547c6ae99SBarry Smith ratioj = my/My; 73647c6ae99SBarry 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); 73747c6ae99SBarry Smith } else { 73847c6ae99SBarry Smith ratioj = (my-1)/(My-1); 73947c6ae99SBarry 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); 74047c6ae99SBarry Smith } 74147c6ae99SBarry Smith if (mz == Mz) { 74247c6ae99SBarry Smith ratiok = 1; 7431321219cSEthan Coon } else if (bz == DMDA_BOUNDARY_PERIODIC) { 74447c6ae99SBarry Smith ratiok = mz/Mz; 74547c6ae99SBarry 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); 74647c6ae99SBarry Smith } else { 74747c6ae99SBarry Smith ratiok = (mz-1)/(Mz-1); 74847c6ae99SBarry 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); 74947c6ae99SBarry Smith } 75047c6ae99SBarry Smith 751aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 752aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 753aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 75447c6ae99SBarry Smith 755aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 756aa219208SBarry 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); 757aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 75847c6ae99SBarry Smith 75947c6ae99SBarry Smith /* create interpolation matrix, determining exact preallocation */ 76047c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)dac)->comm,m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 76147c6ae99SBarry Smith /* loop over local fine grid nodes counting interpolating points */ 76247c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 76347c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 76447c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 76547c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 76647c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 76747c6ae99SBarry Smith i_c = (i/ratioi); 76847c6ae99SBarry Smith j_c = (j/ratioj); 76947c6ae99SBarry Smith l_c = (l/ratiok); 770aa219208SBarry 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\ 77147c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 772aa219208SBarry 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\ 77347c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 774aa219208SBarry 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\ 77547c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 77647c6ae99SBarry Smith 77747c6ae99SBarry Smith /* 77847c6ae99SBarry Smith Only include those interpolation points that are truly 77947c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 78047c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 78147c6ae99SBarry Smith */ 78247c6ae99SBarry Smith nc = 0; 78347c6ae99SBarry Smith col = dof*(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)); 78447c6ae99SBarry Smith cols[nc++] = idx_c[col]/dof; 78547c6ae99SBarry Smith if (i_c*ratioi != i) { 78647c6ae99SBarry Smith cols[nc++] = idx_c[col+dof]/dof; 78747c6ae99SBarry Smith } 78847c6ae99SBarry Smith if (j_c*ratioj != j) { 78947c6ae99SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*dof]/dof; 79047c6ae99SBarry Smith } 79147c6ae99SBarry Smith if (l_c*ratiok != l) { 79247c6ae99SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof; 79347c6ae99SBarry Smith } 79447c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 79547c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c+1)*dof]/dof; 79647c6ae99SBarry Smith } 79747c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 79847c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof; 79947c6ae99SBarry Smith } 80047c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 80147c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; 80247c6ae99SBarry Smith } 80347c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 80447c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; 80547c6ae99SBarry Smith } 80647c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 80747c6ae99SBarry Smith } 80847c6ae99SBarry Smith } 80947c6ae99SBarry Smith } 81047c6ae99SBarry Smith ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr); 81147c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr); 81247c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 81347c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 81447c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 81547c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 81647c6ae99SBarry Smith 81747c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 8182adb9dcfSBarry Smith if (!NEWVERSION) { 819b3bd94feSDave May 82047c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 82147c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 82247c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 82347c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 82447c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 82547c6ae99SBarry Smith 82647c6ae99SBarry Smith i_c = (i/ratioi); 82747c6ae99SBarry Smith j_c = (j/ratioj); 82847c6ae99SBarry Smith l_c = (l/ratiok); 82947c6ae99SBarry Smith 83047c6ae99SBarry Smith /* 83147c6ae99SBarry Smith Only include those interpolation points that are truly 83247c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 83347c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 83447c6ae99SBarry Smith */ 83547c6ae99SBarry Smith x = ((double)(i - i_c*ratioi))/((double)ratioi); 83647c6ae99SBarry Smith y = ((double)(j - j_c*ratioj))/((double)ratioj); 83747c6ae99SBarry Smith z = ((double)(l - l_c*ratiok))/((double)ratiok); 838b3bd94feSDave May 83947c6ae99SBarry Smith nc = 0; 84047c6ae99SBarry Smith /* one left and below; or we are right on it */ 84147c6ae99SBarry Smith col = dof*(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)); 84247c6ae99SBarry Smith 84347c6ae99SBarry Smith cols[nc] = idx_c[col]/dof; 84447c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 84547c6ae99SBarry Smith 84647c6ae99SBarry Smith if (i_c*ratioi != i) { 84747c6ae99SBarry Smith cols[nc] = idx_c[col+dof]/dof; 84847c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 84947c6ae99SBarry Smith } 85047c6ae99SBarry Smith 85147c6ae99SBarry Smith if (j_c*ratioj != j) { 85247c6ae99SBarry Smith cols[nc] = idx_c[col+m_ghost_c*dof]/dof; 85347c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 85447c6ae99SBarry Smith } 85547c6ae99SBarry Smith 85647c6ae99SBarry Smith if (l_c*ratiok != l) { 85747c6ae99SBarry Smith cols[nc] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof; 85847c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 85947c6ae99SBarry Smith } 86047c6ae99SBarry Smith 86147c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 86247c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c+1)*dof]/dof; 86347c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 86447c6ae99SBarry Smith } 86547c6ae99SBarry Smith 86647c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 86747c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof; 86847c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 86947c6ae99SBarry Smith } 87047c6ae99SBarry Smith 87147c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 87247c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; 87347c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. + (2.0*z-1.)); 87447c6ae99SBarry Smith } 87547c6ae99SBarry Smith 87647c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 87747c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; 87847c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 87947c6ae99SBarry Smith } 88047c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 88147c6ae99SBarry Smith } 88247c6ae99SBarry Smith } 88347c6ae99SBarry Smith } 884b3bd94feSDave May 885b3bd94feSDave May } else { 886b3bd94feSDave May PetscScalar *xi,*eta,*zeta; 887b3bd94feSDave May PetscInt li,nxi,lj,neta,lk,nzeta,n; 888b3bd94feSDave May PetscScalar Ni[8]; 889b3bd94feSDave May 890b3bd94feSDave May /* compute local coordinate arrays */ 891b3bd94feSDave May nxi = ratioi + 1; 892b3bd94feSDave May neta = ratioj + 1; 893b3bd94feSDave May nzeta = ratiok + 1; 894b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr); 895b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr); 896b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*nzeta,&zeta);CHKERRQ(ierr); 897b3bd94feSDave May for (li=0; li<nxi; li++) { 89852218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 899b3bd94feSDave May } 900b3bd94feSDave May for (lj=0; lj<neta; lj++) { 90152218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 902b3bd94feSDave May } 903b3bd94feSDave May for (lk=0; lk<nzeta; lk++) { 90452218ef2SJed Brown zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1)); 905b3bd94feSDave May } 906b3bd94feSDave May 907b3bd94feSDave May for (l=l_start; l<l_start+p_f; l++) { 908b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 909b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 910b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 911b3bd94feSDave May row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 912b3bd94feSDave May 913b3bd94feSDave May i_c = (i/ratioi); 914b3bd94feSDave May j_c = (j/ratioj); 915b3bd94feSDave May l_c = (l/ratiok); 916b3bd94feSDave May 917b3bd94feSDave May /* remainders */ 918b3bd94feSDave May li = i - ratioi * (i/ratioi); 919b3bd94feSDave May if (i==mx-1){ li = nxi-1; } 920b3bd94feSDave May lj = j - ratioj * (j/ratioj); 921b3bd94feSDave May if (j==my-1){ lj = neta-1; } 922b3bd94feSDave May lk = l - ratiok * (l/ratiok); 923b3bd94feSDave May if (l==mz-1){ lk = nzeta-1; } 924b3bd94feSDave May 925b3bd94feSDave May /* corners */ 926b3bd94feSDave May col = dof*(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)); 927b3bd94feSDave May cols[0] = idx_c[col]/dof; 928b3bd94feSDave May Ni[0] = 1.0; 929b3bd94feSDave May if ( (li==0) || (li==nxi-1) ) { 930b3bd94feSDave May if ( (lj==0) || (lj==neta-1) ) { 931b3bd94feSDave May if ( (lk==0) || (lk==nzeta-1) ) { 932b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 933b3bd94feSDave May continue; 934b3bd94feSDave May } 935b3bd94feSDave May } 936b3bd94feSDave May } 937b3bd94feSDave May 938b3bd94feSDave May /* edges + interior */ 939b3bd94feSDave May /* remainders */ 940b3bd94feSDave May if (i==mx-1){ i_c--; } 941b3bd94feSDave May if (j==my-1){ j_c--; } 942b3bd94feSDave May if (l==mz-1){ l_c--; } 943b3bd94feSDave May 944b3bd94feSDave May col = dof*(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)); 945b3bd94feSDave May cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */ 946b3bd94feSDave May cols[1] = idx_c[col+dof]/dof; /* one right and below */ 947b3bd94feSDave May cols[2] = idx_c[col+m_ghost_c*dof]/dof; /* one left and above */ 948b3bd94feSDave May cols[3] = idx_c[col+(m_ghost_c+1)*dof]/dof; /* one right and above */ 949b3bd94feSDave May 950b3bd94feSDave May cols[4] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof; /* one left and below and front; or we are right on it */ 951b3bd94feSDave May cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; /* one right and below, and front */ 952b3bd94feSDave May cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;/* one left and above and front*/ 953b3bd94feSDave May cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; /* one right and above and front */ 954b3bd94feSDave May 955b3bd94feSDave May Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 956b3bd94feSDave May Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 957b3bd94feSDave May Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 958b3bd94feSDave May Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 959b3bd94feSDave May 960b3bd94feSDave May Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 961b3bd94feSDave May Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 962b3bd94feSDave May Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 963b3bd94feSDave May Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 964b3bd94feSDave May 965b3bd94feSDave May for (n=0; n<8; n++) { 966b3bd94feSDave May if( PetscAbsScalar(Ni[n])<1.0e-32) { cols[n]=-1; } 967b3bd94feSDave May } 968b3bd94feSDave May ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 969b3bd94feSDave May 970b3bd94feSDave May } 971b3bd94feSDave May } 972b3bd94feSDave May } 973b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 974b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 975b3bd94feSDave May ierr = PetscFree(zeta);CHKERRQ(ierr); 976b3bd94feSDave May } 977b3bd94feSDave May 97847c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 97947c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 98047c6ae99SBarry Smith 98147c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 982fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 98347c6ae99SBarry Smith PetscFunctionReturn(0); 98447c6ae99SBarry Smith } 98547c6ae99SBarry Smith 98647c6ae99SBarry Smith #undef __FUNCT__ 987e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_DA" 988e727c939SJed Brown PetscErrorCode DMCreateInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale) 98947c6ae99SBarry Smith { 99047c6ae99SBarry Smith PetscErrorCode ierr; 99147c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 9921321219cSEthan Coon DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf; 993aa219208SBarry Smith DMDAStencilType stc,stf; 99447c6ae99SBarry Smith DM_DA *ddc = (DM_DA*)dac->data; 99547c6ae99SBarry Smith 99647c6ae99SBarry Smith PetscFunctionBegin; 99747c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 99847c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 99947c6ae99SBarry Smith PetscValidPointer(A,3); 100047c6ae99SBarry Smith if (scale) PetscValidPointer(scale,4); 100147c6ae99SBarry Smith 10021321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 10031321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1004aa219208SBarry Smith if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr); 1005aa219208SBarry Smith if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr); 1006aa219208SBarry Smith if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr); 10071321219cSEthan Coon if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr); 1008aa219208SBarry Smith if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr); 100947c6ae99SBarry Smith if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 101047c6ae99SBarry 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"); 101147c6ae99SBarry 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"); 101247c6ae99SBarry Smith 1013aa219208SBarry Smith if (ddc->interptype == DMDA_Q1){ 101447c6ae99SBarry Smith if (dimc == 1){ 1015e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr); 101647c6ae99SBarry Smith } else if (dimc == 2){ 1017e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr); 101847c6ae99SBarry Smith } else if (dimc == 3){ 1019e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr); 102085afcc9aSBarry Smith } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 1021aa219208SBarry Smith } else if (ddc->interptype == DMDA_Q0){ 102247c6ae99SBarry Smith if (dimc == 1){ 1023e727c939SJed Brown ierr = DMCreateInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr); 102447c6ae99SBarry Smith } else if (dimc == 2){ 1025e727c939SJed Brown ierr = DMCreateInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr); 102647c6ae99SBarry Smith } else if (dimc == 3){ 1027e727c939SJed Brown ierr = DMCreateInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr); 102885afcc9aSBarry Smith } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 102947c6ae99SBarry Smith } 103047c6ae99SBarry Smith if (scale) { 1031e727c939SJed Brown ierr = DMCreateInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr); 103247c6ae99SBarry Smith } 103347c6ae99SBarry Smith PetscFunctionReturn(0); 103447c6ae99SBarry Smith } 103547c6ae99SBarry Smith 103647c6ae99SBarry Smith #undef __FUNCT__ 1037e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_1D" 1038e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_1D(DM dac,DM daf,VecScatter *inject) 10390bb2b966SJungho Lee { 10400bb2b966SJungho Lee PetscErrorCode ierr; 10410bb2b966SJungho Lee PetscInt i,i_start,m_f,Mx,*idx_f,dof; 10420bb2b966SJungho Lee PetscInt m_ghost,*idx_c,m_ghost_c; 10430bb2b966SJungho Lee PetscInt row,i_start_ghost,mx,m_c,nc,ratioi; 10440bb2b966SJungho Lee PetscInt i_start_c,i_start_ghost_c; 10450bb2b966SJungho Lee PetscInt *cols; 10460bb2b966SJungho Lee DMDABoundaryType bx; 10470bb2b966SJungho Lee Vec vecf,vecc; 10480bb2b966SJungho Lee IS isf; 10490bb2b966SJungho Lee 10500bb2b966SJungho Lee PetscFunctionBegin; 10510bb2b966SJungho Lee ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 10520bb2b966SJungho Lee ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 10530bb2b966SJungho Lee if (bx == DMDA_BOUNDARY_PERIODIC) { 10540bb2b966SJungho Lee ratioi = mx/Mx; 10550bb2b966SJungho 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); 10560bb2b966SJungho Lee } else { 10570bb2b966SJungho Lee ratioi = (mx-1)/(Mx-1); 10580bb2b966SJungho 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); 10590bb2b966SJungho Lee } 10600bb2b966SJungho Lee 10610bb2b966SJungho Lee ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 10620bb2b966SJungho Lee ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 10630bb2b966SJungho Lee ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 10640bb2b966SJungho Lee 10650bb2b966SJungho Lee ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 10660bb2b966SJungho Lee ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 10670bb2b966SJungho Lee ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 10680bb2b966SJungho Lee 10690bb2b966SJungho Lee 10700bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 10710bb2b966SJungho Lee nc = 0; 10720bb2b966SJungho Lee ierr = PetscMalloc(m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr); 10730bb2b966SJungho Lee 10740bb2b966SJungho Lee 10750bb2b966SJungho Lee for (i=i_start_c; i<i_start_c+m_c; i++) { 10760bb2b966SJungho Lee PetscInt i_f = i*ratioi; 10770bb2b966SJungho Lee 10780bb2b966SJungho Lee 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\ 10790bb2b966SJungho Lee i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 10800bb2b966SJungho Lee row = idx_f[dof*(i_f-i_start_ghost)]; 10810bb2b966SJungho Lee cols[nc++] = row/dof; 10820bb2b966SJungho Lee } 10830bb2b966SJungho Lee 10840bb2b966SJungho Lee 10850bb2b966SJungho Lee ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 10860bb2b966SJungho Lee ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 10870bb2b966SJungho Lee ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 10880bb2b966SJungho Lee ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr); 10890bb2b966SJungho Lee ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 10900bb2b966SJungho Lee ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 10910bb2b966SJungho Lee ierr = ISDestroy(&isf);CHKERRQ(ierr); 10920bb2b966SJungho Lee PetscFunctionReturn(0); 10930bb2b966SJungho Lee } 10940bb2b966SJungho Lee 10950bb2b966SJungho Lee #undef __FUNCT__ 1096e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_2D" 1097e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_2D(DM dac,DM daf,VecScatter *inject) 109847c6ae99SBarry Smith { 109947c6ae99SBarry Smith PetscErrorCode ierr; 110047c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof; 110147c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c; 110247c6ae99SBarry Smith PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; 1103076202ddSJed Brown PetscInt i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 110447c6ae99SBarry Smith PetscInt *cols; 11051321219cSEthan Coon DMDABoundaryType bx,by; 110647c6ae99SBarry Smith Vec vecf,vecc; 110747c6ae99SBarry Smith IS isf; 110847c6ae99SBarry Smith 110947c6ae99SBarry Smith PetscFunctionBegin; 11101321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 11111321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 11121321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC) { 111347c6ae99SBarry Smith ratioi = mx/Mx; 111447c6ae99SBarry 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); 111547c6ae99SBarry Smith } else { 111647c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 111747c6ae99SBarry 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); 111847c6ae99SBarry Smith } 11191321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC) { 112047c6ae99SBarry Smith ratioj = my/My; 112147c6ae99SBarry 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); 112247c6ae99SBarry Smith } else { 112347c6ae99SBarry Smith ratioj = (my-1)/(My-1); 112447c6ae99SBarry 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); 112547c6ae99SBarry Smith } 112647c6ae99SBarry Smith 1127aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 1128aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 1129aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 113047c6ae99SBarry Smith 1131aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 1132aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 1133aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 113447c6ae99SBarry Smith 113547c6ae99SBarry Smith 113647c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 113747c6ae99SBarry Smith nc = 0; 113847c6ae99SBarry Smith ierr = PetscMalloc(n_f*m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr); 1139076202ddSJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1140076202ddSJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1141076202ddSJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj; 1142076202ddSJed 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\ 1143076202ddSJed Brown j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1144076202ddSJed 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\ 1145076202ddSJed Brown i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1146076202ddSJed Brown row = idx_f[dof*(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 114747c6ae99SBarry Smith cols[nc++] = row/dof; 114847c6ae99SBarry Smith } 114947c6ae99SBarry Smith } 115047c6ae99SBarry Smith 115147c6ae99SBarry Smith ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 11529a42bb27SBarry Smith ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 11539a42bb27SBarry Smith ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 115447c6ae99SBarry Smith ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr); 11559a42bb27SBarry Smith ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 11569a42bb27SBarry Smith ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1157fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 115847c6ae99SBarry Smith PetscFunctionReturn(0); 115947c6ae99SBarry Smith } 116047c6ae99SBarry Smith 116147c6ae99SBarry Smith #undef __FUNCT__ 1162e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA_3D" 1163e727c939SJed Brown PetscErrorCode DMCreateInjection_DA_3D(DM dac,DM daf,VecScatter *inject) 1164b1757049SJed Brown { 1165b1757049SJed Brown PetscErrorCode ierr; 1166b1757049SJed Brown PetscInt i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz; 1167b1757049SJed Brown PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c; 1168b1757049SJed Brown PetscInt i_start_ghost,j_start_ghost,k_start_ghost; 1169b1757049SJed Brown PetscInt mx,my,mz,ratioi,ratioj,ratiok; 1170b1757049SJed Brown PetscInt i_start_c,j_start_c,k_start_c; 1171b1757049SJed Brown PetscInt m_c,n_c,p_c; 1172b1757049SJed Brown PetscInt i_start_ghost_c,j_start_ghost_c,k_start_ghost_c; 1173b1757049SJed Brown PetscInt row,nc,dof; 1174b1757049SJed Brown PetscInt *idx_c,*idx_f; 1175b1757049SJed Brown PetscInt *cols; 11761321219cSEthan Coon DMDABoundaryType bx,by,bz; 1177b1757049SJed Brown Vec vecf,vecc; 1178b1757049SJed Brown IS isf; 1179b1757049SJed Brown 1180b1757049SJed Brown PetscFunctionBegin; 11811321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 11821321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1183b1757049SJed Brown 11841321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 1185b1757049SJed Brown ratioi = mx/Mx; 1186b1757049SJed 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); 1187b1757049SJed Brown } else { 1188b1757049SJed Brown ratioi = (mx-1)/(Mx-1); 1189b1757049SJed 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); 1190b1757049SJed Brown } 11911321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC){ 1192b1757049SJed Brown ratioj = my/My; 1193b1757049SJed 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); 1194b1757049SJed Brown } else { 1195b1757049SJed Brown ratioj = (my-1)/(My-1); 1196b1757049SJed 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); 1197b1757049SJed Brown } 11981321219cSEthan Coon if (bz == DMDA_BOUNDARY_PERIODIC){ 1199b1757049SJed Brown ratiok = mz/Mz; 1200b1757049SJed 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); 1201b1757049SJed Brown } else { 1202b1757049SJed Brown ratiok = (mz-1)/(Mz-1); 1203b1757049SJed 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); 1204b1757049SJed Brown } 1205b1757049SJed Brown 1206b1757049SJed Brown ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1207b1757049SJed Brown ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1208b1757049SJed Brown ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 1209b1757049SJed Brown 1210b1757049SJed Brown ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1211b1757049SJed 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); 1212b1757049SJed Brown ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 1213b1757049SJed Brown 1214b1757049SJed Brown 1215b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1216b1757049SJed Brown nc = 0; 1217b1757049SJed Brown ierr = PetscMalloc(n_f*m_f*p_f*sizeof(PetscInt),&cols);CHKERRQ(ierr); 1218b1757049SJed Brown for (k=k_start_c; k<k_start_c+p_c; k++) { 1219b1757049SJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1220b1757049SJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1221b1757049SJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok; 1222b1757049SJed 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 " 1223b1757049SJed Brown "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost); 1224b1757049SJed 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 " 1225b1757049SJed Brown "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1226b1757049SJed 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 " 1227b1757049SJed Brown "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1228b1757049SJed Brown row = idx_f[dof*(m_ghost*n_ghost*(k_f-k_start_ghost) + m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 1229b1757049SJed Brown cols[nc++] = row/dof; 1230b1757049SJed Brown } 1231b1757049SJed Brown } 1232b1757049SJed Brown } 1233b1757049SJed Brown 1234b1757049SJed Brown ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 1235b1757049SJed Brown ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 1236b1757049SJed Brown ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 1237b1757049SJed Brown ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr); 1238b1757049SJed Brown ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 1239b1757049SJed Brown ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1240fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 1241b1757049SJed Brown PetscFunctionReturn(0); 1242b1757049SJed Brown } 1243b1757049SJed Brown 1244b1757049SJed Brown #undef __FUNCT__ 1245e727c939SJed Brown #define __FUNCT__ "DMCreateInjection_DA" 1246e727c939SJed Brown PetscErrorCode DMCreateInjection_DA(DM dac,DM daf,VecScatter *inject) 124747c6ae99SBarry Smith { 124847c6ae99SBarry Smith PetscErrorCode ierr; 124947c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 12501321219cSEthan Coon DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf; 1251aa219208SBarry Smith DMDAStencilType stc,stf; 125247c6ae99SBarry Smith 125347c6ae99SBarry Smith PetscFunctionBegin; 125447c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 125547c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 125647c6ae99SBarry Smith PetscValidPointer(inject,3); 125747c6ae99SBarry Smith 12581321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 12591321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1260aa219208SBarry Smith if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr); 1261aa219208SBarry Smith if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr); 1262aa219208SBarry Smith if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr); 12631321219cSEthan Coon if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr); 1264aa219208SBarry Smith if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr); 126547c6ae99SBarry Smith if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 126647c6ae99SBarry Smith if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 126747c6ae99SBarry Smith if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 126847c6ae99SBarry Smith 12690bb2b966SJungho Lee if (dimc == 1){ 1270e727c939SJed Brown ierr = DMCreateInjection_DA_1D(dac,daf,inject);CHKERRQ(ierr); 12710bb2b966SJungho Lee } else if (dimc == 2) { 1272e727c939SJed Brown ierr = DMCreateInjection_DA_2D(dac,daf,inject);CHKERRQ(ierr); 1273b1757049SJed Brown } else if (dimc == 3) { 1274e727c939SJed Brown ierr = DMCreateInjection_DA_3D(dac,daf,inject);CHKERRQ(ierr); 127547c6ae99SBarry Smith } 127647c6ae99SBarry Smith PetscFunctionReturn(0); 127747c6ae99SBarry Smith } 127847c6ae99SBarry Smith 127947c6ae99SBarry Smith #undef __FUNCT__ 1280e727c939SJed Brown #define __FUNCT__ "DMCreateAggregates_DA" 1281e727c939SJed Brown PetscErrorCode DMCreateAggregates_DA(DM dac,DM daf,Mat *rest) 128247c6ae99SBarry Smith { 128347c6ae99SBarry Smith PetscErrorCode ierr; 128447c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc; 128547c6ae99SBarry Smith PetscInt dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 12861321219cSEthan Coon DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf; 1287aa219208SBarry Smith DMDAStencilType stc,stf; 128847c6ae99SBarry Smith PetscInt i,j,l; 128947c6ae99SBarry Smith PetscInt i_start,j_start,l_start, m_f,n_f,p_f; 129047c6ae99SBarry Smith PetscInt i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost; 129147c6ae99SBarry Smith PetscInt *idx_f; 129247c6ae99SBarry Smith PetscInt i_c,j_c,l_c; 129347c6ae99SBarry Smith PetscInt i_start_c,j_start_c,l_start_c, m_c,n_c,p_c; 129447c6ae99SBarry Smith PetscInt i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c; 129547c6ae99SBarry Smith PetscInt *idx_c; 129647c6ae99SBarry Smith PetscInt d; 129747c6ae99SBarry Smith PetscInt a; 129847c6ae99SBarry Smith PetscInt max_agg_size; 129947c6ae99SBarry Smith PetscInt *fine_nodes; 130047c6ae99SBarry Smith PetscScalar *one_vec; 130147c6ae99SBarry Smith PetscInt fn_idx; 130247c6ae99SBarry Smith 130347c6ae99SBarry Smith PetscFunctionBegin; 130447c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 130547c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 130647c6ae99SBarry Smith PetscValidPointer(rest,3); 130747c6ae99SBarry Smith 13081321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 13091321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1310aa219208SBarry Smith if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr); 1311aa219208SBarry Smith if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr); 1312aa219208SBarry Smith if (sc != sf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil width of DMDA do not match %D %D",sc,sf);CHKERRQ(ierr); 13131321219cSEthan Coon if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr); 1314aa219208SBarry Smith if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr); 131547c6ae99SBarry Smith 131647c6ae99SBarry 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); 131747c6ae99SBarry 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); 131847c6ae99SBarry 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); 131947c6ae99SBarry Smith 132047c6ae99SBarry Smith if (Pc < 0) Pc = 1; 132147c6ae99SBarry Smith if (Pf < 0) Pf = 1; 132247c6ae99SBarry Smith if (Nc < 0) Nc = 1; 132347c6ae99SBarry Smith if (Nf < 0) Nf = 1; 132447c6ae99SBarry Smith 1325aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1326aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1327aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 132847c6ae99SBarry Smith 1329aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1330aa219208SBarry 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); 1331aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 133247c6ae99SBarry Smith 133347c6ae99SBarry Smith /* 133447c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 133547c6ae99SBarry Smith for dimension 1 and 2 respectively. 133647c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 133747c6ae99SBarry Smith and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate. 133847c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 133947c6ae99SBarry Smith */ 134047c6ae99SBarry Smith 134147c6ae99SBarry Smith max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1); 134247c6ae99SBarry Smith 134347c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 134447c6ae99SBarry Smith ierr = MatCreateMPIAIJ( ((PetscObject)daf)->comm, m_c*n_c*p_c*dofc, m_f*n_f*p_f*doff, Mc*Nc*Pc*dofc, Mf*Nf*Pf*doff, 134547c6ae99SBarry Smith max_agg_size, PETSC_NULL, max_agg_size, PETSC_NULL, rest);CHKERRQ(ierr); 134647c6ae99SBarry Smith 134747c6ae99SBarry Smith /* store nodes in the fine grid here */ 134847c6ae99SBarry Smith ierr = PetscMalloc2(max_agg_size,PetscScalar, &one_vec,max_agg_size,PetscInt, &fine_nodes);CHKERRQ(ierr); 134947c6ae99SBarry Smith for(i=0; i<max_agg_size; i++) one_vec[i] = 1.0; 135047c6ae99SBarry Smith 135147c6ae99SBarry Smith /* loop over all coarse nodes */ 135247c6ae99SBarry Smith for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) { 135347c6ae99SBarry Smith for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) { 135447c6ae99SBarry Smith for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) { 135547c6ae99SBarry Smith for(d=0; d<dofc; d++) { 135647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 135747c6ae99SBarry 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; 135847c6ae99SBarry Smith 135947c6ae99SBarry Smith fn_idx = 0; 136047c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 136147c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 136247c6ae99SBarry Smith (same for other dimensions) 136347c6ae99SBarry Smith */ 136447c6ae99SBarry Smith for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) { 136547c6ae99SBarry Smith for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) { 136647c6ae99SBarry Smith for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) { 136747c6ae99SBarry 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; 136847c6ae99SBarry Smith fn_idx++; 136947c6ae99SBarry Smith } 137047c6ae99SBarry Smith } 137147c6ae99SBarry Smith } 137247c6ae99SBarry Smith /* add all these points to one aggregate */ 137347c6ae99SBarry Smith ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr); 137447c6ae99SBarry Smith } 137547c6ae99SBarry Smith } 137647c6ae99SBarry Smith } 137747c6ae99SBarry Smith } 137847c6ae99SBarry Smith ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr); 137947c6ae99SBarry Smith ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 138047c6ae99SBarry Smith ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 138147c6ae99SBarry Smith PetscFunctionReturn(0); 138247c6ae99SBarry Smith } 1383