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