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 16064c8009SBarry Smith /* 17aa219208SBarry Smith DMDAGetWireBasketInterpolation - Gets the interpolation for a wirebasket based coarse space 18064c8009SBarry Smith 19064c8009SBarry Smith */ 20c0decd05SBarry Smith PetscErrorCode DMDAGetWireBasketInterpolation(PC pc,DM da,PC_Exotic *exotic,Mat Aglobal,MatReuse reuse,Mat *P) 21064c8009SBarry Smith { 22064c8009SBarry Smith PetscErrorCode ierr; 23064c8009SBarry 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; 2428d20b34SBarry Smith PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[26],*globals,Ng,*IIint,*IIsurf,Nt; 25064c8009SBarry Smith Mat Xint, Xsurf,Xint_tmp; 26064c8009SBarry Smith IS isint,issurf,is,row,col; 27064c8009SBarry Smith ISLocalToGlobalMapping ltg; 28064c8009SBarry Smith MPI_Comm comm; 29064c8009SBarry Smith Mat A,Aii,Ais,Asi,*Aholder,iAii; 30064c8009SBarry Smith MatFactorInfo info; 31064c8009SBarry Smith PetscScalar *xsurf,*xint; 321683a169SBarry Smith const PetscScalar *rxint; 338e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 34064c8009SBarry Smith PetscScalar tmp; 35064c8009SBarry Smith #endif 36064c8009SBarry Smith PetscTable ht; 37064c8009SBarry Smith 38064c8009SBarry Smith PetscFunctionBegin; 390a545947SLisandro Dalcin ierr = DMDAGetInfo(da,&dim,NULL,NULL,NULL,&mp,&np,&pp,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 40ce94432eSBarry Smith if (dof != 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only for single field problems"); 41ce94432eSBarry Smith if (dim != 3) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only coded for 3d problems"); 420a545947SLisandro Dalcin ierr = DMDAGetCorners(da,NULL,NULL,NULL,&m,&n,&p);CHKERRQ(ierr); 43aa219208SBarry Smith ierr = DMDAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth);CHKERRQ(ierr); 44064c8009SBarry Smith istart = istart ? -1 : 0; 45064c8009SBarry Smith jstart = jstart ? -1 : 0; 46064c8009SBarry Smith kstart = kstart ? -1 : 0; 47064c8009SBarry Smith 48064c8009SBarry Smith /* 49064c8009SBarry Smith the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 50064c8009SBarry Smith to all the local degrees of freedom (this includes the vertices, edges and faces). 51064c8009SBarry Smith 52064c8009SBarry Smith Xint are the subset of the interpolation into the interior 53064c8009SBarry Smith 54064c8009SBarry Smith Xface are the interpolation onto faces but not into the interior 55064c8009SBarry Smith 56064c8009SBarry Smith Xsurf are the interpolation onto the vertices and edges (the surfbasket) 57064c8009SBarry Smith Xint 58064c8009SBarry Smith Symbolically one could write P = (Xface) after interchanging the rows to match the natural ordering on the domain 59064c8009SBarry Smith Xsurf 60064c8009SBarry Smith */ 61064c8009SBarry Smith N = (m - istart)*(n - jstart)*(p - kstart); 62064c8009SBarry Smith Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 63064c8009SBarry Smith Nface = 2*((m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart)); 64064c8009SBarry Smith Nwire = 4*((m-2-istart) + (n-2-jstart) + (p-2-kstart)) + 8; 65064c8009SBarry Smith Nsurf = Nface + Nwire; 660298fd71SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nint,26,NULL,&Xint);CHKERRQ(ierr); 670298fd71SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nsurf,26,NULL,&Xsurf);CHKERRQ(ierr); 688c778c55SBarry Smith ierr = MatDenseGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 69064c8009SBarry Smith 70064c8009SBarry Smith /* 71064c8009SBarry Smith Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 72064c8009SBarry Smith Xsurf will be all zero (thus making the coarse matrix singular). 73064c8009SBarry Smith */ 74e32f2f54SBarry 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"); 75e32f2f54SBarry 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"); 76e32f2f54SBarry 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"); 77064c8009SBarry Smith 78064c8009SBarry Smith cnt = 0; 792fa5cd67SKarl Rupp 802fa5cd67SKarl Rupp xsurf[cnt++] = 1; 812fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + Nsurf] = 1; 822fa5cd67SKarl Rupp xsurf[cnt++ + 2*Nsurf] = 1; 832fa5cd67SKarl Rupp 842fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 852fa5cd67SKarl Rupp xsurf[cnt++ + 3*Nsurf] = 1; 862fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 4*Nsurf] = 1; 872fa5cd67SKarl Rupp xsurf[cnt++ + 5*Nsurf] = 1; 88064c8009SBarry Smith } 892fa5cd67SKarl Rupp 902fa5cd67SKarl Rupp xsurf[cnt++ + 6*Nsurf] = 1; 912fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 7*Nsurf] = 1; 922fa5cd67SKarl Rupp xsurf[cnt++ + 8*Nsurf] = 1; 932fa5cd67SKarl Rupp 942fa5cd67SKarl Rupp for (k=1; k<p-1-kstart; k++) { 952fa5cd67SKarl Rupp xsurf[cnt++ + 9*Nsurf] = 1; 962fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 10*Nsurf] = 1; 972fa5cd67SKarl Rupp xsurf[cnt++ + 11*Nsurf] = 1; 982fa5cd67SKarl Rupp 992fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 1002fa5cd67SKarl Rupp xsurf[cnt++ + 12*Nsurf] = 1; 1012fa5cd67SKarl Rupp /* these are the interior nodes */ 1022fa5cd67SKarl Rupp xsurf[cnt++ + 13*Nsurf] = 1; 1032fa5cd67SKarl Rupp } 1042fa5cd67SKarl Rupp 1052fa5cd67SKarl Rupp xsurf[cnt++ + 14*Nsurf] = 1; 1062fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 15*Nsurf] = 1; 1072fa5cd67SKarl Rupp xsurf[cnt++ + 16*Nsurf] = 1; 1082fa5cd67SKarl Rupp } 1092fa5cd67SKarl Rupp 1102fa5cd67SKarl Rupp xsurf[cnt++ + 17*Nsurf] = 1; 1112fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 18*Nsurf] = 1; 1122fa5cd67SKarl Rupp xsurf[cnt++ + 19*Nsurf] = 1; 1132fa5cd67SKarl Rupp 1142fa5cd67SKarl Rupp for (j=1;j<n-1-jstart;j++) { 1152fa5cd67SKarl Rupp xsurf[cnt++ + 20*Nsurf] = 1; 1162fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 21*Nsurf] = 1; 1172fa5cd67SKarl Rupp xsurf[cnt++ + 22*Nsurf] = 1; 1182fa5cd67SKarl Rupp } 1192fa5cd67SKarl Rupp 1202fa5cd67SKarl Rupp xsurf[cnt++ + 23*Nsurf] = 1; 1212fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 24*Nsurf] = 1; 1222fa5cd67SKarl Rupp xsurf[cnt++ + 25*Nsurf] = 1; 1232fa5cd67SKarl Rupp 124064c8009SBarry Smith 1258e722e36SBarry Smith /* interpolations only sum to 1 when using direct solver */ 1268e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 127064c8009SBarry Smith for (i=0; i<Nsurf; i++) { 128064c8009SBarry Smith tmp = 0.0; 1292fa5cd67SKarl Rupp for (j=0; j<26; j++) tmp += xsurf[i+j*Nsurf]; 13057622a8eSBarry 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,(double)PetscAbsScalar(tmp)); 131064c8009SBarry Smith } 132064c8009SBarry Smith #endif 1338c778c55SBarry Smith ierr = MatDenseRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 134064c8009SBarry Smith /* ierr = MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);*/ 135064c8009SBarry Smith 136064c8009SBarry Smith 137064c8009SBarry Smith /* 138064c8009SBarry Smith I are the indices for all the needed vertices (in global numbering) 139064c8009SBarry Smith Iint are the indices for the interior values, I surf for the surface values 1407dae84e0SHong Zhang (This is just for the part of the global matrix obtained with MatCreateSubMatrix(), it 141aa219208SBarry Smith is NOT the local DMDA ordering.) 142064c8009SBarry Smith IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 143064c8009SBarry Smith */ 144064c8009SBarry Smith #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 145dcca6d9dSJed Brown ierr = PetscMalloc3(N,&II,Nint,&Iint,Nsurf,&Isurf);CHKERRQ(ierr); 146dcca6d9dSJed Brown ierr = PetscMalloc2(Nint,&IIint,Nsurf,&IIsurf);CHKERRQ(ierr); 147064c8009SBarry Smith for (k=0; k<p-kstart; k++) { 148064c8009SBarry Smith for (j=0; j<n-jstart; j++) { 149064c8009SBarry Smith for (i=0; i<m-istart; i++) { 150064c8009SBarry Smith II[c++] = i + j*mwidth + k*mwidth*nwidth; 151064c8009SBarry Smith 152064c8009SBarry Smith if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 153064c8009SBarry Smith IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 154064c8009SBarry Smith Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 155064c8009SBarry Smith } else { 156064c8009SBarry Smith IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 157064c8009SBarry Smith Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 158064c8009SBarry Smith } 159064c8009SBarry Smith } 160064c8009SBarry Smith } 161064c8009SBarry Smith } 162e32f2f54SBarry Smith if (c != N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"c != N"); 163e32f2f54SBarry Smith if (cint != Nint) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"cint != Nint"); 164e32f2f54SBarry Smith if (csurf != Nsurf) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"csurf != Nsurf"); 1651411c6eeSJed Brown ierr = DMGetLocalToGlobalMapping(da,<g);CHKERRQ(ierr); 166064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,N,II,II);CHKERRQ(ierr); 167064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint);CHKERRQ(ierr); 168064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf);CHKERRQ(ierr); 169064c8009SBarry Smith ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 17070b3c8c7SBarry Smith ierr = ISCreateGeneral(comm,N,II,PETSC_COPY_VALUES,&is);CHKERRQ(ierr); 17170b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,PETSC_COPY_VALUES,&isint);CHKERRQ(ierr); 17270b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,PETSC_COPY_VALUES,&issurf);CHKERRQ(ierr); 173064c8009SBarry Smith ierr = PetscFree3(II,Iint,Isurf);CHKERRQ(ierr); 174064c8009SBarry Smith 1757dae84e0SHong Zhang ierr = MatCreateSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder);CHKERRQ(ierr); 176064c8009SBarry Smith A = *Aholder; 177064c8009SBarry Smith ierr = PetscFree(Aholder);CHKERRQ(ierr); 178064c8009SBarry Smith 1797dae84e0SHong Zhang ierr = MatCreateSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii);CHKERRQ(ierr); 1807dae84e0SHong Zhang ierr = MatCreateSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais);CHKERRQ(ierr); 1817dae84e0SHong Zhang ierr = MatCreateSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi);CHKERRQ(ierr); 182064c8009SBarry Smith 183064c8009SBarry Smith /* 184064c8009SBarry Smith Solve for the interpolation onto the interior Xint 185064c8009SBarry Smith */ 18692e4c2edSBarry Smith ierr = MatMatMult(Ais,Xsurf,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&Xint_tmp);CHKERRQ(ierr); 1878e722e36SBarry Smith ierr = MatScale(Xint_tmp,-1.0);CHKERRQ(ierr); 1888e722e36SBarry Smith if (exotic->directSolve) { 1892692d6eeSBarry Smith ierr = MatGetFactor(Aii,MATSOLVERPETSC,MAT_FACTOR_LU,&iAii);CHKERRQ(ierr); 190064c8009SBarry Smith ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 1912692d6eeSBarry Smith ierr = MatGetOrdering(Aii,MATORDERINGND,&row,&col);CHKERRQ(ierr); 192064c8009SBarry Smith ierr = MatLUFactorSymbolic(iAii,Aii,row,col,&info);CHKERRQ(ierr); 193fcfd50ebSBarry Smith ierr = ISDestroy(&row);CHKERRQ(ierr); 194fcfd50ebSBarry Smith ierr = ISDestroy(&col);CHKERRQ(ierr); 195064c8009SBarry Smith ierr = MatLUFactorNumeric(iAii,Aii,&info);CHKERRQ(ierr); 196064c8009SBarry Smith ierr = MatMatSolve(iAii,Xint_tmp,Xint);CHKERRQ(ierr); 1976bf464f9SBarry Smith ierr = MatDestroy(&iAii);CHKERRQ(ierr); 1988e722e36SBarry Smith } else { 1998e722e36SBarry Smith Vec b,x; 2008e722e36SBarry Smith PetscScalar *xint_tmp; 201064c8009SBarry Smith 2028c778c55SBarry Smith ierr = MatDenseGetArray(Xint,&xint);CHKERRQ(ierr); 2030a545947SLisandro Dalcin ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&x);CHKERRQ(ierr); 2048c778c55SBarry Smith ierr = MatDenseGetArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 2050a545947SLisandro Dalcin ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&b);CHKERRQ(ierr); 20623ee1639SBarry Smith ierr = KSPSetOperators(exotic->ksp,Aii,Aii);CHKERRQ(ierr); 2078e722e36SBarry Smith for (i=0; i<26; i++) { 2088e722e36SBarry Smith ierr = VecPlaceArray(x,xint+i*Nint);CHKERRQ(ierr); 2098e722e36SBarry Smith ierr = VecPlaceArray(b,xint_tmp+i*Nint);CHKERRQ(ierr); 2108e722e36SBarry Smith ierr = KSPSolve(exotic->ksp,b,x);CHKERRQ(ierr); 211c0decd05SBarry Smith ierr = KSPCheckSolve(exotic->ksp,pc,x);CHKERRQ(ierr); 2128e722e36SBarry Smith ierr = VecResetArray(x);CHKERRQ(ierr); 2138e722e36SBarry Smith ierr = VecResetArray(b);CHKERRQ(ierr); 2148e722e36SBarry Smith } 2158c778c55SBarry Smith ierr = MatDenseRestoreArray(Xint,&xint);CHKERRQ(ierr); 2168c778c55SBarry Smith ierr = MatDenseRestoreArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 2176bf464f9SBarry Smith ierr = VecDestroy(&x);CHKERRQ(ierr); 2186bf464f9SBarry Smith ierr = VecDestroy(&b);CHKERRQ(ierr); 2198e722e36SBarry Smith } 2206bf464f9SBarry Smith ierr = MatDestroy(&Xint_tmp);CHKERRQ(ierr); 2218e722e36SBarry Smith 2228e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 2231683a169SBarry Smith ierr = MatDenseGetArrayRead(Xint,&rxint);CHKERRQ(ierr); 224064c8009SBarry Smith for (i=0; i<Nint; i++) { 225064c8009SBarry Smith tmp = 0.0; 2261683a169SBarry Smith for (j=0; j<26; j++) tmp += rxint[i+j*Nint]; 2272fa5cd67SKarl Rupp 22857622a8eSBarry 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,(double)PetscAbsScalar(tmp)); 229064c8009SBarry Smith } 2301683a169SBarry Smith ierr = MatDenseRestoreArrayRead(Xint,&rxint);CHKERRQ(ierr); 231064c8009SBarry Smith /* ierr =MatView(Xint,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ 232064c8009SBarry Smith #endif 233064c8009SBarry Smith 234064c8009SBarry Smith 235064c8009SBarry Smith /* total vertices total faces total edges */ 236064c8009SBarry 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); 237064c8009SBarry Smith 238064c8009SBarry Smith /* 239064c8009SBarry Smith For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 240064c8009SBarry Smith */ 241064c8009SBarry Smith cnt = 0; 2422fa5cd67SKarl Rupp 243064c8009SBarry Smith gl[cnt++] = 0; { gl[cnt++] = 1;} gl[cnt++] = m-istart-1; 244064c8009SBarry Smith { gl[cnt++] = mwidth; { gl[cnt++] = mwidth+1;} gl[cnt++] = mwidth + m-istart-1;} 245064c8009SBarry Smith gl[cnt++] = mwidth*(n-jstart-1); { gl[cnt++] = mwidth*(n-jstart-1)+1;} gl[cnt++] = mwidth*(n-jstart-1) + m-istart-1; 246064c8009SBarry Smith { 247064c8009SBarry Smith gl[cnt++] = mwidth*nwidth; { gl[cnt++] = mwidth*nwidth+1;} gl[cnt++] = mwidth*nwidth+ m-istart-1; 248064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 249064c8009SBarry 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; 250064c8009SBarry Smith } 251064c8009SBarry 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; 252064c8009SBarry 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;} 253064c8009SBarry 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; 254064c8009SBarry Smith 255064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 256064c8009SBarry Smith /* convert that to global numbering and get them on all processes */ 257064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,26,gl,gl);CHKERRQ(ierr); 258064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 259785e854fSJed Brown ierr = PetscMalloc1(26*mp*np*pp,&globals);CHKERRQ(ierr); 260*ffc4695bSBarry Smith ierr = MPI_Allgather(gl,26,MPIU_INT,globals,26,MPIU_INT,PetscObjectComm((PetscObject)da));CHKERRMPI(ierr); 261064c8009SBarry Smith 262064c8009SBarry Smith /* Number the coarse grid points from 0 to Ntotal */ 2630298fd71SBarry Smith ierr = MatGetSize(Aglobal,&Nt,NULL);CHKERRQ(ierr); 26412dd4568SBarry Smith ierr = PetscTableCreate(Ntotal/3,Nt+1,&ht);CHKERRQ(ierr); 265064c8009SBarry Smith for (i=0; i<26*mp*np*pp; i++) { 266064c8009SBarry Smith ierr = PetscTableAddCount(ht,globals[i]+1);CHKERRQ(ierr); 267064c8009SBarry Smith } 268064c8009SBarry Smith ierr = PetscTableGetCount(ht,&cnt);CHKERRQ(ierr); 269e32f2f54SBarry 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); 270064c8009SBarry Smith ierr = PetscFree(globals);CHKERRQ(ierr); 271064c8009SBarry Smith for (i=0; i<26; i++) { 272064c8009SBarry Smith ierr = PetscTableFind(ht,gl[i]+1,&gl[i]);CHKERRQ(ierr); 273064c8009SBarry Smith gl[i]--; 274064c8009SBarry Smith } 2756bc0bbbfSBarry Smith ierr = PetscTableDestroy(&ht);CHKERRQ(ierr); 276064c8009SBarry Smith /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 277064c8009SBarry Smith 278064c8009SBarry Smith /* construct global interpolation matrix */ 2790298fd71SBarry Smith ierr = MatGetLocalSize(Aglobal,&Ng,NULL);CHKERRQ(ierr); 280064c8009SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 281ce94432eSBarry Smith ierr = MatCreateAIJ(PetscObjectComm((PetscObject)da),Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,NULL,Nint+Nsurf,NULL,P);CHKERRQ(ierr); 282064c8009SBarry Smith } else { 283064c8009SBarry Smith ierr = MatZeroEntries(*P);CHKERRQ(ierr); 284064c8009SBarry Smith } 285064c8009SBarry Smith ierr = MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 2861683a169SBarry Smith ierr = MatDenseGetArrayRead(Xint,&rxint);CHKERRQ(ierr); 2871683a169SBarry Smith ierr = MatSetValues(*P,Nint,IIint,26,gl,rxint,INSERT_VALUES);CHKERRQ(ierr); 2881683a169SBarry Smith ierr = MatDenseRestoreArrayRead(Xint,&rxint);CHKERRQ(ierr); 2891683a169SBarry Smith ierr = MatDenseGetArrayRead(Xsurf,&rxint);CHKERRQ(ierr); 2901683a169SBarry Smith ierr = MatSetValues(*P,Nsurf,IIsurf,26,gl,rxint,INSERT_VALUES);CHKERRQ(ierr); 2911683a169SBarry Smith ierr = MatDenseRestoreArrayRead(Xsurf,&rxint);CHKERRQ(ierr); 292064c8009SBarry Smith ierr = MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 293064c8009SBarry Smith ierr = MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 294064c8009SBarry Smith ierr = PetscFree2(IIint,IIsurf);CHKERRQ(ierr); 295064c8009SBarry Smith 2968e722e36SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 297064c8009SBarry Smith { 298064c8009SBarry Smith Vec x,y; 299064c8009SBarry Smith PetscScalar *yy; 300ce94432eSBarry Smith ierr = VecCreateMPI(PetscObjectComm((PetscObject)da),Ng,PETSC_DETERMINE,&y);CHKERRQ(ierr); 301ce94432eSBarry Smith ierr = VecCreateMPI(PetscObjectComm((PetscObject)da),PETSC_DETERMINE,Ntotal,&x);CHKERRQ(ierr); 302064c8009SBarry Smith ierr = VecSet(x,1.0);CHKERRQ(ierr); 303064c8009SBarry Smith ierr = MatMult(*P,x,y);CHKERRQ(ierr); 304064c8009SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 305064c8009SBarry Smith for (i=0; i<Ng; i++) { 30657622a8eSBarry 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,(double)PetscAbsScalar(yy[i])); 307064c8009SBarry Smith } 308064c8009SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 309064c8009SBarry Smith ierr = VecDestroy(x);CHKERRQ(ierr); 310064c8009SBarry Smith ierr = VecDestroy(y);CHKERRQ(ierr); 311064c8009SBarry Smith } 312064c8009SBarry Smith #endif 313064c8009SBarry Smith 314fcfd50ebSBarry Smith ierr = MatDestroy(&Aii);CHKERRQ(ierr); 315fcfd50ebSBarry Smith ierr = MatDestroy(&Ais);CHKERRQ(ierr); 316fcfd50ebSBarry Smith ierr = MatDestroy(&Asi);CHKERRQ(ierr); 317fcfd50ebSBarry Smith ierr = MatDestroy(&A);CHKERRQ(ierr); 318fcfd50ebSBarry Smith ierr = ISDestroy(&is);CHKERRQ(ierr); 319fcfd50ebSBarry Smith ierr = ISDestroy(&isint);CHKERRQ(ierr); 320fcfd50ebSBarry Smith ierr = ISDestroy(&issurf);CHKERRQ(ierr); 321fcfd50ebSBarry Smith ierr = MatDestroy(&Xint);CHKERRQ(ierr); 322fcfd50ebSBarry Smith ierr = MatDestroy(&Xsurf);CHKERRQ(ierr); 323064c8009SBarry Smith PetscFunctionReturn(0); 324064c8009SBarry Smith } 325064c8009SBarry Smith 326064c8009SBarry Smith /* 327aa219208SBarry Smith DMDAGetFaceInterpolation - Gets the interpolation for a face based coarse space 328064c8009SBarry Smith 329064c8009SBarry Smith */ 330c0decd05SBarry Smith PetscErrorCode DMDAGetFaceInterpolation(PC pc,DM da,PC_Exotic *exotic,Mat Aglobal,MatReuse reuse,Mat *P) 331064c8009SBarry Smith { 332064c8009SBarry Smith PetscErrorCode ierr; 333064c8009SBarry 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; 33428d20b34SBarry Smith PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[6],*globals,Ng,*IIint,*IIsurf,Nt; 335064c8009SBarry Smith Mat Xint, Xsurf,Xint_tmp; 336064c8009SBarry Smith IS isint,issurf,is,row,col; 337064c8009SBarry Smith ISLocalToGlobalMapping ltg; 338064c8009SBarry Smith MPI_Comm comm; 339064c8009SBarry Smith Mat A,Aii,Ais,Asi,*Aholder,iAii; 340064c8009SBarry Smith MatFactorInfo info; 341064c8009SBarry Smith PetscScalar *xsurf,*xint; 3421683a169SBarry Smith const PetscScalar *rxint; 343064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 344064c8009SBarry Smith PetscScalar tmp; 345064c8009SBarry Smith #endif 346064c8009SBarry Smith PetscTable ht; 347064c8009SBarry Smith 348064c8009SBarry Smith PetscFunctionBegin; 3490a545947SLisandro Dalcin ierr = DMDAGetInfo(da,&dim,NULL,NULL,NULL,&mp,&np,&pp,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 350ce94432eSBarry Smith if (dof != 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only for single field problems"); 351ce94432eSBarry Smith if (dim != 3) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only coded for 3d problems"); 3520a545947SLisandro Dalcin ierr = DMDAGetCorners(da,NULL,NULL,NULL,&m,&n,&p);CHKERRQ(ierr); 353aa219208SBarry Smith ierr = DMDAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth);CHKERRQ(ierr); 354064c8009SBarry Smith istart = istart ? -1 : 0; 355064c8009SBarry Smith jstart = jstart ? -1 : 0; 356064c8009SBarry Smith kstart = kstart ? -1 : 0; 357064c8009SBarry Smith 358064c8009SBarry Smith /* 359064c8009SBarry Smith the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 360064c8009SBarry Smith to all the local degrees of freedom (this includes the vertices, edges and faces). 361064c8009SBarry Smith 362064c8009SBarry Smith Xint are the subset of the interpolation into the interior 363064c8009SBarry Smith 364064c8009SBarry Smith Xface are the interpolation onto faces but not into the interior 365064c8009SBarry Smith 366064c8009SBarry Smith Xsurf are the interpolation onto the vertices and edges (the surfbasket) 367064c8009SBarry Smith Xint 368064c8009SBarry Smith Symbolically one could write P = (Xface) after interchanging the rows to match the natural ordering on the domain 369064c8009SBarry Smith Xsurf 370064c8009SBarry Smith */ 371064c8009SBarry Smith N = (m - istart)*(n - jstart)*(p - kstart); 372064c8009SBarry Smith Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 373064c8009SBarry Smith Nface = 2*((m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart)); 374064c8009SBarry Smith Nwire = 4*((m-2-istart) + (n-2-jstart) + (p-2-kstart)) + 8; 375064c8009SBarry Smith Nsurf = Nface + Nwire; 3760298fd71SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nint,6,NULL,&Xint);CHKERRQ(ierr); 3770298fd71SBarry Smith ierr = MatCreateSeqDense(MPI_COMM_SELF,Nsurf,6,NULL,&Xsurf);CHKERRQ(ierr); 3788c778c55SBarry Smith ierr = MatDenseGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 379064c8009SBarry Smith 380064c8009SBarry Smith /* 381064c8009SBarry Smith Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 382064c8009SBarry Smith Xsurf will be all zero (thus making the coarse matrix singular). 383064c8009SBarry Smith */ 384e32f2f54SBarry 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"); 385e32f2f54SBarry 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"); 386e32f2f54SBarry 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"); 387064c8009SBarry Smith 388064c8009SBarry Smith cnt = 0; 3892fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 3902fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 0*Nsurf] = 1; 391064c8009SBarry Smith } 3922fa5cd67SKarl Rupp 3932fa5cd67SKarl Rupp for (k=1; k<p-1-kstart; k++) { 3942fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 1*Nsurf] = 1; 3952fa5cd67SKarl Rupp for (j=1; j<n-1-jstart; j++) { 3962fa5cd67SKarl Rupp xsurf[cnt++ + 2*Nsurf] = 1; 3972fa5cd67SKarl Rupp /* these are the interior nodes */ 3982fa5cd67SKarl Rupp xsurf[cnt++ + 3*Nsurf] = 1; 3992fa5cd67SKarl Rupp } 4002fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 4*Nsurf] = 1; 4012fa5cd67SKarl Rupp } 4022fa5cd67SKarl Rupp for (j=1;j<n-1-jstart;j++) { 4032fa5cd67SKarl Rupp for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 5*Nsurf] = 1; 4042fa5cd67SKarl Rupp } 405064c8009SBarry Smith 406064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 407064c8009SBarry Smith for (i=0; i<Nsurf; i++) { 408064c8009SBarry Smith tmp = 0.0; 4092fa5cd67SKarl Rupp for (j=0; j<6; j++) tmp += xsurf[i+j*Nsurf]; 4102fa5cd67SKarl Rupp 41157622a8eSBarry 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,(double)PetscAbsScalar(tmp)); 412064c8009SBarry Smith } 413064c8009SBarry Smith #endif 4148c778c55SBarry Smith ierr = MatDenseRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 415064c8009SBarry Smith /* ierr = MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);*/ 416064c8009SBarry Smith 417064c8009SBarry Smith 418064c8009SBarry Smith /* 419064c8009SBarry Smith I are the indices for all the needed vertices (in global numbering) 420064c8009SBarry Smith Iint are the indices for the interior values, I surf for the surface values 4217dae84e0SHong Zhang (This is just for the part of the global matrix obtained with MatCreateSubMatrix(), it 422aa219208SBarry Smith is NOT the local DMDA ordering.) 423064c8009SBarry Smith IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 424064c8009SBarry Smith */ 425064c8009SBarry Smith #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 426dcca6d9dSJed Brown ierr = PetscMalloc3(N,&II,Nint,&Iint,Nsurf,&Isurf);CHKERRQ(ierr); 427dcca6d9dSJed Brown ierr = PetscMalloc2(Nint,&IIint,Nsurf,&IIsurf);CHKERRQ(ierr); 428064c8009SBarry Smith for (k=0; k<p-kstart; k++) { 429064c8009SBarry Smith for (j=0; j<n-jstart; j++) { 430064c8009SBarry Smith for (i=0; i<m-istart; i++) { 431064c8009SBarry Smith II[c++] = i + j*mwidth + k*mwidth*nwidth; 432064c8009SBarry Smith 433064c8009SBarry Smith if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 434064c8009SBarry Smith IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 435064c8009SBarry Smith Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 436064c8009SBarry Smith } else { 437064c8009SBarry Smith IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 438064c8009SBarry Smith Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 439064c8009SBarry Smith } 440064c8009SBarry Smith } 441064c8009SBarry Smith } 442064c8009SBarry Smith } 443e32f2f54SBarry Smith if (c != N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"c != N"); 444e32f2f54SBarry Smith if (cint != Nint) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"cint != Nint"); 445e32f2f54SBarry Smith if (csurf != Nsurf) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"csurf != Nsurf"); 4461411c6eeSJed Brown ierr = DMGetLocalToGlobalMapping(da,<g);CHKERRQ(ierr); 447064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,N,II,II);CHKERRQ(ierr); 448064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint);CHKERRQ(ierr); 449064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf);CHKERRQ(ierr); 450064c8009SBarry Smith ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 45170b3c8c7SBarry Smith ierr = ISCreateGeneral(comm,N,II,PETSC_COPY_VALUES,&is);CHKERRQ(ierr); 45270b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,PETSC_COPY_VALUES,&isint);CHKERRQ(ierr); 45370b3c8c7SBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,PETSC_COPY_VALUES,&issurf);CHKERRQ(ierr); 454064c8009SBarry Smith ierr = PetscFree3(II,Iint,Isurf);CHKERRQ(ierr); 455064c8009SBarry Smith 456671e8369SHong Zhang ierr = ISSort(is);CHKERRQ(ierr); 4577dae84e0SHong Zhang ierr = MatCreateSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder);CHKERRQ(ierr); 458064c8009SBarry Smith A = *Aholder; 459064c8009SBarry Smith ierr = PetscFree(Aholder);CHKERRQ(ierr); 460064c8009SBarry Smith 4617dae84e0SHong Zhang ierr = MatCreateSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii);CHKERRQ(ierr); 4627dae84e0SHong Zhang ierr = MatCreateSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais);CHKERRQ(ierr); 4637dae84e0SHong Zhang ierr = MatCreateSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi);CHKERRQ(ierr); 464064c8009SBarry Smith 465064c8009SBarry Smith /* 466064c8009SBarry Smith Solve for the interpolation onto the interior Xint 467064c8009SBarry Smith */ 46892e4c2edSBarry Smith ierr = MatMatMult(Ais,Xsurf,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&Xint_tmp);CHKERRQ(ierr); 469064c8009SBarry Smith ierr = MatScale(Xint_tmp,-1.0);CHKERRQ(ierr); 470064c8009SBarry Smith 4718e722e36SBarry Smith if (exotic->directSolve) { 4722692d6eeSBarry Smith ierr = MatGetFactor(Aii,MATSOLVERPETSC,MAT_FACTOR_LU,&iAii);CHKERRQ(ierr); 473064c8009SBarry Smith ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 4742692d6eeSBarry Smith ierr = MatGetOrdering(Aii,MATORDERINGND,&row,&col);CHKERRQ(ierr); 475064c8009SBarry Smith ierr = MatLUFactorSymbolic(iAii,Aii,row,col,&info);CHKERRQ(ierr); 476fcfd50ebSBarry Smith ierr = ISDestroy(&row);CHKERRQ(ierr); 477fcfd50ebSBarry Smith ierr = ISDestroy(&col);CHKERRQ(ierr); 478064c8009SBarry Smith ierr = MatLUFactorNumeric(iAii,Aii,&info);CHKERRQ(ierr); 479064c8009SBarry Smith ierr = MatMatSolve(iAii,Xint_tmp,Xint);CHKERRQ(ierr); 480fcfd50ebSBarry Smith ierr = MatDestroy(&iAii);CHKERRQ(ierr); 481064c8009SBarry Smith } else { 482064c8009SBarry Smith Vec b,x; 483064c8009SBarry Smith PetscScalar *xint_tmp; 484064c8009SBarry Smith 4858c778c55SBarry Smith ierr = MatDenseGetArray(Xint,&xint);CHKERRQ(ierr); 4860a545947SLisandro Dalcin ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&x);CHKERRQ(ierr); 4878c778c55SBarry Smith ierr = MatDenseGetArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 4880a545947SLisandro Dalcin ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,NULL,&b);CHKERRQ(ierr); 48923ee1639SBarry Smith ierr = KSPSetOperators(exotic->ksp,Aii,Aii);CHKERRQ(ierr); 490064c8009SBarry Smith for (i=0; i<6; i++) { 491064c8009SBarry Smith ierr = VecPlaceArray(x,xint+i*Nint);CHKERRQ(ierr); 492064c8009SBarry Smith ierr = VecPlaceArray(b,xint_tmp+i*Nint);CHKERRQ(ierr); 4938e722e36SBarry Smith ierr = KSPSolve(exotic->ksp,b,x);CHKERRQ(ierr); 494c0decd05SBarry Smith ierr = KSPCheckSolve(exotic->ksp,pc,x);CHKERRQ(ierr); 495064c8009SBarry Smith ierr = VecResetArray(x);CHKERRQ(ierr); 496064c8009SBarry Smith ierr = VecResetArray(b);CHKERRQ(ierr); 497064c8009SBarry Smith } 4988c778c55SBarry Smith ierr = MatDenseRestoreArray(Xint,&xint);CHKERRQ(ierr); 4998c778c55SBarry Smith ierr = MatDenseRestoreArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 5006bf464f9SBarry Smith ierr = VecDestroy(&x);CHKERRQ(ierr); 5016bf464f9SBarry Smith ierr = VecDestroy(&b);CHKERRQ(ierr); 502064c8009SBarry Smith } 5036bf464f9SBarry Smith ierr = MatDestroy(&Xint_tmp);CHKERRQ(ierr); 504064c8009SBarry Smith 505064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 5061683a169SBarry Smith ierr = MatDenseGetArrayRead(Xint,&rxint);CHKERRQ(ierr); 507064c8009SBarry Smith for (i=0; i<Nint; i++) { 508064c8009SBarry Smith tmp = 0.0; 5091683a169SBarry Smith for (j=0; j<6; j++) tmp += rxint[i+j*Nint]; 5102fa5cd67SKarl Rupp 51157622a8eSBarry 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,(double)PetscAbsScalar(tmp)); 512064c8009SBarry Smith } 5131683a169SBarry Smith ierr = MatDenseRestoreArrayRead(Xint,&rxint);CHKERRQ(ierr); 514064c8009SBarry Smith /* ierr =MatView(Xint,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ 515064c8009SBarry Smith #endif 516064c8009SBarry Smith 517064c8009SBarry Smith 518064c8009SBarry Smith /* total faces */ 519064c8009SBarry Smith Ntotal = mp*np*(pp+1) + mp*pp*(np+1) + np*pp*(mp+1); 520064c8009SBarry Smith 521064c8009SBarry Smith /* 522064c8009SBarry Smith For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 523064c8009SBarry Smith */ 524064c8009SBarry Smith cnt = 0; 525064c8009SBarry Smith { gl[cnt++] = mwidth+1;} 526064c8009SBarry Smith { 527064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth+1;} 528064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 529064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth+mwidth*(n-jstart-1)+1;} 530064c8009SBarry Smith } 531064c8009SBarry Smith { gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth+1;} 532064c8009SBarry Smith 533064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 534064c8009SBarry Smith /* convert that to global numbering and get them on all processes */ 535064c8009SBarry Smith ierr = ISLocalToGlobalMappingApply(ltg,6,gl,gl);CHKERRQ(ierr); 536064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 537785e854fSJed Brown ierr = PetscMalloc1(6*mp*np*pp,&globals);CHKERRQ(ierr); 538*ffc4695bSBarry Smith ierr = MPI_Allgather(gl,6,MPIU_INT,globals,6,MPIU_INT,PetscObjectComm((PetscObject)da));CHKERRMPI(ierr); 539064c8009SBarry Smith 540064c8009SBarry Smith /* Number the coarse grid points from 0 to Ntotal */ 5410298fd71SBarry Smith ierr = MatGetSize(Aglobal,&Nt,NULL);CHKERRQ(ierr); 54228d20b34SBarry Smith ierr = PetscTableCreate(Ntotal/3,Nt+1,&ht);CHKERRQ(ierr); 543064c8009SBarry Smith for (i=0; i<6*mp*np*pp; i++) { 544064c8009SBarry Smith ierr = PetscTableAddCount(ht,globals[i]+1);CHKERRQ(ierr); 545064c8009SBarry Smith } 546064c8009SBarry Smith ierr = PetscTableGetCount(ht,&cnt);CHKERRQ(ierr); 547e32f2f54SBarry 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); 548064c8009SBarry Smith ierr = PetscFree(globals);CHKERRQ(ierr); 549064c8009SBarry Smith for (i=0; i<6; i++) { 550064c8009SBarry Smith ierr = PetscTableFind(ht,gl[i]+1,&gl[i]);CHKERRQ(ierr); 551064c8009SBarry Smith gl[i]--; 552064c8009SBarry Smith } 5536bc0bbbfSBarry Smith ierr = PetscTableDestroy(&ht);CHKERRQ(ierr); 554064c8009SBarry Smith /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 555064c8009SBarry Smith 556064c8009SBarry Smith /* construct global interpolation matrix */ 5570298fd71SBarry Smith ierr = MatGetLocalSize(Aglobal,&Ng,NULL);CHKERRQ(ierr); 558064c8009SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 559ce94432eSBarry Smith ierr = MatCreateAIJ(PetscObjectComm((PetscObject)da),Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,NULL,Nint,NULL,P);CHKERRQ(ierr); 560064c8009SBarry Smith } else { 561064c8009SBarry Smith ierr = MatZeroEntries(*P);CHKERRQ(ierr); 562064c8009SBarry Smith } 563064c8009SBarry Smith ierr = MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 5641683a169SBarry Smith ierr = MatDenseGetArrayRead(Xint,&rxint);CHKERRQ(ierr); 5651683a169SBarry Smith ierr = MatSetValues(*P,Nint,IIint,6,gl,rxint,INSERT_VALUES);CHKERRQ(ierr); 5661683a169SBarry Smith ierr = MatDenseRestoreArrayRead(Xint,&rxint);CHKERRQ(ierr); 5671683a169SBarry Smith ierr = MatDenseGetArrayRead(Xsurf,&rxint);CHKERRQ(ierr); 5681683a169SBarry Smith ierr = MatSetValues(*P,Nsurf,IIsurf,6,gl,rxint,INSERT_VALUES);CHKERRQ(ierr); 5691683a169SBarry Smith ierr = MatDenseRestoreArrayRead(Xsurf,&rxint);CHKERRQ(ierr); 570064c8009SBarry Smith ierr = MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 571064c8009SBarry Smith ierr = MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 572064c8009SBarry Smith ierr = PetscFree2(IIint,IIsurf);CHKERRQ(ierr); 573064c8009SBarry Smith 574064c8009SBarry Smith 575064c8009SBarry Smith #if defined(PETSC_USE_DEBUG_foo) 576064c8009SBarry Smith { 577064c8009SBarry Smith Vec x,y; 578064c8009SBarry Smith PetscScalar *yy; 579ce94432eSBarry Smith ierr = VecCreateMPI(PetscObjectComm((PetscObject)da),Ng,PETSC_DETERMINE,&y);CHKERRQ(ierr); 580ce94432eSBarry Smith ierr = VecCreateMPI(PetscObjectComm((PetscObject)da),PETSC_DETERMINE,Ntotal,&x);CHKERRQ(ierr); 581064c8009SBarry Smith ierr = VecSet(x,1.0);CHKERRQ(ierr); 582064c8009SBarry Smith ierr = MatMult(*P,x,y);CHKERRQ(ierr); 583064c8009SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 584064c8009SBarry Smith for (i=0; i<Ng; i++) { 58557622a8eSBarry 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,(double)PetscAbsScalar(yy[i])); 586064c8009SBarry Smith } 587064c8009SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 588064c8009SBarry Smith ierr = VecDestroy(x);CHKERRQ(ierr); 589064c8009SBarry Smith ierr = VecDestroy(y);CHKERRQ(ierr); 590064c8009SBarry Smith } 591064c8009SBarry Smith #endif 592064c8009SBarry Smith 593fcfd50ebSBarry Smith ierr = MatDestroy(&Aii);CHKERRQ(ierr); 594fcfd50ebSBarry Smith ierr = MatDestroy(&Ais);CHKERRQ(ierr); 595fcfd50ebSBarry Smith ierr = MatDestroy(&Asi);CHKERRQ(ierr); 596fcfd50ebSBarry Smith ierr = MatDestroy(&A);CHKERRQ(ierr); 597fcfd50ebSBarry Smith ierr = ISDestroy(&is);CHKERRQ(ierr); 598fcfd50ebSBarry Smith ierr = ISDestroy(&isint);CHKERRQ(ierr); 599fcfd50ebSBarry Smith ierr = ISDestroy(&issurf);CHKERRQ(ierr); 600fcfd50ebSBarry Smith ierr = MatDestroy(&Xint);CHKERRQ(ierr); 601fcfd50ebSBarry Smith ierr = MatDestroy(&Xsurf);CHKERRQ(ierr); 602064c8009SBarry Smith PetscFunctionReturn(0); 603064c8009SBarry Smith } 604174b6946SBarry Smith 6057233f9f0SBarry Smith 6067233f9f0SBarry Smith /*@ 6077233f9f0SBarry Smith PCExoticSetType - Sets the type of coarse grid interpolation to use 6087233f9f0SBarry Smith 6093f9fe445SBarry Smith Logically Collective on PC 6107233f9f0SBarry Smith 6117233f9f0SBarry Smith Input Parameters: 6127233f9f0SBarry Smith + pc - the preconditioner context 6137233f9f0SBarry Smith - type - either PC_EXOTIC_FACE or PC_EXOTIC_WIREBASKET (defaults to face) 6147233f9f0SBarry Smith 61595452b02SPatrick Sanan Notes: 61695452b02SPatrick Sanan The face based interpolation has 1 degree of freedom per face and ignores the 617563e08c6SBarry Smith edge and vertex values completely in the coarse problem. For any seven point 618563e08c6SBarry Smith stencil the interpolation of a constant on all faces into the interior is that constant. 619563e08c6SBarry Smith 620563e08c6SBarry Smith The wirebasket interpolation has 1 degree of freedom per vertex, per edge and 621563e08c6SBarry Smith per face. A constant on the subdomain boundary is interpolated as that constant 622563e08c6SBarry Smith in the interior of the domain. 623563e08c6SBarry Smith 624563e08c6SBarry Smith The coarse grid matrix is obtained via the Galerkin computation A_c = R A R^T, hence 625563e08c6SBarry Smith if A is nonsingular A_c is also nonsingular. 626563e08c6SBarry Smith 627563e08c6SBarry Smith Both interpolations are suitable for only scalar problems. 628563e08c6SBarry Smith 6297233f9f0SBarry Smith Level: intermediate 6307233f9f0SBarry Smith 6317233f9f0SBarry Smith 6327233f9f0SBarry Smith .seealso: PCEXOTIC, PCExoticType() 6337233f9f0SBarry Smith @*/ 6347087cfbeSBarry Smith PetscErrorCode PCExoticSetType(PC pc,PCExoticType type) 6357233f9f0SBarry Smith { 6364ac538c5SBarry Smith PetscErrorCode ierr; 6377233f9f0SBarry Smith 6387233f9f0SBarry Smith PetscFunctionBegin; 6390700a824SBarry Smith PetscValidHeaderSpecific(pc,PC_CLASSID,1); 640c5eb9154SBarry Smith PetscValidLogicalCollectiveEnum(pc,type,2); 6414ac538c5SBarry Smith ierr = PetscTryMethod(pc,"PCExoticSetType_C",(PC,PCExoticType),(pc,type));CHKERRQ(ierr); 6427233f9f0SBarry Smith PetscFunctionReturn(0); 6437233f9f0SBarry Smith } 6447233f9f0SBarry Smith 645f7a08781SBarry Smith static PetscErrorCode PCExoticSetType_Exotic(PC pc,PCExoticType type) 6467233f9f0SBarry Smith { 647f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 64831567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 6497233f9f0SBarry Smith 6507233f9f0SBarry Smith PetscFunctionBegin; 6517233f9f0SBarry Smith ctx->type = type; 6527233f9f0SBarry Smith PetscFunctionReturn(0); 6537233f9f0SBarry Smith } 6547233f9f0SBarry Smith 6557233f9f0SBarry Smith PetscErrorCode PCSetUp_Exotic(PC pc) 656174b6946SBarry Smith { 657174b6946SBarry Smith PetscErrorCode ierr; 65896bdf778SBarry Smith Mat A; 659f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 66031567311SBarry Smith PC_Exotic *ex = (PC_Exotic*) mg->innerctx; 66196bdf778SBarry Smith MatReuse reuse = (ex->P) ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 662174b6946SBarry Smith 663174b6946SBarry Smith PetscFunctionBegin; 664ce94432eSBarry Smith if (!pc->dm) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Need to call PCSetDM() before using this PC"); 66523ee1639SBarry Smith ierr = PCGetOperators(pc,NULL,&A);CHKERRQ(ierr); 6667233f9f0SBarry Smith if (ex->type == PC_EXOTIC_FACE) { 667c0decd05SBarry Smith ierr = DMDAGetFaceInterpolation(pc,pc->dm,ex,A,reuse,&ex->P);CHKERRQ(ierr); 6687233f9f0SBarry Smith } else if (ex->type == PC_EXOTIC_WIREBASKET) { 669c0decd05SBarry Smith ierr = DMDAGetWireBasketInterpolation(pc,pc->dm,ex,A,reuse,&ex->P);CHKERRQ(ierr); 670ce94432eSBarry Smith } else SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Unknown exotic coarse space %d",ex->type); 67196bdf778SBarry Smith ierr = PCMGSetInterpolation(pc,1,ex->P);CHKERRQ(ierr); 672d0660788SBarry Smith /* if PC has attached DM we must remove it or the PCMG will use it to compute incorrect sized vectors and interpolations */ 6730298fd71SBarry Smith ierr = PCSetDM(pc,NULL);CHKERRQ(ierr); 6747233f9f0SBarry Smith ierr = PCSetUp_MG(pc);CHKERRQ(ierr); 675174b6946SBarry Smith PetscFunctionReturn(0); 676174b6946SBarry Smith } 677174b6946SBarry Smith 6787233f9f0SBarry Smith PetscErrorCode PCDestroy_Exotic(PC pc) 679174b6946SBarry Smith { 680174b6946SBarry Smith PetscErrorCode ierr; 681f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 68231567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 683174b6946SBarry Smith 684174b6946SBarry Smith PetscFunctionBegin; 685fcfd50ebSBarry Smith ierr = MatDestroy(&ctx->P);CHKERRQ(ierr); 686fcfd50ebSBarry Smith ierr = KSPDestroy(&ctx->ksp);CHKERRQ(ierr); 6877233f9f0SBarry Smith ierr = PetscFree(ctx);CHKERRQ(ierr); 6887233f9f0SBarry Smith ierr = PCDestroy_MG(pc);CHKERRQ(ierr); 689174b6946SBarry Smith PetscFunctionReturn(0); 690174b6946SBarry Smith } 691174b6946SBarry Smith 6927233f9f0SBarry Smith PetscErrorCode PCView_Exotic(PC pc,PetscViewer viewer) 6937233f9f0SBarry Smith { 694f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 6957233f9f0SBarry Smith PetscErrorCode ierr; 696ace3abfcSBarry Smith PetscBool iascii; 69731567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 6987233f9f0SBarry Smith 6997233f9f0SBarry Smith PetscFunctionBegin; 700251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 7017233f9f0SBarry Smith if (iascii) { 7027233f9f0SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Exotic type = %s\n",PCExoticTypes[ctx->type]);CHKERRQ(ierr); 7038e722e36SBarry Smith if (ctx->directSolve) { 7048e722e36SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using direct solver to construct interpolation\n");CHKERRQ(ierr); 7058e722e36SBarry Smith } else { 7068e722e36SBarry Smith PetscViewer sviewer; 7078e722e36SBarry Smith PetscMPIInt rank; 7088e722e36SBarry Smith 7098e722e36SBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Using iterative solver to construct interpolation\n");CHKERRQ(ierr); 7108e722e36SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 7118e722e36SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); /* should not need to push this twice? */ 7123f08860eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 713*ffc4695bSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRMPI(ierr); 7148e722e36SBarry Smith if (!rank) { 7158e722e36SBarry Smith ierr = KSPView(ctx->ksp,sviewer);CHKERRQ(ierr); 7168e722e36SBarry Smith } 7173f08860eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 7188e722e36SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 7198e722e36SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 7208e722e36SBarry Smith } 7217233f9f0SBarry Smith } 7227233f9f0SBarry Smith ierr = PCView_MG(pc,viewer);CHKERRQ(ierr); 7237233f9f0SBarry Smith PetscFunctionReturn(0); 7247233f9f0SBarry Smith } 7257233f9f0SBarry Smith 7264416b707SBarry Smith PetscErrorCode PCSetFromOptions_Exotic(PetscOptionItems *PetscOptionsObject,PC pc) 7277233f9f0SBarry Smith { 7287233f9f0SBarry Smith PetscErrorCode ierr; 729ace3abfcSBarry Smith PetscBool flg; 730f3fbd535SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 7317233f9f0SBarry Smith PCExoticType mgctype; 73231567311SBarry Smith PC_Exotic *ctx = (PC_Exotic*) mg->innerctx; 7337233f9f0SBarry Smith 7347233f9f0SBarry Smith PetscFunctionBegin; 735e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Exotic coarse space options");CHKERRQ(ierr); 7367233f9f0SBarry Smith ierr = PetscOptionsEnum("-pc_exotic_type","face or wirebasket","PCExoticSetType",PCExoticTypes,(PetscEnum)ctx->type,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr); 7377233f9f0SBarry Smith if (flg) { 7387233f9f0SBarry Smith ierr = PCExoticSetType(pc,mgctype);CHKERRQ(ierr); 7397233f9f0SBarry Smith } 7400298fd71SBarry Smith ierr = PetscOptionsBool("-pc_exotic_direct_solver","use direct solver to construct interpolation","None",ctx->directSolve,&ctx->directSolve,NULL);CHKERRQ(ierr); 7418e722e36SBarry Smith if (!ctx->directSolve) { 7428e722e36SBarry Smith if (!ctx->ksp) { 7438e722e36SBarry Smith const char *prefix; 7448e722e36SBarry Smith ierr = KSPCreate(PETSC_COMM_SELF,&ctx->ksp);CHKERRQ(ierr); 745422a814eSBarry Smith ierr = KSPSetErrorIfNotConverged(ctx->ksp,pc->erroriffailure);CHKERRQ(ierr); 7468e722e36SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 7473bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ctx->ksp);CHKERRQ(ierr); 7488e722e36SBarry Smith ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 7498e722e36SBarry Smith ierr = KSPSetOptionsPrefix(ctx->ksp,prefix);CHKERRQ(ierr); 7508e722e36SBarry Smith ierr = KSPAppendOptionsPrefix(ctx->ksp,"exotic_");CHKERRQ(ierr); 7518e722e36SBarry Smith } 7528e722e36SBarry Smith ierr = KSPSetFromOptions(ctx->ksp);CHKERRQ(ierr); 7538e722e36SBarry Smith } 7547233f9f0SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 7557233f9f0SBarry Smith PetscFunctionReturn(0); 7567233f9f0SBarry Smith } 7577233f9f0SBarry Smith 758174b6946SBarry Smith 759174b6946SBarry Smith /*MC 7607233f9f0SBarry Smith PCEXOTIC - Two level overlapping Schwarz preconditioner with exotic (non-standard) coarse grid spaces 761174b6946SBarry Smith 7627233f9f0SBarry Smith This uses the PCMG infrastructure restricted to two levels and the face and wirebasket based coarse 76324c3aa18SBarry Smith grid spaces. 76424c3aa18SBarry Smith 76595452b02SPatrick Sanan Notes: 76695452b02SPatrick 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 76724c3aa18SBarry Smith 76896a0c994SBarry Smith References: 76996a0c994SBarry Smith + 1. - These coarse grid spaces originate in the work of Bramble, Pasciak and Schatz, "The Construction 77096a0c994SBarry Smith of Preconditioners for Elliptic Problems by Substructing IV", Mathematics of Computation, volume 53, 1989. 77196a0c994SBarry Smith . 2. - They were generalized slightly in "Domain Decomposition Method for Linear Elasticity", Ph. D. thesis, Barry Smith, 7724f02bc6aSBarry Smith New York University, 1990. 77396a0c994SBarry Smith . 3. - They were then explored in great detail in Dryja, Smith, Widlund, "Schwarz Analysis 7743b65e785SBarry Smith of Iterative Substructuring Methods for Elliptic Problems in Three Dimensions, SIAM Journal on Numerical 77596a0c994SBarry Smith Analysis, volume 31. 1994. These were developed in the context of iterative substructuring preconditioners. 77696a0c994SBarry Smith . 4. - They were then ingeniously applied as coarse grid spaces for overlapping Schwarz methods by Dohrmann and Widlund. 7773b65e785SBarry Smith They refer to them as GDSW (generalized Dryja, Smith, Widlund preconditioners). See, for example, 7783b65e785SBarry Smith Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Extending theory for domain decomposition algorithms to irregular subdomains. In Ulrich Langer, Marco 7793b65e785SBarry Smith Discacciati, David Keyes, Olof Widlund, and Walter Zulehner, editors, Proceedings 7803b65e785SBarry Smith of the 17th International Conference on Domain Decomposition Methods in 78196a0c994SBarry Smith Science and Engineering, held in Strobl, Austria, 2006, number 60 in 78296a0c994SBarry Smith Springer Verlag, Lecture Notes in Computational Science and Engineering, 2007. 78396a0c994SBarry Smith . 5. - Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. A family of energy minimizing coarse spaces for overlapping Schwarz preconditioners. In Ulrich Langer, 7843b65e785SBarry Smith Marco Discacciati, David Keyes, Olof Widlund, and Walter Zulehner, editors, Proceedings 7853b65e785SBarry Smith of the 17th International Conference on Domain Decomposition Methods 78696a0c994SBarry Smith in Science and Engineering, held in Strobl, Austria, 2006, number 60 in 78796a0c994SBarry Smith Springer Verlag, Lecture Notes in Computational Science and Engineering, 2007 78896a0c994SBarry Smith . 6. - Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Domain decomposition 7893b65e785SBarry Smith for less regular subdomains: Overlapping Schwarz in two dimensions. SIAM J. 79096a0c994SBarry Smith Numer. Anal., 46(4), 2008. 79196a0c994SBarry Smith - 7. - Clark R. Dohrmann and Olof B. Widlund. An overlapping Schwarz 7923b65e785SBarry Smith algorithm for almost incompressible elasticity. Technical Report 79396a0c994SBarry Smith TR2008 912, Department of Computer Science, Courant Institute 7943b65e785SBarry Smith of Mathematical Sciences, New York University, May 2008. URL: 7957233f9f0SBarry Smith 7967233f9f0SBarry Smith Options Database: The usual PCMG options are supported, such as -mg_levels_pc_type <type> -mg_coarse_pc_type <type> 7977233f9f0SBarry Smith -pc_mg_type <type> 7987233f9f0SBarry Smith 79925a35f6fSSatish Balay Level: advanced 800174b6946SBarry Smith 8016c699258SBarry Smith .seealso: PCMG, PCSetDM(), PCExoticType, PCExoticSetType() 802174b6946SBarry Smith M*/ 803174b6946SBarry Smith 8048cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_Exotic(PC pc) 805174b6946SBarry Smith { 806174b6946SBarry Smith PetscErrorCode ierr; 8077233f9f0SBarry Smith PC_Exotic *ex; 808f3fbd535SBarry Smith PC_MG *mg; 809174b6946SBarry Smith 810174b6946SBarry Smith PetscFunctionBegin; 811f91d8e95SBarry Smith /* if type was previously mg; must manually destroy it because call to PCSetType(pc,PCMG) will not destroy it */ 8122fa5cd67SKarl Rupp if (pc->ops->destroy) { 8132fa5cd67SKarl Rupp ierr = (*pc->ops->destroy)(pc);CHKERRQ(ierr); 8140a545947SLisandro Dalcin pc->data = NULL; 8152fa5cd67SKarl Rupp } 816503cfb0cSBarry Smith ierr = PetscFree(((PetscObject)pc)->type_name);CHKERRQ(ierr); 8170a545947SLisandro Dalcin ((PetscObject)pc)->type_name = NULL; 818f91d8e95SBarry Smith 819174b6946SBarry Smith ierr = PCSetType(pc,PCMG);CHKERRQ(ierr); 8200298fd71SBarry Smith ierr = PCMGSetLevels(pc,2,NULL);CHKERRQ(ierr); 8212134b1e4SBarry Smith ierr = PCMGSetGalerkin(pc,PC_MG_GALERKIN_PMAT);CHKERRQ(ierr); 822b00a9115SJed Brown ierr = PetscNew(&ex);CHKERRQ(ierr); \ 8237233f9f0SBarry Smith ex->type = PC_EXOTIC_FACE; 824f3fbd535SBarry Smith mg = (PC_MG*) pc->data; 82531567311SBarry Smith mg->innerctx = ex; 8267233f9f0SBarry Smith 8277233f9f0SBarry Smith 8287233f9f0SBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Exotic; 8297233f9f0SBarry Smith pc->ops->view = PCView_Exotic; 8307233f9f0SBarry Smith pc->ops->destroy = PCDestroy_Exotic; 8316c699258SBarry Smith pc->ops->setup = PCSetUp_Exotic; 8322fa5cd67SKarl Rupp 833bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCExoticSetType_C",PCExoticSetType_Exotic);CHKERRQ(ierr); 834174b6946SBarry Smith PetscFunctionReturn(0); 835174b6946SBarry Smith } 836