#define PETSCDM_DLL /* Code for interpolating between grids represented by DAs */ #include "src/dm/da/daimpl.h" /*I "petscda.h" I*/ #include "petscmg.h" #undef __FUNCT__ #define __FUNCT__ "DMGetInterpolationScale" PetscErrorCode PETSCDM_DLLEXPORT DMGetInterpolationScale(DM dac,DM daf,Mat mat,Vec *scale) { PetscErrorCode ierr; Vec fine; PetscScalar one = 1.0; PetscFunctionBegin; ierr = DMCreateGlobalVector(daf,&fine);CHKERRQ(ierr); ierr = DMCreateGlobalVector(dac,scale);CHKERRQ(ierr); ierr = VecSet(fine,one);CHKERRQ(ierr); ierr = MatRestrict(mat,fine,*scale);CHKERRQ(ierr); ierr = VecDestroy(fine);CHKERRQ(ierr); ierr = VecReciprocal(*scale);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DAGetInterpolation_1D_Q1" PetscErrorCode DAGetInterpolation_1D_Q1(DA dac,DA daf,Mat *A) { PetscErrorCode ierr; PetscInt i,i_start,m_f,Mx,*idx_f; PetscInt m_ghost,*idx_c,m_ghost_c; PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; PetscScalar v[2],x,*coors = 0,*ccoors; Mat mat; DAPeriodicType pt; Vec vcoors,cvcoors; PetscFunctionBegin; ierr = DAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&pt,0);CHKERRQ(ierr); ierr = DAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0);CHKERRQ(ierr); if (pt == DA_XPERIODIC) { ratio = mx/Mx; if (ratio*Mx != mx) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); } else { ratio = (mx-1)/(Mx-1); if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); } ierr = DAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); ierr = DAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); ierr = DAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); ierr = DAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); ierr = DAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); ierr = DAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); /* create interpolation matrix */ ierr = MatCreate(dac->comm,&mat);CHKERRQ(ierr); ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); if (!DAXPeriodic(pt)){ierr = MatSetOption(mat,MAT_COLUMNS_SORTED);CHKERRQ(ierr);} ierr = DAGetCoordinates(daf,&vcoors);CHKERRQ(ierr); if (vcoors) { ierr = DAGetGhostedCoordinates(dac,&cvcoors);CHKERRQ(ierr); ierr = DAVecGetArray(daf->da_coordinates,vcoors,&coors);CHKERRQ(ierr); ierr = DAVecGetArray(dac->da_coordinates,cvcoors,&ccoors);CHKERRQ(ierr); } /* loop over local fine grid nodes setting interpolation for those*/ for (i=i_start; ida_coordinates,vcoors,&coors);CHKERRQ(ierr); ierr = DAVecRestoreArray(dac->da_coordinates,cvcoors,&ccoors);CHKERRQ(ierr); } ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); ierr = MatDestroy(mat);CHKERRQ(ierr); ierr = PetscLogFlops(5*m_f);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DAGetInterpolation_1D_Q0" PetscErrorCode DAGetInterpolation_1D_Q0(DA dac,DA daf,Mat *A) { PetscErrorCode ierr; PetscInt i,i_start,m_f,Mx,*idx_f; PetscInt m_ghost,*idx_c,m_ghost_c; PetscInt row,col,i_start_ghost,mx,m_c,nc,ratio; PetscInt i_c,i_start_c,i_start_ghost_c,cols[2],dof; PetscScalar v[2],x; Mat mat; DAPeriodicType pt; PetscFunctionBegin; ierr = DAGetInfo(dac,0,&Mx,0,0,0,0,0,0,0,&pt,0);CHKERRQ(ierr); ierr = DAGetInfo(daf,0,&mx,0,0,0,0,0,&dof,0,0,0);CHKERRQ(ierr); if (pt == DA_XPERIODIC) { ratio = mx/Mx; if (ratio*Mx != mx) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); } else { ratio = (mx-1)/(Mx-1); if (ratio*(Mx-1) != mx-1) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); } ierr = DAGetCorners(daf,&i_start,0,0,&m_f,0,0);CHKERRQ(ierr); ierr = DAGetGhostCorners(daf,&i_start_ghost,0,0,&m_ghost,0,0);CHKERRQ(ierr); ierr = DAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); ierr = DAGetCorners(dac,&i_start_c,0,0,&m_c,0,0);CHKERRQ(ierr); ierr = DAGetGhostCorners(dac,&i_start_ghost_c,0,0,&m_ghost_c,0,0);CHKERRQ(ierr); ierr = DAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); /* create interpolation matrix */ ierr = MatCreate(dac->comm,&mat);CHKERRQ(ierr); ierr = MatSetSizes(mat,m_f,m_c,mx,Mx);CHKERRQ(ierr); ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(mat,2,PETSC_NULL);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(mat,2,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); if (!DAXPeriodic(pt)) {ierr = MatSetOption(mat,MAT_COLUMNS_SORTED);CHKERRQ(ierr);} /* loop over local fine grid nodes setting interpolation for those*/ for (i=i_start; icomm,&size_c);CHKERRQ(ierr); ierr = MPI_Comm_size(daf->comm,&size_f);CHKERRQ(ierr); ierr = MPI_Comm_rank(daf->comm,&rank_f);CHKERRQ(ierr); col_scale = size_f/size_c; col_shift = Mx*My*(rank_f/size_c); ierr = MatPreallocateInitialize(daf->comm,m_f*n_f,col_scale*m_c*n_c,dnz,onz);CHKERRQ(ierr); for (j=j_start; jcomm,&mat);CHKERRQ(ierr); ierr = MatSetSizes(mat,m_f*n_f,col_scale*m_c*n_c,mx*my,col_scale*Mx*My);CHKERRQ(ierr); ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); if (!DAXPeriodic(pt) && !DAYPeriodic(pt)) {ierr = MatSetOption(mat,MAT_COLUMNS_SORTED);CHKERRQ(ierr);} ierr = DAGetCoordinates(daf,&vcoors);CHKERRQ(ierr); if (vcoors) { ierr = DAGetGhostedCoordinates(dac,&cvcoors);CHKERRQ(ierr); ierr = DAVecGetArray(daf->da_coordinates,vcoors,&coors);CHKERRQ(ierr); ierr = DAVecGetArray(dac->da_coordinates,cvcoors,&ccoors);CHKERRQ(ierr); } /* loop over local fine grid nodes setting interpolation for those*/ for (j=j_start; jda_coordinates,vcoors,&coors);CHKERRQ(ierr); ierr = DAVecRestoreArray(dac->da_coordinates,cvcoors,&ccoors);CHKERRQ(ierr); } ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); ierr = MatDestroy(mat);CHKERRQ(ierr); ierr = PetscLogFlops(13*m_f*n_f);CHKERRQ(ierr); PetscFunctionReturn(0); } /* dof degree of freedom per node, nonperiodic */ #undef __FUNCT__ #define __FUNCT__ "DAGetInterpolation_3D_Q1" PetscErrorCode DAGetInterpolation_3D_Q1(DA dac,DA daf,Mat *A) { PetscErrorCode ierr; PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof,l; PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c,Mz,mz; PetscInt row,col,i_start_ghost,j_start_ghost,cols[8],mx,m_c,my,nc,ratioi,ratioj,ratiok; PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; PetscInt l_start,p_f,l_start_ghost,p_ghost,l_start_c,p_c; PetscInt l_start_ghost_c,p_ghost_c,l_c,*dnz,*onz; PetscScalar v[8],x,y,z; Mat mat; DAPeriodicType pt; DACoor3d ***coors = 0,***ccoors; Vec vcoors,cvcoors; PetscFunctionBegin; ierr = DAGetInfo(dac,0,&Mx,&My,&Mz,0,0,0,0,0,&pt,0);CHKERRQ(ierr); ierr = DAGetInfo(daf,0,&mx,&my,&mz,0,0,0,&dof,0,0,0);CHKERRQ(ierr); if (mx == Mx) { ratioi = 1; } else if (DAXPeriodic(pt)){ ratioi = mx/Mx; if (ratioi*Mx != mx) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); } else { ratioi = (mx-1)/(Mx-1); if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); } if (my == My) { ratioj = 1; } else if (DAYPeriodic(pt)){ ratioj = my/My; if (ratioj*My != my) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); } else { ratioj = (my-1)/(My-1); if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); } if (mz == Mz) { ratiok = 1; } else if (DAZPeriodic(pt)){ ratiok = mz/Mz; if (ratiok*Mz != mz) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: mz/Mz must be integer: mz %D Mz %D",mz,Mz); } else { ratiok = (mz-1)/(Mz-1); if (ratiok*(Mz-1) != mz-1) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mz - 1)/(Mz - 1) must be integer: mz %D Mz %D",mz,Mz); } ierr = DAGetCorners(daf,&i_start,&j_start,&l_start,&m_f,&n_f,&p_f);CHKERRQ(ierr); ierr = DAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,&l_start_ghost,&m_ghost,&n_ghost,&p_ghost);CHKERRQ(ierr); ierr = DAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); ierr = DAGetCorners(dac,&i_start_c,&j_start_c,&l_start_c,&m_c,&n_c,&p_c);CHKERRQ(ierr); ierr = DAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,&l_start_ghost_c,&m_ghost_c,&n_ghost_c,&p_ghost_c);CHKERRQ(ierr); ierr = DAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); /* create interpolation matrix, determining exact preallocation */ ierr = MatPreallocateInitialize(dac->comm,m_f*n_f*p_f,m_c*n_c*p_c,dnz,onz);CHKERRQ(ierr); /* loop over local fine grid nodes counting interpolating points */ for (l=l_start; lcomm,&mat);CHKERRQ(ierr); ierr = MatSetSizes(mat,m_f*n_f*p_f,m_c*n_c*p_c,mx*my*mz,Mx*My*Mz);CHKERRQ(ierr); ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(mat,0,dnz);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(mat,0,dnz,0,onz);CHKERRQ(ierr); ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); if (!DAXPeriodic(pt) && !DAYPeriodic(pt) && !DAZPeriodic(pt)) {ierr = MatSetOption(mat,MAT_COLUMNS_SORTED);CHKERRQ(ierr);} ierr = DAGetCoordinates(daf,&vcoors);CHKERRQ(ierr); if (vcoors) { ierr = DAGetGhostedCoordinates(dac,&cvcoors);CHKERRQ(ierr); ierr = DAVecGetArray(daf->da_coordinates,vcoors,&coors);CHKERRQ(ierr); ierr = DAVecGetArray(dac->da_coordinates,cvcoors,&ccoors);CHKERRQ(ierr); } /* loop over local fine grid nodes setting interpolation for those*/ for (l=l_start; lda_coordinates,vcoors,&coors);CHKERRQ(ierr); ierr = DAVecRestoreArray(dac->da_coordinates,cvcoors,&ccoors);CHKERRQ(ierr); } ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatCreateMAIJ(mat,dof,A);CHKERRQ(ierr); ierr = MatDestroy(mat);CHKERRQ(ierr); ierr = PetscLogFlops(13*m_f*n_f);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DAGetInterpolation" /*@C DAGetInterpolation - Gets an interpolation matrix that maps between grids associated with two DAs. Collective on DA Input Parameters: + dac - the coarse grid DA - daf - the fine grid DA Output Parameters: + A - the interpolation matrix - scale - a scaling vector used to scale the coarse grid restricted vector before applying the grid function or grid Jacobian to it. Level: intermediate .keywords: interpolation, restriction, multigrid .seealso: DARefine(), DAGetInjection() @*/ PetscErrorCode PETSCDM_DLLEXPORT DAGetInterpolation(DA dac,DA daf,Mat *A,Vec *scale) { PetscErrorCode ierr; PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; DAPeriodicType wrapc,wrapf; DAStencilType stc,stf; PetscFunctionBegin; PetscValidHeaderSpecific(dac,DA_COOKIE,1); PetscValidHeaderSpecific(daf,DA_COOKIE,2); PetscValidPointer(A,3); if (scale) PetscValidPointer(scale,4); ierr = DAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&wrapc,&stc);CHKERRQ(ierr); ierr = DAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&wrapf,&stf);CHKERRQ(ierr); if (dimc != dimf) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Dimensions of DA do not match %D %D",dimc,dimf);CHKERRQ(ierr); if (dofc != doff) SETERRQ2(PETSC_ERR_ARG_INCOMP,"DOF of DA do not match %D %D",dofc,doff);CHKERRQ(ierr); if (sc != sf) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Stencil width of DA do not match %D %D",sc,sf);CHKERRQ(ierr); if (wrapc != wrapf) SETERRQ(PETSC_ERR_ARG_INCOMP,"Periodic type different in two DAs");CHKERRQ(ierr); if (stc != stf) SETERRQ(PETSC_ERR_ARG_INCOMP,"Stencil type different in two DAs");CHKERRQ(ierr); if (Mc < 2 && Mf > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); if (dimc > 1 && Nc < 2 && Nf > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); if (dimc > 2 && Pc < 2 && Pf > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); if (dac->interptype == DA_Q1){ if (dimc == 1){ ierr = DAGetInterpolation_1D_Q1(dac,daf,A);CHKERRQ(ierr); } else if (dimc == 2){ ierr = DAGetInterpolation_2D_Q1(dac,daf,A);CHKERRQ(ierr); } else if (dimc == 3){ ierr = DAGetInterpolation_3D_Q1(dac,daf,A);CHKERRQ(ierr); } else { SETERRQ2(PETSC_ERR_SUP,"No support for this DA dimension %D for interpolation type %d",dimc,(int)dac->interptype); } } else if (dac->interptype == DA_Q0){ if (dimc == 1){ ierr = DAGetInterpolation_1D_Q0(dac,daf,A);CHKERRQ(ierr); } else { SETERRQ2(PETSC_ERR_SUP,"No support for this DA dimension %D for interpolation type %d",dimc,(int)dac->interptype); } } if (scale) { ierr = DMGetInterpolationScale((DM)dac,(DM)daf,*A,scale);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DAGetInjection_2D" PetscErrorCode DAGetInjection_2D(DA dac,DA daf,VecScatter *inject) { PetscErrorCode ierr; PetscInt i,j,i_start,j_start,m_f,n_f,Mx,My,*idx_f,dof; PetscInt m_ghost,n_ghost,*idx_c,m_ghost_c,n_ghost_c; PetscInt row,i_start_ghost,j_start_ghost,mx,m_c,my,nc,ratioi,ratioj; PetscInt i_c,j_c,i_start_c,j_start_c,n_c,i_start_ghost_c,j_start_ghost_c; PetscInt *cols; DAPeriodicType pt; Vec vecf,vecc; IS isf; PetscFunctionBegin; ierr = DAGetInfo(dac,0,&Mx,&My,0,0,0,0,0,0,&pt,0);CHKERRQ(ierr); ierr = DAGetInfo(daf,0,&mx,&my,0,0,0,0,&dof,0,0,0);CHKERRQ(ierr); if (DAXPeriodic(pt)){ ratioi = mx/Mx; if (ratioi*Mx != mx) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: mx/Mx must be integer: mx %D Mx %D",mx,Mx); } else { ratioi = (mx-1)/(Mx-1); if (ratioi*(Mx-1) != mx-1) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: (mx - 1)/(Mx - 1) must be integer: mx %D Mx %D",mx,Mx); } if (DAYPeriodic(pt)){ ratioj = my/My; if (ratioj*My != my) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: my/My must be integer: my %D My %D",my,My); } else { ratioj = (my-1)/(My-1); if (ratioj*(My-1) != my-1) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Ratio between levels: (my - 1)/(My - 1) must be integer: my %D My %D",my,My); } ierr = DAGetCorners(daf,&i_start,&j_start,0,&m_f,&n_f,0);CHKERRQ(ierr); ierr = DAGetGhostCorners(daf,&i_start_ghost,&j_start_ghost,0,&m_ghost,&n_ghost,0);CHKERRQ(ierr); ierr = DAGetGlobalIndices(daf,PETSC_NULL,&idx_f);CHKERRQ(ierr); ierr = DAGetCorners(dac,&i_start_c,&j_start_c,0,&m_c,&n_c,0);CHKERRQ(ierr); ierr = DAGetGhostCorners(dac,&i_start_ghost_c,&j_start_ghost_c,0,&m_ghost_c,&n_ghost_c,0);CHKERRQ(ierr); ierr = DAGetGlobalIndices(dac,PETSC_NULL,&idx_c);CHKERRQ(ierr); /* loop over local fine grid nodes setting interpolation for those*/ nc = 0; ierr = PetscMalloc(n_f*m_f*sizeof(PetscInt),&cols);CHKERRQ(ierr); for (j=j_start; jcomm,dof,nc,cols,&isf);CHKERRQ(ierr); ierr = DAGetGlobalVector(dac,&vecc);CHKERRQ(ierr); ierr = DAGetGlobalVector(daf,&vecf);CHKERRQ(ierr); ierr = VecScatterCreate(vecf,isf,vecc,PETSC_NULL,inject);CHKERRQ(ierr); ierr = DARestoreGlobalVector(dac,&vecc);CHKERRQ(ierr); ierr = DARestoreGlobalVector(daf,&vecf);CHKERRQ(ierr); ierr = ISDestroy(isf);CHKERRQ(ierr); ierr = PetscFree(cols);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DAGetInjection" /*@C DAGetInjection - Gets an injection matrix that maps between grids associated with two DAs. Collective on DA Input Parameters: + dac - the coarse grid DA - daf - the fine grid DA Output Parameters: . inject - the injection scatter Level: intermediate .keywords: interpolation, restriction, multigrid, injection .seealso: DARefine(), DAGetInterpolation() @*/ PetscErrorCode PETSCDM_DLLEXPORT DAGetInjection(DA dac,DA daf,VecScatter *inject) { PetscErrorCode ierr; PetscInt dimc,Mc,Nc,Pc,mc,nc,pc,dofc,sc,dimf,Mf,Nf,Pf,mf,nf,pf,doff,sf; DAPeriodicType wrapc,wrapf; DAStencilType stc,stf; PetscFunctionBegin; PetscValidHeaderSpecific(dac,DA_COOKIE,1); PetscValidHeaderSpecific(daf,DA_COOKIE,2); PetscValidPointer(inject,3); ierr = DAGetInfo(dac,&dimc,&Mc,&Nc,&Pc,&mc,&nc,&pc,&dofc,&sc,&wrapc,&stc);CHKERRQ(ierr); ierr = DAGetInfo(daf,&dimf,&Mf,&Nf,&Pf,&mf,&nf,&pf,&doff,&sf,&wrapf,&stf);CHKERRQ(ierr); if (dimc != dimf) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Dimensions of DA do not match %D %D",dimc,dimf);CHKERRQ(ierr); if (dofc != doff) SETERRQ2(PETSC_ERR_ARG_INCOMP,"DOF of DA do not match %D %D",dofc,doff);CHKERRQ(ierr); if (sc != sf) SETERRQ2(PETSC_ERR_ARG_INCOMP,"Stencil width of DA do not match %D %D",sc,sf);CHKERRQ(ierr); if (wrapc != wrapf) SETERRQ(PETSC_ERR_ARG_INCOMP,"Periodic type different in two DAs");CHKERRQ(ierr); if (stc != stf) SETERRQ(PETSC_ERR_ARG_INCOMP,"Stencil type different in two DAs");CHKERRQ(ierr); if (Mc < 2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in x direction"); if (dimc > 1 && Nc < 2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in y direction"); if (dimc > 2 && Pc < 2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Coarse grid requires at least 2 points in z direction"); if (dimc == 2){ ierr = DAGetInjection_2D(dac,daf,inject);CHKERRQ(ierr); } else { SETERRQ1(PETSC_ERR_SUP,"No support for this DA dimension %D",dimc); } PetscFunctionReturn(0); }