1 #define PETSCKSP_DLL 2 3 4 #include "petscpc.h" /*I "petscpc.h" I*/ 5 #include "petscmg.h" /*I "petscmg.h" I*/ 6 #include "petscda.h" /*I "petscda.h" I*/ 7 #include "../src/ksp/pc/impls/mg/mgimpl.h" 8 9 const char *PCExoticTypes[] = {"face","wirebasket","PCExoticType","PC_Exotic",0}; 10 11 12 13 #undef __FUNCT__ 14 #define __FUNCT__ "DAGetWireBasketInterpolation" 15 /* 16 DAGetWireBasketInterpolation - Gets the interpolation for a wirebasket based coarse space 17 18 */ 19 PetscErrorCode DAGetWireBasketInterpolation(DA da,Mat Aglobal,MatReuse reuse,Mat *P) 20 { 21 PetscErrorCode ierr; 22 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; 23 PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[26],*globals,Ng,*IIint,*IIsurf; 24 Mat Xint, Xsurf,Xint_tmp; 25 IS isint,issurf,is,row,col; 26 ISLocalToGlobalMapping ltg; 27 MPI_Comm comm; 28 Mat A,Aii,Ais,Asi,*Aholder,iAii; 29 MatFactorInfo info; 30 PetscScalar *xsurf,*xint; 31 #if defined(PETSC_USE_DEBUG) 32 PetscScalar tmp; 33 #endif 34 PetscTable ht; 35 36 PetscFunctionBegin; 37 ierr = DAGetInfo(da,&dim,0,0,0,&mp,&np,&pp,&dof,0,0,0);CHKERRQ(ierr); 38 if (dof != 1) SETERRQ(PETSC_ERR_SUP,"Only for single field problems"); 39 if (dim != 3) SETERRQ(PETSC_ERR_SUP,"Only coded for 3d problems"); 40 ierr = DAGetCorners(da,0,0,0,&m,&n,&p);CHKERRQ(ierr); 41 ierr = DAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth);CHKERRQ(ierr); 42 istart = istart ? -1 : 0; 43 jstart = jstart ? -1 : 0; 44 kstart = kstart ? -1 : 0; 45 46 /* 47 the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 48 to all the local degrees of freedom (this includes the vertices, edges and faces). 49 50 Xint are the subset of the interpolation into the interior 51 52 Xface are the interpolation onto faces but not into the interior 53 54 Xsurf are the interpolation onto the vertices and edges (the surfbasket) 55 Xint 56 Symbolically one could write P = ( Xface ) after interchanging the rows to match the natural ordering on the domain 57 Xsurf 58 */ 59 N = (m - istart)*(n - jstart)*(p - kstart); 60 Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 61 Nface = 2*( (m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart) ); 62 Nwire = 4*( (m-2-istart) + (n-2-jstart) + (p-2-kstart) ) + 8; 63 Nsurf = Nface + Nwire; 64 ierr = MatCreateSeqDense(MPI_COMM_SELF,Nint,26,PETSC_NULL,&Xint);CHKERRQ(ierr); 65 ierr = MatCreateSeqDense(MPI_COMM_SELF,Nsurf,26,PETSC_NULL,&Xsurf);CHKERRQ(ierr); 66 ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 67 68 /* 69 Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 70 Xsurf will be all zero (thus making the coarse matrix singular). 71 */ 72 if (m-istart < 3) SETERRQ(PETSC_ERR_SUP,"Number of grid points per process in X direction must be at least 3"); 73 if (n-jstart < 3) SETERRQ(PETSC_ERR_SUP,"Number of grid points per process in Y direction must be at least 3"); 74 if (p-kstart < 3) SETERRQ(PETSC_ERR_SUP,"Number of grid points per process in Z direction must be at least 3"); 75 76 cnt = 0; 77 xsurf[cnt++] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + Nsurf] = 1;} xsurf[cnt++ + 2*Nsurf] = 1; 78 for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 3*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 4*Nsurf] = 1;} xsurf[cnt++ + 5*Nsurf] = 1;} 79 xsurf[cnt++ + 6*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 7*Nsurf] = 1;} xsurf[cnt++ + 8*Nsurf] = 1; 80 for (k=1;k<p-1-kstart;k++) { 81 xsurf[cnt++ + 9*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 10*Nsurf] = 1;} xsurf[cnt++ + 11*Nsurf] = 1; 82 for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 12*Nsurf] = 1; /* these are the interior nodes */ xsurf[cnt++ + 13*Nsurf] = 1;} 83 xsurf[cnt++ + 14*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 15*Nsurf] = 1;} xsurf[cnt++ + 16*Nsurf] = 1; 84 } 85 xsurf[cnt++ + 17*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 18*Nsurf] = 1;} xsurf[cnt++ + 19*Nsurf] = 1; 86 for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 20*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 21*Nsurf] = 1;} xsurf[cnt++ + 22*Nsurf] = 1;} 87 xsurf[cnt++ + 23*Nsurf] = 1; for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 24*Nsurf] = 1;} xsurf[cnt++ + 25*Nsurf] = 1; 88 89 #if defined(PETSC_USE_DEBUG) 90 for (i=0; i<Nsurf; i++) { 91 tmp = 0.0; 92 for (j=0; j<26; j++) { 93 tmp += xsurf[i+j*Nsurf]; 94 } 95 if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_ERR_PLIB,"Wrong Xsurf interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 96 } 97 #endif 98 ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 99 /* ierr = MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);*/ 100 101 102 /* 103 I are the indices for all the needed vertices (in global numbering) 104 Iint are the indices for the interior values, I surf for the surface values 105 (This is just for the part of the global matrix obtained with MatGetSubMatrix(), it 106 is NOT the local DA ordering.) 107 IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 108 */ 109 #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 110 ierr = PetscMalloc3(N,PetscInt,&II,Nint,PetscInt,&Iint,Nsurf,PetscInt,&Isurf);CHKERRQ(ierr); 111 ierr = PetscMalloc2(Nint,PetscInt,&IIint,Nsurf,PetscInt,&IIsurf);CHKERRQ(ierr); 112 for (k=0; k<p-kstart; k++) { 113 for (j=0; j<n-jstart; j++) { 114 for (i=0; i<m-istart; i++) { 115 II[c++] = i + j*mwidth + k*mwidth*nwidth; 116 117 if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 118 IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 119 Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 120 } else { 121 IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 122 Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 123 } 124 } 125 } 126 } 127 if (c != N) SETERRQ(PETSC_ERR_PLIB,"c != N"); 128 if (cint != Nint) SETERRQ(PETSC_ERR_PLIB,"cint != Nint"); 129 if (csurf != Nsurf) SETERRQ(PETSC_ERR_PLIB,"csurf != Nsurf"); 130 ierr = DAGetISLocalToGlobalMapping(da,<g);CHKERRQ(ierr); 131 ierr = ISLocalToGlobalMappingApply(ltg,N,II,II);CHKERRQ(ierr); 132 ierr = ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint);CHKERRQ(ierr); 133 ierr = ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf);CHKERRQ(ierr); 134 ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 135 ierr = ISCreateGeneral(comm,N,II,&is);CHKERRQ(ierr); 136 ierr = ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,&isint);CHKERRQ(ierr); 137 ierr = ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,&issurf);CHKERRQ(ierr); 138 ierr = PetscFree3(II,Iint,Isurf);CHKERRQ(ierr); 139 140 ierr = MatGetSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder);CHKERRQ(ierr); 141 A = *Aholder; 142 ierr = PetscFree(Aholder);CHKERRQ(ierr); 143 144 ierr = MatGetSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii);CHKERRQ(ierr); 145 ierr = MatGetSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais);CHKERRQ(ierr); 146 ierr = MatGetSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi);CHKERRQ(ierr); 147 148 /* 149 Solve for the interpolation onto the interior Xint 150 */ 151 ierr = MatGetFactor(Aii,MAT_SOLVER_PETSC,MAT_FACTOR_LU,&iAii);CHKERRQ(ierr); 152 ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 153 ierr = MatGetOrdering(Aii,MATORDERING_ND,&row,&col);CHKERRQ(ierr); 154 ierr = MatLUFactorSymbolic(iAii,Aii,row,col,&info);CHKERRQ(ierr); 155 ierr = ISDestroy(row);CHKERRQ(ierr); 156 ierr = ISDestroy(col);CHKERRQ(ierr); 157 ierr = MatLUFactorNumeric(iAii,Aii,&info);CHKERRQ(ierr); 158 ierr = MatDuplicate(Xint,MAT_DO_NOT_COPY_VALUES,&Xint_tmp);CHKERRQ(ierr); 159 ierr = MatMatMult(Ais,Xsurf,MAT_REUSE_MATRIX,PETSC_DETERMINE,&Xint_tmp);CHKERRQ(ierr); 160 ierr = MatScale(Xint_tmp,-1.0);CHKERRQ(ierr); 161 ierr = MatMatSolve(iAii,Xint_tmp,Xint);CHKERRQ(ierr); 162 ierr = MatDestroy(Xint_tmp);CHKERRQ(ierr); 163 ierr = MatDestroy(iAii);CHKERRQ(ierr); 164 165 #if defined(PETSC_USE_DEBUG) 166 ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 167 for (i=0; i<Nint; i++) { 168 tmp = 0.0; 169 for (j=0; j<26; j++) { 170 tmp += xint[i+j*Nint]; 171 } 172 if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_ERR_PLIB,"Wrong Xint interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 173 } 174 ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 175 /* ierr =MatView(Xint,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ 176 #endif 177 178 179 /* total vertices total faces total edges */ 180 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); 181 182 /* 183 For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 184 */ 185 cnt = 0; 186 gl[cnt++] = 0; { gl[cnt++] = 1;} gl[cnt++] = m-istart-1; 187 { gl[cnt++] = mwidth; { gl[cnt++] = mwidth+1;} gl[cnt++] = mwidth + m-istart-1;} 188 gl[cnt++] = mwidth*(n-jstart-1); { gl[cnt++] = mwidth*(n-jstart-1)+1;} gl[cnt++] = mwidth*(n-jstart-1) + m-istart-1; 189 { 190 gl[cnt++] = mwidth*nwidth; { gl[cnt++] = mwidth*nwidth+1;} gl[cnt++] = mwidth*nwidth+ m-istart-1; 191 { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 192 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; 193 } 194 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; 195 { 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;} 196 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; 197 198 /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 199 /* convert that to global numbering and get them on all processes */ 200 ierr = ISLocalToGlobalMappingApply(ltg,26,gl,gl);CHKERRQ(ierr); 201 /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 202 ierr = PetscMalloc(26*mp*np*pp*sizeof(PetscInt),&globals);CHKERRQ(ierr); 203 ierr = MPI_Allgather(gl,26,MPIU_INT,globals,26,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr); 204 205 /* Number the coarse grid points from 0 to Ntotal */ 206 ierr = PetscTableCreate(Ntotal/3,&ht);CHKERRQ(ierr); 207 for (i=0; i<26*mp*np*pp; i++){ 208 ierr = PetscTableAddCount(ht,globals[i]+1);CHKERRQ(ierr); 209 } 210 ierr = PetscTableGetCount(ht,&cnt);CHKERRQ(ierr); 211 if (cnt != Ntotal) SETERRQ2(PETSC_ERR_PLIB,"Hash table size %D not equal to total number coarse grid points %D",cnt,Ntotal); 212 ierr = PetscFree(globals);CHKERRQ(ierr); 213 for (i=0; i<26; i++) { 214 ierr = PetscTableFind(ht,gl[i]+1,&gl[i]);CHKERRQ(ierr); 215 gl[i]--; 216 } 217 ierr = PetscTableDestroy(ht);CHKERRQ(ierr); 218 /* PetscIntView(26,gl,PETSC_VIEWER_STDOUT_WORLD); */ 219 220 /* construct global interpolation matrix */ 221 ierr = MatGetLocalSize(Aglobal,&Ng,PETSC_NULL);CHKERRQ(ierr); 222 if (reuse == MAT_INITIAL_MATRIX) { 223 ierr = MatCreateMPIAIJ(((PetscObject)da)->comm,Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,PETSC_NULL,Nint+Nsurf,PETSC_NULL,P);CHKERRQ(ierr); 224 } else { 225 ierr = MatZeroEntries(*P);CHKERRQ(ierr); 226 } 227 ierr = MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 228 ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 229 ierr = MatSetValues(*P,Nint,IIint,26,gl,xint,INSERT_VALUES);CHKERRQ(ierr); 230 ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 231 ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 232 ierr = MatSetValues(*P,Nsurf,IIsurf,26,gl,xsurf,INSERT_VALUES);CHKERRQ(ierr); 233 ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 234 ierr = MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 235 ierr = MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 236 ierr = PetscFree2(IIint,IIsurf);CHKERRQ(ierr); 237 238 #if defined(PETSC_USE_DEBUG) 239 { 240 Vec x,y; 241 PetscScalar *yy; 242 ierr = VecCreateMPI(((PetscObject)da)->comm,Ng,PETSC_DETERMINE,&y);CHKERRQ(ierr); 243 ierr = VecCreateMPI(((PetscObject)da)->comm,PETSC_DETERMINE,Ntotal,&x);CHKERRQ(ierr); 244 ierr = VecSet(x,1.0);CHKERRQ(ierr); 245 ierr = MatMult(*P,x,y);CHKERRQ(ierr); 246 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 247 for (i=0; i<Ng; i++) { 248 if (PetscAbsScalar(yy[i]-1.0) > 1.e-10) SETERRQ2(PETSC_ERR_PLIB,"Wrong p interpolation at i %D value %G",i,PetscAbsScalar(yy[i])); 249 } 250 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 251 ierr = VecDestroy(x);CHKERRQ(ierr); 252 ierr = VecDestroy(y);CHKERRQ(ierr); 253 } 254 #endif 255 256 ierr = MatDestroy(Aii);CHKERRQ(ierr); 257 ierr = MatDestroy(Ais);CHKERRQ(ierr); 258 ierr = MatDestroy(Asi);CHKERRQ(ierr); 259 ierr = MatDestroy(A);CHKERRQ(ierr); 260 ierr = ISDestroy(is);CHKERRQ(ierr); 261 ierr = ISDestroy(isint);CHKERRQ(ierr); 262 ierr = ISDestroy(issurf);CHKERRQ(ierr); 263 ierr = MatDestroy(Xint);CHKERRQ(ierr); 264 ierr = MatDestroy(Xsurf);CHKERRQ(ierr); 265 PetscFunctionReturn(0); 266 } 267 268 #undef __FUNCT__ 269 #define __FUNCT__ "DAGetFaceInterpolation" 270 /* 271 DAGetFaceInterpolation - Gets the interpolation for a face based coarse space 272 273 */ 274 PetscErrorCode DAGetFaceInterpolation(DA da,Mat Aglobal,MatReuse reuse,Mat *P) 275 { 276 PetscErrorCode ierr; 277 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; 278 PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[6],*globals,Ng,*IIint,*IIsurf; 279 Mat Xint, Xsurf,Xint_tmp; 280 IS isint,issurf,is,row,col; 281 ISLocalToGlobalMapping ltg; 282 MPI_Comm comm; 283 Mat A,Aii,Ais,Asi,*Aholder,iAii; 284 MatFactorInfo info; 285 PetscScalar *xsurf,*xint; 286 #if defined(PETSC_USE_DEBUG_foo) 287 PetscScalar tmp; 288 #endif 289 PetscTable ht; 290 291 PetscFunctionBegin; 292 ierr = DAGetInfo(da,&dim,0,0,0,&mp,&np,&pp,&dof,0,0,0);CHKERRQ(ierr); 293 if (dof != 1) SETERRQ(PETSC_ERR_SUP,"Only for single field problems"); 294 if (dim != 3) SETERRQ(PETSC_ERR_SUP,"Only coded for 3d problems"); 295 ierr = DAGetCorners(da,0,0,0,&m,&n,&p);CHKERRQ(ierr); 296 ierr = DAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth);CHKERRQ(ierr); 297 istart = istart ? -1 : 0; 298 jstart = jstart ? -1 : 0; 299 kstart = kstart ? -1 : 0; 300 301 /* 302 the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) 303 to all the local degrees of freedom (this includes the vertices, edges and faces). 304 305 Xint are the subset of the interpolation into the interior 306 307 Xface are the interpolation onto faces but not into the interior 308 309 Xsurf are the interpolation onto the vertices and edges (the surfbasket) 310 Xint 311 Symbolically one could write P = ( Xface ) after interchanging the rows to match the natural ordering on the domain 312 Xsurf 313 */ 314 N = (m - istart)*(n - jstart)*(p - kstart); 315 Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); 316 Nface = 2*( (m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart) ); 317 Nwire = 4*( (m-2-istart) + (n-2-jstart) + (p-2-kstart) ) + 8; 318 Nsurf = Nface + Nwire; 319 ierr = MatCreateSeqDense(MPI_COMM_SELF,Nint,6,PETSC_NULL,&Xint);CHKERRQ(ierr); 320 ierr = MatCreateSeqDense(MPI_COMM_SELF,Nsurf,6,PETSC_NULL,&Xsurf);CHKERRQ(ierr); 321 ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 322 323 /* 324 Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of 325 Xsurf will be all zero (thus making the coarse matrix singular). 326 */ 327 if (m-istart < 3) SETERRQ(PETSC_ERR_SUP,"Number of grid points per process in X direction must be at least 3"); 328 if (n-jstart < 3) SETERRQ(PETSC_ERR_SUP,"Number of grid points per process in Y direction must be at least 3"); 329 if (p-kstart < 3) SETERRQ(PETSC_ERR_SUP,"Number of grid points per process in Z direction must be at least 3"); 330 331 cnt = 0; 332 for (j=1;j<n-1-jstart;j++) { for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 0*Nsurf] = 1;} } 333 for (k=1;k<p-1-kstart;k++) { 334 for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 1*Nsurf] = 1;} 335 for (j=1;j<n-1-jstart;j++) { xsurf[cnt++ + 2*Nsurf] = 1; /* these are the interior nodes */ xsurf[cnt++ + 3*Nsurf] = 1;} 336 for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 4*Nsurf] = 1;} 337 } 338 for (j=1;j<n-1-jstart;j++) {for (i=1; i<m-istart-1; i++) { xsurf[cnt++ + 5*Nsurf] = 1;} } 339 340 #if defined(PETSC_USE_DEBUG_foo) 341 for (i=0; i<Nsurf; i++) { 342 tmp = 0.0; 343 for (j=0; j<6; j++) { 344 tmp += xsurf[i+j*Nsurf]; 345 } 346 if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_ERR_PLIB,"Wrong Xsurf interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 347 } 348 #endif 349 ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 350 /* ierr = MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);*/ 351 352 353 /* 354 I are the indices for all the needed vertices (in global numbering) 355 Iint are the indices for the interior values, I surf for the surface values 356 (This is just for the part of the global matrix obtained with MatGetSubMatrix(), it 357 is NOT the local DA ordering.) 358 IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering 359 */ 360 #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) 361 ierr = PetscMalloc3(N,PetscInt,&II,Nint,PetscInt,&Iint,Nsurf,PetscInt,&Isurf);CHKERRQ(ierr); 362 ierr = PetscMalloc2(Nint,PetscInt,&IIint,Nsurf,PetscInt,&IIsurf);CHKERRQ(ierr); 363 for (k=0; k<p-kstart; k++) { 364 for (j=0; j<n-jstart; j++) { 365 for (i=0; i<m-istart; i++) { 366 II[c++] = i + j*mwidth + k*mwidth*nwidth; 367 368 if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { 369 IIint[cint] = i + j*mwidth + k*mwidth*nwidth; 370 Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 371 } else { 372 IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; 373 Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); 374 } 375 } 376 } 377 } 378 if (c != N) SETERRQ(PETSC_ERR_PLIB,"c != N"); 379 if (cint != Nint) SETERRQ(PETSC_ERR_PLIB,"cint != Nint"); 380 if (csurf != Nsurf) SETERRQ(PETSC_ERR_PLIB,"csurf != Nsurf"); 381 ierr = DAGetISLocalToGlobalMapping(da,<g);CHKERRQ(ierr); 382 ierr = ISLocalToGlobalMappingApply(ltg,N,II,II);CHKERRQ(ierr); 383 ierr = ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint);CHKERRQ(ierr); 384 ierr = ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf);CHKERRQ(ierr); 385 ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 386 ierr = ISCreateGeneral(comm,N,II,&is);CHKERRQ(ierr); 387 ierr = ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,&isint);CHKERRQ(ierr); 388 ierr = ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,&issurf);CHKERRQ(ierr); 389 ierr = PetscFree3(II,Iint,Isurf);CHKERRQ(ierr); 390 391 ierr = MatGetSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder);CHKERRQ(ierr); 392 A = *Aholder; 393 ierr = PetscFree(Aholder);CHKERRQ(ierr); 394 395 ierr = MatGetSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii);CHKERRQ(ierr); 396 ierr = MatGetSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais);CHKERRQ(ierr); 397 ierr = MatGetSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi);CHKERRQ(ierr); 398 399 /* 400 Solve for the interpolation onto the interior Xint 401 */ 402 ierr = MatDuplicate(Xint,MAT_DO_NOT_COPY_VALUES,&Xint_tmp);CHKERRQ(ierr); 403 ierr = MatMatMult(Ais,Xsurf,MAT_REUSE_MATRIX,PETSC_DETERMINE,&Xint_tmp);CHKERRQ(ierr); 404 ierr = MatScale(Xint_tmp,-1.0);CHKERRQ(ierr); 405 406 if (0) { 407 ierr = MatGetFactor(Aii,MAT_SOLVER_PETSC,MAT_FACTOR_LU,&iAii);CHKERRQ(ierr); 408 ierr = MatFactorInfoInitialize(&info);CHKERRQ(ierr); 409 ierr = MatGetOrdering(Aii,MATORDERING_ND,&row,&col);CHKERRQ(ierr); 410 ierr = MatLUFactorSymbolic(iAii,Aii,row,col,&info);CHKERRQ(ierr); 411 ierr = ISDestroy(row);CHKERRQ(ierr); 412 ierr = ISDestroy(col);CHKERRQ(ierr); 413 ierr = MatLUFactorNumeric(iAii,Aii,&info);CHKERRQ(ierr); 414 ierr = MatMatSolve(iAii,Xint_tmp,Xint);CHKERRQ(ierr); 415 ierr = MatDestroy(iAii);CHKERRQ(ierr); 416 } else { 417 KSP ksp; 418 Vec b,x; 419 PetscScalar *xint_tmp; 420 421 ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 422 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,Nint,0,&x);CHKERRQ(ierr); 423 ierr = MatGetArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 424 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,Nint,0,&b);CHKERRQ(ierr); 425 ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 426 ierr = KSPSetOperators(ksp,Aii,Aii,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 427 for (i=0; i<6; i++) { 428 ierr = VecPlaceArray(x,xint+i*Nint);CHKERRQ(ierr); 429 ierr = VecPlaceArray(b,xint_tmp+i*Nint);CHKERRQ(ierr); 430 ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); 431 ierr = VecResetArray(x);CHKERRQ(ierr); 432 ierr = VecResetArray(b);CHKERRQ(ierr); 433 } 434 ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 435 ierr = MatRestoreArray(Xint_tmp,&xint_tmp);CHKERRQ(ierr); 436 ierr = KSPDestroy(ksp);CHKERRQ(ierr); 437 ierr = VecDestroy(x);CHKERRQ(ierr); 438 ierr = VecDestroy(b);CHKERRQ(ierr); 439 } 440 ierr = MatDestroy(Xint_tmp);CHKERRQ(ierr); 441 442 #if defined(PETSC_USE_DEBUG_foo) 443 ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 444 for (i=0; i<Nint; i++) { 445 tmp = 0.0; 446 for (j=0; j<6; j++) { 447 tmp += xint[i+j*Nint]; 448 } 449 if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_ERR_PLIB,"Wrong Xint interpolation at i %D value %G",i,PetscAbsScalar(tmp)); 450 } 451 ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 452 /* ierr =MatView(Xint,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ 453 #endif 454 455 456 /* total faces */ 457 Ntotal = mp*np*(pp+1) + mp*pp*(np+1) + np*pp*(mp+1); 458 459 /* 460 For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points 461 */ 462 cnt = 0; 463 { gl[cnt++] = mwidth+1;} 464 { 465 { gl[cnt++] = mwidth*nwidth+1;} 466 { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1;} 467 { gl[cnt++] = mwidth*nwidth+mwidth*(n-jstart-1)+1;} 468 } 469 { gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth+1;} 470 471 /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 472 /* convert that to global numbering and get them on all processes */ 473 ierr = ISLocalToGlobalMappingApply(ltg,6,gl,gl);CHKERRQ(ierr); 474 /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 475 ierr = PetscMalloc(6*mp*np*pp*sizeof(PetscInt),&globals);CHKERRQ(ierr); 476 ierr = MPI_Allgather(gl,6,MPIU_INT,globals,6,MPIU_INT,((PetscObject)da)->comm);CHKERRQ(ierr); 477 478 /* Number the coarse grid points from 0 to Ntotal */ 479 ierr = PetscTableCreate(Ntotal/3,&ht);CHKERRQ(ierr); 480 for (i=0; i<6*mp*np*pp; i++){ 481 ierr = PetscTableAddCount(ht,globals[i]+1);CHKERRQ(ierr); 482 } 483 ierr = PetscTableGetCount(ht,&cnt);CHKERRQ(ierr); 484 if (cnt != Ntotal) SETERRQ2(PETSC_ERR_PLIB,"Hash table size %D not equal to total number coarse grid points %D",cnt,Ntotal); 485 ierr = PetscFree(globals);CHKERRQ(ierr); 486 for (i=0; i<6; i++) { 487 ierr = PetscTableFind(ht,gl[i]+1,&gl[i]);CHKERRQ(ierr); 488 gl[i]--; 489 } 490 ierr = PetscTableDestroy(ht);CHKERRQ(ierr); 491 /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ 492 493 /* construct global interpolation matrix */ 494 ierr = MatGetLocalSize(Aglobal,&Ng,PETSC_NULL);CHKERRQ(ierr); 495 if (reuse == MAT_INITIAL_MATRIX) { 496 ierr = MatCreateMPIAIJ(((PetscObject)da)->comm,Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,PETSC_NULL,Nint,PETSC_NULL,P);CHKERRQ(ierr); 497 } else { 498 ierr = MatZeroEntries(*P);CHKERRQ(ierr); 499 } 500 ierr = MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 501 ierr = MatGetArray(Xint,&xint);CHKERRQ(ierr); 502 ierr = MatSetValues(*P,Nint,IIint,6,gl,xint,INSERT_VALUES);CHKERRQ(ierr); 503 ierr = MatRestoreArray(Xint,&xint);CHKERRQ(ierr); 504 ierr = MatGetArray(Xsurf,&xsurf);CHKERRQ(ierr); 505 ierr = MatSetValues(*P,Nsurf,IIsurf,6,gl,xsurf,INSERT_VALUES);CHKERRQ(ierr); 506 ierr = MatRestoreArray(Xsurf,&xsurf);CHKERRQ(ierr); 507 ierr = MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 508 ierr = MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 509 ierr = PetscFree2(IIint,IIsurf);CHKERRQ(ierr); 510 511 512 #if defined(PETSC_USE_DEBUG_foo) 513 { 514 Vec x,y; 515 PetscScalar *yy; 516 ierr = VecCreateMPI(((PetscObject)da)->comm,Ng,PETSC_DETERMINE,&y);CHKERRQ(ierr); 517 ierr = VecCreateMPI(((PetscObject)da)->comm,PETSC_DETERMINE,Ntotal,&x);CHKERRQ(ierr); 518 ierr = VecSet(x,1.0);CHKERRQ(ierr); 519 ierr = MatMult(*P,x,y);CHKERRQ(ierr); 520 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 521 for (i=0; i<Ng; i++) { 522 if (PetscAbsScalar(yy[i]-1.0) > 1.e-10) SETERRQ2(PETSC_ERR_PLIB,"Wrong p interpolation at i %D value %G",i,PetscAbsScalar(yy[i])); 523 } 524 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 525 ierr = VecDestroy(x);CHKERRQ(ierr); 526 ierr = VecDestroy(y);CHKERRQ(ierr); 527 } 528 #endif 529 530 ierr = MatDestroy(Aii);CHKERRQ(ierr); 531 ierr = MatDestroy(Ais);CHKERRQ(ierr); 532 ierr = MatDestroy(Asi);CHKERRQ(ierr); 533 ierr = MatDestroy(A);CHKERRQ(ierr); 534 ierr = ISDestroy(is);CHKERRQ(ierr); 535 ierr = ISDestroy(isint);CHKERRQ(ierr); 536 ierr = ISDestroy(issurf);CHKERRQ(ierr); 537 ierr = MatDestroy(Xint);CHKERRQ(ierr); 538 ierr = MatDestroy(Xsurf);CHKERRQ(ierr); 539 PetscFunctionReturn(0); 540 } 541 542 typedef struct { 543 DA da; 544 PCExoticType type; 545 Mat P; /* the interpolation matrix */ 546 } PC_Exotic; 547 548 #undef __FUNCT__ 549 #define __FUNCT__ "PCExoticSetType" 550 /*@ 551 PCExoticSetType - Sets the type of coarse grid interpolation to use 552 553 Collective on PC 554 555 Input Parameters: 556 + pc - the preconditioner context 557 - type - either PC_EXOTIC_FACE or PC_EXOTIC_WIREBASKET (defaults to face) 558 559 Notes: The face based interpolation has 1 degree of freedom per face and ignores the 560 edge and vertex values completely in the coarse problem. For any seven point 561 stencil the interpolation of a constant on all faces into the interior is that constant. 562 563 The wirebasket interpolation has 1 degree of freedom per vertex, per edge and 564 per face. A constant on the subdomain boundary is interpolated as that constant 565 in the interior of the domain. 566 567 The coarse grid matrix is obtained via the Galerkin computation A_c = R A R^T, hence 568 if A is nonsingular A_c is also nonsingular. 569 570 Both interpolations are suitable for only scalar problems. 571 572 Level: intermediate 573 574 575 .seealso: PCEXOTIC, PCExoticType() 576 @*/ 577 PetscErrorCode PETSCKSP_DLLEXPORT PCExoticSetType(PC pc,PCExoticType type) 578 { 579 PetscErrorCode ierr,(*f)(PC,PCExoticType); 580 581 PetscFunctionBegin; 582 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 583 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCExoticSetType_C",(void (**)(void))&f);CHKERRQ(ierr); 584 if (f) { 585 ierr = (*f)(pc,type);CHKERRQ(ierr); 586 } 587 PetscFunctionReturn(0); 588 } 589 590 #undef __FUNCT__ 591 #define __FUNCT__ "PCExoticSetType_Exotic" 592 PetscErrorCode PETSCKSP_DLLEXPORT PCExoticSetType_Exotic(PC pc,PCExoticType type) 593 { 594 PC_MG **mg = (PC_MG**)pc->data; 595 PC_Exotic *ctx = (PC_Exotic*) mg[0]->innerctx; 596 597 PetscFunctionBegin; 598 ctx->type = type; 599 PetscFunctionReturn(0); 600 } 601 602 #undef __FUNCT__ 603 #define __FUNCT__ "PCSetUp_Exotic" 604 PetscErrorCode PCSetUp_Exotic(PC pc) 605 { 606 PetscErrorCode ierr; 607 Mat A; 608 PC_MG **mg = (PC_MG**)pc->data; 609 PC_Exotic *ex = (PC_Exotic*) mg[0]->innerctx; 610 DA da = ex->da; 611 MatReuse reuse = (ex->P) ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 612 613 PetscFunctionBegin; 614 ierr = PCGetOperators(pc,PETSC_NULL,&A,PETSC_NULL);CHKERRQ(ierr); 615 if (ex->type == PC_EXOTIC_FACE) { 616 ierr = DAGetFaceInterpolation(da,A,reuse,&ex->P);CHKERRQ(ierr); 617 } else if (ex->type == PC_EXOTIC_WIREBASKET) { 618 ierr = DAGetWireBasketInterpolation(da,A,reuse,&ex->P);CHKERRQ(ierr); 619 } else SETERRQ1(PETSC_ERR_PLIB,"Unknown exotic coarse space %d",ex->type); 620 ierr = PCMGSetInterpolation(pc,1,ex->P);CHKERRQ(ierr); 621 ierr = PCSetUp_MG(pc);CHKERRQ(ierr); 622 PetscFunctionReturn(0); 623 } 624 625 #undef __FUNCT__ 626 #define __FUNCT__ "PCDestroy_Exotic" 627 PetscErrorCode PCDestroy_Exotic(PC pc) 628 { 629 PetscErrorCode ierr; 630 PC_MG **mg = (PC_MG**)pc->data; 631 PC_Exotic *ctx = (PC_Exotic*) mg[0]->innerctx; 632 633 PetscFunctionBegin; 634 if (ctx->da) {ierr = DADestroy(ctx->da);CHKERRQ(ierr);} 635 if (ctx->P) {ierr = MatDestroy(ctx->P);CHKERRQ(ierr);} 636 ierr = PetscFree(ctx);CHKERRQ(ierr); 637 ierr = PCDestroy_MG(pc);CHKERRQ(ierr); 638 PetscFunctionReturn(0); 639 } 640 641 #undef __FUNCT__ 642 #define __FUNCT__ "PCSetUp_Exotic_Error" 643 PetscErrorCode PCSetUp_Exotic_Error(PC pc) 644 { 645 PetscFunctionBegin; 646 SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"You are using the Exotic preconditioner but never called PCSetDA()"); 647 PetscFunctionReturn(0); 648 } 649 650 #undef __FUNCT__ 651 #define __FUNCT__ "PCSetDA" 652 /*@ 653 PCSetDA - Sets the DA that is to be used by the PCEXOTIC or certain other preconditioners 654 655 Collective on PC 656 657 Input Parameters: 658 + pc - the preconditioner context 659 - da - the da 660 661 Level: intermediate 662 663 664 .seealso: PCEXOTIC, PCExoticType() 665 @*/ 666 PetscErrorCode PETSCKSP_DLLEXPORT PCSetDA(PC pc,DA da) 667 { 668 PetscErrorCode ierr,(*f)(PC,DA); 669 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 672 PetscValidHeaderSpecific(da,DM_COOKIE,1); 673 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCSetDA_C",(void (**)(void))&f);CHKERRQ(ierr); 674 if (f) { 675 ierr = (*f)(pc,da);CHKERRQ(ierr); 676 } 677 PetscFunctionReturn(0); 678 } 679 680 681 #undef __FUNCT__ 682 #define __FUNCT__ "PCSetDA_Exotic" 683 PetscErrorCode PETSCKSP_DLLEXPORT PCSetDA_Exotic(PC pc,DA da) 684 { 685 PetscErrorCode ierr; 686 PC_MG **mg = (PC_MG**)pc->data; 687 PC_Exotic *ctx = (PC_Exotic*) mg[0]->innerctx; 688 689 PetscFunctionBegin; 690 ctx->da = da; 691 pc->ops->setup = PCSetUp_Exotic; 692 ierr = PetscObjectReference((PetscObject)da);CHKERRQ(ierr); 693 PetscFunctionReturn(0); 694 } 695 696 #undef __FUNCT__ 697 #define __FUNCT__ "PCView_Exotic" 698 PetscErrorCode PCView_Exotic(PC pc,PetscViewer viewer) 699 { 700 PC_MG **mg = (PC_MG**)pc->data; 701 PetscErrorCode ierr; 702 PetscTruth iascii; 703 PC_Exotic *ctx = (PC_Exotic*) mg[0]->innerctx; 704 705 PetscFunctionBegin; 706 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 707 if (iascii) { 708 ierr = PetscViewerASCIIPrintf(viewer," Exotic type = %s\n",PCExoticTypes[ctx->type]);CHKERRQ(ierr); 709 } 710 ierr = PCView_MG(pc,viewer);CHKERRQ(ierr); 711 PetscFunctionReturn(0); 712 } 713 714 #undef __FUNCT__ 715 #define __FUNCT__ "PCSetFromOptions_Exotic" 716 PetscErrorCode PCSetFromOptions_Exotic(PC pc) 717 { 718 PetscErrorCode ierr; 719 PetscTruth flg; 720 PC_MG **mg = (PC_MG**)pc->data; 721 PCExoticType mgctype; 722 PC_Exotic *ctx = (PC_Exotic*) mg[0]->innerctx; 723 724 PetscFunctionBegin; 725 ierr = PetscOptionsHead("Exotic coarse space options");CHKERRQ(ierr); 726 ierr = PetscOptionsEnum("-pc_exotic_type","face or wirebasket","PCExoticSetType",PCExoticTypes,(PetscEnum)ctx->type,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr); 727 if (flg) { 728 ierr = PCExoticSetType(pc,mgctype);CHKERRQ(ierr); 729 } 730 ierr = PetscOptionsTail();CHKERRQ(ierr); 731 PetscFunctionReturn(0); 732 } 733 734 735 /*MC 736 PCEXOTIC - Two level overlapping Schwarz preconditioner with exotic (non-standard) coarse grid spaces 737 738 This uses the PCMG infrastructure restricted to two levels and the face and wirebasket based coarse 739 grid spaces. These coarse grid spaces originate in the work of Bramble, Pasciak and Schatz, "The Construction 740 of Preconditioners for Elliptic Problems by Substructing IV", Mathematics of Computation, volume 53 pages 1--24, 1989. 741 They were generalized slightly in "Domain Decomposition Method for Linear Elasticity", Ph. D. thesis, Barry Smith, 742 New York University, 1990. They were then explored in great detail in Dryja, Smith, Widlund, "Schwarz Analysis 743 of Iterative Substructuring Methods for Elliptic Problems in Three Dimensions, SIAM Journal on Numerical 744 Analysis, volume 31. pages 1662-1694, 1994. These were developed in the context of iterative substructuring preconditioners. 745 They were then ingeniously applied as coarse grid spaces for overlapping Schwarz methods by Dohrmann and Widlund. 746 They refer to them as GDSW (generalized Dryja, Smith, Widlund preconditioners). See, for example, 747 Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Extending theory for domain decomposition algorithms to irregular subdomains. In Ulrich Langer, Marco 748 Discacciati, David Keyes, Olof Widlund, and Walter Zulehner, editors, Proceedings 749 of the 17th International Conference on Domain Decomposition Methods in 750 Science and Engineering, held in Strobl, Austria, July 3-7, 2006, number 60 in 751 Springer-Verlag, Lecture Notes in Computational Science and Engineering, pages 255-261, 2007. 752 Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. A family of energy min- 753 imizing coarse spaces for overlapping Schwarz preconditioners. In Ulrich Langer, 754 Marco Discacciati, David Keyes, OlofWidlund, andWalter Zulehner, editors, Proceedings 755 of the 17th International Conference on Domain Decomposition Methods 756 in Science and Engineering, held in Strobl, Austria, July 3-7, 2006, number 60 in 757 Springer-Verlag, Lecture Notes in Computational Science and Engineering, pages 247-254, 2007 758 Clark R. Dohrmann, Axel Klawonn, and Olof B. Widlund. Domain decomposition 759 for less regular subdomains: Overlapping Schwarz in two dimensions. SIAM J. 760 Numer. Anal., 46(4):2153-2168, 2008. 761 Clark R. Dohrmann and Olof B. Widlund. An overlapping Schwarz 762 algorithm for almost incompressible elasticity. Technical Report 763 TR2008-912, Department of Computer Science, Courant Institute 764 of Mathematical Sciences, New York University, May 2008. URL: 765 http://cs.nyu.edu/csweb/Research/TechReports/TR2008-912/TR2008-912.pdf 766 767 Options Database: The usual PCMG options are supported, such as -mg_levels_pc_type <type> -mg_coarse_pc_type <type> 768 -pc_mg_type <type> 769 770 Level: advanced 771 772 .seealso: PCMG, PCSetDA(), PCExoticType, PCExoticSetType() 773 M*/ 774 775 EXTERN_C_BEGIN 776 #undef __FUNCT__ 777 #define __FUNCT__ "PCCreate_Exotic" 778 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Exotic(PC pc) 779 { 780 PetscErrorCode ierr; 781 PC_Exotic *ex; 782 PC_MG **mg; 783 784 PetscFunctionBegin; 785 /* if type was previously mg; must manually destroy it because call to PCSetType(pc,PCMG) will not destroy it */ 786 if (pc->ops->destroy) { ierr = (*pc->ops->destroy)(pc);CHKERRQ(ierr); pc->data = 0;} 787 ierr = PetscStrfree(((PetscObject)pc)->type_name);CHKERRQ(ierr); 788 ((PetscObject)pc)->type_name = 0; 789 790 ierr = PCSetType(pc,PCMG);CHKERRQ(ierr); 791 ierr = PCMGSetLevels(pc,2,PETSC_NULL);CHKERRQ(ierr); 792 ierr = PCMGSetGalerkin(pc);CHKERRQ(ierr); 793 ierr = PetscNew(PC_Exotic,&ex);CHKERRQ(ierr);\ 794 ex->type = PC_EXOTIC_FACE; 795 mg = (PC_MG**) pc->data; 796 mg[0]->innerctx = ex; 797 798 799 pc->ops->setfromoptions = PCSetFromOptions_Exotic; 800 pc->ops->view = PCView_Exotic; 801 pc->ops->destroy = PCDestroy_Exotic; 802 pc->ops->setup = PCSetUp_Exotic_Error; 803 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCExoticSetType_C","PCExoticSetType_Exotic",PCExoticSetType_Exotic);CHKERRQ(ierr); 804 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSetDA_C","PCSetDA_Exotic",PCSetDA_Exotic);CHKERRQ(ierr); 805 PetscFunctionReturn(0); 806 } 807 EXTERN_C_END 808