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