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 (((PetscInt64) M)*((PetscInt64) N)*((PetscInt64) dof) > (PetscInt64) 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) || (bx && bx != DM_BOUNDARY_PERIODIC) || (by && by != DM_BOUNDARY_PERIODIC))) { 666 /* 667 Recompute the local to global mappings, this time keeping the 668 information about the cross corner processor numbers and any ghosted 669 but not periodic indices. 670 */ 671 nn = 0; 672 xbase = bases[rank]; 673 for (i=1; i<=s_y; i++) { 674 if (n0 >= 0) { /* left below */ 675 x_t = lx[n0 % m]; 676 y_t = ly[(n0/m)]; 677 s_t = bases[n0] + x_t*y_t - (s_y-i)*x_t - s_x; 678 for (j=0; j<s_x; j++) idx[nn++] = s_t++; 679 } else if (xs-Xs > 0 && ys-Ys > 0) { 680 for (j=0; j<s_x; j++) idx[nn++] = -1; 681 } 682 if (n1 >= 0) { /* directly below */ 683 x_t = x; 684 y_t = ly[(n1/m)]; 685 s_t = bases[n1] + x_t*y_t - (s_y+1-i)*x_t; 686 for (j=0; j<x_t; j++) idx[nn++] = s_t++; 687 } else if (ys-Ys > 0) { 688 if (by == DM_BOUNDARY_MIRROR) { 689 for (j=0; j<x; j++) idx[nn++] = bases[rank] + x*(s_y - i + 1) + j; 690 } else { 691 for (j=0; j<x; j++) idx[nn++] = -1; 692 } 693 } 694 if (n2 >= 0) { /* right below */ 695 x_t = lx[n2 % m]; 696 y_t = ly[(n2/m)]; 697 s_t = bases[n2] + x_t*y_t - (s_y+1-i)*x_t; 698 for (j=0; j<s_x; j++) idx[nn++] = s_t++; 699 } else if (Xe-xe> 0 && ys-Ys > 0) { 700 for (j=0; j<s_x; j++) idx[nn++] = -1; 701 } 702 } 703 704 for (i=0; i<y; i++) { 705 if (n3 >= 0) { /* directly left */ 706 x_t = lx[n3 % m]; 707 /* y_t = y; */ 708 s_t = bases[n3] + (i+1)*x_t - s_x; 709 for (j=0; j<s_x; j++) idx[nn++] = s_t++; 710 } else if (xs-Xs > 0) { 711 if (bx == DM_BOUNDARY_MIRROR) { 712 for (j=0; j<s_x; j++) idx[nn++] = bases[rank] + x*i + s_x - j; 713 } else { 714 for (j=0; j<s_x; j++) idx[nn++] = -1; 715 } 716 } 717 718 for (j=0; j<x; j++) idx[nn++] = xbase++; /* interior */ 719 720 if (n5 >= 0) { /* directly right */ 721 x_t = lx[n5 % m]; 722 /* y_t = y; */ 723 s_t = bases[n5] + (i)*x_t; 724 for (j=0; j<s_x; j++) idx[nn++] = s_t++; 725 } else if (Xe-xe > 0) { 726 if (bx == DM_BOUNDARY_MIRROR) { 727 for (j=0; j<s_x; j++) idx[nn++] = bases[rank] + x*(i + 1) - 2 - j; 728 } else { 729 for (j=0; j<s_x; j++) idx[nn++] = -1; 730 } 731 } 732 } 733 734 for (i=1; i<=s_y; i++) { 735 if (n6 >= 0) { /* left above */ 736 x_t = lx[n6 % m]; 737 /* y_t = ly[(n6/m)]; */ 738 s_t = bases[n6] + (i)*x_t - s_x; 739 for (j=0; j<s_x; j++) idx[nn++] = s_t++; 740 } else if (xs-Xs > 0 && Ye-ye > 0) { 741 for (j=0; j<s_x; j++) idx[nn++] = -1; 742 } 743 if (n7 >= 0) { /* directly above */ 744 x_t = x; 745 /* y_t = ly[(n7/m)]; */ 746 s_t = bases[n7] + (i-1)*x_t; 747 for (j=0; j<x_t; j++) idx[nn++] = s_t++; 748 } else if (Ye-ye > 0) { 749 if (by == DM_BOUNDARY_MIRROR) { 750 for (j=0; j<x; j++) idx[nn++] = bases[rank] + x*(y - i - 1) + j; 751 } else { 752 for (j=0; j<x; j++) idx[nn++] = -1; 753 } 754 } 755 if (n8 >= 0) { /* right above */ 756 x_t = lx[n8 % m]; 757 /* y_t = ly[(n8/m)]; */ 758 s_t = bases[n8] + (i-1)*x_t; 759 for (j=0; j<s_x; j++) idx[nn++] = s_t++; 760 } else if (Xe-xe > 0 && Ye-ye > 0) { 761 for (j=0; j<s_x; j++) idx[nn++] = -1; 762 } 763 } 764 } 765 /* 766 Set the local to global ordering in the global vector, this allows use 767 of VecSetValuesLocal(). 768 */ 769 ierr = ISLocalToGlobalMappingCreate(comm,dof,nn,idx,PETSC_OWN_POINTER,&da->ltogmap);CHKERRQ(ierr); 770 ierr = PetscLogObjectParent((PetscObject)da,(PetscObject)da->ltogmap);CHKERRQ(ierr); 771 772 ierr = PetscFree2(bases,ldims);CHKERRQ(ierr); 773 dd->m = m; dd->n = n; 774 /* note petsc expects xs/xe/Xs/Xe to be multiplied by #dofs in many places */ 775 dd->xs = xs*dof; dd->xe = xe*dof; dd->ys = ys; dd->ye = ye; dd->zs = 0; dd->ze = 1; 776 dd->Xs = Xs*dof; dd->Xe = Xe*dof; dd->Ys = Ys; dd->Ye = Ye; dd->Zs = 0; dd->Ze = 1; 777 778 ierr = VecDestroy(&local);CHKERRQ(ierr); 779 ierr = VecDestroy(&global);CHKERRQ(ierr); 780 781 dd->gtol = gtol; 782 dd->base = base; 783 da->ops->view = DMView_DA_2d; 784 dd->ltol = NULL; 785 dd->ao = NULL; 786 PetscFunctionReturn(0); 787 } 788 789 #undef __FUNCT__ 790 #define __FUNCT__ "DMDACreate2d" 791 /*@C 792 DMDACreate2d - Creates an object that will manage the communication of two-dimensional 793 regular array data that is distributed across some processors. 794 795 Collective on MPI_Comm 796 797 Input Parameters: 798 + comm - MPI communicator 799 . bx,by - type of ghost nodes the array have. 800 Use one of DM_BOUNDARY_NONE, DM_BOUNDARY_GHOSTED, DM_BOUNDARY_PERIODIC. 801 . stencil_type - stencil type. Use either DMDA_STENCIL_BOX or DMDA_STENCIL_STAR. 802 . M,N - global dimension in each direction of the array 803 . m,n - corresponding number of processors in each dimension 804 (or PETSC_DECIDE to have calculated) 805 . dof - number of degrees of freedom per node 806 . s - stencil width 807 - lx, ly - arrays containing the number of nodes in each cell along 808 the x and y coordinates, or NULL. If non-null, these 809 must be of length as m and n, and the corresponding 810 m and n cannot be PETSC_DECIDE. The sum of the lx[] entries 811 must be M, and the sum of the ly[] entries must be N. 812 813 Output Parameter: 814 . da - the resulting distributed array object 815 816 Options Database Key: 817 + -dm_view - Calls DMView() at the conclusion of DMDACreate2d() 818 . -da_grid_x <nx> - number of grid points in x direction, if M < 0 819 . -da_grid_y <ny> - number of grid points in y direction, if N < 0 820 . -da_processors_x <nx> - number of processors in x direction 821 . -da_processors_y <ny> - number of processors in y direction 822 . -da_refine_x <rx> - refinement ratio in x direction 823 . -da_refine_y <ry> - refinement ratio in y direction 824 - -da_refine <n> - refine the DMDA n times before creating, if M or N < 0 825 826 827 Level: beginner 828 829 Notes: 830 The stencil type DMDA_STENCIL_STAR with width 1 corresponds to the 831 standard 5-pt stencil, while DMDA_STENCIL_BOX with width 1 denotes 832 the standard 9-pt stencil. 833 834 The array data itself is NOT stored in the DMDA, it is stored in Vec objects; 835 The appropriate vector objects can be obtained with calls to DMCreateGlobalVector() 836 and DMCreateLocalVector() and calls to VecDuplicate() if more are needed. 837 838 You must call DMSetUp() after this call before using this DM. 839 840 If you wish to use the options database to change values in the DMDA call DMSetFromOptions() after this call 841 but before DMSetUp(). 842 843 .keywords: distributed array, create, two-dimensional 844 845 .seealso: DMDestroy(), DMView(), DMDACreate1d(), DMDACreate3d(), DMGlobalToLocalBegin(), DMDAGetRefinementFactor(), 846 DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMLocalToLocalBegin(), DMLocalToLocalEnd(), DMDASetRefinementFactor(), 847 DMDAGetInfo(), DMCreateGlobalVector(), DMCreateLocalVector(), DMDACreateNaturalVector(), DMLoad(), DMDAGetOwnershipRanges() 848 849 @*/ 850 851 PetscErrorCode DMDACreate2d(MPI_Comm comm,DMBoundaryType bx,DMBoundaryType by,DMDAStencilType stencil_type, 852 PetscInt M,PetscInt N,PetscInt m,PetscInt n,PetscInt dof,PetscInt s,const PetscInt lx[],const PetscInt ly[],DM *da) 853 { 854 PetscErrorCode ierr; 855 856 PetscFunctionBegin; 857 ierr = DMDACreate(comm, da);CHKERRQ(ierr); 858 ierr = DMSetDimension(*da, 2);CHKERRQ(ierr); 859 ierr = DMDASetSizes(*da, M, N, 1);CHKERRQ(ierr); 860 ierr = DMDASetNumProcs(*da, m, n, PETSC_DECIDE);CHKERRQ(ierr); 861 ierr = DMDASetBoundaryType(*da, bx, by, DM_BOUNDARY_NONE);CHKERRQ(ierr); 862 ierr = DMDASetDof(*da, dof);CHKERRQ(ierr); 863 ierr = DMDASetStencilType(*da, stencil_type);CHKERRQ(ierr); 864 ierr = DMDASetStencilWidth(*da, s);CHKERRQ(ierr); 865 ierr = DMDASetOwnershipRanges(*da, lx, ly, NULL);CHKERRQ(ierr); 866 PetscFunctionReturn(0); 867 } 868