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