1174b6946SBarry Smith 2c6db04a5SJed Brown #include <petscdmda.h> /*I "petscdmda.h" I*/ 3af0996ceSBarry Smith #include <petsc/private/pcmgimpl.h> /*I "petscksp.h" I*/ 482c86c8fSBarry Smith #include <petscctable.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 130a545947SLisandro Dalcin const char *const PCExoticTypes[] = {"face","wirebasket","PCExoticType","PC_Exotic",NULL}; 14064c8009SBarry Smith 15064c8009SBarry Smith /* 16aa219208SBarry Smith DMDAGetWireBasketInterpolation - Gets the interpolation for a wirebasket based coarse space 17064c8009SBarry Smith 18064c8009SBarry Smith */ 19c0decd05SBarry Smith PetscErrorCode DMDAGetWireBasketInterpolation(PC pc,DM da,PC_Exotic *exotic,Mat Aglobal,MatReuse reuse,Mat *P) 20064c8009SBarry Smith { 21064c8009SBarry 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; 2228d20b34SBarry Smith PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[26],*globals,Ng,*IIint,*IIsurf,Nt; 23064c8009SBarry Smith Mat Xint, Xsurf,Xint_tmp; 24064c8009SBarry Smith IS isint,issurf,is,row,col; 25064c8009SBarry Smith ISLocalToGlobalMapping ltg; 26064c8009SBarry Smith MPI_Comm comm; 27064c8009SBarry Smith Mat A,Aii,Ais,Asi,*Aholder,iAii; 28064c8009SBarry Smith MatFactorInfo info; 29064c8009SBarry Smith PetscScalar *xsurf,*xint; 301683a169SBarry Smith const PetscScalar *rxint; 318e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 32064c8009SBarry Smith PetscScalar tmp; 33064c8009SBarry Smith #endif 34064c8009SBarry Smith PetscTable ht; 35064c8009SBarry Smith 36064c8009SBarry Smith PetscFunctionBegin; 375f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,&dim,NULL,NULL,NULL,&mp,&np,&pp,&dof,NULL,NULL,NULL,NULL,NULL)); 382c71b3e2SJacob Faibussowitsch PetscCheckFalse(dof != 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only for single field problems"); 392c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim != 3,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only coded for 3d problems"); 405f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,NULL,NULL,NULL,&m,&n,&p)); 415f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth)); 42064c8009SBarry Smith istart = istart ? -1 : 0; 43064c8009SBarry Smith jstart = jstart ? -1 : 0; 44064c8009SBarry Smith kstart = kstart ? -1 : 0; 45064c8009SBarry Smith 46064c8009SBarry Smith /* 47064c8009SBarry Smith the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 48064c8009SBarry Smith to all the local degrees of freedom (this includes the vertices, edges and faces). 49064c8009SBarry Smith 50064c8009SBarry Smith Xint are the subset of the interpolation into the interior 51064c8009SBarry Smith 52064c8009SBarry Smith Xface are the interpolation onto faces but not into the interior 53064c8009SBarry Smith 54064c8009SBarry Smith Xsurf are the interpolation onto the vertices and edges (the surfbasket) 55064c8009SBarry Smith Xint 56064c8009SBarry Smith Symbolically one could write P = (Xface) after interchanging the rows to match the natural ordering on the domain 57064c8009SBarry Smith Xsurf 58064c8009SBarry Smith */ 59064c8009SBarry Smith N = (m - istart)*(n - jstart)*(p - kstart); 60064c8009SBarry Smith Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 61064c8009SBarry Smith Nface = 2*((m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart)); 62064c8009SBarry Smith Nwire = 4*((m-2-istart) + (n-2-jstart) + (p-2-kstart)) + 8; 63064c8009SBarry Smith Nsurf = Nface + Nwire; 645f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(MPI_COMM_SELF,Nint,26,NULL,&Xint)); 655f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(MPI_COMM_SELF,Nsurf,26,NULL,&Xsurf)); 665f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Xsurf,&xsurf)); 67064c8009SBarry Smith 68064c8009SBarry Smith /* 69064c8009SBarry Smith Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 70064c8009SBarry Smith Xsurf will be all zero (thus making the coarse matrix singular). 71064c8009SBarry Smith */ 722c71b3e2SJacob Faibussowitsch PetscCheckFalse(m-istart < 3,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in X direction must be at least 3"); 732c71b3e2SJacob Faibussowitsch PetscCheckFalse(n-jstart < 3,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Y direction must be at least 3"); 742c71b3e2SJacob Faibussowitsch PetscCheckFalse(p-kstart < 3,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Z direction must be at least 3"); 75064c8009SBarry Smith 76064c8009SBarry Smith cnt = 0; 772fa5cd67SKarl Rupp 782fa5cd67SKarl Rupp xsurf[cnt++] = 1; 792fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + Nsurf] = 1; 802fa5cd67SKarl Rupp xsurf[cnt++ + 2*Nsurf] = 1; 812fa5cd67SKarl Rupp 822fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 832fa5cd67SKarl Rupp xsurf[cnt++ + 3*Nsurf] = 1; 842fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 4*Nsurf] = 1; 852fa5cd67SKarl Rupp xsurf[cnt++ + 5*Nsurf] = 1; 86064c8009SBarry Smith } 872fa5cd67SKarl Rupp 882fa5cd67SKarl Rupp xsurf[cnt++ + 6*Nsurf] = 1; 892fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 7*Nsurf] = 1; 902fa5cd67SKarl Rupp xsurf[cnt++ + 8*Nsurf] = 1; 912fa5cd67SKarl Rupp 922fa5cd67SKarl Rupp for (k=1; k<p-1-kstart; k++) { 932fa5cd67SKarl Rupp xsurf[cnt++ + 9*Nsurf] = 1; 942fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 10*Nsurf] = 1; 952fa5cd67SKarl Rupp xsurf[cnt++ + 11*Nsurf] = 1; 962fa5cd67SKarl Rupp 972fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 982fa5cd67SKarl Rupp xsurf[cnt++ + 12*Nsurf] = 1; 992fa5cd67SKarl Rupp /* these are the interior nodes */ 1002fa5cd67SKarl Rupp xsurf[cnt++ + 13*Nsurf] = 1; 1012fa5cd67SKarl Rupp } 1022fa5cd67SKarl Rupp 1032fa5cd67SKarl Rupp xsurf[cnt++ + 14*Nsurf] = 1; 1042fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 15*Nsurf] = 1; 1052fa5cd67SKarl Rupp xsurf[cnt++ + 16*Nsurf] = 1; 1062fa5cd67SKarl Rupp } 1072fa5cd67SKarl Rupp 1082fa5cd67SKarl Rupp xsurf[cnt++ + 17*Nsurf] = 1; 1092fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 18*Nsurf] = 1; 1102fa5cd67SKarl Rupp xsurf[cnt++ + 19*Nsurf] = 1; 1112fa5cd67SKarl Rupp 1122fa5cd67SKarl Rupp for (j=1;j<n-1-jstart;j++) { 1132fa5cd67SKarl Rupp xsurf[cnt++ + 20*Nsurf] = 1; 1142fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 21*Nsurf] = 1; 1152fa5cd67SKarl Rupp xsurf[cnt++ + 22*Nsurf] = 1; 1162fa5cd67SKarl Rupp } 1172fa5cd67SKarl Rupp 1182fa5cd67SKarl Rupp xsurf[cnt++ + 23*Nsurf] = 1; 1192fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 24*Nsurf] = 1; 1202fa5cd67SKarl Rupp xsurf[cnt++ + 25*Nsurf] = 1; 1212fa5cd67SKarl Rupp 1228e722e36SBarry Smith /* interpolations only sum to 1 when using direct solver */ 1238e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 124064c8009SBarry Smith for (i=0; i<Nsurf; i++) { 125064c8009SBarry Smith tmp = 0.0; 1262fa5cd67SKarl Rupp for (j=0; j<26; j++) tmp += xsurf[i+j*Nsurf]; 1272c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(tmp-1.0) > 1.e-10,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xsurf interpolation at i %D value %g",i,(double)PetscAbsScalar(tmp)); 128064c8009SBarry Smith } 129064c8009SBarry Smith #endif 1305f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Xsurf,&xsurf)); 1315f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD));*/ 132064c8009SBarry Smith 133064c8009SBarry Smith /* 134064c8009SBarry Smith I are the indices for all the needed vertices (in global numbering) 135064c8009SBarry Smith Iint are the indices for the interior values, I surf for the surface values 1367dae84e0SHong Zhang (This is just for the part of the global matrix obtained with MatCreateSubMatrix(), it 137aa219208SBarry Smith is NOT the local DMDA ordering.) 138064c8009SBarry Smith IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 139064c8009SBarry Smith */ 140064c8009SBarry Smith #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 1415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(N,&II,Nint,&Iint,Nsurf,&Isurf)); 1425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(Nint,&IIint,Nsurf,&IIsurf)); 143064c8009SBarry Smith for (k=0; k<p-kstart; k++) { 144064c8009SBarry Smith for (j=0; j<n-jstart; j++) { 145064c8009SBarry Smith for (i=0; i<m-istart; i++) { 146064c8009SBarry Smith II[c++] = i + j*mwidth + k*mwidth*nwidth; 147064c8009SBarry Smith 148064c8009SBarry Smith if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 149064c8009SBarry Smith IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 150064c8009SBarry Smith Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 151064c8009SBarry Smith } else { 152064c8009SBarry Smith IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 153064c8009SBarry Smith Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 154064c8009SBarry Smith } 155064c8009SBarry Smith } 156064c8009SBarry Smith } 157064c8009SBarry Smith } 1582c71b3e2SJacob Faibussowitsch PetscCheckFalse(c != N,PETSC_COMM_SELF,PETSC_ERR_PLIB,"c != N"); 1592c71b3e2SJacob Faibussowitsch PetscCheckFalse(cint != Nint,PETSC_COMM_SELF,PETSC_ERR_PLIB,"cint != Nint"); 1602c71b3e2SJacob Faibussowitsch PetscCheckFalse(csurf != Nsurf,PETSC_COMM_SELF,PETSC_ERR_PLIB,"csurf != Nsurf"); 1615f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalToGlobalMapping(da,<g)); 1625f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,N,II,II)); 1635f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint)); 1645f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf)); 1655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)da,&comm)); 1665f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,N,II,PETSC_COPY_VALUES,&is)); 1675f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,PETSC_COPY_VALUES,&isint)); 1685f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,PETSC_COPY_VALUES,&issurf)); 1695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(II,Iint,Isurf)); 170064c8009SBarry Smith 1715f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder)); 172064c8009SBarry Smith A = *Aholder; 1735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(Aholder)); 174064c8009SBarry Smith 1755f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii)); 1765f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais)); 1775f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi)); 178064c8009SBarry Smith 179064c8009SBarry Smith /* 180064c8009SBarry Smith Solve for the interpolation onto the interior Xint 181064c8009SBarry Smith */ 1825f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(Ais,Xsurf,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&Xint_tmp)); 1835f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(Xint_tmp,-1.0)); 1848e722e36SBarry Smith if (exotic->directSolve) { 1855f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetFactor(Aii,MATSOLVERPETSC,MAT_FACTOR_LU,&iAii)); 1865f80ce2aSJacob Faibussowitsch CHKERRQ(MatFactorInfoInitialize(&info)); 1875f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOrdering(Aii,MATORDERINGND,&row,&col)); 1885f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactorSymbolic(iAii,Aii,row,col,&info)); 1895f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&row)); 1905f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&col)); 1915f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactorNumeric(iAii,Aii,&info)); 1925f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatSolve(iAii,Xint_tmp,Xint)); 1935f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&iAii)); 1948e722e36SBarry Smith } else { 1958e722e36SBarry Smith Vec b,x; 1968e722e36SBarry Smith PetscScalar *xint_tmp; 197064c8009SBarry Smith 1985f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Xint,&xint)); 1995f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&x)); 2005f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Xint_tmp,&xint_tmp)); 2015f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&b)); 2025f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(exotic->ksp,Aii,Aii)); 2038e722e36SBarry Smith for (i=0; i<26; i++) { 2045f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(x,xint+i*Nint)); 2055f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(b,xint_tmp+i*Nint)); 2065f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(exotic->ksp,b,x)); 2075f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(exotic->ksp,pc,x)); 2085f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(x)); 2095f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(b)); 2108e722e36SBarry Smith } 2115f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Xint,&xint)); 2125f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Xint_tmp,&xint_tmp)); 2135f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x)); 2145f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&b)); 2158e722e36SBarry Smith } 2165f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Xint_tmp)); 2178e722e36SBarry Smith 2188e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 2195f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Xint,&rxint)); 220064c8009SBarry Smith for (i=0; i<Nint; i++) { 221064c8009SBarry Smith tmp = 0.0; 2221683a169SBarry Smith for (j=0; j<26; j++) tmp += rxint[i+j*Nint]; 2232fa5cd67SKarl Rupp 2242c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(tmp-1.0) > 1.e-10,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xint interpolation at i %D value %g",i,(double)PetscAbsScalar(tmp)); 225064c8009SBarry Smith } 2265f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Xint,&rxint)); 2275f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatView(Xint,PETSC_VIEWER_STDOUT_WORLD)); */ 228064c8009SBarry Smith #endif 229064c8009SBarry Smith 230064c8009SBarry Smith /* total vertices total faces total edges */ 231064c8009SBarry 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); 232064c8009SBarry Smith 233064c8009SBarry Smith /* 234064c8009SBarry Smith For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 235064c8009SBarry Smith */ 236064c8009SBarry Smith cnt = 0; 2372fa5cd67SKarl Rupp 238064c8009SBarry Smith gl[cnt++] = 0; { gl[cnt++] = 1;} gl[cnt++] = m-istart-1; 239064c8009SBarry Smith { gl[cnt++] = mwidth; { gl[cnt++] = mwidth+1;} gl[cnt++] = mwidth + m-istart-1;} 240064c8009SBarry Smith gl[cnt++] = mwidth*(n-jstart-1); { gl[cnt++] = mwidth*(n-jstart-1)+1;} gl[cnt++] = mwidth*(n-jstart-1) + m-istart-1; 241064c8009SBarry Smith { 242064c8009SBarry Smith gl[cnt++] = mwidth*nwidth; { gl[cnt++] = mwidth*nwidth+1;} gl[cnt++] = mwidth*nwidth+ m-istart-1; 243064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 244064c8009SBarry 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; 245064c8009SBarry Smith } 246064c8009SBarry 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; 247064c8009SBarry 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;} 248064c8009SBarry 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; 249064c8009SBarry Smith 250064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 251064c8009SBarry Smith /* convert that to global numbering and get them on all processes */ 2525f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,26,gl,gl)); 253064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 2545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(26*mp*np*pp,&globals)); 2555f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allgather(gl,26,MPIU_INT,globals,26,MPIU_INT,PetscObjectComm((PetscObject)da))); 256064c8009SBarry Smith 257064c8009SBarry Smith /* Number the coarse grid points from 0 to Ntotal */ 2585f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(Aglobal,&Nt,NULL)); 2595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableCreate(Ntotal/3,Nt+1,&ht)); 260064c8009SBarry Smith for (i=0; i<26*mp*np*pp; i++) { 2615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableAddCount(ht,globals[i]+1)); 262064c8009SBarry Smith } 2635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableGetCount(ht,&cnt)); 2642c71b3e2SJacob Faibussowitsch PetscCheckFalse(cnt != Ntotal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hash table size %D not equal to total number coarse grid points %D",cnt,Ntotal); 2655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(globals)); 266064c8009SBarry Smith for (i=0; i<26; i++) { 2675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableFind(ht,gl[i]+1,&gl[i])); 268064c8009SBarry Smith gl[i]--; 269064c8009SBarry Smith } 2705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableDestroy(&ht)); 271064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 272064c8009SBarry Smith 273064c8009SBarry Smith /* construct global interpolation matrix */ 2745f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(Aglobal,&Ng,NULL)); 275064c8009SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 2765f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateAIJ(PetscObjectComm((PetscObject)da),Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,NULL,Nint+Nsurf,NULL,P)); 277064c8009SBarry Smith } else { 2785f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(*P)); 279064c8009SBarry Smith } 2805f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE)); 2815f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Xint,&rxint)); 2825f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(*P,Nint,IIint,26,gl,rxint,INSERT_VALUES)); 2835f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Xint,&rxint)); 2845f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Xsurf,&rxint)); 2855f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(*P,Nsurf,IIsurf,26,gl,rxint,INSERT_VALUES)); 2865f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Xsurf,&rxint)); 2875f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY)); 2885f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY)); 2895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(IIint,IIsurf)); 290064c8009SBarry Smith 2918e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 292064c8009SBarry Smith { 293064c8009SBarry Smith Vec x,y; 294064c8009SBarry Smith PetscScalar *yy; 2955f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateMPI(PetscObjectComm((PetscObject)da),Ng,PETSC_DETERMINE,&y)); 2965f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateMPI(PetscObjectComm((PetscObject)da),PETSC_DETERMINE,Ntotal,&x)); 2975f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(x,1.0)); 2985f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(*P,x,y)); 2995f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(y,&yy)); 300064c8009SBarry Smith for (i=0; i<Ng; i++) { 3012c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(yy[i]-1.0) > 1.e-10,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong p interpolation at i %D value %g",i,(double)PetscAbsScalar(yy[i])); 302064c8009SBarry Smith } 3035f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(y,&yy)); 3045f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(x)); 3055f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(y)); 306064c8009SBarry Smith } 307064c8009SBarry Smith #endif 308064c8009SBarry Smith 3095f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Aii)); 3105f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Ais)); 3115f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Asi)); 3125f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 3135f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is)); 3145f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isint)); 3155f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&issurf)); 3165f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Xint)); 3175f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Xsurf)); 318064c8009SBarry Smith PetscFunctionReturn(0); 319064c8009SBarry Smith } 320064c8009SBarry Smith 321064c8009SBarry Smith /* 322aa219208SBarry Smith DMDAGetFaceInterpolation - Gets the interpolation for a face based coarse space 323064c8009SBarry Smith 324064c8009SBarry Smith */ 325c0decd05SBarry Smith PetscErrorCode DMDAGetFaceInterpolation(PC pc,DM da,PC_Exotic *exotic,Mat Aglobal,MatReuse reuse,Mat *P) 326064c8009SBarry Smith { 327064c8009SBarry 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; 32828d20b34SBarry Smith PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[6],*globals,Ng,*IIint,*IIsurf,Nt; 329064c8009SBarry Smith Mat Xint, Xsurf,Xint_tmp; 330064c8009SBarry Smith IS isint,issurf,is,row,col; 331064c8009SBarry Smith ISLocalToGlobalMapping ltg; 332064c8009SBarry Smith MPI_Comm comm; 333064c8009SBarry Smith Mat A,Aii,Ais,Asi,*Aholder,iAii; 334064c8009SBarry Smith MatFactorInfo info; 335064c8009SBarry Smith PetscScalar *xsurf,*xint; 3361683a169SBarry Smith const PetscScalar *rxint; 337064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 338064c8009SBarry Smith PetscScalar tmp; 339064c8009SBarry Smith #endif 340064c8009SBarry Smith PetscTable ht; 341064c8009SBarry Smith 342064c8009SBarry Smith PetscFunctionBegin; 3435f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,&dim,NULL,NULL,NULL,&mp,&np,&pp,&dof,NULL,NULL,NULL,NULL,NULL)); 3442c71b3e2SJacob Faibussowitsch PetscCheckFalse(dof != 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only for single field problems"); 3452c71b3e2SJacob Faibussowitsch PetscCheckFalse(dim != 3,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only coded for 3d problems"); 3465f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,NULL,NULL,NULL,&m,&n,&p)); 3475f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth)); 348064c8009SBarry Smith istart = istart ? -1 : 0; 349064c8009SBarry Smith jstart = jstart ? -1 : 0; 350064c8009SBarry Smith kstart = kstart ? -1 : 0; 351064c8009SBarry Smith 352064c8009SBarry Smith /* 353064c8009SBarry Smith the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 354064c8009SBarry Smith to all the local degrees of freedom (this includes the vertices, edges and faces). 355064c8009SBarry Smith 356064c8009SBarry Smith Xint are the subset of the interpolation into the interior 357064c8009SBarry Smith 358064c8009SBarry Smith Xface are the interpolation onto faces but not into the interior 359064c8009SBarry Smith 360064c8009SBarry Smith Xsurf are the interpolation onto the vertices and edges (the surfbasket) 361064c8009SBarry Smith Xint 362064c8009SBarry Smith Symbolically one could write P = (Xface) after interchanging the rows to match the natural ordering on the domain 363064c8009SBarry Smith Xsurf 364064c8009SBarry Smith */ 365064c8009SBarry Smith N = (m - istart)*(n - jstart)*(p - kstart); 366064c8009SBarry Smith Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 367064c8009SBarry Smith Nface = 2*((m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart)); 368064c8009SBarry Smith Nwire = 4*((m-2-istart) + (n-2-jstart) + (p-2-kstart)) + 8; 369064c8009SBarry Smith Nsurf = Nface + Nwire; 3705f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(MPI_COMM_SELF,Nint,6,NULL,&Xint)); 3715f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSeqDense(MPI_COMM_SELF,Nsurf,6,NULL,&Xsurf)); 3725f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Xsurf,&xsurf)); 373064c8009SBarry Smith 374064c8009SBarry Smith /* 375064c8009SBarry Smith Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 376064c8009SBarry Smith Xsurf will be all zero (thus making the coarse matrix singular). 377064c8009SBarry Smith */ 3782c71b3e2SJacob Faibussowitsch PetscCheckFalse(m-istart < 3,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in X direction must be at least 3"); 3792c71b3e2SJacob Faibussowitsch PetscCheckFalse(n-jstart < 3,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Y direction must be at least 3"); 3802c71b3e2SJacob Faibussowitsch PetscCheckFalse(p-kstart < 3,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Z direction must be at least 3"); 381064c8009SBarry Smith 382064c8009SBarry Smith cnt = 0; 3832fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 3842fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 0*Nsurf] = 1; 385064c8009SBarry Smith } 3862fa5cd67SKarl Rupp 3872fa5cd67SKarl Rupp for (k=1; k<p-1-kstart; k++) { 3882fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 1*Nsurf] = 1; 3892fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 3902fa5cd67SKarl Rupp xsurf[cnt++ + 2*Nsurf] = 1; 3912fa5cd67SKarl Rupp /* these are the interior nodes */ 3922fa5cd67SKarl Rupp xsurf[cnt++ + 3*Nsurf] = 1; 3932fa5cd67SKarl Rupp } 3942fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 4*Nsurf] = 1; 3952fa5cd67SKarl Rupp } 3962fa5cd67SKarl Rupp for (j=1;j<n-1-jstart;j++) { 3972fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 5*Nsurf] = 1; 3982fa5cd67SKarl Rupp } 399064c8009SBarry Smith 400064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 401064c8009SBarry Smith for (i=0; i<Nsurf; i++) { 402064c8009SBarry Smith tmp = 0.0; 4032fa5cd67SKarl Rupp for (j=0; j<6; j++) tmp += xsurf[i+j*Nsurf]; 4042fa5cd67SKarl Rupp 4052c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(tmp-1.0) > 1.e-10,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xsurf interpolation at i %D value %g",i,(double)PetscAbsScalar(tmp)); 406064c8009SBarry Smith } 407064c8009SBarry Smith #endif 4085f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Xsurf,&xsurf)); 4095f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD));*/ 410064c8009SBarry Smith 411064c8009SBarry Smith /* 412064c8009SBarry Smith I are the indices for all the needed vertices (in global numbering) 413064c8009SBarry Smith Iint are the indices for the interior values, I surf for the surface values 4147dae84e0SHong Zhang (This is just for the part of the global matrix obtained with MatCreateSubMatrix(), it 415aa219208SBarry Smith is NOT the local DMDA ordering.) 416064c8009SBarry Smith IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 417064c8009SBarry Smith */ 418064c8009SBarry Smith #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 4195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(N,&II,Nint,&Iint,Nsurf,&Isurf)); 4205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(Nint,&IIint,Nsurf,&IIsurf)); 421064c8009SBarry Smith for (k=0; k<p-kstart; k++) { 422064c8009SBarry Smith for (j=0; j<n-jstart; j++) { 423064c8009SBarry Smith for (i=0; i<m-istart; i++) { 424064c8009SBarry Smith II[c++] = i + j*mwidth + k*mwidth*nwidth; 425064c8009SBarry Smith 426064c8009SBarry Smith if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 427064c8009SBarry Smith IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 428064c8009SBarry Smith Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 429064c8009SBarry Smith } else { 430064c8009SBarry Smith IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 431064c8009SBarry Smith Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 432064c8009SBarry Smith } 433064c8009SBarry Smith } 434064c8009SBarry Smith } 435064c8009SBarry Smith } 4362c71b3e2SJacob Faibussowitsch PetscCheckFalse(c != N,PETSC_COMM_SELF,PETSC_ERR_PLIB,"c != N"); 4372c71b3e2SJacob Faibussowitsch PetscCheckFalse(cint != Nint,PETSC_COMM_SELF,PETSC_ERR_PLIB,"cint != Nint"); 4382c71b3e2SJacob Faibussowitsch PetscCheckFalse(csurf != Nsurf,PETSC_COMM_SELF,PETSC_ERR_PLIB,"csurf != Nsurf"); 4395f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalToGlobalMapping(da,<g)); 4405f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,N,II,II)); 4415f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint)); 4425f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf)); 4435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)da,&comm)); 4445f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(comm,N,II,PETSC_COPY_VALUES,&is)); 4455f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,PETSC_COPY_VALUES,&isint)); 4465f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,PETSC_COPY_VALUES,&issurf)); 4475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(II,Iint,Isurf)); 448064c8009SBarry Smith 4495f80ce2aSJacob Faibussowitsch CHKERRQ(ISSort(is)); 4505f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder)); 451064c8009SBarry Smith A = *Aholder; 4525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(Aholder)); 453064c8009SBarry Smith 4545f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii)); 4555f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais)); 4565f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi)); 457064c8009SBarry Smith 458064c8009SBarry Smith /* 459064c8009SBarry Smith Solve for the interpolation onto the interior Xint 460064c8009SBarry Smith */ 4615f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(Ais,Xsurf,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&Xint_tmp)); 4625f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(Xint_tmp,-1.0)); 463064c8009SBarry Smith 4648e722e36SBarry Smith if (exotic->directSolve) { 4655f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetFactor(Aii,MATSOLVERPETSC,MAT_FACTOR_LU,&iAii)); 4665f80ce2aSJacob Faibussowitsch CHKERRQ(MatFactorInfoInitialize(&info)); 4675f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOrdering(Aii,MATORDERINGND,&row,&col)); 4685f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactorSymbolic(iAii,Aii,row,col,&info)); 4695f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&row)); 4705f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&col)); 4715f80ce2aSJacob Faibussowitsch CHKERRQ(MatLUFactorNumeric(iAii,Aii,&info)); 4725f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatSolve(iAii,Xint_tmp,Xint)); 4735f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&iAii)); 474064c8009SBarry Smith } else { 475064c8009SBarry Smith Vec b,x; 476064c8009SBarry Smith PetscScalar *xint_tmp; 477064c8009SBarry Smith 4785f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Xint,&xint)); 4795f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&x)); 4805f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(Xint_tmp,&xint_tmp)); 4815f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&b)); 4825f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(exotic->ksp,Aii,Aii)); 483064c8009SBarry Smith for (i=0; i<6; i++) { 4845f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(x,xint+i*Nint)); 4855f80ce2aSJacob Faibussowitsch CHKERRQ(VecPlaceArray(b,xint_tmp+i*Nint)); 4865f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(exotic->ksp,b,x)); 4875f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(exotic->ksp,pc,x)); 4885f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(x)); 4895f80ce2aSJacob Faibussowitsch CHKERRQ(VecResetArray(b)); 490064c8009SBarry Smith } 4915f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Xint,&xint)); 4925f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(Xint_tmp,&xint_tmp)); 4935f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&x)); 4945f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&b)); 495064c8009SBarry Smith } 4965f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Xint_tmp)); 497064c8009SBarry Smith 498064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 4995f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Xint,&rxint)); 500064c8009SBarry Smith for (i=0; i<Nint; i++) { 501064c8009SBarry Smith tmp = 0.0; 5021683a169SBarry Smith for (j=0; j<6; j++) tmp += rxint[i+j*Nint]; 5032fa5cd67SKarl Rupp 5042c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(tmp-1.0) > 1.e-10,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xint interpolation at i %D value %g",i,(double)PetscAbsScalar(tmp)); 505064c8009SBarry Smith } 5065f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Xint,&rxint)); 5075f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatView(Xint,PETSC_VIEWER_STDOUT_WORLD)); */ 508064c8009SBarry Smith #endif 509064c8009SBarry Smith 510064c8009SBarry Smith /* total faces */ 511064c8009SBarry Smith Ntotal = mp*np*(pp+1) + mp*pp*(np+1) + np*pp*(mp+1); 512064c8009SBarry Smith 513064c8009SBarry Smith /* 514064c8009SBarry Smith For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 515064c8009SBarry Smith */ 516064c8009SBarry Smith cnt = 0; 517064c8009SBarry Smith { gl[cnt++] = mwidth+1;} 518064c8009SBarry Smith { 519064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth+1;} 520064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 521064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth+mwidth*(n-jstart-1)+1;} 522064c8009SBarry Smith } 523064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth+1;} 524064c8009SBarry Smith 525064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 526064c8009SBarry Smith /* convert that to global numbering and get them on all processes */ 5275f80ce2aSJacob Faibussowitsch CHKERRQ(ISLocalToGlobalMappingApply(ltg,6,gl,gl)); 528064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 5295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(6*mp*np*pp,&globals)); 5305f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allgather(gl,6,MPIU_INT,globals,6,MPIU_INT,PetscObjectComm((PetscObject)da))); 531064c8009SBarry Smith 532064c8009SBarry Smith /* Number the coarse grid points from 0 to Ntotal */ 5335f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(Aglobal,&Nt,NULL)); 5345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableCreate(Ntotal/3,Nt+1,&ht)); 535064c8009SBarry Smith for (i=0; i<6*mp*np*pp; i++) { 5365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableAddCount(ht,globals[i]+1)); 537064c8009SBarry Smith } 5385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableGetCount(ht,&cnt)); 5392c71b3e2SJacob Faibussowitsch PetscCheckFalse(cnt != Ntotal,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hash table size %D not equal to total number coarse grid points %D",cnt,Ntotal); 5405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(globals)); 541064c8009SBarry Smith for (i=0; i<6; i++) { 5425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableFind(ht,gl[i]+1,&gl[i])); 543064c8009SBarry Smith gl[i]--; 544064c8009SBarry Smith } 5455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTableDestroy(&ht)); 546064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 547064c8009SBarry Smith 548064c8009SBarry Smith /* construct global interpolation matrix */ 5495f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(Aglobal,&Ng,NULL)); 550064c8009SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 5515f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateAIJ(PetscObjectComm((PetscObject)da),Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,NULL,Nint,NULL,P)); 552064c8009SBarry Smith } else { 5535f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(*P)); 554064c8009SBarry Smith } 5555f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE)); 5565f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Xint,&rxint)); 5575f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(*P,Nint,IIint,6,gl,rxint,INSERT_VALUES)); 5585f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Xint,&rxint)); 5595f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArrayRead(Xsurf,&rxint)); 5605f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(*P,Nsurf,IIsurf,6,gl,rxint,INSERT_VALUES)); 5615f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArrayRead(Xsurf,&rxint)); 5625f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY)); 5635f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY)); 5645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(IIint,IIsurf)); 565064c8009SBarry Smith 566064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 567064c8009SBarry Smith { 568064c8009SBarry Smith Vec x,y; 569064c8009SBarry Smith PetscScalar *yy; 5705f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateMPI(PetscObjectComm((PetscObject)da),Ng,PETSC_DETERMINE,&y)); 5715f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateMPI(PetscObjectComm((PetscObject)da),PETSC_DETERMINE,Ntotal,&x)); 5725f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(x,1.0)); 5735f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(*P,x,y)); 5745f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(y,&yy)); 575064c8009SBarry Smith for (i=0; i<Ng; i++) { 5762c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(yy[i]-1.0) > 1.e-10,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong p interpolation at i %D value %g",i,(double)PetscAbsScalar(yy[i])); 577064c8009SBarry Smith } 5785f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(y,&yy)); 5795f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(x)); 5805f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(y)); 581064c8009SBarry Smith } 582064c8009SBarry Smith #endif 583064c8009SBarry Smith 5845f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Aii)); 5855f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Ais)); 5865f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Asi)); 5875f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 5885f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is)); 5895f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&isint)); 5905f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&issurf)); 5915f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Xint)); 5925f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Xsurf)); 593064c8009SBarry Smith PetscFunctionReturn(0); 594064c8009SBarry Smith } 595174b6946SBarry Smith 5967233f9f0SBarry Smith /*@ 5977233f9f0SBarry Smith PCExoticSetType - Sets the type of coarse grid interpolation to use 5987233f9f0SBarry Smith 5993f9fe445SBarry Smith Logically Collective on PC 6007233f9f0SBarry Smith 6017233f9f0SBarry Smith Input Parameters: 6027233f9f0SBarry Smith + pc - the preconditioner context 6037233f9f0SBarry Smith - type - either PC_EXOTIC_FACE or PC_EXOTIC_WIREBASKET (defaults to face) 6047233f9f0SBarry Smith 60595452b02SPatrick Sanan Notes: 60695452b02SPatrick Sanan The face based interpolation has 1 degree of freedom per face and ignores the 607563e08c6SBarry Smith edge and vertex values completely in the coarse problem. For any seven point 608563e08c6SBarry Smith stencil the interpolation of a constant on all faces into the interior is that constant. 609563e08c6SBarry Smith 610563e08c6SBarry Smith The wirebasket interpolation has 1 degree of freedom per vertex, per edge and 611563e08c6SBarry Smith per face. A constant on the subdomain boundary is interpolated as that constant 612563e08c6SBarry Smith in the interior of the domain. 613563e08c6SBarry Smith 614563e08c6SBarry Smith The coarse grid matrix is obtained via the Galerkin computation A_c = R A R^T, hence 615563e08c6SBarry Smith if A is nonsingular A_c is also nonsingular. 616563e08c6SBarry Smith 617563e08c6SBarry Smith Both interpolations are suitable for only scalar problems. 618563e08c6SBarry Smith 6197233f9f0SBarry Smith Level: intermediate 6207233f9f0SBarry Smith 6217233f9f0SBarry Smith .seealso: PCEXOTIC, PCExoticType() 6227233f9f0SBarry Smith @*/ 6237087cfbeSBarry Smith PetscErrorCode PCExoticSetType(PC pc,PCExoticType type) 6247233f9f0SBarry Smith { 6257233f9f0SBarry Smith PetscFunctionBegin; 6260700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 627c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,type,2); 6285f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(pc,"PCExoticSetType_C",(PC,PCExoticType),(pc,type))); 6297233f9f0SBarry Smith PetscFunctionReturn(0); 6307233f9f0SBarry Smith } 6317233f9f0SBarry Smith 632f7a08781SBarry Smith static PetscErrorCode PCExoticSetType_Exotic(PC pc,PCExoticType type) 6337233f9f0SBarry Smith { 634f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 63531567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 6367233f9f0SBarry Smith 6377233f9f0SBarry Smith PetscFunctionBegin; 6387233f9f0SBarry Smith ctx->type = type; 6397233f9f0SBarry Smith PetscFunctionReturn(0); 6407233f9f0SBarry Smith } 6417233f9f0SBarry Smith 6427233f9f0SBarry Smith PetscErrorCode PCSetUp_Exotic(PC pc) 643174b6946SBarry Smith { 64496bdf778SBarry Smith Mat A; 645f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 64631567311SBarry Smith PC_Exotic *ex = (PC_Exotic*) mg->innerctx; 64796bdf778SBarry Smith MatReuse reuse = (ex->P) ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 648174b6946SBarry Smith 649174b6946SBarry Smith PetscFunctionBegin; 650*28b400f6SJacob Faibussowitsch PetscCheck(pc->dm,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Need to call PCSetDM() before using this PC"); 6515f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOperators(pc,NULL,&A)); 6527233f9f0SBarry Smith if (ex->type == PC_EXOTIC_FACE) { 6535f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetFaceInterpolation(pc,pc->dm,ex,A,reuse,&ex->P)); 6547233f9f0SBarry Smith } else if (ex->type == PC_EXOTIC_WIREBASKET) { 6555f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetWireBasketInterpolation(pc,pc->dm,ex,A,reuse,&ex->P)); 65698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unknown exotic coarse space %d",ex->type); 6575f80ce2aSJacob Faibussowitsch CHKERRQ(PCMGSetInterpolation(pc,1,ex->P)); 658d0660788SBarry Smith /* if PC has attached DM we must remove it or the PCMG will use it to compute incorrect sized vectors and interpolations */ 6595f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetDM(pc,NULL)); 6605f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetUp_MG(pc)); 661174b6946SBarry Smith PetscFunctionReturn(0); 662174b6946SBarry Smith } 663174b6946SBarry Smith 6647233f9f0SBarry Smith PetscErrorCode PCDestroy_Exotic(PC pc) 665174b6946SBarry Smith { 666f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 66731567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 668174b6946SBarry Smith 669174b6946SBarry Smith PetscFunctionBegin; 6705f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&ctx->P)); 6715f80ce2aSJacob Faibussowitsch CHKERRQ(KSPDestroy(&ctx->ksp)); 6725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ctx)); 6735f80ce2aSJacob Faibussowitsch CHKERRQ(PCDestroy_MG(pc)); 674174b6946SBarry Smith PetscFunctionReturn(0); 675174b6946SBarry Smith } 676174b6946SBarry Smith 6777233f9f0SBarry Smith PetscErrorCode PCView_Exotic(PC pc,PetscViewer viewer) 6787233f9f0SBarry Smith { 679f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 680ace3abfcSBarry Smith PetscBool iascii; 68131567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 6827233f9f0SBarry Smith 6837233f9f0SBarry Smith PetscFunctionBegin; 6845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 6857233f9f0SBarry Smith if (iascii) { 6865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Exotic type = %s\n",PCExoticTypes[ctx->type])); 6878e722e36SBarry Smith if (ctx->directSolve) { 6885f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Using direct solver to construct interpolation\n")); 6898e722e36SBarry Smith } else { 6908e722e36SBarry Smith PetscViewer sviewer; 6918e722e36SBarry Smith PetscMPIInt rank; 6928e722e36SBarry Smith 6935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Using iterative solver to construct interpolation\n")); 6945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(viewer)); 6955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPushTab(viewer)); /* should not need to push this twice? */ 6965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 6975f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank)); 698dd400576SPatrick Sanan if (rank == 0) { 6995f80ce2aSJacob Faibussowitsch CHKERRQ(KSPView(ctx->ksp,sviewer)); 7008e722e36SBarry Smith } 7015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 7025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(viewer)); 7035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPopTab(viewer)); 7048e722e36SBarry Smith } 7057233f9f0SBarry Smith } 7065f80ce2aSJacob Faibussowitsch CHKERRQ(PCView_MG(pc,viewer)); 7077233f9f0SBarry Smith PetscFunctionReturn(0); 7087233f9f0SBarry Smith } 7097233f9f0SBarry Smith 7104416b707SBarry Smith PetscErrorCode PCSetFromOptions_Exotic(PetscOptionItems *PetscOptionsObject,PC pc) 7117233f9f0SBarry Smith { 712ace3abfcSBarry Smith PetscBool flg; 713f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 7147233f9f0SBarry Smith PCExoticType mgctype; 71531567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 7167233f9f0SBarry Smith 7177233f9f0SBarry Smith PetscFunctionBegin; 7185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHead(PetscOptionsObject,"Exotic coarse space options")); 7195f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsEnum("-pc_exotic_type","face or wirebasket","PCExoticSetType",PCExoticTypes,(PetscEnum)ctx->type,(PetscEnum*)&mgctype,&flg)); 7207233f9f0SBarry Smith if (flg) { 7215f80ce2aSJacob Faibussowitsch CHKERRQ(PCExoticSetType(pc,mgctype)); 7227233f9f0SBarry Smith } 7235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-pc_exotic_direct_solver","use direct solver to construct interpolation","None",ctx->directSolve,&ctx->directSolve,NULL)); 7248e722e36SBarry Smith if (!ctx->directSolve) { 7258e722e36SBarry Smith if (!ctx->ksp) { 7268e722e36SBarry Smith const char *prefix; 7275f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(PETSC_COMM_SELF,&ctx->ksp)); 7285f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetErrorIfNotConverged(ctx->ksp,pc->erroriffailure)); 7295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)pc,1)); 7305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)ctx->ksp)); 7315f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOptionsPrefix(pc,&prefix)); 7325f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(ctx->ksp,prefix)); 7335f80ce2aSJacob Faibussowitsch CHKERRQ(KSPAppendOptionsPrefix(ctx->ksp,"exotic_")); 7348e722e36SBarry Smith } 7355f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(ctx->ksp)); 7368e722e36SBarry Smith } 7375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsTail()); 7387233f9f0SBarry Smith PetscFunctionReturn(0); 7397233f9f0SBarry Smith } 7407233f9f0SBarry Smith 741174b6946SBarry Smith /*MC 7427233f9f0SBarry Smith PCEXOTIC - Two level overlapping Schwarz preconditioner with exotic (non-standard) coarse grid spaces 743174b6946SBarry Smith 7447233f9f0SBarry Smith This uses the PCMG infrastructure restricted to two levels and the face and wirebasket based coarse 74524c3aa18SBarry Smith grid spaces. 74624c3aa18SBarry Smith 74795452b02SPatrick Sanan Notes: 74895452b02SPatrick Sanan 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 74924c3aa18SBarry Smith 75096a0c994SBarry Smith References: 751606c0280SSatish Balay + * - These coarse grid spaces originate in the work of Bramble, Pasciak and Schatz, "The Construction 75296a0c994SBarry Smith of Preconditioners for Elliptic Problems by Substructing IV", Mathematics of Computation, volume 53, 1989. 753606c0280SSatish Balay . * - They were generalized slightly in "Domain Decomposition Method for Linear Elasticity", Ph. D. thesis, Barry Smith, 7544f02bc6aSBarry Smith New York University, 1990. 755606c0280SSatish Balay . * - They were then explored in great detail in Dryja, Smith, Widlund, "Schwarz Analysis 7563b65e785SBarry Smith of Iterative Substructuring Methods for Elliptic Problems in Three Dimensions, SIAM Journal on Numerical 75796a0c994SBarry Smith Analysis, volume 31. 1994. These were developed in the context of iterative substructuring preconditioners. 758606c0280SSatish Balay . * - They were then ingeniously applied as coarse grid spaces for overlapping Schwarz methods by Dohrmann and Widlund. 7593b65e785SBarry Smith They refer to them as GDSW (generalized Dryja, Smith, Widlund preconditioners). See, for example, 7603b65e785SBarry Smith Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Extending theory for domain decomposition algorithms to irregular subdomains. In Ulrich Langer, Marco 7613b65e785SBarry Smith Discacciati, David Keyes, Olof Widlund, and Walter Zulehner, editors, Proceedings 7623b65e785SBarry Smith of the 17th International Conference on Domain Decomposition Methods in 76396a0c994SBarry Smith Science and Engineering, held in Strobl, Austria, 2006, number 60 in 76496a0c994SBarry Smith Springer Verlag, Lecture Notes in Computational Science and Engineering, 2007. 765606c0280SSatish Balay . * - Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. A family of energy minimizing coarse spaces for overlapping Schwarz preconditioners. In Ulrich Langer, 7663b65e785SBarry Smith Marco Discacciati, David Keyes, Olof Widlund, and Walter Zulehner, editors, Proceedings 7673b65e785SBarry Smith of the 17th International Conference on Domain Decomposition Methods 76896a0c994SBarry Smith in Science and Engineering, held in Strobl, Austria, 2006, number 60 in 76996a0c994SBarry Smith Springer Verlag, Lecture Notes in Computational Science and Engineering, 2007 770606c0280SSatish Balay . * - Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Domain decomposition 7713b65e785SBarry Smith for less regular subdomains: Overlapping Schwarz in two dimensions. SIAM J. 77296a0c994SBarry Smith Numer. Anal., 46(4), 2008. 773606c0280SSatish Balay - * - Clark R. Dohrmann and Olof B. Widlund. An overlapping Schwarz 7743b65e785SBarry Smith algorithm for almost incompressible elasticity. Technical Report 77596a0c994SBarry Smith TR2008 912, Department of Computer Science, Courant Institute 7763b65e785SBarry Smith of Mathematical Sciences, New York University, May 2008. URL: 7777233f9f0SBarry Smith 7787233f9f0SBarry Smith Options Database: The usual PCMG options are supported, such as -mg_levels_pc_type <type> -mg_coarse_pc_type <type> 7797233f9f0SBarry Smith -pc_mg_type <type> 7807233f9f0SBarry Smith 78125a35f6fSSatish Balay Level: advanced 782174b6946SBarry Smith 7836c699258SBarry Smith .seealso: PCMG, PCSetDM(), PCExoticType, PCExoticSetType() 784174b6946SBarry Smith M*/ 785174b6946SBarry Smith 7868cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Exotic(PC pc) 787174b6946SBarry Smith { 7887233f9f0SBarry Smith PC_Exotic *ex; 789f3fbd535SBarry Smith PC_MG *mg; 790174b6946SBarry Smith 791174b6946SBarry Smith PetscFunctionBegin; 792f91d8e95SBarry Smith /* if type was previously mg; must manually destroy it because call to PCSetType(pc,PCMG) will not destroy it */ 7932fa5cd67SKarl Rupp if (pc->ops->destroy) { 7945f80ce2aSJacob Faibussowitsch CHKERRQ((*pc->ops->destroy)(pc)); 7950a545947SLisandro Dalcin pc->data = NULL; 7962fa5cd67SKarl Rupp } 7975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(((PetscObject)pc)->type_name)); 7980a545947SLisandro Dalcin ((PetscObject)pc)->type_name = NULL; 799f91d8e95SBarry Smith 8005f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc,PCMG)); 8015f80ce2aSJacob Faibussowitsch CHKERRQ(PCMGSetLevels(pc,2,NULL)); 8025f80ce2aSJacob Faibussowitsch CHKERRQ(PCMGSetGalerkin(pc,PC_MG_GALERKIN_PMAT)); 8035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(&ex)); \ 8047233f9f0SBarry Smith ex->type = PC_EXOTIC_FACE; 805f3fbd535SBarry Smith mg = (PC_MG*) pc->data; 80631567311SBarry Smith mg->innerctx = ex; 8077233f9f0SBarry Smith 8087233f9f0SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Exotic; 8097233f9f0SBarry Smith pc->ops->view = PCView_Exotic; 8107233f9f0SBarry Smith pc->ops->destroy = PCDestroy_Exotic; 8116c699258SBarry Smith pc->ops->setup = PCSetUp_Exotic; 8122fa5cd67SKarl Rupp 8135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCExoticSetType_C",PCExoticSetType_Exotic)); 814174b6946SBarry Smith PetscFunctionReturn(0); 815174b6946SBarry Smith } 816