1 2 /* 3 Code for manipulating distributed regular arrays in parallel. 4 */ 5 6 #include <petsc-private/daimpl.h> /*I "petscdmda.h" I*/ 7 8 #undef __FUNCT__ 9 #define __FUNCT__ "DMCreateCoordinateDM_DA" 10 PetscErrorCode DMCreateCoordinateDM_DA(DM dm, DM *cdm) 11 { 12 DM_DA *da = (DM_DA *) dm->data; 13 PetscMPIInt size; 14 PetscErrorCode ierr; 15 16 PetscFunctionBegin; 17 ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 18 if (da->dim == 1) { 19 PetscInt s,m,*lc,l; 20 DMDABoundaryType bx; 21 22 ierr = DMDAGetInfo(dm,0,&m,0,0,0,0,0,0,&s,&bx,0,0,0);CHKERRQ(ierr); 23 ierr = DMDAGetCorners(dm,0,0,0,&l,0,0);CHKERRQ(ierr); 24 ierr = PetscMalloc(size * sizeof(PetscInt), &lc);CHKERRQ(ierr); 25 ierr = MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr); 26 ierr = DMDACreate1d(((PetscObject)dm)->comm,bx,m,1,s,lc,cdm);CHKERRQ(ierr); 27 ierr = PetscFree(lc);CHKERRQ(ierr); 28 } else if (da->dim == 2) { 29 PetscInt i,s,m,*lc,*ld,l,k,n,M,N; 30 DMDABoundaryType bx,by; 31 32 ierr = DMDAGetInfo(dm,0,&m,&n,0,&M,&N,0,0,&s,&bx,&by,0,0);CHKERRQ(ierr); 33 ierr = DMDAGetCorners(dm,0,0,0,&l,&k,0);CHKERRQ(ierr); 34 ierr = PetscMalloc2(size,PetscInt,&lc,size,PetscInt,&ld);CHKERRQ(ierr); 35 /* only first M values in lc matter */ 36 ierr = MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr); 37 /* every Mth value in ld matters */ 38 ierr = MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr); 39 for (i = 0; i < N; ++i) { 40 ld[i] = ld[M*i]; 41 } 42 if (bx == DMDA_BOUNDARY_MIRROR || by == DMDA_BOUNDARY_MIRROR) { 43 ierr = DMDACreate2d(((PetscObject)dm)->comm,bx,by,DMDA_STENCIL_STAR,m,n,M,N,2,s,lc,ld,cdm);CHKERRQ(ierr); 44 } else { 45 ierr = DMDACreate2d(((PetscObject)dm)->comm,bx,by,DMDA_STENCIL_BOX,m,n,M,N,2,s,lc,ld,cdm);CHKERRQ(ierr); 46 } 47 ierr = PetscFree2(lc,ld);CHKERRQ(ierr); 48 } else if (da->dim == 3) { 49 PetscInt i,s,m,*lc,*ld,*le,l,k,q,n,M,N,P,p; 50 DMDABoundaryType bx,by,bz; 51 52 ierr = DMDAGetInfo(dm,0,&m,&n,&p,&M,&N,&P,0,&s,&bx,&by,&bz,0);CHKERRQ(ierr); 53 ierr = DMDAGetCorners(dm,0,0,0,&l,&k,&q);CHKERRQ(ierr); 54 ierr = PetscMalloc3(size,PetscInt,&lc,size,PetscInt,&ld,size,PetscInt,&le);CHKERRQ(ierr); 55 /* only first M values in lc matter */ 56 ierr = MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr); 57 /* every Mth value in ld matters */ 58 ierr = MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr); 59 for (i = 0; i < N; ++i) { 60 ld[i] = ld[M*i]; 61 } 62 ierr = MPI_Allgather(&q,1,MPIU_INT,le,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr); 63 for (i = 0; i < P; ++i) { 64 le[i] = le[M*N*i]; 65 } 66 ierr = DMDACreate3d(((PetscObject)dm)->comm,bx,by,bz,DMDA_STENCIL_BOX,m,n,p,M,N,P,3,s,lc,ld,le,cdm);CHKERRQ(ierr); 67 ierr = PetscFree3(lc,ld,le);CHKERRQ(ierr); 68 } 69 PetscFunctionReturn(0); 70 } 71 72 #undef __FUNCT__ 73 #define __FUNCT__ "DMDASetFieldName" 74 /*@C 75 DMDASetFieldName - Sets the names of individual field components in multicomponent 76 vectors associated with a DMDA. 77 78 Not Collective 79 80 Input Parameters: 81 + da - the distributed array 82 . nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the 83 number of degrees of freedom per node within the DMDA 84 - names - the name of the field (component) 85 86 Level: intermediate 87 88 .keywords: distributed array, get, component name 89 90 .seealso: DMDAGetFieldName(), DMDASetCoordinateName(), DMDAGetCoordinateName() 91 @*/ 92 PetscErrorCode DMDASetFieldName(DM da,PetscInt nf,const char name[]) 93 { 94 PetscErrorCode ierr; 95 DM_DA *dd = (DM_DA*)da->data; 96 97 PetscFunctionBegin; 98 PetscValidHeaderSpecific(da,DM_CLASSID,1); 99 if (nf < 0 || nf >= dd->w) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf); 100 ierr = PetscFree(dd->fieldname[nf]);CHKERRQ(ierr); 101 ierr = PetscStrallocpy(name,&dd->fieldname[nf]);CHKERRQ(ierr); 102 PetscFunctionReturn(0); 103 } 104 105 #undef __FUNCT__ 106 #define __FUNCT__ "DMDAGetFieldName" 107 /*@C 108 DMDAGetFieldName - Gets the names of individual field components in multicomponent 109 vectors associated with a DMDA. 110 111 Not Collective 112 113 Input Parameter: 114 + da - the distributed array 115 - nf - field number for the DMDA (0, 1, ... dof-1), where dof indicates the 116 number of degrees of freedom per node within the DMDA 117 118 Output Parameter: 119 . names - the name of the field (component) 120 121 Level: intermediate 122 123 .keywords: distributed array, get, component name 124 125 .seealso: DMDASetFieldName(), DMDASetCoordinateName(), DMDAGetCoordinateName() 126 @*/ 127 PetscErrorCode DMDAGetFieldName(DM da,PetscInt nf,const char **name) 128 { 129 DM_DA *dd = (DM_DA*)da->data; 130 131 PetscFunctionBegin; 132 PetscValidHeaderSpecific(da,DM_CLASSID,1); 133 PetscValidPointer(name,3); 134 if (nf < 0 || nf >= dd->w) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf); 135 *name = dd->fieldname[nf]; 136 PetscFunctionReturn(0); 137 } 138 139 #undef __FUNCT__ 140 #define __FUNCT__ "DMDASetCoordinateName" 141 /*@C 142 DMDASetCoordinateName - Sets the name of the coordinate directions associated with a DMDA, for example "x" or "y" 143 144 Not Collective 145 146 Input Parameters: 147 + da - the distributed array 148 . nf - coordinate number for the DMDA (0, 1, ... dim-1), 149 - name - the name of the coordinate 150 151 Level: intermediate 152 153 .keywords: distributed array, get, component name 154 155 .seealso: DMDAGetCoordinateName(), DMDASetFieldName(), DMDAGetFieldName() 156 @*/ 157 PetscErrorCode DMDASetCoordinateName(DM da,PetscInt nf,const char name[]) 158 { 159 PetscErrorCode ierr; 160 DM_DA *dd = (DM_DA*)da->data; 161 162 PetscFunctionBegin; 163 PetscValidHeaderSpecific(da,DM_CLASSID,1); 164 if (nf < 0 || nf >= dd->dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid coordinate number: %D",nf); 165 ierr = PetscFree(dd->coordinatename[nf]);CHKERRQ(ierr); 166 ierr = PetscStrallocpy(name,&dd->coordinatename[nf]);CHKERRQ(ierr); 167 PetscFunctionReturn(0); 168 } 169 170 #undef __FUNCT__ 171 #define __FUNCT__ "DMDAGetCoordinateName" 172 /*@C 173 DMDAGetCoordinateName - Gets the name of a coodinate direction associated with a DMDA. 174 175 Not Collective 176 177 Input Parameter: 178 + da - the distributed array 179 - nf - number for the DMDA (0, 1, ... dim-1) 180 181 Output Parameter: 182 . names - the name of the coordinate direction 183 184 Level: intermediate 185 186 .keywords: distributed array, get, component name 187 188 .seealso: DMDASetCoordinateName(), DMDASetFieldName(), DMDAGetFieldName() 189 @*/ 190 PetscErrorCode DMDAGetCoordinateName(DM da,PetscInt nf,const char **name) 191 { 192 DM_DA *dd = (DM_DA*)da->data; 193 194 PetscFunctionBegin; 195 PetscValidHeaderSpecific(da,DM_CLASSID,1); 196 PetscValidPointer(name,3); 197 if (nf < 0 || nf >= dd->dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Invalid coordinate number: %D",nf); 198 *name = dd->coordinatename[nf]; 199 PetscFunctionReturn(0); 200 } 201 202 #undef __FUNCT__ 203 #define __FUNCT__ "DMDAGetCorners" 204 /*@ 205 DMDAGetCorners - Returns the global (x,y,z) indices of the lower left 206 corner of the local region, excluding ghost points. 207 208 Not Collective 209 210 Input Parameter: 211 . da - the distributed array 212 213 Output Parameters: 214 + x,y,z - the corner indices (where y and z are optional; these are used 215 for 2D and 3D problems) 216 - m,n,p - widths in the corresponding directions (where n and p are optional; 217 these are used for 2D and 3D problems) 218 219 Note: 220 The corner information is independent of the number of degrees of 221 freedom per node set with the DMDACreateXX() routine. Thus the x, y, z, and 222 m, n, p can be thought of as coordinates on a logical grid, where each 223 grid point has (potentially) several degrees of freedom. 224 Any of y, z, n, and p can be passed in as PETSC_NULL if not needed. 225 226 Level: beginner 227 228 .keywords: distributed array, get, corners, nodes, local indices 229 230 .seealso: DMDAGetGhostCorners(), DMDAGetOwnershipRanges() 231 @*/ 232 PetscErrorCode DMDAGetCorners(DM da,PetscInt *x,PetscInt *y,PetscInt *z,PetscInt *m,PetscInt *n,PetscInt *p) 233 { 234 PetscInt w; 235 DM_DA *dd = (DM_DA*)da->data; 236 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(da,DM_CLASSID,1); 239 /* since the xs, xe ... have all been multiplied by the number of degrees 240 of freedom per cell, w = dd->w, we divide that out before returning.*/ 241 w = dd->w; 242 if (x) *x = dd->xs/w + dd->xo; if (m) *m = (dd->xe - dd->xs)/w; 243 /* the y and z have NOT been multiplied by w */ 244 if (y) *y = dd->ys + dd->yo; if (n) *n = (dd->ye - dd->ys); 245 if (z) *z = dd->zs + dd->zo; if (p) *p = (dd->ze - dd->zs); 246 PetscFunctionReturn(0); 247 } 248 249 #undef __FUNCT__ 250 #define __FUNCT__ "DMDAGetLocalBoundingBox" 251 /*@ 252 DMDAGetLocalBoundingBox - Returns the local bounding box for the DMDA. 253 254 Not Collective 255 256 Input Parameter: 257 . da - the distributed array 258 259 Output Parameters: 260 + lmin - local minimum coordinates (length dim, optional) 261 - lmax - local maximim coordinates (length dim, optional) 262 263 Level: beginner 264 265 .keywords: distributed array, get, coordinates 266 267 .seealso: DMDAGetCoordinateDA(), DMGetCoordinates(), DMDAGetBoundingBox() 268 @*/ 269 PetscErrorCode DMDAGetLocalBoundingBox(DM da,PetscReal lmin[],PetscReal lmax[]) 270 { 271 PetscErrorCode ierr; 272 Vec coords = PETSC_NULL; 273 PetscInt dim,i,j; 274 const PetscScalar *local_coords; 275 PetscReal min[3]={PETSC_MAX_REAL,PETSC_MAX_REAL,PETSC_MAX_REAL},max[3]={PETSC_MIN_REAL,PETSC_MIN_REAL,PETSC_MIN_REAL}; 276 PetscInt N,Ni; 277 DM_DA *dd = (DM_DA*)da->data; 278 279 PetscFunctionBegin; 280 PetscValidHeaderSpecific(da,DM_CLASSID,1); 281 dim = dd->dim; 282 ierr = DMGetCoordinates(da,&coords);CHKERRQ(ierr); 283 if (coords) { 284 ierr = VecGetArrayRead(coords,&local_coords);CHKERRQ(ierr); 285 ierr = VecGetLocalSize(coords,&N);CHKERRQ(ierr); 286 Ni = N/dim; 287 for (i=0; i<Ni; i++) { 288 for (j=0; j<3; j++) { 289 min[j] = j < dim ? PetscMin(min[j],PetscRealPart(local_coords[i*dim+j])) : 0; 290 max[j] = j < dim ? PetscMax(max[j],PetscRealPart(local_coords[i*dim+j])) : 0; 291 } 292 } 293 ierr = VecRestoreArrayRead(coords,&local_coords);CHKERRQ(ierr); 294 } else { /* Just use grid indices */ 295 DMDALocalInfo info; 296 ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); 297 min[0] = info.xs; 298 min[1] = info.ys; 299 min[2] = info.zs; 300 max[0] = info.xs + info.xm-1; 301 max[1] = info.ys + info.ym-1; 302 max[2] = info.zs + info.zm-1; 303 } 304 if (lmin) {ierr = PetscMemcpy(lmin,min,dim*sizeof(PetscReal));CHKERRQ(ierr);} 305 if (lmax) {ierr = PetscMemcpy(lmax,max,dim*sizeof(PetscReal));CHKERRQ(ierr);} 306 PetscFunctionReturn(0); 307 } 308 309 #undef __FUNCT__ 310 #define __FUNCT__ "DMDAGetBoundingBox" 311 /*@ 312 DMDAGetBoundingBox - Returns the global bounding box for the DMDA. 313 314 Collective on DMDA 315 316 Input Parameter: 317 . da - the distributed array 318 319 Output Parameters: 320 + gmin - global minimum coordinates (length dim, optional) 321 - gmax - global maximim coordinates (length dim, optional) 322 323 Level: beginner 324 325 .keywords: distributed array, get, coordinates 326 327 .seealso: DMDAGetCoordinateDA(), DMGetCoordinates(), DMDAGetLocalBoundingBox() 328 @*/ 329 PetscErrorCode DMDAGetBoundingBox(DM da,PetscReal gmin[],PetscReal gmax[]) 330 { 331 PetscErrorCode ierr; 332 PetscMPIInt count; 333 PetscReal lmin[3],lmax[3]; 334 DM_DA *dd = (DM_DA*)da->data; 335 336 PetscFunctionBegin; 337 PetscValidHeaderSpecific(da,DM_CLASSID,1); 338 count = PetscMPIIntCast(dd->dim); 339 ierr = DMDAGetLocalBoundingBox(da,lmin,lmax);CHKERRQ(ierr); 340 if (gmin) {ierr = MPI_Allreduce(lmin,gmin,count,MPIU_REAL,MPIU_MIN,((PetscObject)da)->comm);CHKERRQ(ierr);} 341 if (gmax) {ierr = MPI_Allreduce(lmax,gmax,count,MPIU_REAL,MPIU_MAX,((PetscObject)da)->comm);CHKERRQ(ierr);} 342 PetscFunctionReturn(0); 343 } 344 345 #undef __FUNCT__ 346 #define __FUNCT__ "DMDAGetReducedDMDA" 347 /*@ 348 DMDAGetReducedDMDA - Gets the DMDA with the same layout but with fewer or more fields 349 350 Collective on DMDA 351 352 Input Parameter: 353 + da - the distributed array 354 . nfields - number of fields in new DMDA 355 356 Output Parameter: 357 . nda - the new DMDA 358 359 Level: intermediate 360 361 .keywords: distributed array, get, corners, nodes, local indices, coordinates 362 363 .seealso: DMDAGetGhostCorners(), DMSetCoordinates(), DMDASetUniformCoordinates(), DMGetCoordinates(), DMDAGetGhostedCoordinates() 364 @*/ 365 PetscErrorCode DMDAGetReducedDMDA(DM da,PetscInt nfields,DM *nda) 366 { 367 PetscErrorCode ierr; 368 DM_DA *dd = (DM_DA*)da->data; 369 PetscInt s,m,n,p,M,N,P,dim,Mo,No,Po; 370 const PetscInt *lx,*ly,*lz; 371 DMDABoundaryType bx,by,bz; 372 DMDAStencilType stencil_type; 373 PetscInt ox,oy,oz; 374 PetscInt cl,rl; 375 376 PetscFunctionBegin; 377 dim = dd->dim; 378 M = dd->M; 379 N = dd->N; 380 P = dd->P; 381 m = dd->m; 382 n = dd->n; 383 p = dd->p; 384 s = dd->s; 385 bx = dd->bx; 386 by = dd->by; 387 bz = dd->bz; 388 stencil_type = dd->stencil_type; 389 ierr = DMDAGetOwnershipRanges(da,&lx,&ly,&lz);CHKERRQ(ierr); 390 if (dim == 1) { 391 ierr = DMDACreate1d(((PetscObject)da)->comm,bx,M,nfields,s,dd->lx,nda);CHKERRQ(ierr); 392 } else if (dim == 2) { 393 ierr = DMDACreate2d(((PetscObject)da)->comm,bx,by,stencil_type,M,N,m,n,nfields,s,lx,ly,nda);CHKERRQ(ierr); 394 } else if (dim == 3) { 395 ierr = DMDACreate3d(((PetscObject)da)->comm,bx,by,bz,stencil_type,M,N,P,m,n,p,nfields,s,lx,ly,lz,nda);CHKERRQ(ierr); 396 } 397 if (da->coordinates) { 398 ierr = PetscObjectReference((PetscObject)da->coordinates);CHKERRQ(ierr); 399 (*nda)->coordinates = da->coordinates; 400 } 401 402 /* allow for getting a reduced DA corresponding to a domain decomposition */ 403 ierr = DMDAGetOffset(da,&ox,&oy,&oz,&Mo,&No,&Po);CHKERRQ(ierr); 404 ierr = DMDASetOffset(*nda,ox,oy,oz,Mo,No,Po);CHKERRQ(ierr); 405 406 /* allow for getting a reduced DA corresponding to a coarsened DA */ 407 ierr = DMGetCoarsenLevel(da,&cl);CHKERRQ(ierr); 408 ierr = DMGetRefineLevel(da,&rl);CHKERRQ(ierr); 409 (*nda)->levelup = rl; 410 (*nda)->leveldown = cl; 411 PetscFunctionReturn(0); 412 } 413 414