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