1 2 /* 3 Plots vectors obtained with DMDACreate2d() 4 */ 5 6 #include <petsc/private/dmdaimpl.h> /*I "petscdmda.h" I*/ 7 #include <petsc/private/vecimpl.h> 8 #include <petscdraw.h> 9 #include <petscviewerhdf5.h> 10 11 /* 12 The data that is passed into the graphics callback 13 */ 14 typedef struct { 15 PetscMPIInt rank; 16 PetscInt m,n,dof,k; 17 PetscReal xmin,xmax,ymin,ymax,min,max; 18 const PetscScalar *xy,*v; 19 PetscBool showaxis,showgrid; 20 const char *name0,*name1; 21 } ZoomCtx; 22 23 /* 24 This does the drawing for one particular field 25 in one particular set of coordinates. It is a callback 26 called from PetscDrawZoom() 27 */ 28 #undef __FUNCT__ 29 #define __FUNCT__ "VecView_MPI_Draw_DA2d_Zoom" 30 PetscErrorCode VecView_MPI_Draw_DA2d_Zoom(PetscDraw draw,void *ctx) 31 { 32 ZoomCtx *zctx = (ZoomCtx*)ctx; 33 PetscErrorCode ierr; 34 PetscInt m,n,i,j,k,dof,id,c1,c2,c3,c4; 35 PetscReal min,max,x1,x2,x3,x4,y_1,y2,y3,y4; 36 const PetscScalar *xy,*v; 37 38 PetscFunctionBegin; 39 m = zctx->m; 40 n = zctx->n; 41 dof = zctx->dof; 42 k = zctx->k; 43 xy = zctx->xy; 44 v = zctx->v; 45 min = zctx->min; 46 max = zctx->max; 47 48 /* PetscDraw the contour plot patch */ 49 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 50 for (j=0; j<n-1; j++) { 51 for (i=0; i<m-1; i++) { 52 id = i+j*m; 53 x1 = PetscRealPart(xy[2*id]); 54 y_1 = PetscRealPart(xy[2*id+1]); 55 c1 = PetscDrawRealToColor(PetscRealPart(v[k+dof*id]),min,max); 56 57 id = i+j*m+1; 58 x2 = PetscRealPart(xy[2*id]); 59 y2 = PetscRealPart(xy[2*id+1]); 60 c2 = PetscDrawRealToColor(PetscRealPart(v[k+dof*id]),min,max); 61 62 id = i+j*m+1+m; 63 x3 = PetscRealPart(xy[2*id]); 64 y3 = PetscRealPart(xy[2*id+1]); 65 c3 = PetscDrawRealToColor(PetscRealPart(v[k+dof*id]),min,max); 66 67 id = i+j*m+m; 68 x4 = PetscRealPart(xy[2*id]); 69 y4 = PetscRealPart(xy[2*id+1]); 70 c4 = PetscDrawRealToColor(PetscRealPart(v[k+dof*id]),min,max); 71 72 ierr = PetscDrawTriangle(draw,x1,y_1,x2,y2,x3,y3,c1,c2,c3);CHKERRQ(ierr); 73 ierr = PetscDrawTriangle(draw,x1,y_1,x3,y3,x4,y4,c1,c3,c4);CHKERRQ(ierr); 74 if (zctx->showgrid) { 75 ierr = PetscDrawLine(draw,x1,y_1,x2,y2,PETSC_DRAW_BLACK);CHKERRQ(ierr); 76 ierr = PetscDrawLine(draw,x2,y2,x3,y3,PETSC_DRAW_BLACK);CHKERRQ(ierr); 77 ierr = PetscDrawLine(draw,x3,y3,x4,y4,PETSC_DRAW_BLACK);CHKERRQ(ierr); 78 ierr = PetscDrawLine(draw,x4,y4,x1,y_1,PETSC_DRAW_BLACK);CHKERRQ(ierr); 79 } 80 } 81 } 82 if (zctx->showaxis && !zctx->rank) { 83 if (zctx->name0 || zctx->name1) { 84 PetscReal xl,yl,xr,yr,x,y; 85 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 86 x = xl + .30*(xr - xl); 87 xl = xl + .01*(xr - xl); 88 y = yr - .30*(yr - yl); 89 yl = yl + .01*(yr - yl); 90 if (zctx->name0) {ierr = PetscDrawString(draw,x,yl,PETSC_DRAW_BLACK,zctx->name0);CHKERRQ(ierr);} 91 if (zctx->name1) {ierr = PetscDrawStringVertical(draw,xl,y,PETSC_DRAW_BLACK,zctx->name1);CHKERRQ(ierr);} 92 } 93 /* 94 Ideally we would use the PetscDrawAxis object to manage displaying the coordinate limits 95 but that may require some refactoring. 96 */ 97 { 98 double xmin = (double)zctx->xmin, ymin = (double)zctx->ymin; 99 double xmax = (double)zctx->xmax, ymax = (double)zctx->ymax; 100 char value[16]; size_t len; PetscReal w; 101 ierr = PetscSNPrintf(value,16,"%0.2e",xmin);CHKERRQ(ierr); 102 ierr = PetscDrawString(draw,xmin,ymin - .05*(ymax - ymin),PETSC_DRAW_BLACK,value);CHKERRQ(ierr); 103 ierr = PetscSNPrintf(value,16,"%0.2e",xmax);CHKERRQ(ierr); 104 ierr = PetscStrlen(value,&len);CHKERRQ(ierr); 105 ierr = PetscDrawStringGetSize(draw,&w,NULL);CHKERRQ(ierr); 106 ierr = PetscDrawString(draw,xmax - len*w,ymin - .05*(ymax - ymin),PETSC_DRAW_BLACK,value);CHKERRQ(ierr); 107 ierr = PetscSNPrintf(value,16,"%0.2e",ymin);CHKERRQ(ierr); 108 ierr = PetscDrawString(draw,xmin - .05*(xmax - xmin),ymin,PETSC_DRAW_BLACK,value);CHKERRQ(ierr); 109 ierr = PetscSNPrintf(value,16,"%0.2e",ymax);CHKERRQ(ierr); 110 ierr = PetscDrawString(draw,xmin - .05*(xmax - xmin),ymax,PETSC_DRAW_BLACK,value);CHKERRQ(ierr); 111 } 112 } 113 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 114 PetscFunctionReturn(0); 115 } 116 117 #undef __FUNCT__ 118 #define __FUNCT__ "VecView_MPI_Draw_DA2d" 119 PetscErrorCode VecView_MPI_Draw_DA2d(Vec xin,PetscViewer viewer) 120 { 121 DM da,dac,dag; 122 PetscErrorCode ierr; 123 PetscInt N,s,M,w,ncoors = 4; 124 const PetscInt *lx,*ly; 125 PetscReal coors[4]; 126 PetscDraw draw,popup; 127 PetscBool isnull,useports = PETSC_FALSE; 128 MPI_Comm comm; 129 Vec xlocal,xcoor,xcoorl; 130 DMBoundaryType bx,by; 131 DMDAStencilType st; 132 ZoomCtx zctx; 133 PetscDrawViewPorts *ports = NULL; 134 PetscViewerFormat format; 135 PetscInt *displayfields; 136 PetscInt ndisplayfields,i,nbounds; 137 const PetscReal *bounds; 138 139 PetscFunctionBegin; 140 zctx.showgrid = PETSC_FALSE; 141 zctx.showaxis = PETSC_TRUE; 142 143 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 144 ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 145 if (isnull) PetscFunctionReturn(0); 146 147 ierr = PetscViewerDrawGetBounds(viewer,&nbounds,&bounds);CHKERRQ(ierr); 148 149 ierr = VecGetDM(xin,&da);CHKERRQ(ierr); 150 if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA"); 151 152 ierr = PetscObjectGetComm((PetscObject)xin,&comm);CHKERRQ(ierr); 153 ierr = MPI_Comm_rank(comm,&zctx.rank);CHKERRQ(ierr); 154 155 ierr = DMDAGetInfo(da,0,&M,&N,0,&zctx.m,&zctx.n,0,&w,&s,&bx,&by,0,&st);CHKERRQ(ierr); 156 ierr = DMDAGetOwnershipRanges(da,&lx,&ly,NULL);CHKERRQ(ierr); 157 158 /* 159 Obtain a sequential vector that is going to contain the local values plus ONE layer of 160 ghosted values to draw the graphics from. We also need its corresponding DMDA (dac) that will 161 update the local values pluse ONE layer of ghost values. 162 */ 163 ierr = PetscObjectQuery((PetscObject)da,"GraphicsGhosted",(PetscObject*)&xlocal);CHKERRQ(ierr); 164 if (!xlocal) { 165 if (bx != DM_BOUNDARY_NONE || by != DM_BOUNDARY_NONE || s != 1 || st != DMDA_STENCIL_BOX) { 166 /* 167 if original da is not of stencil width one, or periodic or not a box stencil then 168 create a special DMDA to handle one level of ghost points for graphics 169 */ 170 ierr = DMDACreate2d(comm,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,w,1,lx,ly,&dac);CHKERRQ(ierr); 171 ierr = PetscInfo(da,"Creating auxilary DMDA for managing graphics ghost points\n");CHKERRQ(ierr); 172 } else { 173 /* otherwise we can use the da we already have */ 174 dac = da; 175 } 176 /* create local vector for holding ghosted values used in graphics */ 177 ierr = DMCreateLocalVector(dac,&xlocal);CHKERRQ(ierr); 178 if (dac != da) { 179 /* don't keep any public reference of this DMDA, is is only available through xlocal */ 180 ierr = PetscObjectDereference((PetscObject)dac);CHKERRQ(ierr); 181 } else { 182 /* remove association between xlocal and da, because below we compose in the opposite 183 direction and if we left this connect we'd get a loop, so the objects could 184 never be destroyed */ 185 ierr = PetscObjectRemoveReference((PetscObject)xlocal,"__PETSc_dm");CHKERRQ(ierr); 186 } 187 ierr = PetscObjectCompose((PetscObject)da,"GraphicsGhosted",(PetscObject)xlocal);CHKERRQ(ierr); 188 ierr = PetscObjectDereference((PetscObject)xlocal);CHKERRQ(ierr); 189 } else { 190 if (bx != DM_BOUNDARY_NONE || by != DM_BOUNDARY_NONE || s != 1 || st != DMDA_STENCIL_BOX) { 191 ierr = VecGetDM(xlocal, &dac);CHKERRQ(ierr); 192 } else { 193 dac = da; 194 } 195 } 196 197 /* 198 Get local (ghosted) values of vector 199 */ 200 ierr = DMGlobalToLocalBegin(dac,xin,INSERT_VALUES,xlocal);CHKERRQ(ierr); 201 ierr = DMGlobalToLocalEnd(dac,xin,INSERT_VALUES,xlocal);CHKERRQ(ierr); 202 ierr = VecGetArrayRead(xlocal,&zctx.v);CHKERRQ(ierr); 203 204 /* 205 Get coordinates of nodes 206 */ 207 ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr); 208 if (!xcoor) { 209 ierr = DMDASetUniformCoordinates(da,0.0,1.0,0.0,1.0,0.0,0.0);CHKERRQ(ierr); 210 ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr); 211 } 212 213 /* 214 Determine the min and max coordinates in plot 215 */ 216 ierr = VecStrideMin(xcoor,0,NULL,&zctx.xmin);CHKERRQ(ierr); 217 ierr = VecStrideMax(xcoor,0,NULL,&zctx.xmax);CHKERRQ(ierr); 218 ierr = VecStrideMin(xcoor,1,NULL,&zctx.ymin);CHKERRQ(ierr); 219 ierr = VecStrideMax(xcoor,1,NULL,&zctx.ymax);CHKERRQ(ierr); 220 ierr = PetscOptionsGetBool(NULL,NULL,"-draw_contour_axis",&zctx.showaxis,NULL);CHKERRQ(ierr); 221 if (zctx.showaxis) { 222 coors[0] = zctx.xmin - .05*(zctx.xmax - zctx.xmin); coors[1] = zctx.ymin - .05*(zctx.ymax - zctx.ymin); 223 coors[2] = zctx.xmax + .05*(zctx.xmax - zctx.xmin); coors[3] = zctx.ymax + .05*(zctx.ymax - zctx.ymin); 224 } else { 225 coors[0] = zctx.xmin; coors[1] = zctx.ymin; coors[2] = zctx.xmax; coors[3] = zctx.ymax; 226 } 227 ierr = PetscOptionsGetRealArray(NULL,NULL,"-draw_coordinates",coors,&ncoors,NULL);CHKERRQ(ierr); 228 ierr = PetscInfo4(da,"Preparing DMDA 2d contour plot coordinates %g %g %g %g\n",(double)coors[0],(double)coors[1],(double)coors[2],(double)coors[3]);CHKERRQ(ierr); 229 230 /* 231 Get local ghosted version of coordinates 232 */ 233 ierr = PetscObjectQuery((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject*)&xcoorl);CHKERRQ(ierr); 234 if (!xcoorl) { 235 /* create DMDA to get local version of graphics */ 236 ierr = DMDACreate2d(comm,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,2,1,lx,ly,&dag);CHKERRQ(ierr); 237 ierr = PetscInfo(dag,"Creating auxilary DMDA for managing graphics coordinates ghost points\n");CHKERRQ(ierr); 238 ierr = DMCreateLocalVector(dag,&xcoorl);CHKERRQ(ierr); 239 ierr = PetscObjectCompose((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject)xcoorl);CHKERRQ(ierr); 240 ierr = PetscObjectDereference((PetscObject)dag);CHKERRQ(ierr); 241 ierr = PetscObjectDereference((PetscObject)xcoorl);CHKERRQ(ierr); 242 } else { 243 ierr = VecGetDM(xcoorl,&dag);CHKERRQ(ierr); 244 } 245 ierr = DMGlobalToLocalBegin(dag,xcoor,INSERT_VALUES,xcoorl);CHKERRQ(ierr); 246 ierr = DMGlobalToLocalEnd(dag,xcoor,INSERT_VALUES,xcoorl);CHKERRQ(ierr); 247 ierr = VecGetArrayRead(xcoorl,&zctx.xy);CHKERRQ(ierr); 248 ierr = DMDAGetCoordinateName(da,0,&zctx.name0);CHKERRQ(ierr); 249 ierr = DMDAGetCoordinateName(da,1,&zctx.name1);CHKERRQ(ierr); 250 251 /* 252 Get information about size of area each processor must do graphics for 253 */ 254 ierr = DMDAGetInfo(dac,NULL,&M,&N,NULL,NULL,NULL,NULL,&zctx.dof,NULL,&bx,&by,NULL,NULL);CHKERRQ(ierr); 255 ierr = DMDAGetGhostCorners(dac,NULL,NULL,NULL,&zctx.m,&zctx.n,NULL);CHKERRQ(ierr); 256 ierr = PetscOptionsGetBool(NULL,NULL,"-draw_contour_grid",&zctx.showgrid,NULL);CHKERRQ(ierr); 257 258 ierr = DMDASelectFields(da,&ndisplayfields,&displayfields);CHKERRQ(ierr); 259 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 260 ierr = PetscOptionsGetBool(NULL,NULL,"-draw_ports",&useports,NULL);CHKERRQ(ierr); 261 if (format == PETSC_VIEWER_DRAW_PORTS) useports = PETSC_TRUE; 262 if (useports) { 263 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 264 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 265 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 266 ierr = PetscDrawViewPortsCreate(draw,ndisplayfields,&ports);CHKERRQ(ierr); 267 } 268 269 /* 270 Loop over each field; drawing each in a different window 271 */ 272 for (i=0; i<ndisplayfields; i++) { 273 zctx.k = displayfields[i]; 274 275 /* determine the min and max value in plot */ 276 ierr = VecStrideMin(xin,zctx.k,NULL,&zctx.min);CHKERRQ(ierr); 277 ierr = VecStrideMax(xin,zctx.k,NULL,&zctx.max);CHKERRQ(ierr); 278 if (zctx.k < nbounds) { 279 zctx.min = bounds[2*zctx.k]; 280 zctx.max = bounds[2*zctx.k+1]; 281 } 282 if (zctx.min == zctx.max) { 283 zctx.min -= 1.e-12; 284 zctx.max += 1.e-12; 285 } 286 ierr = PetscInfo2(da,"DMDA 2d contour plot min %g max %g\n",(double)zctx.min,(double)zctx.max);CHKERRQ(ierr); 287 288 if (useports) { 289 ierr = PetscDrawViewPortsSet(ports,i);CHKERRQ(ierr); 290 } else { 291 const char *title; 292 ierr = PetscViewerDrawGetDraw(viewer,i,&draw);CHKERRQ(ierr); 293 ierr = DMDAGetFieldName(da,zctx.k,&title);CHKERRQ(ierr); 294 if (title) {ierr = PetscDrawSetTitle(draw,title);CHKERRQ(ierr);} 295 } 296 297 ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr); 298 ierr = PetscDrawScalePopup(popup,zctx.min,zctx.max);CHKERRQ(ierr); 299 ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr); 300 ierr = PetscDrawZoom(draw,VecView_MPI_Draw_DA2d_Zoom,&zctx);CHKERRQ(ierr); 301 if (!useports) {ierr = PetscDrawSave(draw);CHKERRQ(ierr);} 302 } 303 if (useports) { 304 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 305 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 306 } 307 308 ierr = PetscDrawViewPortsDestroy(ports);CHKERRQ(ierr); 309 ierr = PetscFree(displayfields);CHKERRQ(ierr); 310 ierr = VecRestoreArrayRead(xcoorl,&zctx.xy);CHKERRQ(ierr); 311 ierr = VecRestoreArrayRead(xlocal,&zctx.v);CHKERRQ(ierr); 312 PetscFunctionReturn(0); 313 } 314 315 #if defined(PETSC_HAVE_HDF5) 316 #undef __FUNCT__ 317 #define __FUNCT__ "VecGetHDF5ChunkSize" 318 static PetscErrorCode VecGetHDF5ChunkSize(DM_DA *da, Vec xin, PetscInt dimension, PetscInt timestep, hsize_t *chunkDims) 319 { 320 PetscMPIInt comm_size; 321 PetscErrorCode ierr; 322 hsize_t chunk_size, target_size, dim; 323 hsize_t vec_size = sizeof(PetscScalar)*da->M*da->N*da->P*da->w; 324 hsize_t avg_local_vec_size,KiB = 1024,MiB = KiB*KiB,GiB = MiB*KiB,min_size = MiB; 325 hsize_t max_chunks = 64*KiB; /* HDF5 internal limitation */ 326 hsize_t max_chunk_size = 4*GiB; /* HDF5 internal limitation */ 327 PetscInt zslices=da->p, yslices=da->n, xslices=da->m; 328 329 PetscFunctionBegin; 330 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)xin), &comm_size);CHKERRQ(ierr); 331 avg_local_vec_size = (hsize_t) ceil(vec_size*1.0/comm_size); /* we will attempt to use this as the chunk size */ 332 333 target_size = (hsize_t) ceil(PetscMin(vec_size,PetscMin(max_chunk_size,PetscMax(avg_local_vec_size,PetscMax(ceil(vec_size*1.0/max_chunks),min_size))))); 334 /* following line uses sizeof(PetscReal) instead of sizeof(PetscScalar) because the last dimension of chunkDims[] captures the 2* when complex numbers are being used */ 335 chunk_size = (hsize_t) PetscMax(1,chunkDims[0])*PetscMax(1,chunkDims[1])*PetscMax(1,chunkDims[2])*PetscMax(1,chunkDims[3])*PetscMax(1,chunkDims[4])*PetscMax(1,chunkDims[5])*sizeof(PetscReal); 336 337 /* 338 if size/rank > max_chunk_size, we need radical measures: even going down to 339 avg_local_vec_size is not enough, so we simply use chunk size of 4 GiB no matter 340 what, composed in the most efficient way possible. 341 N.B. this minimises the number of chunks, which may or may not be the optimal 342 solution. In a BG, for example, the optimal solution is probably to make # chunks = # 343 IO nodes involved, but this author has no access to a BG to figure out how to 344 reliably find the right number. And even then it may or may not be enough. 345 */ 346 if (avg_local_vec_size > max_chunk_size) { 347 /* check if we can just split local z-axis: is that enough? */ 348 zslices = (PetscInt)ceil(vec_size*1.0/(da->p*max_chunk_size))*zslices; 349 if (zslices > da->P) { 350 /* lattice is too large in xy-directions, splitting z only is not enough */ 351 zslices = da->P; 352 yslices= (PetscInt)ceil(vec_size*1.0/(zslices*da->n*max_chunk_size))*yslices; 353 if (yslices > da->N) { 354 /* lattice is too large in x-direction, splitting along z, y is not enough */ 355 yslices = da->N; 356 xslices= (PetscInt)ceil(vec_size*1.0/(zslices*yslices*da->m*max_chunk_size))*xslices; 357 } 358 } 359 dim = 0; 360 if (timestep >= 0) { 361 ++dim; 362 } 363 /* prefer to split z-axis, even down to planar slices */ 364 if (dimension == 3) { 365 chunkDims[dim++] = (hsize_t) da->P/zslices; 366 chunkDims[dim++] = (hsize_t) da->N/yslices; 367 chunkDims[dim++] = (hsize_t) da->M/xslices; 368 } else { 369 /* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */ 370 chunkDims[dim++] = (hsize_t) da->N/yslices; 371 chunkDims[dim++] = (hsize_t) da->M/xslices; 372 } 373 chunk_size = (hsize_t) PetscMax(1,chunkDims[0])*PetscMax(1,chunkDims[1])*PetscMax(1,chunkDims[2])*PetscMax(1,chunkDims[3])*PetscMax(1,chunkDims[4])*PetscMax(1,chunkDims[5])*sizeof(double); 374 } else { 375 if (target_size < chunk_size) { 376 /* only change the defaults if target_size < chunk_size */ 377 dim = 0; 378 if (timestep >= 0) { 379 ++dim; 380 } 381 /* prefer to split z-axis, even down to planar slices */ 382 if (dimension == 3) { 383 /* try splitting the z-axis to core-size bits, i.e. divide chunk size by # comm_size in z-direction */ 384 if (target_size >= chunk_size/da->p) { 385 /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */ 386 chunkDims[dim] = (hsize_t) ceil(da->P*1.0/da->p); 387 } else { 388 /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be 389 radical and let everyone write all they've got */ 390 chunkDims[dim++] = (hsize_t) ceil(da->P*1.0/da->p); 391 chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n); 392 chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m); 393 } 394 } else { 395 /* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */ 396 if (target_size >= chunk_size/da->n) { 397 /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */ 398 chunkDims[dim] = (hsize_t) ceil(da->N*1.0/da->n); 399 } else { 400 /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be 401 radical and let everyone write all they've got */ 402 chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n); 403 chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m); 404 } 405 406 } 407 chunk_size = (hsize_t) PetscMax(1,chunkDims[0])*PetscMax(1,chunkDims[1])*PetscMax(1,chunkDims[2])*PetscMax(1,chunkDims[3])*PetscMax(1,chunkDims[4])*PetscMax(1,chunkDims[5])*sizeof(double); 408 } else { 409 /* precomputed chunks are fine, we don't need to do anything */ 410 } 411 } 412 PetscFunctionReturn(0); 413 } 414 #endif 415 416 #if defined(PETSC_HAVE_HDF5) 417 #undef __FUNCT__ 418 #define __FUNCT__ "VecView_MPI_HDF5_DA" 419 PetscErrorCode VecView_MPI_HDF5_DA(Vec xin,PetscViewer viewer) 420 { 421 DM dm; 422 DM_DA *da; 423 hid_t filespace; /* file dataspace identifier */ 424 hid_t chunkspace; /* chunk dataset property identifier */ 425 hid_t plist_id; /* property list identifier */ 426 hid_t dset_id; /* dataset identifier */ 427 hid_t memspace; /* memory dataspace identifier */ 428 hid_t file_id; 429 hid_t group; 430 hid_t memscalartype; /* scalar type for mem (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */ 431 hid_t filescalartype; /* scalar type for file (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */ 432 hsize_t dim; 433 hsize_t maxDims[6]={0}, dims[6]={0}, chunkDims[6]={0}, count[6]={0}, offset[6]={0}; /* we depend on these being sane later on */ 434 PetscInt timestep, dimension; 435 const PetscScalar *x; 436 const char *vecname; 437 PetscErrorCode ierr; 438 PetscBool dim2; 439 PetscBool spoutput; 440 441 PetscFunctionBegin; 442 ierr = PetscViewerHDF5OpenGroup(viewer, &file_id, &group);CHKERRQ(ierr); 443 ierr = PetscViewerHDF5GetTimestep(viewer, ×tep);CHKERRQ(ierr); 444 ierr = PetscViewerHDF5GetBaseDimension2(viewer,&dim2);CHKERRQ(ierr); 445 ierr = PetscViewerHDF5GetSPOutput(viewer,&spoutput);CHKERRQ(ierr); 446 447 ierr = VecGetDM(xin,&dm);CHKERRQ(ierr); 448 if (!dm) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA"); 449 da = (DM_DA*)dm->data; 450 ierr = DMGetDimension(dm, &dimension);CHKERRQ(ierr); 451 452 /* Create the dataspace for the dataset. 453 * 454 * dims - holds the current dimensions of the dataset 455 * 456 * maxDims - holds the maximum dimensions of the dataset (unlimited 457 * for the number of time steps with the current dimensions for the 458 * other dimensions; so only additional time steps can be added). 459 * 460 * chunkDims - holds the size of a single time step (required to 461 * permit extending dataset). 462 */ 463 dim = 0; 464 if (timestep >= 0) { 465 dims[dim] = timestep+1; 466 maxDims[dim] = H5S_UNLIMITED; 467 chunkDims[dim] = 1; 468 ++dim; 469 } 470 if (dimension == 3) { 471 ierr = PetscHDF5IntCast(da->P,dims+dim);CHKERRQ(ierr); 472 maxDims[dim] = dims[dim]; 473 chunkDims[dim] = dims[dim]; 474 ++dim; 475 } 476 if (dimension > 1) { 477 ierr = PetscHDF5IntCast(da->N,dims+dim);CHKERRQ(ierr); 478 maxDims[dim] = dims[dim]; 479 chunkDims[dim] = dims[dim]; 480 ++dim; 481 } 482 ierr = PetscHDF5IntCast(da->M,dims+dim);CHKERRQ(ierr); 483 maxDims[dim] = dims[dim]; 484 chunkDims[dim] = dims[dim]; 485 ++dim; 486 if (da->w > 1 || dim2) { 487 ierr = PetscHDF5IntCast(da->w,dims+dim);CHKERRQ(ierr); 488 maxDims[dim] = dims[dim]; 489 chunkDims[dim] = dims[dim]; 490 ++dim; 491 } 492 #if defined(PETSC_USE_COMPLEX) 493 dims[dim] = 2; 494 maxDims[dim] = dims[dim]; 495 chunkDims[dim] = dims[dim]; 496 ++dim; 497 #endif 498 499 ierr = VecGetHDF5ChunkSize(da, xin, dimension, timestep, chunkDims); CHKERRQ(ierr); 500 501 PetscStackCallHDF5Return(filespace,H5Screate_simple,(dim, dims, maxDims)); 502 503 #if defined(PETSC_USE_REAL_SINGLE) 504 memscalartype = H5T_NATIVE_FLOAT; 505 filescalartype = H5T_NATIVE_FLOAT; 506 #elif defined(PETSC_USE_REAL___FLOAT128) 507 #error "HDF5 output with 128 bit floats not supported." 508 #else 509 memscalartype = H5T_NATIVE_DOUBLE; 510 if (spoutput == PETSC_TRUE) filescalartype = H5T_NATIVE_FLOAT; 511 else filescalartype = H5T_NATIVE_DOUBLE; 512 #endif 513 514 /* Create the dataset with default properties and close filespace */ 515 ierr = PetscObjectGetName((PetscObject)xin,&vecname);CHKERRQ(ierr); 516 if (!H5Lexists(group, vecname, H5P_DEFAULT)) { 517 /* Create chunk */ 518 PetscStackCallHDF5Return(chunkspace,H5Pcreate,(H5P_DATASET_CREATE)); 519 PetscStackCallHDF5(H5Pset_chunk,(chunkspace, dim, chunkDims)); 520 521 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800) 522 PetscStackCallHDF5Return(dset_id,H5Dcreate2,(group, vecname, filescalartype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT)); 523 #else 524 PetscStackCallHDF5Return(dset_id,H5Dcreate,(group, vecname, filescalartype, filespace, H5P_DEFAULT)); 525 #endif 526 } else { 527 PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, vecname, H5P_DEFAULT)); 528 PetscStackCallHDF5(H5Dset_extent,(dset_id, dims)); 529 } 530 PetscStackCallHDF5(H5Sclose,(filespace)); 531 532 /* Each process defines a dataset and writes it to the hyperslab in the file */ 533 dim = 0; 534 if (timestep >= 0) { 535 offset[dim] = timestep; 536 ++dim; 537 } 538 if (dimension == 3) {ierr = PetscHDF5IntCast(da->zs,offset + dim++);CHKERRQ(ierr);} 539 if (dimension > 1) {ierr = PetscHDF5IntCast(da->ys,offset + dim++);CHKERRQ(ierr);} 540 ierr = PetscHDF5IntCast(da->xs/da->w,offset + dim++);CHKERRQ(ierr); 541 if (da->w > 1 || dim2) offset[dim++] = 0; 542 #if defined(PETSC_USE_COMPLEX) 543 offset[dim++] = 0; 544 #endif 545 dim = 0; 546 if (timestep >= 0) { 547 count[dim] = 1; 548 ++dim; 549 } 550 if (dimension == 3) {ierr = PetscHDF5IntCast(da->ze - da->zs,count + dim++);CHKERRQ(ierr);} 551 if (dimension > 1) {ierr = PetscHDF5IntCast(da->ye - da->ys,count + dim++);CHKERRQ(ierr);} 552 ierr = PetscHDF5IntCast((da->xe - da->xs)/da->w,count + dim++);CHKERRQ(ierr); 553 if (da->w > 1 || dim2) {ierr = PetscHDF5IntCast(da->w,count + dim++);CHKERRQ(ierr);} 554 #if defined(PETSC_USE_COMPLEX) 555 count[dim++] = 2; 556 #endif 557 PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL)); 558 PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id)); 559 PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL)); 560 561 /* Create property list for collective dataset write */ 562 PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_DATASET_XFER)); 563 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 564 PetscStackCallHDF5(H5Pset_dxpl_mpio,(plist_id, H5FD_MPIO_COLLECTIVE)); 565 #endif 566 /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */ 567 568 ierr = VecGetArrayRead(xin, &x);CHKERRQ(ierr); 569 PetscStackCallHDF5(H5Dwrite,(dset_id, memscalartype, memspace, filespace, plist_id, x)); 570 PetscStackCallHDF5(H5Fflush,(file_id, H5F_SCOPE_GLOBAL)); 571 ierr = VecRestoreArrayRead(xin, &x);CHKERRQ(ierr); 572 573 /* Close/release resources */ 574 if (group != file_id) { 575 PetscStackCallHDF5(H5Gclose,(group)); 576 } 577 PetscStackCallHDF5(H5Pclose,(plist_id)); 578 PetscStackCallHDF5(H5Sclose,(filespace)); 579 PetscStackCallHDF5(H5Sclose,(memspace)); 580 PetscStackCallHDF5(H5Dclose,(dset_id)); 581 ierr = PetscInfo1(xin,"Wrote Vec object with name %s\n",vecname);CHKERRQ(ierr); 582 PetscFunctionReturn(0); 583 } 584 #endif 585 586 extern PetscErrorCode VecView_MPI_Draw_DA1d(Vec,PetscViewer); 587 588 #if defined(PETSC_HAVE_MPIIO) 589 #undef __FUNCT__ 590 #define __FUNCT__ "DMDAArrayMPIIO" 591 static PetscErrorCode DMDAArrayMPIIO(DM da,PetscViewer viewer,Vec xin,PetscBool write) 592 { 593 PetscErrorCode ierr; 594 MPI_File mfdes; 595 PetscMPIInt gsizes[4],lsizes[4],lstarts[4],asiz,dof; 596 MPI_Datatype view; 597 const PetscScalar *array; 598 MPI_Offset off; 599 MPI_Aint ub,ul; 600 PetscInt type,rows,vecrows,tr[2]; 601 DM_DA *dd = (DM_DA*)da->data; 602 PetscBool skipheader; 603 604 PetscFunctionBegin; 605 ierr = VecGetSize(xin,&vecrows);CHKERRQ(ierr); 606 ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipheader);CHKERRQ(ierr); 607 if (!write) { 608 /* Read vector header. */ 609 if (!skipheader) { 610 ierr = PetscViewerBinaryRead(viewer,tr,2,NULL,PETSC_INT);CHKERRQ(ierr); 611 type = tr[0]; 612 rows = tr[1]; 613 if (type != VEC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Not vector next in file"); 614 if (rows != vecrows) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Vector in file not same size as DMDA vector"); 615 } 616 } else { 617 tr[0] = VEC_FILE_CLASSID; 618 tr[1] = vecrows; 619 if (!skipheader) { 620 ierr = PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 621 } 622 } 623 624 ierr = PetscMPIIntCast(dd->w,&dof);CHKERRQ(ierr); 625 gsizes[0] = dof; 626 ierr = PetscMPIIntCast(dd->M,gsizes+1);CHKERRQ(ierr); 627 ierr = PetscMPIIntCast(dd->N,gsizes+2);CHKERRQ(ierr); 628 ierr = PetscMPIIntCast(dd->P,gsizes+3);CHKERRQ(ierr); 629 lsizes[0] = dof; 630 ierr = PetscMPIIntCast((dd->xe-dd->xs)/dof,lsizes+1);CHKERRQ(ierr); 631 ierr = PetscMPIIntCast(dd->ye-dd->ys,lsizes+2);CHKERRQ(ierr); 632 ierr = PetscMPIIntCast(dd->ze-dd->zs,lsizes+3);CHKERRQ(ierr); 633 lstarts[0] = 0; 634 ierr = PetscMPIIntCast(dd->xs/dof,lstarts+1);CHKERRQ(ierr); 635 ierr = PetscMPIIntCast(dd->ys,lstarts+2);CHKERRQ(ierr); 636 ierr = PetscMPIIntCast(dd->zs,lstarts+3);CHKERRQ(ierr); 637 ierr = MPI_Type_create_subarray(da->dim+1,gsizes,lsizes,lstarts,MPI_ORDER_FORTRAN,MPIU_SCALAR,&view);CHKERRQ(ierr); 638 ierr = MPI_Type_commit(&view);CHKERRQ(ierr); 639 640 ierr = PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);CHKERRQ(ierr); 641 ierr = PetscViewerBinaryGetMPIIOOffset(viewer,&off);CHKERRQ(ierr); 642 ierr = MPI_File_set_view(mfdes,off,MPIU_SCALAR,view,(char*)"native",MPI_INFO_NULL);CHKERRQ(ierr); 643 ierr = VecGetArrayRead(xin,&array);CHKERRQ(ierr); 644 asiz = lsizes[1]*(lsizes[2] > 0 ? lsizes[2] : 1)*(lsizes[3] > 0 ? lsizes[3] : 1)*dof; 645 if (write) { 646 ierr = MPIU_File_write_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);CHKERRQ(ierr); 647 } else { 648 ierr = MPIU_File_read_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);CHKERRQ(ierr); 649 } 650 ierr = MPI_Type_get_extent(view,&ul,&ub);CHKERRQ(ierr); 651 ierr = PetscViewerBinaryAddMPIIOOffset(viewer,ub);CHKERRQ(ierr); 652 ierr = VecRestoreArrayRead(xin,&array);CHKERRQ(ierr); 653 ierr = MPI_Type_free(&view);CHKERRQ(ierr); 654 PetscFunctionReturn(0); 655 } 656 #endif 657 658 #undef __FUNCT__ 659 #define __FUNCT__ "VecView_MPI_DA" 660 PetscErrorCode VecView_MPI_DA(Vec xin,PetscViewer viewer) 661 { 662 DM da; 663 PetscErrorCode ierr; 664 PetscInt dim; 665 Vec natural; 666 PetscBool isdraw,isvtk; 667 #if defined(PETSC_HAVE_HDF5) 668 PetscBool ishdf5; 669 #endif 670 const char *prefix,*name; 671 PetscViewerFormat format; 672 673 PetscFunctionBegin; 674 ierr = VecGetDM(xin,&da);CHKERRQ(ierr); 675 if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA"); 676 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 677 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERVTK,&isvtk);CHKERRQ(ierr); 678 #if defined(PETSC_HAVE_HDF5) 679 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 680 #endif 681 if (isdraw) { 682 ierr = DMDAGetInfo(da,&dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); 683 if (dim == 1) { 684 ierr = VecView_MPI_Draw_DA1d(xin,viewer);CHKERRQ(ierr); 685 } else if (dim == 2) { 686 ierr = VecView_MPI_Draw_DA2d(xin,viewer);CHKERRQ(ierr); 687 } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot graphically view vector associated with this dimensional DMDA %D",dim); 688 } else if (isvtk) { /* Duplicate the Vec and hold a reference to the DM */ 689 Vec Y; 690 ierr = PetscObjectReference((PetscObject)da);CHKERRQ(ierr); 691 ierr = VecDuplicate(xin,&Y);CHKERRQ(ierr); 692 if (((PetscObject)xin)->name) { 693 /* If xin was named, copy the name over to Y. The duplicate names are safe because nobody else will ever see Y. */ 694 ierr = PetscObjectSetName((PetscObject)Y,((PetscObject)xin)->name);CHKERRQ(ierr); 695 } 696 ierr = VecCopy(xin,Y);CHKERRQ(ierr); 697 ierr = PetscViewerVTKAddField(viewer,(PetscObject)da,DMDAVTKWriteAll,PETSC_VTK_POINT_FIELD,(PetscObject)Y);CHKERRQ(ierr); 698 #if defined(PETSC_HAVE_HDF5) 699 } else if (ishdf5) { 700 ierr = VecView_MPI_HDF5_DA(xin,viewer);CHKERRQ(ierr); 701 #endif 702 } else { 703 #if defined(PETSC_HAVE_MPIIO) 704 PetscBool isbinary,isMPIIO; 705 706 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 707 if (isbinary) { 708 ierr = PetscViewerBinaryGetUseMPIIO(viewer,&isMPIIO);CHKERRQ(ierr); 709 if (isMPIIO) { 710 ierr = DMDAArrayMPIIO(da,viewer,xin,PETSC_TRUE);CHKERRQ(ierr); 711 PetscFunctionReturn(0); 712 } 713 } 714 #endif 715 716 /* call viewer on natural ordering */ 717 ierr = PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);CHKERRQ(ierr); 718 ierr = DMDACreateNaturalVector(da,&natural);CHKERRQ(ierr); 719 ierr = PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);CHKERRQ(ierr); 720 ierr = DMDAGlobalToNaturalBegin(da,xin,INSERT_VALUES,natural);CHKERRQ(ierr); 721 ierr = DMDAGlobalToNaturalEnd(da,xin,INSERT_VALUES,natural);CHKERRQ(ierr); 722 ierr = PetscObjectGetName((PetscObject)xin,&name);CHKERRQ(ierr); 723 ierr = PetscObjectSetName((PetscObject)natural,name);CHKERRQ(ierr); 724 725 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 726 if (format == PETSC_VIEWER_BINARY_MATLAB) { 727 /* temporarily remove viewer format so it won't trigger in the VecView() */ 728 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_DEFAULT);CHKERRQ(ierr); 729 } 730 731 ierr = VecView(natural,viewer);CHKERRQ(ierr); 732 733 if (format == PETSC_VIEWER_BINARY_MATLAB) { 734 MPI_Comm comm; 735 FILE *info; 736 const char *fieldname; 737 char fieldbuf[256]; 738 PetscInt dim,ni,nj,nk,pi,pj,pk,dof,n; 739 740 /* set the viewer format back into the viewer */ 741 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 742 ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 743 ierr = PetscViewerBinaryGetInfoPointer(viewer,&info);CHKERRQ(ierr); 744 ierr = DMDAGetInfo(da,&dim,&ni,&nj,&nk,&pi,&pj,&pk,&dof,0,0,0,0,0);CHKERRQ(ierr); 745 ierr = PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr); 746 ierr = PetscFPrintf(comm,info,"#$$ tmp = PetscBinaryRead(fd); \n");CHKERRQ(ierr); 747 if (dim == 1) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d);\n",dof,ni);CHKERRQ(ierr); } 748 if (dim == 2) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d);\n",dof,ni,nj);CHKERRQ(ierr); } 749 if (dim == 3) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d,%d);\n",dof,ni,nj,nk);CHKERRQ(ierr); } 750 751 for (n=0; n<dof; n++) { 752 ierr = DMDAGetFieldName(da,n,&fieldname);CHKERRQ(ierr); 753 if (!fieldname || !fieldname[0]) { 754 ierr = PetscSNPrintf(fieldbuf,sizeof fieldbuf,"field%D",n);CHKERRQ(ierr); 755 fieldname = fieldbuf; 756 } 757 if (dim == 1) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:))';\n",name,fieldname,n+1);CHKERRQ(ierr); } 758 if (dim == 2) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:,:))';\n",name,fieldname,n+1);CHKERRQ(ierr); } 759 if (dim == 3) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = permute(squeeze(tmp(%d,:,:,:)),[2 1 3]);\n",name,fieldname,n+1);CHKERRQ(ierr);} 760 } 761 ierr = PetscFPrintf(comm,info,"#$$ clear tmp; \n");CHKERRQ(ierr); 762 ierr = PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr); 763 } 764 765 ierr = VecDestroy(&natural);CHKERRQ(ierr); 766 } 767 PetscFunctionReturn(0); 768 } 769 770 #if defined(PETSC_HAVE_HDF5) 771 #undef __FUNCT__ 772 #define __FUNCT__ "VecLoad_HDF5_DA" 773 PetscErrorCode VecLoad_HDF5_DA(Vec xin, PetscViewer viewer) 774 { 775 DM da; 776 PetscErrorCode ierr; 777 hsize_t dim,rdim; 778 hsize_t dims[6]={0},count[6]={0},offset[6]={0}; 779 PetscInt dimension,timestep,dofInd; 780 PetscScalar *x; 781 const char *vecname; 782 hid_t filespace; /* file dataspace identifier */ 783 hid_t plist_id; /* property list identifier */ 784 hid_t dset_id; /* dataset identifier */ 785 hid_t memspace; /* memory dataspace identifier */ 786 hid_t file_id,group; 787 hid_t scalartype; /* scalar type (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */ 788 DM_DA *dd; 789 PetscBool dim2 = PETSC_FALSE; 790 791 PetscFunctionBegin; 792 #if defined(PETSC_USE_REAL_SINGLE) 793 scalartype = H5T_NATIVE_FLOAT; 794 #elif defined(PETSC_USE_REAL___FLOAT128) 795 #error "HDF5 output with 128 bit floats not supported." 796 #else 797 scalartype = H5T_NATIVE_DOUBLE; 798 #endif 799 800 ierr = PetscViewerHDF5OpenGroup(viewer, &file_id, &group);CHKERRQ(ierr); 801 ierr = PetscViewerHDF5GetTimestep(viewer, ×tep);CHKERRQ(ierr); 802 ierr = PetscObjectGetName((PetscObject)xin,&vecname);CHKERRQ(ierr); 803 ierr = VecGetDM(xin,&da);CHKERRQ(ierr); 804 dd = (DM_DA*)da->data; 805 ierr = DMGetDimension(da, &dimension);CHKERRQ(ierr); 806 807 /* Open dataset */ 808 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800) 809 PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, vecname, H5P_DEFAULT)); 810 #else 811 PetscStackCallHDF5Return(dset_id,H5Dopen,(group, vecname)); 812 #endif 813 814 /* Retrieve the dataspace for the dataset */ 815 PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id)); 816 PetscStackCallHDF5Return(rdim,H5Sget_simple_extent_dims,(filespace, dims, NULL)); 817 818 /* Expected dimension for holding the dof's */ 819 #if defined(PETSC_USE_COMPLEX) 820 dofInd = rdim-2; 821 #else 822 dofInd = rdim-1; 823 #endif 824 825 /* The expected number of dimensions, assuming basedimension2 = false */ 826 dim = dimension; 827 if (dd->w > 1) ++dim; 828 if (timestep >= 0) ++dim; 829 #if defined(PETSC_USE_COMPLEX) 830 ++dim; 831 #endif 832 833 /* In this case the input dataset have one extra, unexpected dimension. */ 834 if (rdim == dim+1) { 835 /* In this case the block size unity */ 836 if (dd->w == 1 && dims[dofInd] == 1) dim2 = PETSC_TRUE; 837 838 /* Special error message for the case where dof does not match the input file */ 839 else if (dd->w != (PetscInt) dims[dofInd]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Number of dofs in file is %D, not %D as expected",(PetscInt)dims[dofInd],dd->w); 840 841 /* Other cases where rdim != dim cannot be handled currently */ 842 } else if (rdim != dim) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Dimension of array in file is %d, not %d as expected with dof = %D",rdim,dim,dd->w); 843 844 /* Set up the hyperslab size */ 845 dim = 0; 846 if (timestep >= 0) { 847 offset[dim] = timestep; 848 count[dim] = 1; 849 ++dim; 850 } 851 if (dimension == 3) { 852 ierr = PetscHDF5IntCast(dd->zs,offset + dim);CHKERRQ(ierr); 853 ierr = PetscHDF5IntCast(dd->ze - dd->zs,count + dim);CHKERRQ(ierr); 854 ++dim; 855 } 856 if (dimension > 1) { 857 ierr = PetscHDF5IntCast(dd->ys,offset + dim);CHKERRQ(ierr); 858 ierr = PetscHDF5IntCast(dd->ye - dd->ys,count + dim);CHKERRQ(ierr); 859 ++dim; 860 } 861 ierr = PetscHDF5IntCast(dd->xs/dd->w,offset + dim);CHKERRQ(ierr); 862 ierr = PetscHDF5IntCast((dd->xe - dd->xs)/dd->w,count + dim);CHKERRQ(ierr); 863 ++dim; 864 if (dd->w > 1 || dim2) { 865 offset[dim] = 0; 866 ierr = PetscHDF5IntCast(dd->w,count + dim);CHKERRQ(ierr); 867 ++dim; 868 } 869 #if defined(PETSC_USE_COMPLEX) 870 offset[dim] = 0; 871 count[dim] = 2; 872 ++dim; 873 #endif 874 875 /* Create the memory and filespace */ 876 PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL)); 877 PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL)); 878 879 /* Create property list for collective dataset write */ 880 PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_DATASET_XFER)); 881 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 882 PetscStackCallHDF5(H5Pset_dxpl_mpio,(plist_id, H5FD_MPIO_COLLECTIVE)); 883 #endif 884 /* To read dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */ 885 886 ierr = VecGetArray(xin, &x);CHKERRQ(ierr); 887 PetscStackCallHDF5(H5Dread,(dset_id, scalartype, memspace, filespace, plist_id, x)); 888 ierr = VecRestoreArray(xin, &x);CHKERRQ(ierr); 889 890 /* Close/release resources */ 891 if (group != file_id) { 892 PetscStackCallHDF5(H5Gclose,(group)); 893 } 894 PetscStackCallHDF5(H5Pclose,(plist_id)); 895 PetscStackCallHDF5(H5Sclose,(filespace)); 896 PetscStackCallHDF5(H5Sclose,(memspace)); 897 PetscStackCallHDF5(H5Dclose,(dset_id)); 898 PetscFunctionReturn(0); 899 } 900 #endif 901 902 #undef __FUNCT__ 903 #define __FUNCT__ "VecLoad_Binary_DA" 904 PetscErrorCode VecLoad_Binary_DA(Vec xin, PetscViewer viewer) 905 { 906 DM da; 907 PetscErrorCode ierr; 908 Vec natural; 909 const char *prefix; 910 PetscInt bs; 911 PetscBool flag; 912 DM_DA *dd; 913 #if defined(PETSC_HAVE_MPIIO) 914 PetscBool isMPIIO; 915 #endif 916 917 PetscFunctionBegin; 918 ierr = VecGetDM(xin,&da);CHKERRQ(ierr); 919 dd = (DM_DA*)da->data; 920 #if defined(PETSC_HAVE_MPIIO) 921 ierr = PetscViewerBinaryGetUseMPIIO(viewer,&isMPIIO);CHKERRQ(ierr); 922 if (isMPIIO) { 923 ierr = DMDAArrayMPIIO(da,viewer,xin,PETSC_FALSE);CHKERRQ(ierr); 924 PetscFunctionReturn(0); 925 } 926 #endif 927 928 ierr = PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);CHKERRQ(ierr); 929 ierr = DMDACreateNaturalVector(da,&natural);CHKERRQ(ierr); 930 ierr = PetscObjectSetName((PetscObject)natural,((PetscObject)xin)->name);CHKERRQ(ierr); 931 ierr = PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);CHKERRQ(ierr); 932 ierr = VecLoad(natural,viewer);CHKERRQ(ierr); 933 ierr = DMDANaturalToGlobalBegin(da,natural,INSERT_VALUES,xin);CHKERRQ(ierr); 934 ierr = DMDANaturalToGlobalEnd(da,natural,INSERT_VALUES,xin);CHKERRQ(ierr); 935 ierr = VecDestroy(&natural);CHKERRQ(ierr); 936 ierr = PetscInfo(xin,"Loading vector from natural ordering into DMDA\n");CHKERRQ(ierr); 937 ierr = PetscOptionsGetInt(NULL,((PetscObject)xin)->prefix,"-vecload_block_size",&bs,&flag);CHKERRQ(ierr); 938 if (flag && bs != dd->w) { 939 ierr = PetscInfo2(xin,"Block size in file %D not equal to DMDA's dof %D\n",bs,dd->w);CHKERRQ(ierr); 940 } 941 PetscFunctionReturn(0); 942 } 943 944 #undef __FUNCT__ 945 #define __FUNCT__ "VecLoad_Default_DA" 946 PetscErrorCode VecLoad_Default_DA(Vec xin, PetscViewer viewer) 947 { 948 PetscErrorCode ierr; 949 DM da; 950 PetscBool isbinary; 951 #if defined(PETSC_HAVE_HDF5) 952 PetscBool ishdf5; 953 #endif 954 955 PetscFunctionBegin; 956 ierr = VecGetDM(xin,&da);CHKERRQ(ierr); 957 if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA"); 958 959 #if defined(PETSC_HAVE_HDF5) 960 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 961 #endif 962 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 963 964 if (isbinary) { 965 ierr = VecLoad_Binary_DA(xin,viewer);CHKERRQ(ierr); 966 #if defined(PETSC_HAVE_HDF5) 967 } else if (ishdf5) { 968 ierr = VecLoad_HDF5_DA(xin,viewer);CHKERRQ(ierr); 969 #endif 970 } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for vector loading", ((PetscObject)viewer)->type_name); 971 PetscFunctionReturn(0); 972 } 973