1174b6946SBarry Smith 2c6db04a5SJed Brown #include <petscpcmg.h> /*I "petscpcmg.h" I*/ 3c6db04a5SJed Brown #include <petscdmda.h> /*I "petscdmda.h" I*/ 4c6db04a5SJed Brown #include <../src/ksp/pc/impls/mg/mgimpl.h> 57233f9f0SBarry Smith 68e722e36SBarry Smith typedef struct { 78e722e36SBarry Smith PCExoticType type; 88e722e36SBarry Smith Mat P; /* the constructed interpolation matrix */ 9ace3abfcSBarry Smith PetscBool directSolve; /* use direct LU factorization to construct interpolation */ 108e722e36SBarry Smith KSP ksp; 118e722e36SBarry Smith } PC_Exotic; 12174b6946SBarry Smith 138e722e36SBarry Smith const char *PCExoticTypes[] = {"face","wirebasket","PCExoticType","PC_Exotic",0}; 14064c8009SBarry Smith 15064c8009SBarry Smith 16064c8009SBarry Smith #undef __FUNCT__ 17aa219208SBarry Smith #define __FUNCT__ "DMDAGetWireBasketInterpolation" 18064c8009SBarry Smith /* 19aa219208SBarry Smith DMDAGetWireBasketInterpolation - Gets the interpolation for a wirebasket based coarse space 20064c8009SBarry Smith 21064c8009SBarry Smith */ 22aa219208SBarry Smith PetscErrorCode DMDAGetWireBasketInterpolation(DM da,PC_Exotic *exotic,Mat Aglobal,MatReuse reuse,Mat *P) 23064c8009SBarry Smith { 24064c8009SBarry Smith PetscErrorCode ierr; 25064c8009SBarry Smith PetscInt dim,i,j,k,m,n,p,dof,Nint,Nface,Nwire,Nsurf,*Iint,*Isurf,cint = 0,csurf = 0,istart,jstart,kstart,*II,N,c = 0; 2628d20b34SBarry Smith PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[26],*globals,Ng,*IIint,*IIsurf,Nt; 27064c8009SBarry Smith Mat Xint, Xsurf,Xint_tmp; 28064c8009SBarry Smith IS isint,issurf,is,row,col; 29064c8009SBarry Smith ISLocalToGlobalMapping ltg; 30064c8009SBarry Smith MPI_Comm comm; 31064c8009SBarry Smith Mat A,Aii,Ais,Asi,*Aholder,iAii; 32064c8009SBarry Smith MatFactorInfo info; 33064c8009SBarry Smith PetscScalar *xsurf,*xint; 348e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 35064c8009SBarry Smith PetscScalar tmp; 36064c8009SBarry Smith #endif 37064c8009SBarry Smith PetscTable ht; 38064c8009SBarry Smith 39064c8009SBarry Smith PetscFunctionBegin; 401321219cSEthan Coon ierr = DMDAGetInfo(da,&dim,0,0,0,&mp,&np,&pp,&dof,0,0,0,0,0);CHKERRQ(ierr); 41e7e72b3dSBarry Smith if (dof != 1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Only for single field problems"); 42e7e72b3dSBarry Smith if (dim != 3) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Only coded for 3d problems"); 43aa219208SBarry Smith ierr = DMDAGetCorners(da,0,0,0,&m,&n,&p);CHKERRQ(ierr); 44aa219208SBarry Smith ierr = DMDAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth);CHKERRQ(ierr); 45064c8009SBarry Smith istart = istart ? -1 : 0; 46064c8009SBarry Smith jstart = jstart ? -1 : 0; 47064c8009SBarry Smith kstart = kstart ? -1 : 0; 48064c8009SBarry Smith 49064c8009SBarry Smith /* 50064c8009SBarry Smith the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 51064c8009SBarry Smith to all the local degrees of freedom (this includes the vertices, edges and faces). 52064c8009SBarry Smith 53064c8009SBarry Smith Xint are the subset of the interpolation into the interior 54064c8009SBarry Smith 55064c8009SBarry Smith Xface are the interpolation onto faces but not into the interior 56064c8009SBarry Smith 57064c8009SBarry Smith Xsurf are the interpolation onto the vertices and edges (the surfbasket) 58064c8009SBarry Smith Xint 59064c8009SBarry Smith Symbolically one could write P = ( Xface ) after interchanging the rows to match the natural ordering on the domain 60064c8009SBarry Smith Xsurf 61064c8009SBarry Smith */ 62064c8009SBarry Smith N = (m - istart)*(n - jstart)*(p - kstart); 63064c8009SBarry Smith Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 64064c8009SBarry Smith Nface = 2*( (m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart) ); 65064c8009SBarry Smith Nwire = 4*( (m-2-istart) + (n-2-jstart) + (p-2-kstart) ) + 8; 66064c8009SBarry Smith Nsurf = Nface + Nwire; 67064c8009SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nint,26,PETSC_NULL,&Xint);CHKERRQ(ierr); 68064c8009SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nsurf,26,PETSC_NULL,&Xsurf);CHKERRQ(ierr); 69064c8009SBarry Smith ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 70064c8009SBarry Smith 71064c8009SBarry Smith /* 72064c8009SBarry Smith Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 73064c8009SBarry Smith Xsurf will be all zero (thus making the coarse matrix singular). 74064c8009SBarry Smith */ 75e32f2f54SBarry Smith if (m-istart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in X direction must be at least 3"); 76e32f2f54SBarry Smith if (n-jstart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Y direction must be at least 3"); 77e32f2f54SBarry Smith if (p-kstart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Z direction must be at least 3"); 78064c8009SBarry Smith 79064c8009SBarry Smith cnt = 0; 80064c8009SBarry Smith xsurf[cnt++] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + Nsurf] = 1;} xsurf[cnt++ + 2*Nsurf] = 1; 81064c8009SBarry Smith for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 3*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 4*Nsurf] = 1;} xsurf[cnt++ + 5*Nsurf] = 1;} 82064c8009SBarry Smith xsurf[cnt++ + 6*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 7*Nsurf] = 1;} xsurf[cnt++ + 8*Nsurf] = 1; 83064c8009SBarry Smith for (k=1;k<p-1-kstart;k++) { 84064c8009SBarry Smith xsurf[cnt++ + 9*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 10*Nsurf] = 1;} xsurf[cnt++ + 11*Nsurf] = 1; 85064c8009SBarry Smith for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 12*Nsurf] = 1; /* these are the interior nodes */ xsurf[cnt++ + 13*Nsurf] = 1;} 86064c8009SBarry Smith xsurf[cnt++ + 14*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 15*Nsurf] = 1;} xsurf[cnt++ + 16*Nsurf] = 1; 87064c8009SBarry Smith } 88064c8009SBarry Smith xsurf[cnt++ + 17*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 18*Nsurf] = 1;} xsurf[cnt++ + 19*Nsurf] = 1; 89064c8009SBarry Smith for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 20*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 21*Nsurf] = 1;} xsurf[cnt++ + 22*Nsurf] = 1;} 90064c8009SBarry Smith xsurf[cnt++ + 23*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 24*Nsurf] = 1;} xsurf[cnt++ + 25*Nsurf] = 1; 91064c8009SBarry Smith 928e722e36SBarry Smith /* interpolations only sum to 1 when using direct solver */ 938e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 94064c8009SBarry Smith for (i=0; i<Nsurf; i++) { 95064c8009SBarry Smith tmp = 0.0; 96064c8009SBarry Smith for (j=0; j<26; j++) { 97064c8009SBarry Smith tmp += xsurf[i+j*Nsurf]; 98064c8009SBarry Smith } 99e32f2f54SBarry Smith if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xsurf interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 100064c8009SBarry Smith } 101064c8009SBarry Smith #endif 102064c8009SBarry Smith ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 103064c8009SBarry Smith /* ierr = MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);*/ 104064c8009SBarry Smith 105064c8009SBarry Smith 106064c8009SBarry Smith /* 107064c8009SBarry Smith I are the indices for all the needed vertices (in global numbering) 108064c8009SBarry Smith Iint are the indices for the interior values, I surf for the surface values 109064c8009SBarry Smith (This is just for the part of the global matrix obtained with MatGetSubMatrix(), it 110aa219208SBarry Smith is NOT the local DMDA ordering.) 111064c8009SBarry Smith IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 112064c8009SBarry Smith */ 113064c8009SBarry Smith #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 114064c8009SBarry Smith ierr = PetscMalloc3(N,PetscInt,&II,Nint,PetscInt,&Iint,Nsurf,PetscInt,&Isurf);CHKERRQ(ierr); 115064c8009SBarry Smith ierr = PetscMalloc2(Nint,PetscInt,&IIint,Nsurf,PetscInt,&IIsurf);CHKERRQ(ierr); 116064c8009SBarry Smith for (k=0; k<p-kstart; k++) { 117064c8009SBarry Smith for (j=0; j<n-jstart; j++) { 118064c8009SBarry Smith for (i=0; i<m-istart; i++) { 119064c8009SBarry Smith II[c++] = i + j*mwidth + k*mwidth*nwidth; 120064c8009SBarry Smith 121064c8009SBarry Smith if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 122064c8009SBarry Smith IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 123064c8009SBarry Smith Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 124064c8009SBarry Smith } else { 125064c8009SBarry Smith IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 126064c8009SBarry Smith Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 127064c8009SBarry Smith } 128064c8009SBarry Smith } 129064c8009SBarry Smith } 130064c8009SBarry Smith } 131e32f2f54SBarry Smith if (c != N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"c != N"); 132e32f2f54SBarry Smith if (cint != Nint) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"cint != Nint"); 133e32f2f54SBarry Smith if (csurf != Nsurf) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"csurf != Nsurf"); 1341411c6eeSJed Brown ierr = DMGetLocalToGlobalMapping(da,<g);CHKERRQ(ierr); 135064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,N,II,II);CHKERRQ(ierr); 136064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint);CHKERRQ(ierr); 137064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf);CHKERRQ(ierr); 138064c8009SBarry Smith ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 13970b3c8c7SBarry Smith ierr = ISCreateGeneral(comm,N,II,PETSC_COPY_VALUES,&is);CHKERRQ(ierr); 14070b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,PETSC_COPY_VALUES,&isint);CHKERRQ(ierr); 14170b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,PETSC_COPY_VALUES,&issurf);CHKERRQ(ierr); 142064c8009SBarry Smith ierr = PetscFree3(II,Iint,Isurf);CHKERRQ(ierr); 143064c8009SBarry Smith 144064c8009SBarry Smith ierr = MatGetSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder);CHKERRQ(ierr); 145064c8009SBarry Smith A = *Aholder; 146064c8009SBarry Smith ierr = PetscFree(Aholder);CHKERRQ(ierr); 147064c8009SBarry Smith 148064c8009SBarry Smith ierr = MatGetSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii);CHKERRQ(ierr); 149064c8009SBarry Smith ierr = MatGetSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais);CHKERRQ(ierr); 150064c8009SBarry Smith ierr = MatGetSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi);CHKERRQ(ierr); 151064c8009SBarry Smith 152064c8009SBarry Smith /* 153064c8009SBarry Smith Solve for the interpolation onto the interior Xint 154064c8009SBarry Smith */ 15592e4c2edSBarry Smith ierr = MatMatMult(Ais,Xsurf,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&Xint_tmp);CHKERRQ(ierr); 1568e722e36SBarry Smith ierr = MatScale(Xint_tmp,-1.0);CHKERRQ(ierr); 1578e722e36SBarry Smith if (exotic->directSolve) { 1582692d6eeSBarry Smith ierr = MatGetFactor(Aii,MATSOLVERPETSC,MAT_FACTOR_LU,&iAii);CHKERRQ(ierr); 159064c8009SBarry Smith ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 1602692d6eeSBarry Smith ierr = MatGetOrdering(Aii,MATORDERINGND,&row,&col);CHKERRQ(ierr); 161064c8009SBarry Smith ierr = MatLUFactorSymbolic(iAii,Aii,row,col,&info);CHKERRQ(ierr); 162fcfd50ebSBarry Smith ierr = ISDestroy(&row);CHKERRQ(ierr); 163fcfd50ebSBarry Smith ierr = ISDestroy(&col);CHKERRQ(ierr); 164064c8009SBarry Smith ierr = MatLUFactorNumeric(iAii,Aii,&info);CHKERRQ(ierr); 165064c8009SBarry Smith ierr = MatMatSolve(iAii,Xint_tmp,Xint);CHKERRQ(ierr); 1666bf464f9SBarry Smith ierr = MatDestroy(&iAii);CHKERRQ(ierr); 1678e722e36SBarry Smith } else { 1688e722e36SBarry Smith Vec b,x; 1698e722e36SBarry Smith PetscScalar *xint_tmp; 170064c8009SBarry Smith 1718e722e36SBarry Smith ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 1728e722e36SBarry Smith ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,Nint,0,&x);CHKERRQ(ierr); 1738e722e36SBarry Smith ierr = MatGetArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 1748e722e36SBarry Smith ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,Nint,0,&b);CHKERRQ(ierr); 1758e722e36SBarry Smith ierr = KSPSetOperators(exotic->ksp,Aii,Aii,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 1768e722e36SBarry Smith for (i=0; i<26; i++) { 1778e722e36SBarry Smith ierr = VecPlaceArray(x,xint+i*Nint);CHKERRQ(ierr); 1788e722e36SBarry Smith ierr = VecPlaceArray(b,xint_tmp+i*Nint);CHKERRQ(ierr); 1798e722e36SBarry Smith ierr = KSPSolve(exotic->ksp,b,x);CHKERRQ(ierr); 1808e722e36SBarry Smith ierr = VecResetArray(x);CHKERRQ(ierr); 1818e722e36SBarry Smith ierr = VecResetArray(b);CHKERRQ(ierr); 1828e722e36SBarry Smith } 1838e722e36SBarry Smith ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 1848e722e36SBarry Smith ierr = MatRestoreArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 1856bf464f9SBarry Smith ierr = VecDestroy(&x);CHKERRQ(ierr); 1866bf464f9SBarry Smith ierr = VecDestroy(&b);CHKERRQ(ierr); 1878e722e36SBarry Smith } 1886bf464f9SBarry Smith ierr = MatDestroy(&Xint_tmp);CHKERRQ(ierr); 1898e722e36SBarry Smith 1908e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 191064c8009SBarry Smith ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 192064c8009SBarry Smith for (i=0; i<Nint; i++) { 193064c8009SBarry Smith tmp = 0.0; 194064c8009SBarry Smith for (j=0; j<26; j++) { 195064c8009SBarry Smith tmp += xint[i+j*Nint]; 196064c8009SBarry Smith } 197e32f2f54SBarry Smith if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xint interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 198064c8009SBarry Smith } 199064c8009SBarry Smith ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 200064c8009SBarry Smith /* ierr =MatView(Xint,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ 201064c8009SBarry Smith #endif 202064c8009SBarry Smith 203064c8009SBarry Smith 204064c8009SBarry Smith /* total vertices total faces total edges */ 205064c8009SBarry Smith Ntotal = (mp + 1)*(np + 1)*(pp + 1) + mp*np*(pp+1) + mp*pp*(np+1) + np*pp*(mp+1) + mp*(np+1)*(pp+1) + np*(mp+1)*(pp+1) + pp*(mp+1)*(np+1); 206064c8009SBarry Smith 207064c8009SBarry Smith /* 208064c8009SBarry Smith For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 209064c8009SBarry Smith */ 210064c8009SBarry Smith cnt = 0; 211064c8009SBarry Smith gl[cnt++] = 0; { gl[cnt++] = 1;} gl[cnt++] = m-istart-1; 212064c8009SBarry Smith { gl[cnt++] = mwidth; { gl[cnt++] = mwidth+1;} gl[cnt++] = mwidth + m-istart-1;} 213064c8009SBarry Smith gl[cnt++] = mwidth*(n-jstart-1); { gl[cnt++] = mwidth*(n-jstart-1)+1;} gl[cnt++] = mwidth*(n-jstart-1) + m-istart-1; 214064c8009SBarry Smith { 215064c8009SBarry Smith gl[cnt++] = mwidth*nwidth; { gl[cnt++] = mwidth*nwidth+1;} gl[cnt++] = mwidth*nwidth+ m-istart-1; 216064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 217064c8009SBarry Smith gl[cnt++] = mwidth*nwidth+ mwidth*(n-jstart-1); { gl[cnt++] = mwidth*nwidth+mwidth*(n-jstart-1)+1;} gl[cnt++] = mwidth*nwidth+mwidth*(n-jstart-1) + m-istart-1; 218064c8009SBarry Smith } 219064c8009SBarry Smith gl[cnt++] = mwidth*nwidth*(p-kstart-1); { gl[cnt++] = mwidth*nwidth*(p-kstart-1)+1;} gl[cnt++] = mwidth*nwidth*(p-kstart-1) + m-istart-1; 220064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth; { gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth+1;} gl[cnt++] = mwidth*nwidth*(p-kstart-1)+mwidth+m-istart-1;} 221064c8009SBarry Smith gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth*(n-jstart-1); { gl[cnt++] = mwidth*nwidth*(p-kstart-1)+ mwidth*(n-jstart-1)+1;} gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth*(n-jstart-1) + m-istart-1; 222064c8009SBarry Smith 223064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 224064c8009SBarry Smith /* convert that to global numbering and get them on all processes */ 225064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,26,gl,gl);CHKERRQ(ierr); 226064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 227064c8009SBarry Smith ierr = PetscMalloc(26*mp*np*pp*sizeof(PetscInt),&globals);CHKERRQ(ierr); 228064c8009SBarry Smith ierr = MPI_Allgather(gl,26,MPIU_INT,globals,26,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr); 229064c8009SBarry Smith 230064c8009SBarry Smith /* Number the coarse grid points from 0 to Ntotal */ 23128d20b34SBarry Smith ierr = MatGetSize(Aglobal,&Nt,PETSC_NULL);CHKERRQ(ierr); 232*12dd4568SBarry Smith ierr = PetscTableCreate(Ntotal/3,Nt+1,&ht);CHKERRQ(ierr); 233064c8009SBarry Smith for (i=0; i<26*mp*np*pp; i++){ 234064c8009SBarry Smith ierr = PetscTableAddCount(ht,globals[i]+1);CHKERRQ(ierr); 235064c8009SBarry Smith } 236064c8009SBarry Smith ierr = PetscTableGetCount(ht,&cnt);CHKERRQ(ierr); 237e32f2f54SBarry Smith if (cnt != Ntotal) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hash table size %D not equal to total number coarse grid points %D",cnt,Ntotal); 238064c8009SBarry Smith ierr = PetscFree(globals);CHKERRQ(ierr); 239064c8009SBarry Smith for (i=0; i<26; i++) { 240064c8009SBarry Smith ierr = PetscTableFind(ht,gl[i]+1,&gl[i]);CHKERRQ(ierr); 241064c8009SBarry Smith gl[i]--; 242064c8009SBarry Smith } 2436bc0bbbfSBarry Smith ierr = PetscTableDestroy(&ht);CHKERRQ(ierr); 244064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 245064c8009SBarry Smith 246064c8009SBarry Smith /* construct global interpolation matrix */ 24728d20b34SBarry Smith ierr = MatGetLocalSize(Aglobal,&Ng,PETSC_NULL);CHKERRQ(ierr); 248064c8009SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 249064c8009SBarry Smith ierr = MatCreateMPIAIJ(((PetscObject)da)->comm,Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,PETSC_NULL,Nint+Nsurf,PETSC_NULL,P);CHKERRQ(ierr); 250064c8009SBarry Smith } else { 251064c8009SBarry Smith ierr = MatZeroEntries(*P);CHKERRQ(ierr); 252064c8009SBarry Smith } 253064c8009SBarry Smith ierr = MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 254064c8009SBarry Smith ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 255064c8009SBarry Smith ierr = MatSetValues(*P,Nint,IIint,26,gl,xint,INSERT_VALUES);CHKERRQ(ierr); 256064c8009SBarry Smith ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 257064c8009SBarry Smith ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 258064c8009SBarry Smith ierr = MatSetValues(*P,Nsurf,IIsurf,26,gl,xsurf,INSERT_VALUES);CHKERRQ(ierr); 259064c8009SBarry Smith ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 260064c8009SBarry Smith ierr = MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 261064c8009SBarry Smith ierr = MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 262064c8009SBarry Smith ierr = PetscFree2(IIint,IIsurf);CHKERRQ(ierr); 263064c8009SBarry Smith 2648e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 265064c8009SBarry Smith { 266064c8009SBarry Smith Vec x,y; 267064c8009SBarry Smith PetscScalar *yy; 268064c8009SBarry Smith ierr = VecCreateMPI(((PetscObject)da)->comm,Ng,PETSC_DETERMINE,&y);CHKERRQ(ierr); 269064c8009SBarry Smith ierr = VecCreateMPI(((PetscObject)da)->comm,PETSC_DETERMINE,Ntotal,&x);CHKERRQ(ierr); 270064c8009SBarry Smith ierr = VecSet(x,1.0);CHKERRQ(ierr); 271064c8009SBarry Smith ierr = MatMult(*P,x,y);CHKERRQ(ierr); 272064c8009SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 273064c8009SBarry Smith for (i=0; i<Ng; i++) { 274e32f2f54SBarry Smith if (PetscAbsScalar(yy[i]-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong p interpolation at i %D value %G",i,PetscAbsScalar(yy[i])); 275064c8009SBarry Smith } 276064c8009SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 277064c8009SBarry Smith ierr = VecDestroy(x);CHKERRQ(ierr); 278064c8009SBarry Smith ierr = VecDestroy(y);CHKERRQ(ierr); 279064c8009SBarry Smith } 280064c8009SBarry Smith #endif 281064c8009SBarry Smith 282fcfd50ebSBarry Smith ierr = MatDestroy(&Aii);CHKERRQ(ierr); 283fcfd50ebSBarry Smith ierr = MatDestroy(&Ais);CHKERRQ(ierr); 284fcfd50ebSBarry Smith ierr = MatDestroy(&Asi);CHKERRQ(ierr); 285fcfd50ebSBarry Smith ierr = MatDestroy(&A);CHKERRQ(ierr); 286fcfd50ebSBarry Smith ierr = ISDestroy(&is);CHKERRQ(ierr); 287fcfd50ebSBarry Smith ierr = ISDestroy(&isint);CHKERRQ(ierr); 288fcfd50ebSBarry Smith ierr = ISDestroy(&issurf);CHKERRQ(ierr); 289fcfd50ebSBarry Smith ierr = MatDestroy(&Xint);CHKERRQ(ierr); 290fcfd50ebSBarry Smith ierr = MatDestroy(&Xsurf);CHKERRQ(ierr); 291064c8009SBarry Smith PetscFunctionReturn(0); 292064c8009SBarry Smith } 293064c8009SBarry Smith 294064c8009SBarry Smith #undef __FUNCT__ 295aa219208SBarry Smith #define __FUNCT__ "DMDAGetFaceInterpolation" 296064c8009SBarry Smith /* 297aa219208SBarry Smith DMDAGetFaceInterpolation - Gets the interpolation for a face based coarse space 298064c8009SBarry Smith 299064c8009SBarry Smith */ 300aa219208SBarry Smith PetscErrorCode DMDAGetFaceInterpolation(DM da,PC_Exotic *exotic,Mat Aglobal,MatReuse reuse,Mat *P) 301064c8009SBarry Smith { 302064c8009SBarry Smith PetscErrorCode ierr; 303064c8009SBarry Smith PetscInt dim,i,j,k,m,n,p,dof,Nint,Nface,Nwire,Nsurf,*Iint,*Isurf,cint = 0,csurf = 0,istart,jstart,kstart,*II,N,c = 0; 30428d20b34SBarry Smith PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[6],*globals,Ng,*IIint,*IIsurf,Nt; 305064c8009SBarry Smith Mat Xint, Xsurf,Xint_tmp; 306064c8009SBarry Smith IS isint,issurf,is,row,col; 307064c8009SBarry Smith ISLocalToGlobalMapping ltg; 308064c8009SBarry Smith MPI_Comm comm; 309064c8009SBarry Smith Mat A,Aii,Ais,Asi,*Aholder,iAii; 310064c8009SBarry Smith MatFactorInfo info; 311064c8009SBarry Smith PetscScalar *xsurf,*xint; 312064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 313064c8009SBarry Smith PetscScalar tmp; 314064c8009SBarry Smith #endif 315064c8009SBarry Smith PetscTable ht; 316064c8009SBarry Smith 317064c8009SBarry Smith PetscFunctionBegin; 3181321219cSEthan Coon ierr = DMDAGetInfo(da,&dim,0,0,0,&mp,&np,&pp,&dof,0,0,0,0,0);CHKERRQ(ierr); 319e7e72b3dSBarry Smith if (dof != 1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Only for single field problems"); 320e7e72b3dSBarry Smith if (dim != 3) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Only coded for 3d problems"); 321aa219208SBarry Smith ierr = DMDAGetCorners(da,0,0,0,&m,&n,&p);CHKERRQ(ierr); 322aa219208SBarry Smith ierr = DMDAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth);CHKERRQ(ierr); 323064c8009SBarry Smith istart = istart ? -1 : 0; 324064c8009SBarry Smith jstart = jstart ? -1 : 0; 325064c8009SBarry Smith kstart = kstart ? -1 : 0; 326064c8009SBarry Smith 327064c8009SBarry Smith /* 328064c8009SBarry Smith the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 329064c8009SBarry Smith to all the local degrees of freedom (this includes the vertices, edges and faces). 330064c8009SBarry Smith 331064c8009SBarry Smith Xint are the subset of the interpolation into the interior 332064c8009SBarry Smith 333064c8009SBarry Smith Xface are the interpolation onto faces but not into the interior 334064c8009SBarry Smith 335064c8009SBarry Smith Xsurf are the interpolation onto the vertices and edges (the surfbasket) 336064c8009SBarry Smith Xint 337064c8009SBarry Smith Symbolically one could write P = ( Xface ) after interchanging the rows to match the natural ordering on the domain 338064c8009SBarry Smith Xsurf 339064c8009SBarry Smith */ 340064c8009SBarry Smith N = (m - istart)*(n - jstart)*(p - kstart); 341064c8009SBarry Smith Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 342064c8009SBarry Smith Nface = 2*( (m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart) ); 343064c8009SBarry Smith Nwire = 4*( (m-2-istart) + (n-2-jstart) + (p-2-kstart) ) + 8; 344064c8009SBarry Smith Nsurf = Nface + Nwire; 345064c8009SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nint,6,PETSC_NULL,&Xint);CHKERRQ(ierr); 346064c8009SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nsurf,6,PETSC_NULL,&Xsurf);CHKERRQ(ierr); 347064c8009SBarry Smith ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 348064c8009SBarry Smith 349064c8009SBarry Smith /* 350064c8009SBarry Smith Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 351064c8009SBarry Smith Xsurf will be all zero (thus making the coarse matrix singular). 352064c8009SBarry Smith */ 353e32f2f54SBarry Smith if (m-istart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in X direction must be at least 3"); 354e32f2f54SBarry Smith if (n-jstart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Y direction must be at least 3"); 355e32f2f54SBarry Smith if (p-kstart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Z direction must be at least 3"); 356064c8009SBarry Smith 357064c8009SBarry Smith cnt = 0; 358064c8009SBarry Smith for (j=1;j<n-1-jstart;j++) { for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 0*Nsurf] = 1;} } 359064c8009SBarry Smith for (k=1;k<p-1-kstart;k++) { 360064c8009SBarry Smith for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 1*Nsurf] = 1;} 361064c8009SBarry Smith for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 2*Nsurf] = 1; /* these are the interior nodes */ xsurf[cnt++ + 3*Nsurf] = 1;} 362064c8009SBarry Smith for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 4*Nsurf] = 1;} 363064c8009SBarry Smith } 364064c8009SBarry Smith for (j=1;j<n-1-jstart;j++) {for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 5*Nsurf] = 1;} } 365064c8009SBarry Smith 366064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 367064c8009SBarry Smith for (i=0; i<Nsurf; i++) { 368064c8009SBarry Smith tmp = 0.0; 369064c8009SBarry Smith for (j=0; j<6; j++) { 370064c8009SBarry Smith tmp += xsurf[i+j*Nsurf]; 371064c8009SBarry Smith } 372e32f2f54SBarry Smith if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xsurf interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 373064c8009SBarry Smith } 374064c8009SBarry Smith #endif 375064c8009SBarry Smith ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 376064c8009SBarry Smith /* ierr = MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);*/ 377064c8009SBarry Smith 378064c8009SBarry Smith 379064c8009SBarry Smith /* 380064c8009SBarry Smith I are the indices for all the needed vertices (in global numbering) 381064c8009SBarry Smith Iint are the indices for the interior values, I surf for the surface values 382064c8009SBarry Smith (This is just for the part of the global matrix obtained with MatGetSubMatrix(), it 383aa219208SBarry Smith is NOT the local DMDA ordering.) 384064c8009SBarry Smith IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 385064c8009SBarry Smith */ 386064c8009SBarry Smith #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 387064c8009SBarry Smith ierr = PetscMalloc3(N,PetscInt,&II,Nint,PetscInt,&Iint,Nsurf,PetscInt,&Isurf);CHKERRQ(ierr); 388064c8009SBarry Smith ierr = PetscMalloc2(Nint,PetscInt,&IIint,Nsurf,PetscInt,&IIsurf);CHKERRQ(ierr); 389064c8009SBarry Smith for (k=0; k<p-kstart; k++) { 390064c8009SBarry Smith for (j=0; j<n-jstart; j++) { 391064c8009SBarry Smith for (i=0; i<m-istart; i++) { 392064c8009SBarry Smith II[c++] = i + j*mwidth + k*mwidth*nwidth; 393064c8009SBarry Smith 394064c8009SBarry Smith if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 395064c8009SBarry Smith IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 396064c8009SBarry Smith Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 397064c8009SBarry Smith } else { 398064c8009SBarry Smith IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 399064c8009SBarry Smith Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 400064c8009SBarry Smith } 401064c8009SBarry Smith } 402064c8009SBarry Smith } 403064c8009SBarry Smith } 404e32f2f54SBarry Smith if (c != N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"c != N"); 405e32f2f54SBarry Smith if (cint != Nint) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"cint != Nint"); 406e32f2f54SBarry Smith if (csurf != Nsurf) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"csurf != Nsurf"); 4071411c6eeSJed Brown ierr = DMGetLocalToGlobalMapping(da,<g);CHKERRQ(ierr); 408064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,N,II,II);CHKERRQ(ierr); 409064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint);CHKERRQ(ierr); 410064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf);CHKERRQ(ierr); 411064c8009SBarry Smith ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 41270b3c8c7SBarry Smith ierr = ISCreateGeneral(comm,N,II,PETSC_COPY_VALUES,&is);CHKERRQ(ierr); 41370b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,PETSC_COPY_VALUES,&isint);CHKERRQ(ierr); 41470b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,PETSC_COPY_VALUES,&issurf);CHKERRQ(ierr); 415064c8009SBarry Smith ierr = PetscFree3(II,Iint,Isurf);CHKERRQ(ierr); 416064c8009SBarry Smith 417064c8009SBarry Smith ierr = MatGetSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder);CHKERRQ(ierr); 418064c8009SBarry Smith A = *Aholder; 419064c8009SBarry Smith ierr = PetscFree(Aholder);CHKERRQ(ierr); 420064c8009SBarry Smith 421064c8009SBarry Smith ierr = MatGetSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii);CHKERRQ(ierr); 422064c8009SBarry Smith ierr = MatGetSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais);CHKERRQ(ierr); 423064c8009SBarry Smith ierr = MatGetSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi);CHKERRQ(ierr); 424064c8009SBarry Smith 425064c8009SBarry Smith /* 426064c8009SBarry Smith Solve for the interpolation onto the interior Xint 427064c8009SBarry Smith */ 42892e4c2edSBarry Smith ierr = MatMatMult(Ais,Xsurf,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&Xint_tmp);CHKERRQ(ierr); 429064c8009SBarry Smith ierr = MatScale(Xint_tmp,-1.0);CHKERRQ(ierr); 430064c8009SBarry Smith 4318e722e36SBarry Smith if (exotic->directSolve) { 4322692d6eeSBarry Smith ierr = MatGetFactor(Aii,MATSOLVERPETSC,MAT_FACTOR_LU,&iAii);CHKERRQ(ierr); 433064c8009SBarry Smith ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 4342692d6eeSBarry Smith ierr = MatGetOrdering(Aii,MATORDERINGND,&row,&col);CHKERRQ(ierr); 435064c8009SBarry Smith ierr = MatLUFactorSymbolic(iAii,Aii,row,col,&info);CHKERRQ(ierr); 436fcfd50ebSBarry Smith ierr = ISDestroy(&row);CHKERRQ(ierr); 437fcfd50ebSBarry Smith ierr = ISDestroy(&col);CHKERRQ(ierr); 438064c8009SBarry Smith ierr = MatLUFactorNumeric(iAii,Aii,&info);CHKERRQ(ierr); 439064c8009SBarry Smith ierr = MatMatSolve(iAii,Xint_tmp,Xint);CHKERRQ(ierr); 440fcfd50ebSBarry Smith ierr = MatDestroy(&iAii);CHKERRQ(ierr); 441064c8009SBarry Smith } else { 442064c8009SBarry Smith Vec b,x; 443064c8009SBarry Smith PetscScalar *xint_tmp; 444064c8009SBarry Smith 445064c8009SBarry Smith ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 446064c8009SBarry Smith ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,Nint,0,&x);CHKERRQ(ierr); 447064c8009SBarry Smith ierr = MatGetArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 448064c8009SBarry Smith ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,Nint,0,&b);CHKERRQ(ierr); 4498e722e36SBarry Smith ierr = KSPSetOperators(exotic->ksp,Aii,Aii,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 450064c8009SBarry Smith for (i=0; i<6; i++) { 451064c8009SBarry Smith ierr = VecPlaceArray(x,xint+i*Nint);CHKERRQ(ierr); 452064c8009SBarry Smith ierr = VecPlaceArray(b,xint_tmp+i*Nint);CHKERRQ(ierr); 4538e722e36SBarry Smith ierr = KSPSolve(exotic->ksp,b,x);CHKERRQ(ierr); 454064c8009SBarry Smith ierr = VecResetArray(x);CHKERRQ(ierr); 455064c8009SBarry Smith ierr = VecResetArray(b);CHKERRQ(ierr); 456064c8009SBarry Smith } 457064c8009SBarry Smith ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 458064c8009SBarry Smith ierr = MatRestoreArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 4596bf464f9SBarry Smith ierr = VecDestroy(&x);CHKERRQ(ierr); 4606bf464f9SBarry Smith ierr = VecDestroy(&b);CHKERRQ(ierr); 461064c8009SBarry Smith } 4626bf464f9SBarry Smith ierr = MatDestroy(&Xint_tmp);CHKERRQ(ierr); 463064c8009SBarry Smith 464064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 465064c8009SBarry Smith ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 466064c8009SBarry Smith for (i=0; i<Nint; i++) { 467064c8009SBarry Smith tmp = 0.0; 468064c8009SBarry Smith for (j=0; j<6; j++) { 469064c8009SBarry Smith tmp += xint[i+j*Nint]; 470064c8009SBarry Smith } 471e32f2f54SBarry Smith if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xint interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 472064c8009SBarry Smith } 473064c8009SBarry Smith ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 474064c8009SBarry Smith /* ierr =MatView(Xint,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ 475064c8009SBarry Smith #endif 476064c8009SBarry Smith 477064c8009SBarry Smith 478064c8009SBarry Smith /* total faces */ 479064c8009SBarry Smith Ntotal = mp*np*(pp+1) + mp*pp*(np+1) + np*pp*(mp+1); 480064c8009SBarry Smith 481064c8009SBarry Smith /* 482064c8009SBarry Smith For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 483064c8009SBarry Smith */ 484064c8009SBarry Smith cnt = 0; 485064c8009SBarry Smith { gl[cnt++] = mwidth+1;} 486064c8009SBarry Smith { 487064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth+1;} 488064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 489064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth+mwidth*(n-jstart-1)+1;} 490064c8009SBarry Smith } 491064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth+1;} 492064c8009SBarry Smith 493064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 494064c8009SBarry Smith /* convert that to global numbering and get them on all processes */ 495064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,6,gl,gl);CHKERRQ(ierr); 496064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 497064c8009SBarry Smith ierr = PetscMalloc(6*mp*np*pp*sizeof(PetscInt),&globals);CHKERRQ(ierr); 498064c8009SBarry Smith ierr = MPI_Allgather(gl,6,MPIU_INT,globals,6,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr); 499064c8009SBarry Smith 500064c8009SBarry Smith /* Number the coarse grid points from 0 to Ntotal */ 50128d20b34SBarry Smith ierr = MatGetSize(Aglobal,&Nt,PETSC_NULL);CHKERRQ(ierr); 50228d20b34SBarry Smith ierr = PetscTableCreate(Ntotal/3,Nt+1,&ht);CHKERRQ(ierr); 503064c8009SBarry Smith for (i=0; i<6*mp*np*pp; i++){ 504064c8009SBarry Smith ierr = PetscTableAddCount(ht,globals[i]+1);CHKERRQ(ierr); 505064c8009SBarry Smith } 506064c8009SBarry Smith ierr = PetscTableGetCount(ht,&cnt);CHKERRQ(ierr); 507e32f2f54SBarry Smith if (cnt != Ntotal) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hash table size %D not equal to total number coarse grid points %D",cnt,Ntotal); 508064c8009SBarry Smith ierr = PetscFree(globals);CHKERRQ(ierr); 509064c8009SBarry Smith for (i=0; i<6; i++) { 510064c8009SBarry Smith ierr = PetscTableFind(ht,gl[i]+1,&gl[i]);CHKERRQ(ierr); 511064c8009SBarry Smith gl[i]--; 512064c8009SBarry Smith } 5136bc0bbbfSBarry Smith ierr = PetscTableDestroy(&ht);CHKERRQ(ierr); 514064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 515064c8009SBarry Smith 516064c8009SBarry Smith /* construct global interpolation matrix */ 51728d20b34SBarry Smith ierr = MatGetLocalSize(Aglobal,&Ng,PETSC_NULL);CHKERRQ(ierr); 518064c8009SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 519064c8009SBarry Smith ierr = MatCreateMPIAIJ(((PetscObject)da)->comm,Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,PETSC_NULL,Nint,PETSC_NULL,P);CHKERRQ(ierr); 520064c8009SBarry Smith } else { 521064c8009SBarry Smith ierr = MatZeroEntries(*P);CHKERRQ(ierr); 522064c8009SBarry Smith } 523064c8009SBarry Smith ierr = MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 524064c8009SBarry Smith ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 525064c8009SBarry Smith ierr = MatSetValues(*P,Nint,IIint,6,gl,xint,INSERT_VALUES);CHKERRQ(ierr); 526064c8009SBarry Smith ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 527064c8009SBarry Smith ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 528064c8009SBarry Smith ierr = MatSetValues(*P,Nsurf,IIsurf,6,gl,xsurf,INSERT_VALUES);CHKERRQ(ierr); 529064c8009SBarry Smith ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 530064c8009SBarry Smith ierr = MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 531064c8009SBarry Smith ierr = MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 532064c8009SBarry Smith ierr = PetscFree2(IIint,IIsurf);CHKERRQ(ierr); 533064c8009SBarry Smith 534064c8009SBarry Smith 535064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 536064c8009SBarry Smith { 537064c8009SBarry Smith Vec x,y; 538064c8009SBarry Smith PetscScalar *yy; 539064c8009SBarry Smith ierr = VecCreateMPI(((PetscObject)da)->comm,Ng,PETSC_DETERMINE,&y);CHKERRQ(ierr); 540064c8009SBarry Smith ierr = VecCreateMPI(((PetscObject)da)->comm,PETSC_DETERMINE,Ntotal,&x);CHKERRQ(ierr); 541064c8009SBarry Smith ierr = VecSet(x,1.0);CHKERRQ(ierr); 542064c8009SBarry Smith ierr = MatMult(*P,x,y);CHKERRQ(ierr); 543064c8009SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 544064c8009SBarry Smith for (i=0; i<Ng; i++) { 545e32f2f54SBarry Smith if (PetscAbsScalar(yy[i]-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong p interpolation at i %D value %G",i,PetscAbsScalar(yy[i])); 546064c8009SBarry Smith } 547064c8009SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 548064c8009SBarry Smith ierr = VecDestroy(x);CHKERRQ(ierr); 549064c8009SBarry Smith ierr = VecDestroy(y);CHKERRQ(ierr); 550064c8009SBarry Smith } 551064c8009SBarry Smith #endif 552064c8009SBarry Smith 553fcfd50ebSBarry Smith ierr = MatDestroy(&Aii);CHKERRQ(ierr); 554fcfd50ebSBarry Smith ierr = MatDestroy(&Ais);CHKERRQ(ierr); 555fcfd50ebSBarry Smith ierr = MatDestroy(&Asi);CHKERRQ(ierr); 556fcfd50ebSBarry Smith ierr = MatDestroy(&A);CHKERRQ(ierr); 557fcfd50ebSBarry Smith ierr = ISDestroy(&is);CHKERRQ(ierr); 558fcfd50ebSBarry Smith ierr = ISDestroy(&isint);CHKERRQ(ierr); 559fcfd50ebSBarry Smith ierr = ISDestroy(&issurf);CHKERRQ(ierr); 560fcfd50ebSBarry Smith ierr = MatDestroy(&Xint);CHKERRQ(ierr); 561fcfd50ebSBarry Smith ierr = MatDestroy(&Xsurf);CHKERRQ(ierr); 562064c8009SBarry Smith PetscFunctionReturn(0); 563064c8009SBarry Smith } 564174b6946SBarry Smith 5657233f9f0SBarry Smith 566174b6946SBarry Smith #undef __FUNCT__ 5677233f9f0SBarry Smith #define __FUNCT__ "PCExoticSetType" 5687233f9f0SBarry Smith /*@ 5697233f9f0SBarry Smith PCExoticSetType - Sets the type of coarse grid interpolation to use 5707233f9f0SBarry Smith 5713f9fe445SBarry Smith Logically Collective on PC 5727233f9f0SBarry Smith 5737233f9f0SBarry Smith Input Parameters: 5747233f9f0SBarry Smith + pc - the preconditioner context 5757233f9f0SBarry Smith - type - either PC_EXOTIC_FACE or PC_EXOTIC_WIREBASKET (defaults to face) 5767233f9f0SBarry Smith 577563e08c6SBarry Smith Notes: The face based interpolation has 1 degree of freedom per face and ignores the 578563e08c6SBarry Smith edge and vertex values completely in the coarse problem. For any seven point 579563e08c6SBarry Smith stencil the interpolation of a constant on all faces into the interior is that constant. 580563e08c6SBarry Smith 581563e08c6SBarry Smith The wirebasket interpolation has 1 degree of freedom per vertex, per edge and 582563e08c6SBarry Smith per face. A constant on the subdomain boundary is interpolated as that constant 583563e08c6SBarry Smith in the interior of the domain. 584563e08c6SBarry Smith 585563e08c6SBarry Smith The coarse grid matrix is obtained via the Galerkin computation A_c = R A R^T, hence 586563e08c6SBarry Smith if A is nonsingular A_c is also nonsingular. 587563e08c6SBarry Smith 588563e08c6SBarry Smith Both interpolations are suitable for only scalar problems. 589563e08c6SBarry Smith 5907233f9f0SBarry Smith Level: intermediate 5917233f9f0SBarry Smith 5927233f9f0SBarry Smith 5937233f9f0SBarry Smith .seealso: PCEXOTIC, PCExoticType() 5947233f9f0SBarry Smith @*/ 5957087cfbeSBarry Smith PetscErrorCode PCExoticSetType(PC pc,PCExoticType type) 5967233f9f0SBarry Smith { 5974ac538c5SBarry Smith PetscErrorCode ierr; 5987233f9f0SBarry Smith 5997233f9f0SBarry Smith PetscFunctionBegin; 6000700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 601c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,type,2); 6024ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCExoticSetType_C",(PC,PCExoticType),(pc,type));CHKERRQ(ierr); 6037233f9f0SBarry Smith PetscFunctionReturn(0); 6047233f9f0SBarry Smith } 6057233f9f0SBarry Smith 6067233f9f0SBarry Smith #undef __FUNCT__ 6077233f9f0SBarry Smith #define __FUNCT__ "PCExoticSetType_Exotic" 6087087cfbeSBarry Smith PetscErrorCode PCExoticSetType_Exotic(PC pc,PCExoticType type) 6097233f9f0SBarry Smith { 610f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 61131567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 6127233f9f0SBarry Smith 6137233f9f0SBarry Smith PetscFunctionBegin; 6147233f9f0SBarry Smith ctx->type = type; 6157233f9f0SBarry Smith PetscFunctionReturn(0); 6167233f9f0SBarry Smith } 6177233f9f0SBarry Smith 6187233f9f0SBarry Smith #undef __FUNCT__ 6197233f9f0SBarry Smith #define __FUNCT__ "PCSetUp_Exotic" 6207233f9f0SBarry Smith PetscErrorCode PCSetUp_Exotic(PC pc) 621174b6946SBarry Smith { 622174b6946SBarry Smith PetscErrorCode ierr; 62396bdf778SBarry Smith Mat A; 624f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 62531567311SBarry Smith PC_Exotic *ex = (PC_Exotic*) mg->innerctx; 62696bdf778SBarry Smith MatReuse reuse = (ex->P) ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 627174b6946SBarry Smith 628174b6946SBarry Smith PetscFunctionBegin; 629e7e72b3dSBarry Smith if (!pc->dm) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to call PCSetDM() before using this PC"); 630174b6946SBarry Smith ierr = PCGetOperators(pc,PETSC_NULL,&A,PETSC_NULL);CHKERRQ(ierr); 6317233f9f0SBarry Smith if (ex->type == PC_EXOTIC_FACE) { 632aa219208SBarry Smith ierr = DMDAGetFaceInterpolation(pc->dm,ex,A,reuse,&ex->P);CHKERRQ(ierr); 6337233f9f0SBarry Smith } else if (ex->type == PC_EXOTIC_WIREBASKET) { 634aa219208SBarry Smith ierr = DMDAGetWireBasketInterpolation(pc->dm,ex,A,reuse,&ex->P);CHKERRQ(ierr); 63565e19b50SBarry Smith } else SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_PLIB,"Unknown exotic coarse space %d",ex->type); 63696bdf778SBarry Smith ierr = PCMGSetInterpolation(pc,1,ex->P);CHKERRQ(ierr); 637d0660788SBarry Smith /* if PC has attached DM we must remove it or the PCMG will use it to compute incorrect sized vectors and interpolations */ 638d0660788SBarry Smith ierr = PCSetDM(pc,PETSC_NULL);CHKERRQ(ierr); 6397233f9f0SBarry Smith ierr = PCSetUp_MG(pc);CHKERRQ(ierr); 640174b6946SBarry Smith PetscFunctionReturn(0); 641174b6946SBarry Smith } 642174b6946SBarry Smith 643174b6946SBarry Smith #undef __FUNCT__ 6447233f9f0SBarry Smith #define __FUNCT__ "PCDestroy_Exotic" 6457233f9f0SBarry Smith PetscErrorCode PCDestroy_Exotic(PC pc) 646174b6946SBarry Smith { 647174b6946SBarry Smith PetscErrorCode ierr; 648f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 64931567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 650174b6946SBarry Smith 651174b6946SBarry Smith PetscFunctionBegin; 652fcfd50ebSBarry Smith ierr = MatDestroy(&ctx->P);CHKERRQ(ierr); 653fcfd50ebSBarry Smith ierr = KSPDestroy(&ctx->ksp);CHKERRQ(ierr); 6547233f9f0SBarry Smith ierr = PetscFree(ctx);CHKERRQ(ierr); 6557233f9f0SBarry Smith ierr = PCDestroy_MG(pc);CHKERRQ(ierr); 656174b6946SBarry Smith PetscFunctionReturn(0); 657174b6946SBarry Smith } 658174b6946SBarry Smith 659174b6946SBarry Smith #undef __FUNCT__ 6607233f9f0SBarry Smith #define __FUNCT__ "PCView_Exotic" 6617233f9f0SBarry Smith PetscErrorCode PCView_Exotic(PC pc,PetscViewer viewer) 6627233f9f0SBarry Smith { 663f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 6647233f9f0SBarry Smith PetscErrorCode ierr; 665ace3abfcSBarry Smith PetscBool iascii; 66631567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 6677233f9f0SBarry Smith 6687233f9f0SBarry Smith PetscFunctionBegin; 6692692d6eeSBarry Smith ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 6707233f9f0SBarry Smith if (iascii) { 6717233f9f0SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Exotic type = %s\n",PCExoticTypes[ctx->type]);CHKERRQ(ierr); 6728e722e36SBarry Smith if (ctx->directSolve) { 6738e722e36SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using direct solver to construct interpolation\n");CHKERRQ(ierr); 6748e722e36SBarry Smith } else { 6758e722e36SBarry Smith PetscViewer sviewer; 6768e722e36SBarry Smith PetscMPIInt rank; 6778e722e36SBarry Smith 6788e722e36SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using iterative solver to construct interpolation\n");CHKERRQ(ierr); 6798e722e36SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 6808e722e36SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); /* should not need to push this twice? */ 6818e722e36SBarry Smith ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 6828e722e36SBarry Smith ierr = MPI_Comm_rank(((PetscObject)pc)->comm,&rank);CHKERRQ(ierr); 6838e722e36SBarry Smith if (!rank) { 6848e722e36SBarry Smith ierr = KSPView(ctx->ksp,sviewer);CHKERRQ(ierr); 6858e722e36SBarry Smith } 6868e722e36SBarry Smith ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 6878e722e36SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 6888e722e36SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 6898e722e36SBarry Smith } 6907233f9f0SBarry Smith } 6917233f9f0SBarry Smith ierr = PCView_MG(pc,viewer);CHKERRQ(ierr); 6927233f9f0SBarry Smith PetscFunctionReturn(0); 6937233f9f0SBarry Smith } 6947233f9f0SBarry Smith 6957233f9f0SBarry Smith #undef __FUNCT__ 6967233f9f0SBarry Smith #define __FUNCT__ "PCSetFromOptions_Exotic" 6977233f9f0SBarry Smith PetscErrorCode PCSetFromOptions_Exotic(PC pc) 6987233f9f0SBarry Smith { 6997233f9f0SBarry Smith PetscErrorCode ierr; 700ace3abfcSBarry Smith PetscBool flg; 701f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 7027233f9f0SBarry Smith PCExoticType mgctype; 70331567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 7047233f9f0SBarry Smith 7057233f9f0SBarry Smith PetscFunctionBegin; 7067233f9f0SBarry Smith ierr = PetscOptionsHead("Exotic coarse space options");CHKERRQ(ierr); 7077233f9f0SBarry Smith ierr = PetscOptionsEnum("-pc_exotic_type","face or wirebasket","PCExoticSetType",PCExoticTypes,(PetscEnum)ctx->type,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr); 7087233f9f0SBarry Smith if (flg) { 7097233f9f0SBarry Smith ierr = PCExoticSetType(pc,mgctype);CHKERRQ(ierr); 7107233f9f0SBarry Smith } 711acfcf0e5SJed Brown ierr = PetscOptionsBool("-pc_exotic_direct_solver","use direct solver to construct interpolation","None",ctx->directSolve,&ctx->directSolve,PETSC_NULL);CHKERRQ(ierr); 7128e722e36SBarry Smith if (!ctx->directSolve) { 7138e722e36SBarry Smith if (!ctx->ksp) { 7148e722e36SBarry Smith const char *prefix; 7158e722e36SBarry Smith ierr = KSPCreate(PETSC_COMM_SELF,&ctx->ksp);CHKERRQ(ierr); 7168e722e36SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 7178e722e36SBarry Smith ierr = PetscLogObjectParent(pc,ctx->ksp);CHKERRQ(ierr); 7188e722e36SBarry Smith ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 7198e722e36SBarry Smith ierr = KSPSetOptionsPrefix(ctx->ksp,prefix);CHKERRQ(ierr); 7208e722e36SBarry Smith ierr = KSPAppendOptionsPrefix(ctx->ksp,"exotic_");CHKERRQ(ierr); 7218e722e36SBarry Smith } 7228e722e36SBarry Smith ierr = KSPSetFromOptions(ctx->ksp);CHKERRQ(ierr); 7238e722e36SBarry Smith } 7247233f9f0SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 7257233f9f0SBarry Smith PetscFunctionReturn(0); 7267233f9f0SBarry Smith } 7277233f9f0SBarry Smith 728174b6946SBarry Smith 729174b6946SBarry Smith /*MC 7307233f9f0SBarry Smith PCEXOTIC - Two level overlapping Schwarz preconditioner with exotic (non-standard) coarse grid spaces 731174b6946SBarry Smith 7327233f9f0SBarry Smith This uses the PCMG infrastructure restricted to two levels and the face and wirebasket based coarse 73324c3aa18SBarry Smith grid spaces. 73424c3aa18SBarry Smith 73524c3aa18SBarry Smith Notes: By default this uses GMRES on the fine grid smoother so this should be used with KSPFGMRES or the smoother changed to not use GMRES 73624c3aa18SBarry Smith 73724c3aa18SBarry Smith References: These coarse grid spaces originate in the work of Bramble, Pasciak and Schatz, "The Construction 7383b65e785SBarry Smith of Preconditioners for Elliptic Problems by Substructing IV", Mathematics of Computation, volume 53 pages 1--24, 1989. 7393b65e785SBarry Smith They were generalized slightly in "Domain Decomposition Method for Linear Elasticity", Ph. D. thesis, Barry Smith, 7403b65e785SBarry Smith New York University, 1990. They were then explored in great detail in Dryja, Smith, Widlund, "Schwarz Analysis 7413b65e785SBarry Smith of Iterative Substructuring Methods for Elliptic Problems in Three Dimensions, SIAM Journal on Numerical 7423b65e785SBarry Smith Analysis, volume 31. pages 1662-1694, 1994. These were developed in the context of iterative substructuring preconditioners. 7433b65e785SBarry Smith They were then ingeniously applied as coarse grid spaces for overlapping Schwarz methods by Dohrmann and Widlund. 7443b65e785SBarry Smith They refer to them as GDSW (generalized Dryja, Smith, Widlund preconditioners). See, for example, 7453b65e785SBarry Smith Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Extending theory for domain decomposition algorithms to irregular subdomains. In Ulrich Langer, Marco 7463b65e785SBarry Smith Discacciati, David Keyes, Olof Widlund, and Walter Zulehner, editors, Proceedings 7473b65e785SBarry Smith of the 17th International Conference on Domain Decomposition Methods in 7483b65e785SBarry Smith Science and Engineering, held in Strobl, Austria, July 3-7, 2006, number 60 in 7493b65e785SBarry Smith Springer-Verlag, Lecture Notes in Computational Science and Engineering, pages 255-261, 2007. 7503b65e785SBarry Smith Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. A family of energy min- 7513b65e785SBarry Smith imizing coarse spaces for overlapping Schwarz preconditioners. In Ulrich Langer, 7523b65e785SBarry Smith Marco Discacciati, David Keyes, Olof Widlund, and Walter Zulehner, editors, Proceedings 7533b65e785SBarry Smith of the 17th International Conference on Domain Decomposition Methods 7543b65e785SBarry Smith in Science and Engineering, held in Strobl, Austria, July 3-7, 2006, number 60 in 7553b65e785SBarry Smith Springer-Verlag, Lecture Notes in Computational Science and Engineering, pages 247-254, 2007 7563b65e785SBarry Smith Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Domain decomposition 7573b65e785SBarry Smith for less regular subdomains: Overlapping Schwarz in two dimensions. SIAM J. 7583b65e785SBarry Smith Numer. Anal., 46(4):2153-2168, 2008. 7593b65e785SBarry Smith Clark R. Dohrmann and Olof B. Widlund. An overlapping Schwarz 7603b65e785SBarry Smith algorithm for almost incompressible elasticity. Technical Report 7613b65e785SBarry Smith TR2008-912, Department of Computer Science, Courant Institute 7623b65e785SBarry Smith of Mathematical Sciences, New York University, May 2008. URL: 7633b65e785SBarry Smith http://cs.nyu.edu/csweb/Research/TechReports/TR2008-912/TR2008-912.pdf 7647233f9f0SBarry Smith 7657233f9f0SBarry Smith Options Database: The usual PCMG options are supported, such as -mg_levels_pc_type <type> -mg_coarse_pc_type <type> 7667233f9f0SBarry Smith -pc_mg_type <type> 7677233f9f0SBarry Smith 76825a35f6fSSatish Balay Level: advanced 769174b6946SBarry Smith 7706c699258SBarry Smith .seealso: PCMG, PCSetDM(), PCExoticType, PCExoticSetType() 771174b6946SBarry Smith M*/ 772174b6946SBarry Smith 773174b6946SBarry Smith EXTERN_C_BEGIN 774174b6946SBarry Smith #undef __FUNCT__ 7757233f9f0SBarry Smith #define __FUNCT__ "PCCreate_Exotic" 7767087cfbeSBarry Smith PetscErrorCode PCCreate_Exotic(PC pc) 777174b6946SBarry Smith { 778174b6946SBarry Smith PetscErrorCode ierr; 7797233f9f0SBarry Smith PC_Exotic *ex; 780f3fbd535SBarry Smith PC_MG *mg; 781174b6946SBarry Smith 782174b6946SBarry Smith PetscFunctionBegin; 783f91d8e95SBarry Smith /* if type was previously mg; must manually destroy it because call to PCSetType(pc,PCMG) will not destroy it */ 784f91d8e95SBarry Smith if (pc->ops->destroy) { ierr = (*pc->ops->destroy)(pc);CHKERRQ(ierr); pc->data = 0;} 785503cfb0cSBarry Smith ierr = PetscFree(((PetscObject)pc)->type_name);CHKERRQ(ierr); 786f91d8e95SBarry Smith ((PetscObject)pc)->type_name = 0; 787f91d8e95SBarry Smith 788174b6946SBarry Smith ierr = PCSetType(pc,PCMG);CHKERRQ(ierr); 789174b6946SBarry Smith ierr = PCMGSetLevels(pc,2,PETSC_NULL);CHKERRQ(ierr); 790c91913d3SJed Brown ierr = PCMGSetGalerkin(pc,PETSC_TRUE);CHKERRQ(ierr); 79196bdf778SBarry Smith ierr = PetscNew(PC_Exotic,&ex);CHKERRQ(ierr);\ 7927233f9f0SBarry Smith ex->type = PC_EXOTIC_FACE; 793f3fbd535SBarry Smith mg = (PC_MG*) pc->data; 79431567311SBarry Smith mg->innerctx = ex; 7957233f9f0SBarry Smith 7967233f9f0SBarry Smith 7977233f9f0SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Exotic; 7987233f9f0SBarry Smith pc->ops->view = PCView_Exotic; 7997233f9f0SBarry Smith pc->ops->destroy = PCDestroy_Exotic; 8006c699258SBarry Smith pc->ops->setup = PCSetUp_Exotic; 8017233f9f0SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCExoticSetType_C","PCExoticSetType_Exotic",PCExoticSetType_Exotic);CHKERRQ(ierr); 802174b6946SBarry Smith PetscFunctionReturn(0); 803174b6946SBarry Smith } 804174b6946SBarry Smith EXTERN_C_END 805