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 9*2adb9dcfSBarry 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 10*2adb9dcfSBarry 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*/ 15c6db04a5SJed Brown #include <petscpcmg.h> 1647c6ae99SBarry Smith 1747c6ae99SBarry Smith #undef __FUNCT__ 1847c6ae99SBarry Smith #define __FUNCT__ "DMGetInterpolationScale" 1947c6ae99SBarry Smith /*@ 2047c6ae99SBarry Smith DMGetInterpolationScale - Forms L = R*1/diag(R*1) - L.*v is like a coarse grid average of the 2147c6ae99SBarry Smith nearby fine grid points. 2247c6ae99SBarry Smith 2347c6ae99SBarry Smith Input Parameters: 2447c6ae99SBarry Smith + dac - DM that defines a coarse mesh 2547c6ae99SBarry Smith . daf - DM that defines a fine mesh 2647c6ae99SBarry Smith - mat - the restriction (or interpolation operator) from fine to coarse 2747c6ae99SBarry Smith 2847c6ae99SBarry Smith Output Parameter: 2947c6ae99SBarry Smith . scale - the scaled vector 3047c6ae99SBarry Smith 3147c6ae99SBarry Smith Level: developer 3247c6ae99SBarry Smith 3347c6ae99SBarry Smith .seealso: DMGetInterpolation() 3447c6ae99SBarry Smith 3547c6ae99SBarry Smith @*/ 367087cfbeSBarry Smith PetscErrorCode DMGetInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale) 3747c6ae99SBarry Smith { 3847c6ae99SBarry Smith PetscErrorCode ierr; 3947c6ae99SBarry Smith Vec fine; 4047c6ae99SBarry Smith PetscScalar one = 1.0; 4147c6ae99SBarry Smith 4247c6ae99SBarry Smith PetscFunctionBegin; 4347c6ae99SBarry Smith ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr); 4447c6ae99SBarry Smith ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr); 4547c6ae99SBarry Smith ierr = VecSet(fine,one);CHKERRQ(ierr); 4647c6ae99SBarry Smith ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr); 47fcfd50ebSBarry Smith ierr = VecDestroy(&fine);CHKERRQ(ierr); 4847c6ae99SBarry Smith ierr = VecReciprocal(*scale);CHKERRQ(ierr); 4947c6ae99SBarry Smith PetscFunctionReturn(0); 5047c6ae99SBarry Smith } 5147c6ae99SBarry Smith 5247c6ae99SBarry Smith #undef __FUNCT__ 5394013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_1D_Q1" 5494013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_1D_Q1(DM dac,DM daf,Mat *A) 5547c6ae99SBarry Smith { 5647c6ae99SBarry Smith PetscErrorCode ierr; 5747c6ae99SBarry Smith PetscInt i,i_start,m_f,Mx,*idx_f; 5847c6ae99SBarry Smith PetscInt m_ghost,*idx_c,m_ghost_c; 5947c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 6047c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 6185afcc9aSBarry Smith PetscScalar v[2],x; 6247c6ae99SBarry Smith Mat mat; 631321219cSEthan Coon DMDABoundaryType bx; 6447c6ae99SBarry Smith 6547c6ae99SBarry Smith PetscFunctionBegin; 661321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 671321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 681321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 6947c6ae99SBarry Smith ratio = mx/Mx; 7047c6ae99SBarry 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); 7147c6ae99SBarry Smith } else { 7247c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 7347c6ae99SBarry 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); 7447c6ae99SBarry Smith } 7547c6ae99SBarry Smith 76aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 77aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 78aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 7947c6ae99SBarry Smith 80aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 81aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 82aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 8347c6ae99SBarry Smith 8447c6ae99SBarry Smith /* create interpolation matrix */ 8547c6ae99SBarry Smith ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr); 8647c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 8747c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 8847c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr); 8947c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_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 */ 9647c6ae99SBarry Smith row = idx_f[dof*(i-i_start_ghost)]/dof; 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 */ 10747c6ae99SBarry Smith x = ((double)(i - i_c*ratio))/((double)ratio); 10847c6ae99SBarry Smith nc = 0; 10947c6ae99SBarry Smith /* one left and below; or we are right on it */ 11047c6ae99SBarry Smith col = dof*(i_c-i_start_ghost_c); 11147c6ae99SBarry Smith cols[nc] = idx_c[col]/dof; 11247c6ae99SBarry Smith v[nc++] = - x + 1.0; 11347c6ae99SBarry Smith /* one right? */ 11447c6ae99SBarry Smith if (i_c*ratio != i) { 11547c6ae99SBarry Smith cols[nc] = idx_c[col+dof]/dof; 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; 128b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*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 */ 135b3bd94feSDave May row = idx_f[dof*(i-i_start_ghost)]/dof; 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); 143b3bd94feSDave May if (i==mx-1){ li = nxi-1; } 144b3bd94feSDave May 145b3bd94feSDave May /* corners */ 146b3bd94feSDave May col = dof*(i_c-i_start_ghost_c); 147b3bd94feSDave May cols[0] = idx_c[col]/dof; 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 */ 156b3bd94feSDave May if (i==mx-1){ i_c--; } 157b3bd94feSDave May 158b3bd94feSDave May col = dof*(i_c-i_start_ghost_c); 159b3bd94feSDave May cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */ 160b3bd94feSDave May cols[1] = idx_c[col+dof]/dof; 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++) { 165b3bd94feSDave May 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 } 17147c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17247c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 17347c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 174fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 17547c6ae99SBarry Smith PetscFunctionReturn(0); 17647c6ae99SBarry Smith } 17747c6ae99SBarry Smith 17847c6ae99SBarry Smith #undef __FUNCT__ 17994013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_1D_Q0" 18094013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_1D_Q0(DM dac,DM daf,Mat *A) 18147c6ae99SBarry Smith { 18247c6ae99SBarry Smith PetscErrorCode ierr; 18347c6ae99SBarry Smith PetscInt i,i_start,m_f,Mx,*idx_f; 18447c6ae99SBarry Smith PetscInt m_ghost,*idx_c,m_ghost_c; 18547c6ae99SBarry Smith PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; 18647c6ae99SBarry Smith PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; 18747c6ae99SBarry Smith PetscScalar v[2],x; 18847c6ae99SBarry Smith Mat mat; 1891321219cSEthan Coon DMDABoundaryType bx; 19047c6ae99SBarry Smith 19147c6ae99SBarry Smith PetscFunctionBegin; 1921321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 1931321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1941321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 19547c6ae99SBarry Smith ratio = mx/Mx; 19647c6ae99SBarry 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); 19747c6ae99SBarry Smith } else { 19847c6ae99SBarry Smith ratio = (mx-1)/(Mx-1); 19947c6ae99SBarry 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); 20047c6ae99SBarry Smith } 20147c6ae99SBarry Smith 202aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 203aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 204aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 20547c6ae99SBarry Smith 206aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 207aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 208aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 20947c6ae99SBarry Smith 21047c6ae99SBarry Smith /* create interpolation matrix */ 21147c6ae99SBarry Smith ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr); 21247c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); 21347c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 21447c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr); 21547c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 21647c6ae99SBarry Smith 21747c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 21847c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 21947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 22047c6ae99SBarry Smith row = idx_f[dof*(i-i_start_ghost)]/dof; 22147c6ae99SBarry Smith 22247c6ae99SBarry Smith i_c = (i/ratio); /* coarse grid node to left of fine grid node */ 22347c6ae99SBarry Smith 22447c6ae99SBarry Smith /* 22547c6ae99SBarry Smith Only include those interpolation points that are truly 22647c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 22747c6ae99SBarry Smith in x direction; since they have no right neighbor 22847c6ae99SBarry Smith */ 22947c6ae99SBarry Smith x = ((double)(i - i_c*ratio))/((double)ratio); 23047c6ae99SBarry Smith nc = 0; 23147c6ae99SBarry Smith /* one left and below; or we are right on it */ 23247c6ae99SBarry Smith col = dof*(i_c-i_start_ghost_c); 23347c6ae99SBarry Smith cols[nc] = idx_c[col]/dof; 23447c6ae99SBarry Smith v[nc++] = - x + 1.0; 23547c6ae99SBarry Smith /* one right? */ 23647c6ae99SBarry Smith if (i_c*ratio != i) { 23747c6ae99SBarry Smith cols[nc] = idx_c[col+dof]/dof; 23847c6ae99SBarry Smith v[nc++] = x; 23947c6ae99SBarry Smith } 24047c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 24147c6ae99SBarry Smith } 24247c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 24347c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 24447c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 245fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 24647c6ae99SBarry Smith ierr = PetscLogFlops(5.0*m_f);CHKERRQ(ierr); 24747c6ae99SBarry Smith PetscFunctionReturn(0); 24847c6ae99SBarry Smith } 24947c6ae99SBarry Smith 25047c6ae99SBarry Smith #undef __FUNCT__ 25194013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_2D_Q1" 25294013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_2D_Q1(DM dac,DM daf,Mat *A) 25347c6ae99SBarry Smith { 25447c6ae99SBarry Smith PetscErrorCode ierr; 25547c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof; 25647c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz; 25747c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 25847c6ae99SBarry 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; 25947c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 26047c6ae99SBarry Smith PetscScalar v[4],x,y; 26147c6ae99SBarry Smith Mat mat; 2621321219cSEthan Coon DMDABoundaryType bx,by; 26347c6ae99SBarry Smith 26447c6ae99SBarry Smith PetscFunctionBegin; 2651321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 2661321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 2671321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 26847c6ae99SBarry Smith ratioi = mx/Mx; 26947c6ae99SBarry 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); 27047c6ae99SBarry Smith } else { 27147c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 27247c6ae99SBarry 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); 27347c6ae99SBarry Smith } 2741321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC){ 27547c6ae99SBarry Smith ratioj = my/My; 27647c6ae99SBarry 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); 27747c6ae99SBarry Smith } else { 27847c6ae99SBarry Smith ratioj = (my-1)/(My-1); 27947c6ae99SBarry 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); 28047c6ae99SBarry Smith } 28147c6ae99SBarry Smith 28247c6ae99SBarry Smith 283aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 284aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 285aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 28647c6ae99SBarry Smith 287aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 288aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 289aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 29047c6ae99SBarry Smith 29147c6ae99SBarry Smith /* 292aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 29347c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 29447c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 29547c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 29647c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 29747c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 29847c6ae99SBarry Smith 29947c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 30047c6ae99SBarry Smith */ 30147c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr); 30247c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr); 30347c6ae99SBarry Smith ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr); 30447c6ae99SBarry Smith col_scale = size_f/size_c; 30547c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 30647c6ae99SBarry Smith 30747c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 30847c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 30947c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 31047c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 31147c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 31247c6ae99SBarry Smith 31347c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 31447c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 31547c6ae99SBarry Smith 316aa219208SBarry 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\ 31747c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 318aa219208SBarry 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\ 31947c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 32047c6ae99SBarry Smith 32147c6ae99SBarry Smith /* 32247c6ae99SBarry Smith Only include those interpolation points that are truly 32347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 32447c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 32547c6ae99SBarry Smith */ 32647c6ae99SBarry Smith nc = 0; 32747c6ae99SBarry Smith /* one left and below; or we are right on it */ 32847c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 32947c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col]/dof; 33047c6ae99SBarry Smith /* one right and below */ 33147c6ae99SBarry Smith if (i_c*ratioi != i) { 33247c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col+dof]/dof; 33347c6ae99SBarry Smith } 33447c6ae99SBarry Smith /* one left and above */ 33547c6ae99SBarry Smith if (j_c*ratioj != j) { 33647c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col+m_ghost_c*dof]/dof; 33747c6ae99SBarry Smith } 33847c6ae99SBarry Smith /* one right and above */ 3390c82216cSJed Brown if (i_c*ratioi != i && j_c*ratioj != j) { 34047c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; 34147c6ae99SBarry Smith } 34247c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 34347c6ae99SBarry Smith } 34447c6ae99SBarry Smith } 34547c6ae99SBarry Smith ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr); 34647c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 34747c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 34847c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 34947c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 35047c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 35147c6ae99SBarry Smith 35247c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 35385afcc9aSBarry Smith if (!NEWVERSION) { 354b3bd94feSDave May 35547c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 35647c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 35747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 35847c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 35947c6ae99SBarry Smith 36047c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 36147c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 36247c6ae99SBarry Smith 36347c6ae99SBarry Smith /* 36447c6ae99SBarry Smith Only include those interpolation points that are truly 36547c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 36647c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 36747c6ae99SBarry Smith */ 36847c6ae99SBarry Smith x = ((double)(i - i_c*ratioi))/((double)ratioi); 36947c6ae99SBarry Smith y = ((double)(j - j_c*ratioj))/((double)ratioj); 370b3bd94feSDave May 37147c6ae99SBarry Smith nc = 0; 37247c6ae99SBarry Smith /* one left and below; or we are right on it */ 37347c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 37447c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col]/dof; 37547c6ae99SBarry Smith v[nc++] = x*y - x - y + 1.0; 37647c6ae99SBarry Smith /* one right and below */ 37747c6ae99SBarry Smith if (i_c*ratioi != i) { 37847c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col+dof]/dof; 37947c6ae99SBarry Smith v[nc++] = -x*y + x; 38047c6ae99SBarry Smith } 38147c6ae99SBarry Smith /* one left and above */ 38247c6ae99SBarry Smith if (j_c*ratioj != j) { 38347c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col+m_ghost_c*dof]/dof; 38447c6ae99SBarry Smith v[nc++] = -x*y + y; 38547c6ae99SBarry Smith } 38647c6ae99SBarry Smith /* one right and above */ 38747c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 38847c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; 38947c6ae99SBarry Smith v[nc++] = x*y; 39047c6ae99SBarry Smith } 39147c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 39247c6ae99SBarry Smith } 39347c6ae99SBarry Smith } 394b3bd94feSDave May 395b3bd94feSDave May } else { 396b3bd94feSDave May PetscScalar Ni[4]; 397b3bd94feSDave May PetscScalar *xi,*eta; 398b3bd94feSDave May PetscInt li,nxi,lj,neta; 399b3bd94feSDave May 400b3bd94feSDave May /* compute local coordinate arrays */ 401b3bd94feSDave May nxi = ratioi + 1; 402b3bd94feSDave May neta = ratioj + 1; 403b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr); 404b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr); 405b3bd94feSDave May for (li=0; li<nxi; li++) { 40652218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 407b3bd94feSDave May } 408b3bd94feSDave May for (lj=0; lj<neta; lj++) { 40952218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 410b3bd94feSDave May } 411b3bd94feSDave May 412b3bd94feSDave May /* loop over local fine grid nodes setting interpolation for those*/ 413b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 414b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 415b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 416b3bd94feSDave May row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 417b3bd94feSDave May 418b3bd94feSDave May i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 419b3bd94feSDave May j_c = (j/ratioj); /* coarse grid node below fine grid node */ 420b3bd94feSDave May 421b3bd94feSDave May /* remainders */ 422b3bd94feSDave May li = i - ratioi * (i/ratioi); 423b3bd94feSDave May if (i==mx-1){ li = nxi-1; } 424b3bd94feSDave May lj = j - ratioj * (j/ratioj); 425b3bd94feSDave May if (j==my-1){ lj = neta-1; } 426b3bd94feSDave May 427b3bd94feSDave May /* corners */ 428b3bd94feSDave May col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 429b3bd94feSDave May cols[0] = col_shift + idx_c[col]/dof; /* left, below */ 430b3bd94feSDave May Ni[0] = 1.0; 431b3bd94feSDave May if ( (li==0) || (li==nxi-1) ) { 432b3bd94feSDave May if ( (lj==0) || (lj==neta-1) ) { 433b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 434b3bd94feSDave May continue; 435b3bd94feSDave May } 436b3bd94feSDave May } 437b3bd94feSDave May 438b3bd94feSDave May /* edges + interior */ 439b3bd94feSDave May /* remainders */ 440b3bd94feSDave May if (i==mx-1){ i_c--; } 441b3bd94feSDave May if (j==my-1){ j_c--; } 442b3bd94feSDave May 443b3bd94feSDave May col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 444b3bd94feSDave May cols[0] = col_shift + idx_c[col]/dof; /* left, below */ 445b3bd94feSDave May cols[1] = col_shift + idx_c[col+dof]/dof; /* right, below */ 446b3bd94feSDave May cols[2] = col_shift + idx_c[col+m_ghost_c*dof]/dof; /* left, above */ 447b3bd94feSDave May cols[3] = col_shift + idx_c[col+(m_ghost_c+1)*dof]/dof; /* right, above */ 448b3bd94feSDave May 449b3bd94feSDave May Ni[0] = 0.25*(1.0-xi[li])*(1.0-eta[lj]); 450b3bd94feSDave May Ni[1] = 0.25*(1.0+xi[li])*(1.0-eta[lj]); 451b3bd94feSDave May Ni[2] = 0.25*(1.0-xi[li])*(1.0+eta[lj]); 452b3bd94feSDave May Ni[3] = 0.25*(1.0+xi[li])*(1.0+eta[lj]); 453b3bd94feSDave May 454b3bd94feSDave May nc = 0; 455b3bd94feSDave May if( PetscAbsScalar(Ni[0])<1.0e-32) { cols[0]=-1; } 456b3bd94feSDave May if( PetscAbsScalar(Ni[1])<1.0e-32) { cols[1]=-1; } 457b3bd94feSDave May if( PetscAbsScalar(Ni[2])<1.0e-32) { cols[2]=-1; } 458b3bd94feSDave May if( PetscAbsScalar(Ni[3])<1.0e-32) { cols[3]=-1; } 459b3bd94feSDave May 460b3bd94feSDave May ierr = MatSetValues(mat,1,&row,4,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 461b3bd94feSDave May } 462b3bd94feSDave May } 463b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 464b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 465b3bd94feSDave May } 46647c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 46747c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 46847c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 469fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 47047c6ae99SBarry Smith PetscFunctionReturn(0); 47147c6ae99SBarry Smith } 47247c6ae99SBarry Smith 47347c6ae99SBarry Smith /* 47447c6ae99SBarry Smith Contributed by Andrei Draganescu <aidraga@sandia.gov> 47547c6ae99SBarry Smith */ 47647c6ae99SBarry Smith #undef __FUNCT__ 47794013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_2D_Q0" 47894013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_2D_Q0(DM dac,DM daf,Mat *A) 47947c6ae99SBarry Smith { 48047c6ae99SBarry Smith PetscErrorCode ierr; 48147c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof; 48247c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,*dnz,*onz; 48347c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[4],mx,m_c,my,nc,ratioi,ratioj; 48447c6ae99SBarry 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; 48547c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 48647c6ae99SBarry Smith PetscScalar v[4]; 48747c6ae99SBarry Smith Mat mat; 4881321219cSEthan Coon DMDABoundaryType bx,by; 48947c6ae99SBarry Smith 49047c6ae99SBarry Smith PetscFunctionBegin; 4911321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 4921321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 4931321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x"); 4941321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y"); 49547c6ae99SBarry Smith ratioi = mx/Mx; 49647c6ae99SBarry Smith ratioj = my/My; 49747c6ae99SBarry 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"); 49847c6ae99SBarry 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"); 49947c6ae99SBarry Smith if (ratioi != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 2"); 50047c6ae99SBarry Smith if (ratioj != 2) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 2"); 50147c6ae99SBarry Smith 502aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 503aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 504aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 50547c6ae99SBarry Smith 506aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 507aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 508aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 50947c6ae99SBarry Smith 51047c6ae99SBarry Smith /* 511aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 51247c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 51347c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 51447c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 51547c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 51647c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 51747c6ae99SBarry Smith 51847c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 51947c6ae99SBarry Smith */ 52047c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr); 52147c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr); 52247c6ae99SBarry Smith ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr); 52347c6ae99SBarry Smith col_scale = size_f/size_c; 52447c6ae99SBarry Smith col_shift = Mx*My*(rank_f/size_c); 52547c6ae99SBarry Smith 52647c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); 52747c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 52847c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 52947c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 53047c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 53147c6ae99SBarry Smith 53247c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 53347c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 53447c6ae99SBarry Smith 535aa219208SBarry 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\ 53647c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 537aa219208SBarry 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\ 53847c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 53947c6ae99SBarry Smith 54047c6ae99SBarry Smith /* 54147c6ae99SBarry Smith Only include those interpolation points that are truly 54247c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 54347c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 54447c6ae99SBarry Smith */ 54547c6ae99SBarry Smith nc = 0; 54647c6ae99SBarry Smith /* one left and below; or we are right on it */ 54747c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 54847c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col]/dof; 54947c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 55047c6ae99SBarry Smith } 55147c6ae99SBarry Smith } 55247c6ae99SBarry Smith ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr); 55347c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); 55447c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 55547c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 55647c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 55747c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 55847c6ae99SBarry Smith 55947c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 56047c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 56147c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 56247c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 56347c6ae99SBarry Smith row = idx_f[dof*(m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 56447c6ae99SBarry Smith 56547c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 56647c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 56747c6ae99SBarry Smith nc = 0; 56847c6ae99SBarry Smith /* one left and below; or we are right on it */ 56947c6ae99SBarry Smith col = dof*(m_ghost_c*(j_c-j_start_ghost_c) + (i_c-i_start_ghost_c)); 57047c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col]/dof; 57147c6ae99SBarry Smith v[nc++] = 1.0; 57247c6ae99SBarry Smith 57347c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 57447c6ae99SBarry Smith } 57547c6ae99SBarry Smith } 57647c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57747c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57847c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 579fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 58047c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f);CHKERRQ(ierr); 58147c6ae99SBarry Smith PetscFunctionReturn(0); 58247c6ae99SBarry Smith } 58347c6ae99SBarry Smith 58447c6ae99SBarry Smith /* 58547c6ae99SBarry Smith Contributed by Jianming Yang <jianming-yang@uiowa.edu> 58647c6ae99SBarry Smith */ 58747c6ae99SBarry Smith #undef __FUNCT__ 58894013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_3D_Q0" 58994013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_3D_Q0(DM dac,DM daf,Mat *A) 59047c6ae99SBarry Smith { 59147c6ae99SBarry Smith PetscErrorCode ierr; 59247c6ae99SBarry Smith PetscInt i,j,l,i_start,j_start,l_start,m_f,n_f,p_f,Mx,My,Mz,*idx_f,dof; 59347c6ae99SBarry Smith PetscInt m_ghost,n_ghost,p_ghost,*idx_c,m_ghost_c,n_ghost_c,p_ghost_c,nc,*dnz,*onz; 59447c6ae99SBarry 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; 59547c6ae99SBarry 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; 59647c6ae99SBarry Smith PetscMPIInt size_c,size_f,rank_f; 59747c6ae99SBarry Smith PetscScalar v[8]; 59847c6ae99SBarry Smith Mat mat; 5991321219cSEthan Coon DMDABoundaryType bx,by,bz; 60047c6ae99SBarry Smith 60147c6ae99SBarry Smith PetscFunctionBegin; 6021321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 6031321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 6041321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in x"); 6051321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in y"); 6061321219cSEthan Coon if (bz == DMDA_BOUNDARY_PERIODIC) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Cannot handle periodic grid in z"); 60747c6ae99SBarry Smith ratioi = mx/Mx; 60847c6ae99SBarry Smith ratioj = my/My; 60947c6ae99SBarry Smith ratiol = mz/Mz; 61047c6ae99SBarry 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"); 61147c6ae99SBarry 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"); 61247c6ae99SBarry 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"); 61347c6ae99SBarry Smith if (ratioi != 2 && ratioi != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in x must be 1 or 2"); 61447c6ae99SBarry Smith if (ratioj != 2 && ratioj != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in y must be 1 or 2"); 61547c6ae99SBarry Smith if (ratiol != 2 && ratiol != 1) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_WRONG,"Coarsening factor in z must be 1 or 2"); 61647c6ae99SBarry Smith 617aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 618aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 619aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 62047c6ae99SBarry Smith 621aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 622aa219208SBarry 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); 623aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 62447c6ae99SBarry Smith /* 625aa219208SBarry Smith Used for handling a coarse DMDA that lives on 1/4 the processors of the fine DMDA. 62647c6ae99SBarry Smith The coarse vector is then duplicated 4 times (each time it lives on 1/4 of the 62747c6ae99SBarry Smith processors). It's effective length is hence 4 times its normal length, this is 62847c6ae99SBarry Smith why the col_scale is multiplied by the interpolation matrix column sizes. 62947c6ae99SBarry Smith sol_shift allows each set of 1/4 processors do its own interpolation using ITS 63047c6ae99SBarry Smith copy of the coarse vector. A bit of a hack but you do better. 63147c6ae99SBarry Smith 63247c6ae99SBarry Smith In the standard case when size_f == size_c col_scale == 1 and col_shift == 0 63347c6ae99SBarry Smith */ 63447c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)dac)->comm,&size_c);CHKERRQ(ierr); 63547c6ae99SBarry Smith ierr = MPI_Comm_size(((PetscObject)daf)->comm,&size_f);CHKERRQ(ierr); 63647c6ae99SBarry Smith ierr = MPI_Comm_rank(((PetscObject)daf)->comm,&rank_f);CHKERRQ(ierr); 63747c6ae99SBarry Smith col_scale = size_f/size_c; 63847c6ae99SBarry Smith col_shift = Mx*My*Mz*(rank_f/size_c); 63947c6ae99SBarry Smith 64047c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)daf)->comm,m_f*n_f*p_f,col_scale*m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 64147c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 64247c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 64347c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 64447c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 64547c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 64647c6ae99SBarry Smith 64747c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 64847c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 64947c6ae99SBarry Smith l_c = (l/ratiol); 65047c6ae99SBarry Smith 651aa219208SBarry 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\ 65247c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 653aa219208SBarry 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\ 65447c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 655aa219208SBarry 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\ 65647c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 65747c6ae99SBarry Smith 65847c6ae99SBarry Smith /* 65947c6ae99SBarry Smith Only include those interpolation points that are truly 66047c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 66147c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 66247c6ae99SBarry Smith */ 66347c6ae99SBarry Smith nc = 0; 66447c6ae99SBarry Smith /* one left and below; or we are right on it */ 66547c6ae99SBarry 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)); 66647c6ae99SBarry Smith cols[nc++] = col_shift + idx_c[col]/dof; 66747c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 66847c6ae99SBarry Smith } 66947c6ae99SBarry Smith } 67047c6ae99SBarry Smith } 67147c6ae99SBarry Smith ierr = MatCreate(((PetscObject)daf)->comm,&mat);CHKERRQ(ierr); 67247c6ae99SBarry 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); 67347c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 67447c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 67547c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 67647c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 67747c6ae99SBarry Smith 67847c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 67947c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 68047c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 68147c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 68247c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 68347c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 68447c6ae99SBarry Smith 68547c6ae99SBarry Smith i_c = (i/ratioi); /* coarse grid node to left of fine grid node */ 68647c6ae99SBarry Smith j_c = (j/ratioj); /* coarse grid node below fine grid node */ 68747c6ae99SBarry Smith l_c = (l/ratiol); 68847c6ae99SBarry Smith nc = 0; 68947c6ae99SBarry Smith /* one left and below; or we are right on it */ 69047c6ae99SBarry 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)); 69147c6ae99SBarry Smith cols[nc] = col_shift + idx_c[col]/dof; 69247c6ae99SBarry Smith v[nc++] = 1.0; 69347c6ae99SBarry Smith 69447c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 69547c6ae99SBarry Smith } 69647c6ae99SBarry Smith } 69747c6ae99SBarry Smith } 69847c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 69947c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 70047c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 701fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 70247c6ae99SBarry Smith ierr = PetscLogFlops(13.0*m_f*n_f*p_f);CHKERRQ(ierr); 70347c6ae99SBarry Smith PetscFunctionReturn(0); 70447c6ae99SBarry Smith } 70547c6ae99SBarry Smith 70647c6ae99SBarry Smith #undef __FUNCT__ 70794013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA_3D_Q1" 70894013140SBarry Smith PetscErrorCode DMGetInterpolation_DA_3D_Q1(DM dac,DM daf,Mat *A) 70947c6ae99SBarry Smith { 71047c6ae99SBarry Smith PetscErrorCode ierr; 71147c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof,l; 71247c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,Mz,mz; 71347c6ae99SBarry Smith PetscInt row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok; 71447c6ae99SBarry Smith PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 71547c6ae99SBarry Smith PetscInt l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c; 71647c6ae99SBarry Smith PetscInt l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz; 71747c6ae99SBarry Smith PetscScalar v[8],x,y,z; 71847c6ae99SBarry Smith Mat mat; 7191321219cSEthan Coon DMDABoundaryType bx,by,bz; 72047c6ae99SBarry Smith 72147c6ae99SBarry Smith PetscFunctionBegin; 7221321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 7231321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 72447c6ae99SBarry Smith if (mx == Mx) { 72547c6ae99SBarry Smith ratioi = 1; 7261321219cSEthan Coon } else if (bx == DMDA_BOUNDARY_PERIODIC) { 72747c6ae99SBarry Smith ratioi = mx/Mx; 72847c6ae99SBarry 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); 72947c6ae99SBarry Smith } else { 73047c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 73147c6ae99SBarry 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); 73247c6ae99SBarry Smith } 73347c6ae99SBarry Smith if (my == My) { 73447c6ae99SBarry Smith ratioj = 1; 7351321219cSEthan Coon } else if (by == DMDA_BOUNDARY_PERIODIC) { 73647c6ae99SBarry Smith ratioj = my/My; 73747c6ae99SBarry 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); 73847c6ae99SBarry Smith } else { 73947c6ae99SBarry Smith ratioj = (my-1)/(My-1); 74047c6ae99SBarry 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); 74147c6ae99SBarry Smith } 74247c6ae99SBarry Smith if (mz == Mz) { 74347c6ae99SBarry Smith ratiok = 1; 7441321219cSEthan Coon } else if (bz == DMDA_BOUNDARY_PERIODIC) { 74547c6ae99SBarry Smith ratiok = mz/Mz; 74647c6ae99SBarry 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); 74747c6ae99SBarry Smith } else { 74847c6ae99SBarry Smith ratiok = (mz-1)/(Mz-1); 74947c6ae99SBarry 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); 75047c6ae99SBarry Smith } 75147c6ae99SBarry Smith 752aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 753aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 754aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 75547c6ae99SBarry Smith 756aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 757aa219208SBarry 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); 758aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 75947c6ae99SBarry Smith 76047c6ae99SBarry Smith /* create interpolation matrix, determining exact preallocation */ 76147c6ae99SBarry Smith ierr = MatPreallocateInitialize(((PetscObject)dac)->comm,m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); 76247c6ae99SBarry Smith /* loop over local fine grid nodes counting interpolating points */ 76347c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 76447c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 76547c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 76647c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 76747c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 76847c6ae99SBarry Smith i_c = (i/ratioi); 76947c6ae99SBarry Smith j_c = (j/ratioj); 77047c6ae99SBarry Smith l_c = (l/ratiok); 771aa219208SBarry 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\ 77247c6ae99SBarry Smith l_start %D l_c %D l_start_ghost_c %D",l_start,l_c,l_start_ghost_c); 773aa219208SBarry 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\ 77447c6ae99SBarry Smith j_start %D j_c %D j_start_ghost_c %D",j_start,j_c,j_start_ghost_c); 775aa219208SBarry 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\ 77647c6ae99SBarry Smith i_start %D i_c %D i_start_ghost_c %D",i_start,i_c,i_start_ghost_c); 77747c6ae99SBarry Smith 77847c6ae99SBarry Smith /* 77947c6ae99SBarry Smith Only include those interpolation points that are truly 78047c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 78147c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 78247c6ae99SBarry Smith */ 78347c6ae99SBarry Smith nc = 0; 78447c6ae99SBarry 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)); 78547c6ae99SBarry Smith cols[nc++] = idx_c[col]/dof; 78647c6ae99SBarry Smith if (i_c*ratioi != i) { 78747c6ae99SBarry Smith cols[nc++] = idx_c[col+dof]/dof; 78847c6ae99SBarry Smith } 78947c6ae99SBarry Smith if (j_c*ratioj != j) { 79047c6ae99SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*dof]/dof; 79147c6ae99SBarry Smith } 79247c6ae99SBarry Smith if (l_c*ratiok != l) { 79347c6ae99SBarry Smith cols[nc++] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof; 79447c6ae99SBarry Smith } 79547c6ae99SBarry Smith if (j_c*ratioj != j && i_c*ratioi != i) { 79647c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c+1)*dof]/dof; 79747c6ae99SBarry Smith } 79847c6ae99SBarry Smith if (j_c*ratioj != j && l_c*ratiok != l) { 79947c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof; 80047c6ae99SBarry Smith } 80147c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l) { 80247c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; 80347c6ae99SBarry Smith } 80447c6ae99SBarry Smith if (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 80547c6ae99SBarry Smith cols[nc++] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; 80647c6ae99SBarry Smith } 80747c6ae99SBarry Smith ierr = MatPreallocateSet(row,nc,cols,dnz,onz);CHKERRQ(ierr); 80847c6ae99SBarry Smith } 80947c6ae99SBarry Smith } 81047c6ae99SBarry Smith } 81147c6ae99SBarry Smith ierr = MatCreate(((PetscObject)dac)->comm,&mat);CHKERRQ(ierr); 81247c6ae99SBarry Smith ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr); 81347c6ae99SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 81447c6ae99SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); 81547c6ae99SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); 81647c6ae99SBarry Smith ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 81747c6ae99SBarry Smith 81847c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 819*2adb9dcfSBarry Smith if (!NEWVERSION) { 820b3bd94feSDave May 82147c6ae99SBarry Smith for (l=l_start; l<l_start+p_f; l++) { 82247c6ae99SBarry Smith for (j=j_start; j<j_start+n_f; j++) { 82347c6ae99SBarry Smith for (i=i_start; i<i_start+m_f; i++) { 82447c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 82547c6ae99SBarry Smith row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 82647c6ae99SBarry Smith 82747c6ae99SBarry Smith i_c = (i/ratioi); 82847c6ae99SBarry Smith j_c = (j/ratioj); 82947c6ae99SBarry Smith l_c = (l/ratiok); 83047c6ae99SBarry Smith 83147c6ae99SBarry Smith /* 83247c6ae99SBarry Smith Only include those interpolation points that are truly 83347c6ae99SBarry Smith nonzero. Note this is very important for final grid lines 83447c6ae99SBarry Smith in x and y directions; since they have no right/top neighbors 83547c6ae99SBarry Smith */ 83647c6ae99SBarry Smith x = ((double)(i - i_c*ratioi))/((double)ratioi); 83747c6ae99SBarry Smith y = ((double)(j - j_c*ratioj))/((double)ratioj); 83847c6ae99SBarry Smith z = ((double)(l - l_c*ratiok))/((double)ratiok); 839b3bd94feSDave May 84047c6ae99SBarry Smith nc = 0; 84147c6ae99SBarry Smith /* one left and below; or we are right on it */ 84247c6ae99SBarry 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)); 84347c6ae99SBarry Smith 84447c6ae99SBarry Smith cols[nc] = idx_c[col]/dof; 84547c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 84647c6ae99SBarry Smith 84747c6ae99SBarry Smith if (i_c*ratioi != i) { 84847c6ae99SBarry Smith cols[nc] = idx_c[col+dof]/dof; 84947c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. - (2.0*y-1.))*(1. - (2.0*z-1.)); 85047c6ae99SBarry Smith } 85147c6ae99SBarry Smith 85247c6ae99SBarry Smith if (j_c*ratioj != j) { 85347c6ae99SBarry Smith cols[nc] = idx_c[col+m_ghost_c*dof]/dof; 85447c6ae99SBarry Smith v[nc++] = .125*(1. - (2.0*x-1.))*(1. + (2.0*y-1.))*(1. - (2.0*z-1.)); 85547c6ae99SBarry Smith } 85647c6ae99SBarry Smith 85747c6ae99SBarry Smith if (l_c*ratiok != l) { 85847c6ae99SBarry Smith cols[nc] = idx_c[col+m_ghost_c*n_ghost_c*dof]/dof; 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 && i_c*ratioi != i) { 86347c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c+1)*dof]/dof; 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 (j_c*ratioj != j && l_c*ratiok != l) { 86847c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof; 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 (i_c*ratioi != i && l_c*ratiok != l) { 87347c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; 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 (i_c*ratioi != i && l_c*ratiok != l && j_c*ratioj != j) { 87847c6ae99SBarry Smith cols[nc] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; 87947c6ae99SBarry Smith v[nc++] = .125*(1. + (2.0*x-1.))*(1. + (2.0*y-1.))*(1. + (2.0*z-1.)); 88047c6ae99SBarry Smith } 88147c6ae99SBarry Smith ierr = MatSetValues(mat,1,&row,nc,cols,v,INSERT_VALUES);CHKERRQ(ierr); 88247c6ae99SBarry Smith } 88347c6ae99SBarry Smith } 88447c6ae99SBarry Smith } 885b3bd94feSDave May 886b3bd94feSDave May } else { 887b3bd94feSDave May PetscScalar *xi,*eta,*zeta; 888b3bd94feSDave May PetscInt li,nxi,lj,neta,lk,nzeta,n; 889b3bd94feSDave May PetscScalar Ni[8]; 890b3bd94feSDave May 891b3bd94feSDave May /* compute local coordinate arrays */ 892b3bd94feSDave May nxi = ratioi + 1; 893b3bd94feSDave May neta = ratioj + 1; 894b3bd94feSDave May nzeta = ratiok + 1; 895b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*nxi,&xi);CHKERRQ(ierr); 896b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*neta,&eta);CHKERRQ(ierr); 897b3bd94feSDave May ierr = PetscMalloc(sizeof(PetscScalar)*nzeta,&zeta);CHKERRQ(ierr); 898b3bd94feSDave May for (li=0; li<nxi; li++) { 89952218ef2SJed Brown xi[li] = -1.0 + (PetscScalar)li*(2.0/(PetscScalar)(nxi-1)); 900b3bd94feSDave May } 901b3bd94feSDave May for (lj=0; lj<neta; lj++) { 90252218ef2SJed Brown eta[lj] = -1.0 + (PetscScalar)lj*(2.0/(PetscScalar)(neta-1)); 903b3bd94feSDave May } 904b3bd94feSDave May for (lk=0; lk<nzeta; lk++) { 90552218ef2SJed Brown zeta[lk] = -1.0 + (PetscScalar)lk*(2.0/(PetscScalar)(nzeta-1)); 906b3bd94feSDave May } 907b3bd94feSDave May 908b3bd94feSDave May for (l=l_start; l<l_start+p_f; l++) { 909b3bd94feSDave May for (j=j_start; j<j_start+n_f; j++) { 910b3bd94feSDave May for (i=i_start; i<i_start+m_f; i++) { 911b3bd94feSDave May /* convert to local "natural" numbering and then to PETSc global numbering */ 912b3bd94feSDave May row = idx_f[dof*(m_ghost*n_ghost*(l-l_start_ghost) + m_ghost*(j-j_start_ghost) + (i-i_start_ghost))]/dof; 913b3bd94feSDave May 914b3bd94feSDave May i_c = (i/ratioi); 915b3bd94feSDave May j_c = (j/ratioj); 916b3bd94feSDave May l_c = (l/ratiok); 917b3bd94feSDave May 918b3bd94feSDave May /* remainders */ 919b3bd94feSDave May li = i - ratioi * (i/ratioi); 920b3bd94feSDave May if (i==mx-1){ li = nxi-1; } 921b3bd94feSDave May lj = j - ratioj * (j/ratioj); 922b3bd94feSDave May if (j==my-1){ lj = neta-1; } 923b3bd94feSDave May lk = l - ratiok * (l/ratiok); 924b3bd94feSDave May if (l==mz-1){ lk = nzeta-1; } 925b3bd94feSDave May 926b3bd94feSDave May /* corners */ 927b3bd94feSDave 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)); 928b3bd94feSDave May cols[0] = idx_c[col]/dof; 929b3bd94feSDave May Ni[0] = 1.0; 930b3bd94feSDave May if ( (li==0) || (li==nxi-1) ) { 931b3bd94feSDave May if ( (lj==0) || (lj==neta-1) ) { 932b3bd94feSDave May if ( (lk==0) || (lk==nzeta-1) ) { 933b3bd94feSDave May ierr = MatSetValue(mat,row,cols[0],Ni[0],INSERT_VALUES);CHKERRQ(ierr); 934b3bd94feSDave May continue; 935b3bd94feSDave May } 936b3bd94feSDave May } 937b3bd94feSDave May } 938b3bd94feSDave May 939b3bd94feSDave May /* edges + interior */ 940b3bd94feSDave May /* remainders */ 941b3bd94feSDave May if (i==mx-1){ i_c--; } 942b3bd94feSDave May if (j==my-1){ j_c--; } 943b3bd94feSDave May if (l==mz-1){ l_c--; } 944b3bd94feSDave May 945b3bd94feSDave 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)); 946b3bd94feSDave May cols[0] = idx_c[col]/dof; /* one left and below; or we are right on it */ 947b3bd94feSDave May cols[1] = idx_c[col+dof]/dof; /* one right and below */ 948b3bd94feSDave May cols[2] = idx_c[col+m_ghost_c*dof]/dof; /* one left and above */ 949b3bd94feSDave May cols[3] = idx_c[col+(m_ghost_c+1)*dof]/dof; /* one right and above */ 950b3bd94feSDave May 951b3bd94feSDave 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 */ 952b3bd94feSDave May cols[5] = idx_c[col+(m_ghost_c*n_ghost_c+1)*dof]/dof; /* one right and below, and front */ 953b3bd94feSDave May cols[6] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c)*dof]/dof;/* one left and above and front*/ 954b3bd94feSDave May cols[7] = idx_c[col+(m_ghost_c*n_ghost_c+m_ghost_c+1)*dof]/dof; /* one right and above and front */ 955b3bd94feSDave May 956b3bd94feSDave May Ni[0] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 957b3bd94feSDave May Ni[1] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0-zeta[lk]); 958b3bd94feSDave May Ni[2] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 959b3bd94feSDave May Ni[3] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0-zeta[lk]); 960b3bd94feSDave May 961b3bd94feSDave May Ni[4] = 0.125*(1.0-xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 962b3bd94feSDave May Ni[5] = 0.125*(1.0+xi[li])*(1.0-eta[lj])*(1.0+zeta[lk]); 963b3bd94feSDave May Ni[6] = 0.125*(1.0-xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 964b3bd94feSDave May Ni[7] = 0.125*(1.0+xi[li])*(1.0+eta[lj])*(1.0+zeta[lk]); 965b3bd94feSDave May 966b3bd94feSDave May for (n=0; n<8; n++) { 967b3bd94feSDave May if( PetscAbsScalar(Ni[n])<1.0e-32) { cols[n]=-1; } 968b3bd94feSDave May } 969b3bd94feSDave May ierr = MatSetValues(mat,1,&row,8,cols,Ni,INSERT_VALUES);CHKERRQ(ierr); 970b3bd94feSDave May 971b3bd94feSDave May } 972b3bd94feSDave May } 973b3bd94feSDave May } 974b3bd94feSDave May ierr = PetscFree(xi);CHKERRQ(ierr); 975b3bd94feSDave May ierr = PetscFree(eta);CHKERRQ(ierr); 976b3bd94feSDave May ierr = PetscFree(zeta);CHKERRQ(ierr); 977b3bd94feSDave May } 978b3bd94feSDave May 97947c6ae99SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 98047c6ae99SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 98147c6ae99SBarry Smith 98247c6ae99SBarry Smith ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); 983fcfd50ebSBarry Smith ierr = MatDestroy(&mat);CHKERRQ(ierr); 98447c6ae99SBarry Smith PetscFunctionReturn(0); 98547c6ae99SBarry Smith } 98647c6ae99SBarry Smith 98747c6ae99SBarry Smith #undef __FUNCT__ 98894013140SBarry Smith #define __FUNCT__ "DMGetInterpolation_DA" 9897087cfbeSBarry Smith PetscErrorCode DMGetInterpolation_DA(DM dac,DM daf,Mat *A,Vec *scale) 99047c6ae99SBarry Smith { 99147c6ae99SBarry Smith PetscErrorCode ierr; 99247c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 9931321219cSEthan Coon DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf; 994aa219208SBarry Smith DMDAStencilType stc,stf; 99547c6ae99SBarry Smith DM_DA *ddc = (DM_DA*)dac->data; 99647c6ae99SBarry Smith 99747c6ae99SBarry Smith PetscFunctionBegin; 99847c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 99947c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 100047c6ae99SBarry Smith PetscValidPointer(A,3); 100147c6ae99SBarry Smith if (scale) PetscValidPointer(scale,4); 100247c6ae99SBarry Smith 10031321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 10041321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1005aa219208SBarry Smith if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr); 1006aa219208SBarry Smith if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr); 1007aa219208SBarry 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); 10081321219cSEthan Coon if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr); 1009aa219208SBarry Smith if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr); 101047c6ae99SBarry Smith if (Mc < 2 && Mf > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 101147c6ae99SBarry 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"); 101247c6ae99SBarry 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"); 101347c6ae99SBarry Smith 1014aa219208SBarry Smith if (ddc->interptype == DMDA_Q1){ 101547c6ae99SBarry Smith if (dimc == 1){ 101694013140SBarry Smith ierr = DMGetInterpolation_DA_1D_Q1(dac,daf,A);CHKERRQ(ierr); 101747c6ae99SBarry Smith } else if (dimc == 2){ 101894013140SBarry Smith ierr = DMGetInterpolation_DA_2D_Q1(dac,daf,A);CHKERRQ(ierr); 101947c6ae99SBarry Smith } else if (dimc == 3){ 102094013140SBarry Smith ierr = DMGetInterpolation_DA_3D_Q1(dac,daf,A);CHKERRQ(ierr); 102185afcc9aSBarry Smith } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 1022aa219208SBarry Smith } else if (ddc->interptype == DMDA_Q0){ 102347c6ae99SBarry Smith if (dimc == 1){ 102494013140SBarry Smith ierr = DMGetInterpolation_DA_1D_Q0(dac,daf,A);CHKERRQ(ierr); 102547c6ae99SBarry Smith } else if (dimc == 2){ 102694013140SBarry Smith ierr = DMGetInterpolation_DA_2D_Q0(dac,daf,A);CHKERRQ(ierr); 102747c6ae99SBarry Smith } else if (dimc == 3){ 102894013140SBarry Smith ierr = DMGetInterpolation_DA_3D_Q0(dac,daf,A);CHKERRQ(ierr); 102985afcc9aSBarry Smith } else SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_SUP,"No support for this DMDA dimension %D for interpolation type %d",dimc,(int)ddc->interptype); 103047c6ae99SBarry Smith } 103147c6ae99SBarry Smith if (scale) { 103247c6ae99SBarry Smith ierr = DMGetInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr); 103347c6ae99SBarry Smith } 103447c6ae99SBarry Smith PetscFunctionReturn(0); 103547c6ae99SBarry Smith } 103647c6ae99SBarry Smith 103747c6ae99SBarry Smith #undef __FUNCT__ 10380bb2b966SJungho Lee #define __FUNCT__ "DMGetInjection_DA_1D" 10390bb2b966SJungho Lee PetscErrorCode DMGetInjection_DA_1D(DM dac,DM daf,VecScatter *inject) 10400bb2b966SJungho Lee { 10410bb2b966SJungho Lee PetscErrorCode ierr; 10420bb2b966SJungho Lee PetscInt i,i_start,m_f,Mx,*idx_f,dof; 10430bb2b966SJungho Lee PetscInt m_ghost,*idx_c,m_ghost_c; 10440bb2b966SJungho Lee PetscInt row,i_start_ghost,mx,m_c,nc,ratioi; 10450bb2b966SJungho Lee PetscInt i_start_c,i_start_ghost_c; 10460bb2b966SJungho Lee PetscInt *cols; 10470bb2b966SJungho Lee DMDABoundaryType bx; 10480bb2b966SJungho Lee Vec vecf,vecc; 10490bb2b966SJungho Lee IS isf; 10500bb2b966SJungho Lee 10510bb2b966SJungho Lee PetscFunctionBegin; 10520bb2b966SJungho Lee ierr = DMDAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&bx,0,0,0);CHKERRQ(ierr); 10530bb2b966SJungho Lee ierr = DMDAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 10540bb2b966SJungho Lee if (bx == DMDA_BOUNDARY_PERIODIC) { 10550bb2b966SJungho Lee ratioi = mx/Mx; 10560bb2b966SJungho 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); 10570bb2b966SJungho Lee } else { 10580bb2b966SJungho Lee ratioi = (mx-1)/(Mx-1); 10590bb2b966SJungho 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); 10600bb2b966SJungho Lee } 10610bb2b966SJungho Lee 10620bb2b966SJungho Lee ierr = DMDAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); 10630bb2b966SJungho Lee ierr = DMDAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); 10640bb2b966SJungho Lee ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 10650bb2b966SJungho Lee 10660bb2b966SJungho Lee ierr = DMDAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); 10670bb2b966SJungho Lee ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); 10680bb2b966SJungho Lee ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 10690bb2b966SJungho Lee 10700bb2b966SJungho Lee 10710bb2b966SJungho Lee /* loop over local fine grid nodes setting interpolation for those*/ 10720bb2b966SJungho Lee nc = 0; 10730bb2b966SJungho Lee ierr = PetscMalloc(m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr); 10740bb2b966SJungho Lee 10750bb2b966SJungho Lee 10760bb2b966SJungho Lee for (i=i_start_c; i<i_start_c+m_c; i++) { 10770bb2b966SJungho Lee PetscInt i_f = i*ratioi; 10780bb2b966SJungho Lee 10790bb2b966SJungho 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\ 10800bb2b966SJungho Lee i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 10810bb2b966SJungho Lee row = idx_f[dof*(i_f-i_start_ghost)]; 10820bb2b966SJungho Lee cols[nc++] = row/dof; 10830bb2b966SJungho Lee } 10840bb2b966SJungho Lee 10850bb2b966SJungho Lee 10860bb2b966SJungho Lee ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 10870bb2b966SJungho Lee ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 10880bb2b966SJungho Lee ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 10890bb2b966SJungho Lee ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr); 10900bb2b966SJungho Lee ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 10910bb2b966SJungho Lee ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 10920bb2b966SJungho Lee ierr = ISDestroy(&isf);CHKERRQ(ierr); 10930bb2b966SJungho Lee PetscFunctionReturn(0); 10940bb2b966SJungho Lee } 10950bb2b966SJungho Lee 10960bb2b966SJungho Lee #undef __FUNCT__ 109794013140SBarry Smith #define __FUNCT__ "DMGetInjection_DA_2D" 109894013140SBarry Smith PetscErrorCode DMGetInjection_DA_2D(DM dac,DM daf,VecScatter *inject) 109947c6ae99SBarry Smith { 110047c6ae99SBarry Smith PetscErrorCode ierr; 110147c6ae99SBarry Smith PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof; 110247c6ae99SBarry Smith PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c; 110347c6ae99SBarry Smith PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; 1104076202ddSJed Brown PetscInt i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; 110547c6ae99SBarry Smith PetscInt *cols; 11061321219cSEthan Coon DMDABoundaryType bx,by; 110747c6ae99SBarry Smith Vec vecf,vecc; 110847c6ae99SBarry Smith IS isf; 110947c6ae99SBarry Smith 111047c6ae99SBarry Smith PetscFunctionBegin; 11111321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&bx,&by,0,0);CHKERRQ(ierr); 11121321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 11131321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC) { 111447c6ae99SBarry Smith ratioi = mx/Mx; 111547c6ae99SBarry 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); 111647c6ae99SBarry Smith } else { 111747c6ae99SBarry Smith ratioi = (mx-1)/(Mx-1); 111847c6ae99SBarry 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); 111947c6ae99SBarry Smith } 11201321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC) { 112147c6ae99SBarry Smith ratioj = my/My; 112247c6ae99SBarry 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); 112347c6ae99SBarry Smith } else { 112447c6ae99SBarry Smith ratioj = (my-1)/(My-1); 112547c6ae99SBarry 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); 112647c6ae99SBarry Smith } 112747c6ae99SBarry Smith 1128aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); 1129aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); 1130aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 113147c6ae99SBarry Smith 1132aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); 1133aa219208SBarry Smith ierr = DMDAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); 1134aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 113547c6ae99SBarry Smith 113647c6ae99SBarry Smith 113747c6ae99SBarry Smith /* loop over local fine grid nodes setting interpolation for those*/ 113847c6ae99SBarry Smith nc = 0; 113947c6ae99SBarry Smith ierr = PetscMalloc(n_f*m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr); 1140076202ddSJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1141076202ddSJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1142076202ddSJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj; 1143076202ddSJed 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\ 1144076202ddSJed Brown j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1145076202ddSJed 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\ 1146076202ddSJed Brown i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1147076202ddSJed Brown row = idx_f[dof*(m_ghost*(j_f-j_start_ghost) + (i_f-i_start_ghost))]; 114847c6ae99SBarry Smith cols[nc++] = row/dof; 114947c6ae99SBarry Smith } 115047c6ae99SBarry Smith } 115147c6ae99SBarry Smith 115247c6ae99SBarry Smith ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 11539a42bb27SBarry Smith ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 11549a42bb27SBarry Smith ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 115547c6ae99SBarry Smith ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr); 11569a42bb27SBarry Smith ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 11579a42bb27SBarry Smith ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1158fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 115947c6ae99SBarry Smith PetscFunctionReturn(0); 116047c6ae99SBarry Smith } 116147c6ae99SBarry Smith 116247c6ae99SBarry Smith #undef __FUNCT__ 1163b1757049SJed Brown #define __FUNCT__ "DMGetInjection_DA_3D" 1164b1757049SJed Brown PetscErrorCode DMGetInjection_DA_3D(DM dac,DM daf,VecScatter *inject) 1165b1757049SJed Brown { 1166b1757049SJed Brown PetscErrorCode ierr; 1167b1757049SJed Brown PetscInt i,j,k,i_start,j_start,k_start,m_f,n_f,p_f,Mx,My,Mz; 1168b1757049SJed Brown PetscInt m_ghost,n_ghost,p_ghost,m_ghost_c,n_ghost_c,p_ghost_c; 1169b1757049SJed Brown PetscInt i_start_ghost,j_start_ghost,k_start_ghost; 1170b1757049SJed Brown PetscInt mx,my,mz,ratioi,ratioj,ratiok; 1171b1757049SJed Brown PetscInt i_start_c,j_start_c,k_start_c; 1172b1757049SJed Brown PetscInt m_c,n_c,p_c; 1173b1757049SJed Brown PetscInt i_start_ghost_c,j_start_ghost_c,k_start_ghost_c; 1174b1757049SJed Brown PetscInt row,nc,dof; 1175b1757049SJed Brown PetscInt *idx_c,*idx_f; 1176b1757049SJed Brown PetscInt *cols; 11771321219cSEthan Coon DMDABoundaryType bx,by,bz; 1178b1757049SJed Brown Vec vecf,vecc; 1179b1757049SJed Brown IS isf; 1180b1757049SJed Brown 1181b1757049SJed Brown PetscFunctionBegin; 11821321219cSEthan Coon ierr = DMDAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); 11831321219cSEthan Coon ierr = DMDAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); 1184b1757049SJed Brown 11851321219cSEthan Coon if (bx == DMDA_BOUNDARY_PERIODIC){ 1186b1757049SJed Brown ratioi = mx/Mx; 1187b1757049SJed 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); 1188b1757049SJed Brown } else { 1189b1757049SJed Brown ratioi = (mx-1)/(Mx-1); 1190b1757049SJed 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); 1191b1757049SJed Brown } 11921321219cSEthan Coon if (by == DMDA_BOUNDARY_PERIODIC){ 1193b1757049SJed Brown ratioj = my/My; 1194b1757049SJed 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); 1195b1757049SJed Brown } else { 1196b1757049SJed Brown ratioj = (my-1)/(My-1); 1197b1757049SJed 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); 1198b1757049SJed Brown } 11991321219cSEthan Coon if (bz == DMDA_BOUNDARY_PERIODIC){ 1200b1757049SJed Brown ratiok = mz/Mz; 1201b1757049SJed 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); 1202b1757049SJed Brown } else { 1203b1757049SJed Brown ratiok = (mz-1)/(Mz-1); 1204b1757049SJed 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); 1205b1757049SJed Brown } 1206b1757049SJed Brown 1207b1757049SJed Brown ierr = DMDAGetCorners(daf,&i_start,&j_start,&k_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1208b1757049SJed Brown ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&k_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1209b1757049SJed Brown ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 1210b1757049SJed Brown 1211b1757049SJed Brown ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&k_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1212b1757049SJed 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); 1213b1757049SJed Brown ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 1214b1757049SJed Brown 1215b1757049SJed Brown 1216b1757049SJed Brown /* loop over local fine grid nodes setting interpolation for those*/ 1217b1757049SJed Brown nc = 0; 1218b1757049SJed Brown ierr = PetscMalloc(n_f*m_f*p_f*sizeof(PetscInt),&cols);CHKERRQ(ierr); 1219b1757049SJed Brown for (k=k_start_c; k<k_start_c+p_c; k++) { 1220b1757049SJed Brown for (j=j_start_c; j<j_start_c+n_c; j++) { 1221b1757049SJed Brown for (i=i_start_c; i<i_start_c+m_c; i++) { 1222b1757049SJed Brown PetscInt i_f = i*ratioi,j_f = j*ratioj,k_f = k*ratiok; 1223b1757049SJed 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 " 1224b1757049SJed Brown "k_c %D k_f %D fine ghost range [%D,%D]",k,k_f,k_start_ghost,k_start_ghost+p_ghost); 1225b1757049SJed 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 " 1226b1757049SJed Brown "j_c %D j_f %D fine ghost range [%D,%D]",j,j_f,j_start_ghost,j_start_ghost+n_ghost); 1227b1757049SJed 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 " 1228b1757049SJed Brown "i_c %D i_f %D fine ghost range [%D,%D]",i,i_f,i_start_ghost,i_start_ghost+m_ghost); 1229b1757049SJed 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))]; 1230b1757049SJed Brown cols[nc++] = row/dof; 1231b1757049SJed Brown } 1232b1757049SJed Brown } 1233b1757049SJed Brown } 1234b1757049SJed Brown 1235b1757049SJed Brown ierr = ISCreateBlock(((PetscObject)daf)->comm,dof,nc,cols,PETSC_OWN_POINTER,&isf);CHKERRQ(ierr); 1236b1757049SJed Brown ierr = DMGetGlobalVector(dac,&vecc);CHKERRQ(ierr); 1237b1757049SJed Brown ierr = DMGetGlobalVector(daf,&vecf);CHKERRQ(ierr); 1238b1757049SJed Brown ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr); 1239b1757049SJed Brown ierr = DMRestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); 1240b1757049SJed Brown ierr = DMRestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); 1241fcfd50ebSBarry Smith ierr = ISDestroy(&isf);CHKERRQ(ierr); 1242b1757049SJed Brown PetscFunctionReturn(0); 1243b1757049SJed Brown } 1244b1757049SJed Brown 1245b1757049SJed Brown #undef __FUNCT__ 124694013140SBarry Smith #define __FUNCT__ "DMGetInjection_DA" 12477087cfbeSBarry Smith PetscErrorCode DMGetInjection_DA(DM dac,DM daf,VecScatter *inject) 124847c6ae99SBarry Smith { 124947c6ae99SBarry Smith PetscErrorCode ierr; 125047c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 12511321219cSEthan Coon DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf; 1252aa219208SBarry Smith DMDAStencilType stc,stf; 125347c6ae99SBarry Smith 125447c6ae99SBarry Smith PetscFunctionBegin; 125547c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 125647c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 125747c6ae99SBarry Smith PetscValidPointer(inject,3); 125847c6ae99SBarry Smith 12591321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 12601321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1261aa219208SBarry Smith if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr); 1262aa219208SBarry Smith if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr); 1263aa219208SBarry 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); 12641321219cSEthan Coon if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr); 1265aa219208SBarry Smith if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr); 126647c6ae99SBarry Smith if (Mc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); 126747c6ae99SBarry Smith if (dimc > 1 && Nc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); 126847c6ae99SBarry Smith if (dimc > 2 && Pc < 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); 126947c6ae99SBarry Smith 12700bb2b966SJungho Lee if (dimc == 1){ 12710bb2b966SJungho Lee ierr = DMGetInjection_DA_1D(dac,daf,inject);CHKERRQ(ierr); 12720bb2b966SJungho Lee } else if (dimc == 2) { 127394013140SBarry Smith ierr = DMGetInjection_DA_2D(dac,daf,inject);CHKERRQ(ierr); 1274b1757049SJed Brown } else if (dimc == 3) { 1275b1757049SJed Brown ierr = DMGetInjection_DA_3D(dac,daf,inject);CHKERRQ(ierr); 127647c6ae99SBarry Smith } 127747c6ae99SBarry Smith PetscFunctionReturn(0); 127847c6ae99SBarry Smith } 127947c6ae99SBarry Smith 128047c6ae99SBarry Smith #undef __FUNCT__ 128194013140SBarry Smith #define __FUNCT__ "DMGetAggregates_DA" 12827087cfbeSBarry Smith PetscErrorCode DMGetAggregates_DA(DM dac,DM daf,Mat *rest) 128347c6ae99SBarry Smith { 128447c6ae99SBarry Smith PetscErrorCode ierr; 128547c6ae99SBarry Smith PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc; 128647c6ae99SBarry Smith PetscInt dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; 12871321219cSEthan Coon DMDABoundaryType bxc,byc,bzc,bxf,byf,bzf; 1288aa219208SBarry Smith DMDAStencilType stc,stf; 128947c6ae99SBarry Smith PetscInt i,j,l; 129047c6ae99SBarry Smith PetscInt i_start,j_start,l_start, m_f,n_f,p_f; 129147c6ae99SBarry Smith PetscInt i_start_ghost,j_start_ghost,l_start_ghost,m_ghost,n_ghost,p_ghost; 129247c6ae99SBarry Smith PetscInt *idx_f; 129347c6ae99SBarry Smith PetscInt i_c,j_c,l_c; 129447c6ae99SBarry Smith PetscInt i_start_c,j_start_c,l_start_c, m_c,n_c,p_c; 129547c6ae99SBarry Smith PetscInt i_start_ghost_c,j_start_ghost_c,l_start_ghost_c,m_ghost_c,n_ghost_c,p_ghost_c; 129647c6ae99SBarry Smith PetscInt *idx_c; 129747c6ae99SBarry Smith PetscInt d; 129847c6ae99SBarry Smith PetscInt a; 129947c6ae99SBarry Smith PetscInt max_agg_size; 130047c6ae99SBarry Smith PetscInt *fine_nodes; 130147c6ae99SBarry Smith PetscScalar *one_vec; 130247c6ae99SBarry Smith PetscInt fn_idx; 130347c6ae99SBarry Smith 130447c6ae99SBarry Smith PetscFunctionBegin; 130547c6ae99SBarry Smith PetscValidHeaderSpecific(dac,DM_CLASSID,1); 130647c6ae99SBarry Smith PetscValidHeaderSpecific(daf,DM_CLASSID,2); 130747c6ae99SBarry Smith PetscValidPointer(rest,3); 130847c6ae99SBarry Smith 13091321219cSEthan Coon ierr = DMDAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&bxc,&byc,&bzc,&stc);CHKERRQ(ierr); 13101321219cSEthan Coon ierr = DMDAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&bxf,&byf,&bzf,&stf);CHKERRQ(ierr); 1311aa219208SBarry Smith if (dimc != dimf) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Dimensions of DMDA do not match %D %D",dimc,dimf);CHKERRQ(ierr); 1312aa219208SBarry Smith if (dofc != doff) SETERRQ2(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"DOF of DMDA do not match %D %D",dofc,doff);CHKERRQ(ierr); 1313aa219208SBarry 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); 13141321219cSEthan Coon if (bxc != bxf || byc != byf || bzc != bzf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Boundary type different in two DMDAs");CHKERRQ(ierr); 1315aa219208SBarry Smith if (stc != stf) SETERRQ(((PetscObject)daf)->comm,PETSC_ERR_ARG_INCOMP,"Stencil type different in two DMDAs");CHKERRQ(ierr); 131647c6ae99SBarry Smith 131747c6ae99SBarry 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); 131847c6ae99SBarry 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); 131947c6ae99SBarry 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); 132047c6ae99SBarry Smith 132147c6ae99SBarry Smith if (Pc < 0) Pc = 1; 132247c6ae99SBarry Smith if (Pf < 0) Pf = 1; 132347c6ae99SBarry Smith if (Nc < 0) Nc = 1; 132447c6ae99SBarry Smith if (Nf < 0) Nf = 1; 132547c6ae99SBarry Smith 1326aa219208SBarry Smith ierr = DMDAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); 1327aa219208SBarry Smith ierr = DMDAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); 1328aa219208SBarry Smith ierr = DMDAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); 132947c6ae99SBarry Smith 1330aa219208SBarry Smith ierr = DMDAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); 1331aa219208SBarry 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); 1332aa219208SBarry Smith ierr = DMDAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); 133347c6ae99SBarry Smith 133447c6ae99SBarry Smith /* 133547c6ae99SBarry Smith Basic idea is as follows. Here's a 2D example, suppose r_x, r_y are the ratios 133647c6ae99SBarry Smith for dimension 1 and 2 respectively. 133747c6ae99SBarry Smith Let (i,j) be a coarse grid node. All the fine grid nodes between r_x*i and r_x*(i+1) 133847c6ae99SBarry Smith and r_y*j and r_y*(j+1) will be grouped into the same coarse grid agregate. 133947c6ae99SBarry Smith Each specific dof on the fine grid is mapped to one dof on the coarse grid. 134047c6ae99SBarry Smith */ 134147c6ae99SBarry Smith 134247c6ae99SBarry Smith max_agg_size = (Mf/Mc+1)*(Nf/Nc+1)*(Pf/Pc+1); 134347c6ae99SBarry Smith 134447c6ae99SBarry Smith /* create the matrix that will contain the restriction operator */ 134547c6ae99SBarry 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, 134647c6ae99SBarry Smith max_agg_size, PETSC_NULL, max_agg_size, PETSC_NULL, rest);CHKERRQ(ierr); 134747c6ae99SBarry Smith 134847c6ae99SBarry Smith /* store nodes in the fine grid here */ 134947c6ae99SBarry Smith ierr = PetscMalloc2(max_agg_size,PetscScalar, &one_vec,max_agg_size,PetscInt, &fine_nodes);CHKERRQ(ierr); 135047c6ae99SBarry Smith for(i=0; i<max_agg_size; i++) one_vec[i] = 1.0; 135147c6ae99SBarry Smith 135247c6ae99SBarry Smith /* loop over all coarse nodes */ 135347c6ae99SBarry Smith for (l_c=l_start_c; l_c<l_start_c+p_c; l_c++) { 135447c6ae99SBarry Smith for (j_c=j_start_c; j_c<j_start_c+n_c; j_c++) { 135547c6ae99SBarry Smith for (i_c=i_start_c; i_c<i_start_c+m_c; i_c++) { 135647c6ae99SBarry Smith for(d=0; d<dofc; d++) { 135747c6ae99SBarry Smith /* convert to local "natural" numbering and then to PETSc global numbering */ 135847c6ae99SBarry 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; 135947c6ae99SBarry Smith 136047c6ae99SBarry Smith fn_idx = 0; 136147c6ae99SBarry Smith /* Corresponding fine points are all points (i_f, j_f, l_f) such that 136247c6ae99SBarry Smith i_c*Mf/Mc <= i_f < (i_c+1)*Mf/Mc 136347c6ae99SBarry Smith (same for other dimensions) 136447c6ae99SBarry Smith */ 136547c6ae99SBarry Smith for (l=l_c*Pf/Pc; l<PetscMin((l_c+1)*Pf/Pc,Pf); l++) { 136647c6ae99SBarry Smith for (j=j_c*Nf/Nc; j<PetscMin((j_c+1)*Nf/Nc,Nf); j++) { 136747c6ae99SBarry Smith for (i=i_c*Mf/Mc; i<PetscMin((i_c+1)*Mf/Mc,Mf); i++) { 136847c6ae99SBarry 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; 136947c6ae99SBarry Smith fn_idx++; 137047c6ae99SBarry Smith } 137147c6ae99SBarry Smith } 137247c6ae99SBarry Smith } 137347c6ae99SBarry Smith /* add all these points to one aggregate */ 137447c6ae99SBarry Smith ierr = MatSetValues(*rest, 1, &a, fn_idx, fine_nodes, one_vec, INSERT_VALUES);CHKERRQ(ierr); 137547c6ae99SBarry Smith } 137647c6ae99SBarry Smith } 137747c6ae99SBarry Smith } 137847c6ae99SBarry Smith } 137947c6ae99SBarry Smith ierr = PetscFree2(one_vec,fine_nodes);CHKERRQ(ierr); 138047c6ae99SBarry Smith ierr = MatAssemblyBegin(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 138147c6ae99SBarry Smith ierr = MatAssemblyEnd(*rest, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 138247c6ae99SBarry Smith PetscFunctionReturn(0); 138347c6ae99SBarry Smith } 1384