1 2 #include <petsc-private/daimpl.h> /*I "petscdmda.h" I*/ 3 4 #undef __FUNCT__ 5 #define __FUNCT__ "DMView_DA_2d" 6 PetscErrorCode DMView_DA_2d(DM da,PetscViewer viewer) 7 { 8 PetscErrorCode ierr; 9 PetscMPIInt rank; 10 PetscBool iascii,isdraw,isbinary; 11 DM_DA *dd = (DM_DA*)da->data; 12 #if defined(PETSC_HAVE_MATLAB_ENGINE) 13 PetscBool ismatlab; 14 #endif 15 16 PetscFunctionBegin; 17 ierr = MPI_Comm_rank(((PetscObject)da)->comm,&rank);CHKERRQ(ierr); 18 19 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 20 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 21 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 22 #if defined(PETSC_HAVE_MATLAB_ENGINE) 23 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);CHKERRQ(ierr); 24 #endif 25 if (iascii) { 26 PetscViewerFormat format; 27 28 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 29 if (format != PETSC_VIEWER_ASCII_VTK && format != PETSC_VIEWER_ASCII_VTK_CELL) { 30 DMDALocalInfo info; 31 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 32 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 33 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Processor [%d] M %D N %D m %D n %D w %D s %D\n",rank,dd->M,dd->N,dd->m,dd->n,dd->w,dd->s);CHKERRQ(ierr); 34 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"X range of indices: %D %D, Y range of indices: %D %D\n",info.xs,info.xs+info.xm,info.ys,info.ys+info.ym);CHKERRQ(ierr); 35 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 36 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 37 } else { 38 ierr = DMView_DA_VTK(da,viewer);CHKERRQ(ierr); 39 } 40 } else if (isdraw) { 41 PetscDraw draw; 42 double ymin = -1*dd->s-1,ymax = dd->N+dd->s; 43 double xmin = -1*dd->s-1,xmax = dd->M+dd->s; 44 double x,y; 45 PetscInt base,*idx; 46 char node[10]; 47 PetscBool isnull; 48 49 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 50 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 51 if (!da->coordinates) { 52 ierr = PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);CHKERRQ(ierr); 53 } 54 ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr); 55 56 /* first processor draw all node lines */ 57 if (!rank) { 58 ymin = 0.0; ymax = dd->N - 1; 59 for (xmin=0; xmin<dd->M; xmin++) { 60 ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_BLACK);CHKERRQ(ierr); 61 } 62 xmin = 0.0; xmax = dd->M - 1; 63 for (ymin=0; ymin<dd->N; ymin++) { 64 ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_BLACK);CHKERRQ(ierr); 65 } 66 } 67 ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); 68 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 69 70 /* draw my box */ 71 ymin = dd->ys; ymax = dd->ye - 1; xmin = dd->xs/dd->w; 72 xmax =(dd->xe-1)/dd->w; 73 ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_RED);CHKERRQ(ierr); 74 ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_RED);CHKERRQ(ierr); 75 ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr); 76 ierr = PetscDrawLine(draw,xmax,ymin,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr); 77 78 /* put in numbers */ 79 base = (dd->base)/dd->w; 80 for (y=ymin; y<=ymax; y++) { 81 for (x=xmin; x<=xmax; x++) { 82 sprintf(node,"%d",(int)base++); 83 ierr = PetscDrawString(draw,x,y,PETSC_DRAW_BLACK,node);CHKERRQ(ierr); 84 } 85 } 86 87 ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); 88 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 89 /* overlay ghost numbers, useful for error checking */ 90 /* put in numbers */ 91 92 base = 0; idx = dd->idx; 93 ymin = dd->Ys; ymax = dd->Ye; xmin = dd->Xs; xmax = dd->Xe; 94 for (y=ymin; y<ymax; y++) { 95 for (x=xmin; x<xmax; x++) { 96 if ((base % dd->w) == 0) { 97 sprintf(node,"%d",(int)(idx[base]/dd->w)); 98 ierr = PetscDrawString(draw,x/dd->w,y,PETSC_DRAW_BLUE,node);CHKERRQ(ierr); 99 } 100 base++; 101 } 102 } 103 ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); 104 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 105 } else if (isbinary){ 106 ierr = DMView_DA_Binary(da,viewer);CHKERRQ(ierr); 107 #if defined(PETSC_HAVE_MATLAB_ENGINE) 108 } else if (ismatlab) { 109 ierr = DMView_DA_Matlab(da,viewer);CHKERRQ(ierr); 110 #endif 111 } else SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Viewer type %s not supported for DMDA 1d",((PetscObject)viewer)->type_name); 112 PetscFunctionReturn(0); 113 } 114 115 /* 116 M is number of grid points 117 m is number of processors 118 119 */ 120 #undef __FUNCT__ 121 #define __FUNCT__ "DMDASplitComm2d" 122 PetscErrorCode DMDASplitComm2d(MPI_Comm comm,PetscInt M,PetscInt N,PetscInt sw,MPI_Comm *outcomm) 123 { 124 PetscErrorCode ierr; 125 PetscInt m,n = 0,x = 0,y = 0; 126 PetscMPIInt size,csize,rank; 127 128 PetscFunctionBegin; 129 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 130 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 131 132 csize = 4*size; 133 do { 134 if (csize % 4) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cannot split communicator of size %d tried %d %D %D",size,csize,x,y); 135 csize = csize/4; 136 137 m = (PetscInt)(0.5 + sqrt(((double)M)*((double)csize)/((double)N))); 138 if (!m) m = 1; 139 while (m > 0) { 140 n = csize/m; 141 if (m*n == csize) break; 142 m--; 143 } 144 if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;} 145 146 x = M/m + ((M % m) > ((csize-1) % m)); 147 y = (N + (csize-1)/m)/n; 148 } while ((x < 4 || y < 4) && csize > 1); 149 if (size != csize) { 150 MPI_Group entire_group,sub_group; 151 PetscMPIInt i,*groupies; 152 153 ierr = MPI_Comm_group(comm,&entire_group);CHKERRQ(ierr); 154 ierr = PetscMalloc(csize*sizeof(PetscInt),&groupies);CHKERRQ(ierr); 155 for (i=0; i<csize; i++) { 156 groupies[i] = (rank/csize)*csize + i; 157 } 158 ierr = MPI_Group_incl(entire_group,csize,groupies,&sub_group);CHKERRQ(ierr); 159 ierr = PetscFree(groupies);CHKERRQ(ierr); 160 ierr = MPI_Comm_create(comm,sub_group,outcomm);CHKERRQ(ierr); 161 ierr = MPI_Group_free(&entire_group);CHKERRQ(ierr); 162 ierr = MPI_Group_free(&sub_group);CHKERRQ(ierr); 163 ierr = PetscInfo1(0,"DMDASplitComm2d:Creating redundant coarse problems of size %d\n",csize);CHKERRQ(ierr); 164 } else { 165 *outcomm = comm; 166 } 167 PetscFunctionReturn(0); 168 } 169 170 #if defined(new) 171 #undef __FUNCT__ 172 #define __FUNCT__ "DMDAGetDiagonal_MFFD" 173 /* 174 DMDAGetDiagonal_MFFD - Gets the diagonal for a matrix free matrix where local 175 function lives on a DMDA 176 177 y ~= (F(u + ha) - F(u))/h, 178 where F = nonlinear function, as set by SNESSetFunction() 179 u = current iterate 180 h = difference interval 181 */ 182 PetscErrorCode DMDAGetDiagonal_MFFD(DM da,Vec U,Vec a) 183 { 184 PetscScalar h,*aa,*ww,v; 185 PetscReal epsilon = PETSC_SQRT_MACHINE_EPSILON,umin = 100.0*PETSC_SQRT_MACHINE_EPSILON; 186 PetscErrorCode ierr; 187 PetscInt gI,nI; 188 MatStencil stencil; 189 DMDALocalInfo info; 190 191 PetscFunctionBegin; 192 ierr = (*ctx->func)(0,U,a,ctx->funcctx);CHKERRQ(ierr); 193 ierr = (*ctx->funcisetbase)(U,ctx->funcctx);CHKERRQ(ierr); 194 195 ierr = VecGetArray(U,&ww);CHKERRQ(ierr); 196 ierr = VecGetArray(a,&aa);CHKERRQ(ierr); 197 198 nI = 0; 199 h = ww[gI]; 200 if (h == 0.0) h = 1.0; 201 #if !defined(PETSC_USE_COMPLEX) 202 if (h < umin && h >= 0.0) h = umin; 203 else if (h < 0.0 && h > -umin) h = -umin; 204 #else 205 if (PetscAbsScalar(h) < umin && PetscRealPart(h) >= 0.0) h = umin; 206 else if (PetscRealPart(h) < 0.0 && PetscAbsScalar(h) < umin) h = -umin; 207 #endif 208 h *= epsilon; 209 210 ww[gI] += h; 211 ierr = (*ctx->funci)(i,w,&v,ctx->funcctx);CHKERRQ(ierr); 212 aa[nI] = (v - aa[nI])/h; 213 ww[gI] -= h; 214 nI++; 215 } 216 ierr = VecRestoreArray(U,&ww);CHKERRQ(ierr); 217 ierr = VecRestoreArray(a,&aa);CHKERRQ(ierr); 218 PetscFunctionReturn(0); 219 } 220 #endif 221 222 #undef __FUNCT__ 223 #define __FUNCT__ "DMSetUp_DA_2D" 224 PetscErrorCode DMSetUp_DA_2D(DM da) 225 { 226 DM_DA *dd = (DM_DA*)da->data; 227 const PetscInt M = dd->M; 228 const PetscInt N = dd->N; 229 PetscInt m = dd->m; 230 PetscInt n = dd->n; 231 PetscInt o = dd->overlap; 232 const PetscInt dof = dd->w; 233 const PetscInt s = dd->s; 234 DMDABoundaryType bx = dd->bx; 235 DMDABoundaryType by = dd->by; 236 DMDAStencilType stencil_type = dd->stencil_type; 237 PetscInt *lx = dd->lx; 238 PetscInt *ly = dd->ly; 239 MPI_Comm comm; 240 PetscMPIInt rank,size; 241 PetscInt xs,xe,ys,ye,x,y,Xs,Xe,Ys,Ye,start,end,IXs,IXe,IYs,IYe; 242 PetscInt up,down,left,right,i,n0,n1,n2,n3,n5,n6,n7,n8,*idx,nn,*idx_cpy; 243 const PetscInt *idx_full; 244 PetscInt xbase,*bases,*ldims,j,x_t,y_t,s_t,base,count; 245 PetscInt s_x,s_y; /* s proportionalized to w */ 246 PetscInt sn0 = 0,sn2 = 0,sn6 = 0,sn8 = 0; 247 Vec local,global; 248 VecScatter ltog,gtol; 249 IS to,from,ltogis; 250 PetscErrorCode ierr; 251 252 PetscFunctionBegin; 253 if (stencil_type == DMDA_STENCIL_BOX && (bx == DMDA_BOUNDARY_MIRROR || by == DMDA_BOUNDARY_MIRROR)) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_SUP,"Mirror boundary and box stencil"); 254 if (dof < 1) SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof); 255 if (s < 0) SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s); 256 ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); 257 #if !defined(PETSC_USE_64BIT_INDICES) 258 if (((Petsc64bitInt) M)*((Petsc64bitInt) N)*((Petsc64bitInt) dof) > (Petsc64bitInt) PETSC_MPI_INT_MAX) SETERRQ3(comm,PETSC_ERR_INT_OVERFLOW,"Mesh of %D by %D by %D (dof) is too large for 32 bit indices",M,N,dof); 259 #endif 260 261 if (dof < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have 1 or more degrees of freedom per node: %D",dof); 262 if (s < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Stencil width cannot be negative: %D",s); 263 264 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 265 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 266 267 dd->dim = 2; 268 ierr = PetscMalloc(dof*sizeof(char*),&dd->fieldname);CHKERRQ(ierr); 269 ierr = PetscMemzero(dd->fieldname,dof*sizeof(char*));CHKERRQ(ierr); 270 271 if (m != PETSC_DECIDE) { 272 if (m < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in X direction: %D",m); 273 else if (m > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in X direction: %D %d",m,size); 274 } 275 if (n != PETSC_DECIDE) { 276 if (n < 1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Non-positive number of processors in Y direction: %D",n); 277 else if (n > size) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Too many processors in Y direction: %D %d",n,size); 278 } 279 280 if (m == PETSC_DECIDE || n == PETSC_DECIDE) { 281 if (n != PETSC_DECIDE) { 282 m = size/n; 283 } else if (m != PETSC_DECIDE) { 284 n = size/m; 285 } else { 286 /* try for squarish distribution */ 287 m = (PetscInt)(0.5 + sqrt(((double)M)*((double)size)/((double)N))); 288 if (!m) m = 1; 289 while (m > 0) { 290 n = size/m; 291 if (m*n == size) break; 292 m--; 293 } 294 if (M > N && m < n) {PetscInt _m = m; m = n; n = _m;} 295 } 296 if (m*n != size) SETERRQ(comm,PETSC_ERR_PLIB,"Unable to create partition, check the size of the communicator and input m and n "); 297 } else if (m*n != size) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Given Bad partition"); 298 299 if (M < m) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in x direction is too fine! %D %D",M,m); 300 if (N < n) SETERRQ2(comm,PETSC_ERR_ARG_OUTOFRANGE,"Partition in y direction is too fine! %D %D",N,n); 301 302 /* 303 Determine locally owned region 304 xs is the first local node number, x is the number of local nodes 305 */ 306 if (!lx) { 307 ierr = PetscMalloc(m*sizeof(PetscInt), &dd->lx);CHKERRQ(ierr); 308 lx = dd->lx; 309 for (i=0; i<m; i++) { 310 lx[i] = M/m + ((M % m) > i); 311 } 312 } 313 x = lx[rank % m]; 314 xs = 0; 315 for (i=0; i<(rank % m); i++) { 316 xs += lx[i]; 317 } 318 #if defined(PETSC_USE_DEBUG) 319 left = xs; 320 for (i=(rank % m); i<m; i++) { 321 left += lx[i]; 322 } 323 if (left != M) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Sum of lx across processors not equal to M: %D %D",left,M); 324 #endif 325 326 /* 327 Determine locally owned region 328 ys is the first local node number, y is the number of local nodes 329 */ 330 if (!ly) { 331 ierr = PetscMalloc(n*sizeof(PetscInt), &dd->ly);CHKERRQ(ierr); 332 ly = dd->ly; 333 for (i=0; i<n; i++) { 334 ly[i] = N/n + ((N % n) > i); 335 } 336 } 337 y = ly[rank/m]; 338 ys = 0; 339 for (i=0; i<(rank/m); i++) { 340 ys += ly[i]; 341 } 342 #if defined(PETSC_USE_DEBUG) 343 left = ys; 344 for (i=(rank/m); i<n; i++) { 345 left += ly[i]; 346 } 347 if (left != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Sum of ly across processors not equal to N: %D %D",left,N); 348 #endif 349 350 /* 351 check if the scatter requires more than one process neighbor or wraps around 352 the domain more than once 353 */ 354 if ((x < s+o) && ((m > 1) || (bx == DMDA_BOUNDARY_PERIODIC))) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local x-width of domain x %D is smaller than stencil width s %D",x,s+o); 355 if ((y < s+o) && ((n > 1) || (by == DMDA_BOUNDARY_PERIODIC))) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local y-width of domain y %D is smaller than stencil width s %D",y,s+o); 356 xe = xs + x; 357 ye = ys + y; 358 359 /* determine ghost region (Xs) and region scattered into (IXs) */ 360 if (xs-s-o > 0) { 361 Xs = xs - s - o; IXs = xs - s - o; 362 } else { 363 if (bx) { 364 Xs = xs - s; 365 } else { 366 Xs = 0; 367 } 368 IXs = 0; 369 } 370 if (xe+s+o <= M) { 371 Xe = xe + s + o; IXe = xe + s + o; 372 } else { 373 if (bx) { 374 Xs = xs - s - o; Xe = xe + s; 375 } else { 376 Xe = M; 377 } 378 IXe = M; 379 } 380 381 if (bx == DMDA_BOUNDARY_PERIODIC || by == DMDA_BOUNDARY_MIRROR) { 382 IXs = xs - s - o; 383 IXe = xe + s + o; 384 Xs = xs - s - o; 385 Xe = xe + s + o; 386 } 387 388 if (ys-s-o > 0) { 389 Ys = ys - s - o; IYs = ys - s - o; 390 } else { 391 if (by) { 392 Ys = ys - s; 393 } else { 394 Ys = 0; 395 } 396 IYs = 0; 397 } 398 if (ye+s+o <= N) { 399 Ye = ye + s + o; IYe = ye + s + o; 400 } else { 401 if (by) { 402 Ye = ye + s; 403 } else { 404 Ye = N; 405 } 406 IYe = N; 407 } 408 409 if (by == DMDA_BOUNDARY_PERIODIC || by == DMDA_BOUNDARY_MIRROR) { 410 IYs = ys - s - o; 411 IYe = ye + s + o; 412 Ys = ys - s - o; 413 Ye = ye + s + o; 414 } 415 416 /* stencil length in each direction */ 417 s_x = s + o; 418 s_y = s + o; 419 420 /* determine starting point of each processor */ 421 nn = x*y; 422 ierr = PetscMalloc2(size+1,PetscInt,&bases,size,PetscInt,&ldims);CHKERRQ(ierr); 423 ierr = MPI_Allgather(&nn,1,MPIU_INT,ldims,1,MPIU_INT,comm);CHKERRQ(ierr); 424 bases[0] = 0; 425 for (i=1; i<=size; i++) { 426 bases[i] = ldims[i-1]; 427 } 428 for (i=1; i<=size; i++) { 429 bases[i] += bases[i-1]; 430 } 431 base = bases[rank]*dof; 432 433 /* allocate the base parallel and sequential vectors */ 434 dd->Nlocal = x*y*dof; 435 ierr = VecCreateMPIWithArray(comm,dof,dd->Nlocal,PETSC_DECIDE,0,&global);CHKERRQ(ierr); 436 dd->nlocal = (Xe-Xs)*(Ye-Ys)*dof; 437 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,dof,dd->nlocal,0,&local);CHKERRQ(ierr); 438 439 /* generate appropriate vector scatters */ 440 /* local to global inserts non-ghost point region into global */ 441 ierr = VecGetOwnershipRange(global,&start,&end);CHKERRQ(ierr); 442 ierr = ISCreateStride(comm,x*y*dof,start,1,&to);CHKERRQ(ierr); 443 444 count = x*y; 445 ierr = PetscMalloc(x*y*sizeof(PetscInt),&idx);CHKERRQ(ierr); 446 left = xs - Xs; right = left + x; 447 down = ys - Ys; up = down + y; 448 count = 0; 449 for (i=down; i<up; i++) { 450 for (j=left; j<right; j++) { 451 idx[count++] = i*(Xe-Xs) + j; 452 } 453 } 454 455 ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&from);CHKERRQ(ierr); 456 ierr = VecScatterCreate(local,from,global,to,<og);CHKERRQ(ierr); 457 ierr = PetscLogObjectParent(dd,ltog);CHKERRQ(ierr); 458 ierr = ISDestroy(&from);CHKERRQ(ierr); 459 ierr = ISDestroy(&to);CHKERRQ(ierr); 460 461 /* global to local must include ghost points within the domain, 462 but not ghost points outside the domain that aren't periodic */ 463 if (stencil_type == DMDA_STENCIL_BOX || o > 0) { 464 count = (IXe-IXs)*(IYe-IYs); 465 ierr = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr); 466 467 left = IXs - Xs; right = left + (IXe-IXs); 468 down = IYs - Ys; up = down + (IYe-IYs); 469 count = 0; 470 for (i=down; i<up; i++) { 471 for (j=left; j<right; j++) { 472 idx[count++] = j + i*(Xe-Xs); 473 } 474 } 475 ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr); 476 477 } else { 478 /* must drop into cross shape region */ 479 /* ---------| 480 | top | 481 |--- ---| up 482 | middle | 483 | | 484 ---- ---- down 485 | bottom | 486 ----------- 487 Xs xs xe Xe */ 488 count = (ys-IYs)*x + y*(IXe-IXs) + (IYe-ye)*x; 489 ierr = PetscMalloc(count*sizeof(PetscInt),&idx);CHKERRQ(ierr); 490 491 left = xs - Xs; right = left + x; 492 down = ys - Ys; up = down + y; 493 count = 0; 494 /* bottom */ 495 for (i=(IYs-Ys); i<down; i++) { 496 for (j=left; j<right; j++) { 497 idx[count++] = j + i*(Xe-Xs); 498 } 499 } 500 /* middle */ 501 for (i=down; i<up; i++) { 502 for (j=(IXs-Xs); j<(IXe-Xs); j++) { 503 idx[count++] = j + i*(Xe-Xs); 504 } 505 } 506 /* top */ 507 for (i=up; i<up+IYe-ye; i++) { 508 for (j=left; j<right; j++) { 509 idx[count++] = j + i*(Xe-Xs); 510 } 511 } 512 ierr = ISCreateBlock(comm,dof,count,idx,PETSC_OWN_POINTER,&to);CHKERRQ(ierr); 513 } 514 515 516 /* determine who lies on each side of us stored in n6 n7 n8 517 n3 n5 518 n0 n1 n2 519 */ 520 521 /* Assume the Non-Periodic Case */ 522 n1 = rank - m; 523 if (rank % m) { 524 n0 = n1 - 1; 525 } else { 526 n0 = -1; 527 } 528 if ((rank+1) % m) { 529 n2 = n1 + 1; 530 n5 = rank + 1; 531 n8 = rank + m + 1; if (n8 >= m*n) n8 = -1; 532 } else { 533 n2 = -1; n5 = -1; n8 = -1; 534 } 535 if (rank % m) { 536 n3 = rank - 1; 537 n6 = n3 + m; if (n6 >= m*n) n6 = -1; 538 } else { 539 n3 = -1; n6 = -1; 540 } 541 n7 = rank + m; if (n7 >= m*n) n7 = -1; 542 543 if (bx == DMDA_BOUNDARY_PERIODIC && by == DMDA_BOUNDARY_PERIODIC) { 544 /* Modify for Periodic Cases */ 545 /* Handle all four corners */ 546 if ((n6 < 0) && (n7 < 0) && (n3 < 0)) n6 = m-1; 547 if ((n8 < 0) && (n7 < 0) && (n5 < 0)) n8 = 0; 548 if ((n2 < 0) && (n5 < 0) && (n1 < 0)) n2 = size-m; 549 if ((n0 < 0) && (n3 < 0) && (n1 < 0)) n0 = size-1; 550 551 /* Handle Top and Bottom Sides */ 552 if (n1 < 0) n1 = rank + m * (n-1); 553 if (n7 < 0) n7 = rank - m * (n-1); 554 if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1; 555 if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1; 556 if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1; 557 if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1; 558 559 /* Handle Left and Right Sides */ 560 if (n3 < 0) n3 = rank + (m-1); 561 if (n5 < 0) n5 = rank - (m-1); 562 if ((n1 >= 0) && (n0 < 0)) n0 = rank-1; 563 if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1; 564 if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1; 565 if ((n7 >= 0) && (n8 < 0)) n8 = rank+1; 566 } else if (by == DMDA_BOUNDARY_PERIODIC) { /* Handle Top and Bottom Sides */ 567 if (n1 < 0) n1 = rank + m * (n-1); 568 if (n7 < 0) n7 = rank - m * (n-1); 569 if ((n3 >= 0) && (n0 < 0)) n0 = size - m + rank - 1; 570 if ((n3 >= 0) && (n6 < 0)) n6 = (rank%m)-1; 571 if ((n5 >= 0) && (n2 < 0)) n2 = size - m + rank + 1; 572 if ((n5 >= 0) && (n8 < 0)) n8 = (rank%m)+1; 573 } else if (bx == DMDA_BOUNDARY_PERIODIC) { /* Handle Left and Right Sides */ 574 if (n3 < 0) n3 = rank + (m-1); 575 if (n5 < 0) n5 = rank - (m-1); 576 if ((n1 >= 0) && (n0 < 0)) n0 = rank-1; 577 if ((n1 >= 0) && (n2 < 0)) n2 = rank-2*m+1; 578 if ((n7 >= 0) && (n6 < 0)) n6 = rank+2*m-1; 579 if ((n7 >= 0) && (n8 < 0)) n8 = rank+1; 580 } 581 582 ierr = PetscMalloc(9*sizeof(PetscInt),&dd->neighbors);CHKERRQ(ierr); 583 dd->neighbors[0] = n0; 584 dd->neighbors[1] = n1; 585 dd->neighbors[2] = n2; 586 dd->neighbors[3] = n3; 587 dd->neighbors[4] = rank; 588 dd->neighbors[5] = n5; 589 dd->neighbors[6] = n6; 590 dd->neighbors[7] = n7; 591 dd->neighbors[8] = n8; 592 593 if (stencil_type == DMDA_STENCIL_STAR && o == 0) { 594 /* save corner processor numbers */ 595 sn0 = n0; sn2 = n2; sn6 = n6; sn8 = n8; 596 n0 = n2 = n6 = n8 = -1; 597 } 598 599 ierr = PetscMalloc((Xe-Xs)*(Ye-Ys)*sizeof(PetscInt),&idx);CHKERRQ(ierr); 600 ierr = PetscLogObjectMemory(da,(Xe-Xs)*(Ye-Ys)*sizeof(PetscInt));CHKERRQ(ierr); 601 602 nn = 0; 603 xbase = bases[rank]; 604 for (i=1; i<=s_y; i++) { 605 if (n0 >= 0) { /* left below */ 606 x_t = lx[n0 % m]; 607 y_t = ly[(n0/m)]; 608 s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x; 609 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 610 } 611 612 if (n1 >= 0) { /* directly below */ 613 x_t = x; 614 y_t = ly[(n1/m)]; 615 s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t; 616 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 617 } else if (by == DMDA_BOUNDARY_MIRROR) { 618 for (j=0; j<x; j++) { idx[nn++] = bases[rank] + x*(s_y - i + 1) + j;} 619 } 620 621 if (n2 >= 0) { /* right below */ 622 x_t = lx[n2 % m]; 623 y_t = ly[(n2/m)]; 624 s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t; 625 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 626 } 627 } 628 629 for (i=0; i<y; i++) { 630 if (n3 >= 0) { /* directly left */ 631 x_t = lx[n3 % m]; 632 /* y_t = y; */ 633 s_t = bases[n3] + (i+1)*x_t - s_x; 634 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 635 } else if (bx == DMDA_BOUNDARY_MIRROR) { 636 for (j=0; j<s_x; j++) { idx[nn++] = bases[rank] + x*i + s_x - j;} 637 } 638 639 for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */ 640 641 if (n5 >= 0) { /* directly right */ 642 x_t = lx[n5 % m]; 643 /* y_t = y; */ 644 s_t = bases[n5] + (i)*x_t; 645 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 646 } else if (bx == DMDA_BOUNDARY_MIRROR) { 647 for (j=0; j<s_x; j++) { idx[nn++] = bases[rank] + x*(i + 1) - 2 - j;} 648 } 649 } 650 651 for (i=1; i<=s_y; i++) { 652 if (n6 >= 0) { /* left above */ 653 x_t = lx[n6 % m]; 654 /* y_t = ly[(n6/m)]; */ 655 s_t = bases[n6] + (i)*x_t - s_x; 656 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 657 } 658 659 if (n7 >= 0) { /* directly above */ 660 x_t = x; 661 /* y_t = ly[(n7/m)]; */ 662 s_t = bases[n7] + (i-1)*x_t; 663 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 664 } else if (by == DMDA_BOUNDARY_MIRROR){ 665 for (j=0; j<x; j++) { idx[nn++] = bases[rank] + x*(y - i - 1) + j;} 666 } 667 668 if (n8 >= 0) { /* right above */ 669 x_t = lx[n8 % m]; 670 /* y_t = ly[(n8/m)]; */ 671 s_t = bases[n8] + (i-1)*x_t; 672 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 673 } 674 } 675 676 ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_COPY_VALUES,&from);CHKERRQ(ierr); 677 ierr = VecScatterCreate(global,from,local,to,>ol);CHKERRQ(ierr); 678 ierr = PetscLogObjectParent(da,gtol);CHKERRQ(ierr); 679 ierr = ISDestroy(&to);CHKERRQ(ierr); 680 ierr = ISDestroy(&from);CHKERRQ(ierr); 681 682 if (stencil_type == DMDA_STENCIL_STAR && o == 0) { 683 n0 = sn0; n2 = sn2; n6 = sn6; n8 = sn8; 684 } 685 686 if (((stencil_type == DMDA_STENCIL_STAR) || 687 (bx && bx != DMDA_BOUNDARY_PERIODIC) || 688 (by && by != DMDA_BOUNDARY_PERIODIC)) && o == 0) { 689 /* 690 Recompute the local to global mappings, this time keeping the 691 information about the cross corner processor numbers and any ghosted 692 but not periodic indices. 693 */ 694 nn = 0; 695 xbase = bases[rank]; 696 for (i=1; i<=s_y; i++) { 697 if (n0 >= 0) { /* left below */ 698 x_t = lx[n0 % m]; 699 y_t = ly[(n0/m)]; 700 s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x; 701 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 702 } else if (xs-Xs > 0 && ys-Ys > 0) { 703 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 704 } 705 if (n1 >= 0) { /* directly below */ 706 x_t = x; 707 y_t = ly[(n1/m)]; 708 s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t; 709 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 710 } else if (ys-Ys > 0) { 711 if (by == DMDA_BOUNDARY_MIRROR) { 712 for (j=0; j<x; j++) { idx[nn++] = bases[rank] + x*(s_y - i + 1) + j;} 713 } else { 714 for (j=0; j<x; j++) { idx[nn++] = -1;} 715 } 716 } 717 if (n2 >= 0) { /* right below */ 718 x_t = lx[n2 % m]; 719 y_t = ly[(n2/m)]; 720 s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t; 721 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 722 } else if (Xe-xe> 0 && ys-Ys > 0) { 723 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 724 } 725 } 726 727 for (i=0; i<y; i++) { 728 if (n3 >= 0) { /* directly left */ 729 x_t = lx[n3 % m]; 730 /* y_t = y; */ 731 s_t = bases[n3] + (i+1)*x_t - s_x; 732 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 733 } else if (xs-Xs > 0) { 734 if (bx == DMDA_BOUNDARY_MIRROR) { 735 for (j=0; j<s_x; j++) { idx[nn++] = bases[rank] + x*i + s_x - j;} 736 } else { 737 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 738 } 739 } 740 741 for (j=0; j<x; j++) { idx[nn++] = xbase++; } /* interior */ 742 743 if (n5 >= 0) { /* directly right */ 744 x_t = lx[n5 % m]; 745 /* y_t = y; */ 746 s_t = bases[n5] + (i)*x_t; 747 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 748 } else if (Xe-xe > 0) { 749 if (bx == DMDA_BOUNDARY_MIRROR) { 750 for (j=0; j<s_x; j++) { idx[nn++] = bases[rank] + x*(i + 1) - 2 - j;} 751 } else { 752 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 753 } 754 } 755 } 756 757 for (i=1; i<=s_y; i++) { 758 if (n6 >= 0) { /* left above */ 759 x_t = lx[n6 % m]; 760 /* y_t = ly[(n6/m)]; */ 761 s_t = bases[n6] + (i)*x_t - s_x; 762 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 763 } else if (xs-Xs > 0 && Ye-ye > 0) { 764 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 765 } 766 if (n7 >= 0) { /* directly above */ 767 x_t = x; 768 /* y_t = ly[(n7/m)]; */ 769 s_t = bases[n7] + (i-1)*x_t; 770 for (j=0; j<x_t; j++) { idx[nn++] = s_t++;} 771 } else if (Ye-ye > 0) { 772 if (by == DMDA_BOUNDARY_MIRROR) { 773 for (j=0; j<x; j++) { idx[nn++] = bases[rank] + x*(y - i - 1) + j;} 774 } else { 775 for (j=0; j<x; j++) { idx[nn++] = -1;} 776 } 777 } 778 if (n8 >= 0) { /* right above */ 779 x_t = lx[n8 % m]; 780 /* y_t = ly[(n8/m)]; */ 781 s_t = bases[n8] + (i-1)*x_t; 782 for (j=0; j<s_x; j++) { idx[nn++] = s_t++;} 783 } else if (Xe-xe > 0 && Ye-ye > 0) { 784 for (j=0; j<s_x; j++) { idx[nn++] = -1;} 785 } 786 } 787 } 788 /* 789 Set the local to global ordering in the global vector, this allows use 790 of VecSetValuesLocal(). 791 */ 792 ierr = ISCreateBlock(comm,dof,nn,idx,PETSC_OWN_POINTER,<ogis);CHKERRQ(ierr); 793 ierr = PetscMalloc(nn*dof*sizeof(PetscInt),&idx_cpy);CHKERRQ(ierr); 794 ierr = PetscLogObjectMemory(da,nn*dof*sizeof(PetscInt));CHKERRQ(ierr); 795 ierr = ISGetIndices(ltogis, &idx_full); 796 ierr = PetscMemcpy(idx_cpy,idx_full,nn*dof*sizeof(PetscInt));CHKERRQ(ierr); 797 ierr = ISRestoreIndices(ltogis, &idx_full); 798 ierr = ISLocalToGlobalMappingCreateIS(ltogis,&da->ltogmap);CHKERRQ(ierr); 799 ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr); 800 ierr = ISDestroy(<ogis);CHKERRQ(ierr); 801 ierr = ISLocalToGlobalMappingBlock(da->ltogmap,dd->w,&da->ltogmapb);CHKERRQ(ierr); 802 ierr = PetscLogObjectParent(da,da->ltogmap);CHKERRQ(ierr); 803 804 ierr = PetscFree2(bases,ldims);CHKERRQ(ierr); 805 dd->m = m; dd->n = n; 806 /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */ 807 dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1; 808 dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1; 809 810 ierr = VecDestroy(&local);CHKERRQ(ierr); 811 ierr = VecDestroy(&global);CHKERRQ(ierr); 812 813 dd->gtol = gtol; 814 dd->ltog = ltog; 815 dd->idx = idx_cpy; 816 dd->Nl = nn*dof; 817 dd->base = base; 818 da->ops->view = DMView_DA_2d; 819 dd->ltol = PETSC_NULL; 820 dd->ao = PETSC_NULL; 821 822 PetscFunctionReturn(0); 823 } 824 825 #undef __FUNCT__ 826 #define __FUNCT__ "DMDACreate2d" 827 /*@C 828 DMDACreate2d - Creates an object that will manage the communication of two-dimensional 829 regular array data that is distributed across some processors. 830 831 Collective on MPI_Comm 832 833 Input Parameters: 834 + comm - MPI communicator 835 . bx,by - type of ghost nodes the array have. 836 Use one of DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_GHOSTED, DMDA_BOUNDARY_PERIODIC. 837 . stencil_type - stencil type. Use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR. 838 . M,N - global dimension in each direction of the array (use -M and or -N to indicate that it may be set to a different value 839 from the command line with -da_grid_x <M> -da_grid_y <N>) 840 . m,n - corresponding number of processors in each dimension 841 (or PETSC_DECIDE to have calculated) 842 . dof - number of degrees of freedom per node 843 . s - stencil width 844 - lx, ly - arrays containing the number of nodes in each cell along 845 the x and y coordinates, or PETSC_NULL. If non-null, these 846 must be of length as m and n, and the corresponding 847 m and n cannot be PETSC_DECIDE. The sum of the lx[] entries 848 must be M, and the sum of the ly[] entries must be N. 849 850 Output Parameter: 851 . da - the resulting distributed array object 852 853 Options Database Key: 854 + -dm_view - Calls DMView() at the conclusion of DMDACreate2d() 855 . -da_grid_x <nx> - number of grid points in x direction, if M < 0 856 . -da_grid_y <ny> - number of grid points in y direction, if N < 0 857 . -da_processors_x <nx> - number of processors in x direction 858 . -da_processors_y <ny> - number of processors in y direction 859 . -da_refine_x <rx> - refinement ratio in x direction 860 . -da_refine_y <ry> - refinement ratio in y direction 861 - -da_refine <n> - refine the DMDA n times before creating, if M or N < 0 862 863 864 Level: beginner 865 866 Notes: 867 The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the 868 standard 5-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes 869 the standard 9-pt stencil. 870 871 The array data itself is NOT stored in the DMDA, it is stored in Vec objects; 872 The appropriate vector objects can be obtained with calls to DMCreateGlobalVector() 873 and DMCreateLocalVector() and calls to VecDuplicate() if more are needed. 874 875 .keywords: distributed array, create, two-dimensional 876 877 .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate3d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(), 878 DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMDALocalToLocalBegin(), DMDALocalToLocalEnd(), DMDASetRefinementFactor(), 879 DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMLoad(), DMDAGetOwnershipRanges() 880 881 @*/ 882 883 PetscErrorCode DMDACreate2d(MPI_Comm comm,DMDABoundaryType bx,DMDABoundaryType by,DMDAStencilType stencil_type, 884 PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da) 885 { 886 PetscErrorCode ierr; 887 888 PetscFunctionBegin; 889 ierr = DMDACreate(comm, da);CHKERRQ(ierr); 890 ierr = DMDASetDim(*da, 2);CHKERRQ(ierr); 891 ierr = DMDASetSizes(*da, M, N, 1);CHKERRQ(ierr); 892 ierr = DMDASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr); 893 ierr = DMDASetBoundaryType(*da, bx, by, DMDA_BOUNDARY_NONE);CHKERRQ(ierr); 894 ierr = DMDASetDof(*da, dof);CHKERRQ(ierr); 895 ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr); 896 ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr); 897 ierr = DMDASetOwnershipRanges(*da, lx, ly, PETSC_NULL);CHKERRQ(ierr); 898 /* This violates the behavior for other classes, but right now users expect negative dimensions to be handled this way */ 899 ierr = DMSetFromOptions(*da);CHKERRQ(ierr); 900 ierr = DMSetUp(*da);CHKERRQ(ierr); 901 ierr = DMViewFromOptions(*da,"-dm_view");CHKERRQ(ierr); 902 PetscFunctionReturn(0); 903 } 904