1 #include <petsc/private/viewerimpl.h> /*I "petscsys.h" I*/ 2 #include <petscviewerhdf5.h> /*I "petscviewerhdf5.h" I*/ 3 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE < 10800) 4 #error "PETSc needs HDF5 version >= 1.8.0" 5 #endif 6 7 typedef struct GroupList { 8 const char *name; 9 struct GroupList *next; 10 } GroupList; 11 12 typedef struct { 13 char *filename; 14 PetscFileMode btype; 15 hid_t file_id; 16 PetscInt timestep; 17 GroupList *groups; 18 PetscBool basedimension2; /* save vectors and DMDA vectors with a dimension of at least 2 even if the bs/dof is 1 */ 19 PetscBool spoutput; /* write data in single precision even if PETSc is compiled with double precision PetscReal */ 20 char *mataij_iname; 21 char *mataij_jname; 22 char *mataij_aname; 23 char *mataij_cname; 24 } PetscViewer_HDF5; 25 26 struct _n_HDF5ReadCtx { 27 hid_t file, group, dataset, dataspace, plist; 28 PetscInt timestep; 29 PetscBool complexVal, dim2, horizontal; 30 }; 31 typedef struct _n_HDF5ReadCtx* HDF5ReadCtx; 32 33 static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v) 34 { 35 PetscErrorCode ierr; 36 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data; 37 38 PetscFunctionBegin; 39 ierr = PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");CHKERRQ(ierr); 40 ierr = PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);CHKERRQ(ierr); 41 ierr = PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);CHKERRQ(ierr); 42 ierr = PetscOptionsTail();CHKERRQ(ierr); 43 PetscFunctionReturn(0); 44 } 45 46 static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer) 47 { 48 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data; 49 PetscErrorCode ierr; 50 51 PetscFunctionBegin; 52 ierr = PetscFree(hdf5->filename);CHKERRQ(ierr); 53 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 54 PetscFunctionReturn(0); 55 } 56 57 PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer) 58 { 59 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 60 PetscErrorCode ierr; 61 62 PetscFunctionBegin; 63 ierr = PetscViewerFileClose_HDF5(viewer);CHKERRQ(ierr); 64 while (hdf5->groups) { 65 GroupList *tmp = hdf5->groups->next; 66 67 ierr = PetscFree(hdf5->groups->name);CHKERRQ(ierr); 68 ierr = PetscFree(hdf5->groups);CHKERRQ(ierr); 69 hdf5->groups = tmp; 70 } 71 ierr = PetscFree(hdf5->mataij_iname);CHKERRQ(ierr); 72 ierr = PetscFree(hdf5->mataij_jname);CHKERRQ(ierr); 73 ierr = PetscFree(hdf5->mataij_aname);CHKERRQ(ierr); 74 ierr = PetscFree(hdf5->mataij_cname);CHKERRQ(ierr); 75 ierr = PetscFree(hdf5);CHKERRQ(ierr); 76 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr); 77 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr); 78 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr); 79 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetBaseDimension2_C",NULL);CHKERRQ(ierr); 80 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetSPOutput_C",NULL);CHKERRQ(ierr); 81 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetAIJNames_C",NULL);CHKERRQ(ierr); 82 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5GetAIJNames_C",NULL);CHKERRQ(ierr); 83 PetscFunctionReturn(0); 84 } 85 86 PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type) 87 { 88 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 89 90 PetscFunctionBegin; 91 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 92 hdf5->btype = type; 93 PetscFunctionReturn(0); 94 } 95 96 PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg) 97 { 98 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 99 100 PetscFunctionBegin; 101 hdf5->basedimension2 = flg; 102 PetscFunctionReturn(0); 103 } 104 105 /*@ 106 PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a 107 dimension of 2. 108 109 Logically Collective on PetscViewer 110 111 Input Parameters: 112 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored 113 - flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1 114 115 Options Database: 116 . -viewer_hdf5_base_dimension2 - turns on (true) or off (false) using a dimension of 2 in the HDF5 file even if the bs/dof of the vector is 1 117 118 119 Notes: 120 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof 121 of one when the dimension is lower. Others think the option is crazy. 122 123 Level: intermediate 124 125 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen() 126 127 @*/ 128 PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg) 129 { 130 PetscErrorCode ierr; 131 132 PetscFunctionBegin; 133 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 134 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr); 135 PetscFunctionReturn(0); 136 } 137 138 /*@ 139 PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a 140 dimension of 2. 141 142 Logically Collective on PetscViewer 143 144 Input Parameter: 145 . viewer - the PetscViewer, must be of type HDF5 146 147 Output Parameter: 148 . flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1 149 150 Notes: 151 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof 152 of one when the dimension is lower. Others think the option is crazy. 153 154 Level: intermediate 155 156 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen() 157 158 @*/ 159 PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg) 160 { 161 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 162 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 165 *flg = hdf5->basedimension2; 166 PetscFunctionReturn(0); 167 } 168 169 PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg) 170 { 171 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 172 173 PetscFunctionBegin; 174 hdf5->spoutput = flg; 175 PetscFunctionReturn(0); 176 } 177 178 /*@ 179 PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is 180 compiled with double precision PetscReal. 181 182 Logically Collective on PetscViewer 183 184 Input Parameters: 185 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored 186 - flg - if PETSC_TRUE the data will be written to disk with single precision 187 188 Options Database: 189 . -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision 190 191 192 Notes: 193 Setting this option does not make any difference if PETSc is compiled with single precision 194 in the first place. It does not affect reading datasets (HDF5 handle this internally). 195 196 Level: intermediate 197 198 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(), 199 PetscReal 200 201 @*/ 202 PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg) 203 { 204 PetscErrorCode ierr; 205 206 PetscFunctionBegin; 207 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 208 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr); 209 PetscFunctionReturn(0); 210 } 211 212 /*@ 213 PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is 214 compiled with double precision PetscReal. 215 216 Logically Collective on PetscViewer 217 218 Input Parameter: 219 . viewer - the PetscViewer, must be of type HDF5 220 221 Output Parameter: 222 . flg - if PETSC_TRUE the data will be written to disk with single precision 223 224 Notes: 225 Setting this option does not make any difference if PETSc is compiled with single precision 226 in the first place. It does not affect reading datasets (HDF5 handle this internally). 227 228 Level: intermediate 229 230 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(), 231 PetscReal 232 233 @*/ 234 PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg) 235 { 236 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 237 238 PetscFunctionBegin; 239 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 240 *flg = hdf5->spoutput; 241 PetscFunctionReturn(0); 242 } 243 244 PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[]) 245 { 246 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 247 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 248 MPI_Info info = MPI_INFO_NULL; 249 #endif 250 hid_t plist_id; 251 PetscErrorCode ierr; 252 253 PetscFunctionBegin; 254 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 255 if (hdf5->filename) {ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);} 256 ierr = PetscStrallocpy(name, &hdf5->filename);CHKERRQ(ierr); 257 /* Set up file access property list with parallel I/O access */ 258 PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS)); 259 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 260 PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), info)); 261 #endif 262 /* Create or open the file collectively */ 263 switch (hdf5->btype) { 264 case FILE_MODE_READ: 265 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id)); 266 break; 267 case FILE_MODE_APPEND: 268 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id)); 269 break; 270 case FILE_MODE_WRITE: 271 PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id)); 272 break; 273 default: 274 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 275 } 276 if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name); 277 PetscStackCallHDF5(H5Pclose,(plist_id)); 278 PetscFunctionReturn(0); 279 } 280 281 static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name) 282 { 283 PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data; 284 285 PetscFunctionBegin; 286 *name = vhdf5->filename; 287 PetscFunctionReturn(0); 288 } 289 290 PetscErrorCode PetscViewerHDF5SetAIJNames_HDF5(PetscViewer viewer, const char iname[], const char jname[], const char aname[], const char cname[]) 291 { 292 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 293 PetscErrorCode ierr; 294 295 PetscFunctionBegin; 296 ierr = PetscFree(hdf5->mataij_iname);CHKERRQ(ierr); 297 ierr = PetscFree(hdf5->mataij_jname);CHKERRQ(ierr); 298 ierr = PetscFree(hdf5->mataij_aname);CHKERRQ(ierr); 299 ierr = PetscFree(hdf5->mataij_cname);CHKERRQ(ierr); 300 ierr = PetscStrallocpy(iname,&hdf5->mataij_iname);CHKERRQ(ierr); 301 ierr = PetscStrallocpy(jname,&hdf5->mataij_jname);CHKERRQ(ierr); 302 ierr = PetscStrallocpy(aname,&hdf5->mataij_aname);CHKERRQ(ierr); 303 ierr = PetscStrallocpy(cname,&hdf5->mataij_cname);CHKERRQ(ierr); 304 PetscFunctionReturn(0); 305 } 306 307 /*@C 308 PetscViewerHDF5SetAIJNames - Set the names of the datasets representing the three AIJ (CRS) arrays and the name of the attribute storing the number of columns within the HDF5 file. 309 310 Collective on PetscViewer 311 312 Input Parameters: 313 + viewer - the PetscViewer; either ASCII or binary 314 . iname - name of dataset i representing row pointers; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 315 . jname - name of dataset j representing column indices 316 . aname - name of dataset a representing matrix values 317 - cname - name of attribute stoting column count 318 319 Level: advanced 320 321 Notes: 322 Current defaults are (iname, jname, aname, cname) = ("jc", "ir", "data", "MATLAB_sparse") so that MAT files can be readily loaded. 323 324 .seealso: MatLoad(), PetscViewerCreate(), PetscViewerSetType(), PETSCVIEWERHDF5, PetscViewerHDF5GetAIJNames() 325 @*/ 326 PetscErrorCode PetscViewerHDF5SetAIJNames(PetscViewer viewer, const char iname[], const char jname[], const char aname[], const char cname[]) 327 { 328 PetscErrorCode ierr; 329 330 PetscFunctionBegin; 331 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 332 PetscValidCharPointer(iname,2); 333 PetscValidCharPointer(jname,3); 334 PetscValidCharPointer(aname,4); 335 PetscValidCharPointer(cname,5); 336 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetAIJNames_C",(PetscViewer,const char[],const char[],const char[],const char[]),(viewer,iname,jname,aname,cname));CHKERRQ(ierr); 337 PetscFunctionReturn(0); 338 } 339 340 PetscErrorCode PetscViewerHDF5GetAIJNames_HDF5(PetscViewer viewer, const char *iname[], const char *jname[], const char *aname[], const char *cname[]) 341 { 342 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 343 344 PetscFunctionBegin; 345 *iname = hdf5->mataij_iname; 346 *jname = hdf5->mataij_jname; 347 *aname = hdf5->mataij_aname; 348 *cname = hdf5->mataij_cname; 349 PetscFunctionReturn(0); 350 } 351 352 /*@C 353 PetscViewerHDF5GetAIJNames - Get the names of the datasets representing the three AIJ (CRS) arrays and the name of the attribute storing the number of columns within the HDF5 file. 354 355 Collective on PetscViewer 356 357 Input Parameters: 358 . viewer - the PetscViewer; either ASCII or binary 359 360 Output Parameters: 361 + iname - name of dataset i representing row pointers; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 362 . jname - name of dataset j representing column indices 363 . aname - name of dataset a representing matrix values 364 - cname - name of attribute stoting column count 365 366 Level: advanced 367 368 Notes: 369 Current defaults are (iname, jname, aname, cname) = ("jc", "ir", "data", "MATLAB_sparse") so that MAT files can be readily loaded. 370 371 .seealso: MatLoad(), PetscViewerCreate(), PetscViewerSetType(), PETSCVIEWERHDF5, PetscViewerHDF5SetAIJNames() 372 @*/ 373 PetscErrorCode PetscViewerHDF5GetAIJNames(PetscViewer viewer, const char *iname[], const char *jname[], const char *aname[], const char *cname[]) 374 { 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 379 PetscValidPointer(iname,2); 380 PetscValidPointer(jname,3); 381 PetscValidPointer(aname,4); 382 PetscValidPointer(cname,5); 383 ierr = PetscUseMethod(viewer,"PetscViewerHDF5GetAIJNames_C",(PetscViewer,const char*[],const char*[],const char*[],const char*[]),(viewer,iname,jname,aname,cname));CHKERRQ(ierr); 384 PetscFunctionReturn(0); 385 } 386 387 /*MC 388 PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file 389 390 391 .seealso: PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET, 392 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING, 393 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, 394 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType() 395 396 Level: beginner 397 M*/ 398 399 PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v) 400 { 401 PetscViewer_HDF5 *hdf5; 402 PetscErrorCode ierr; 403 404 PetscFunctionBegin; 405 ierr = PetscNewLog(v,&hdf5);CHKERRQ(ierr); 406 407 v->data = (void*) hdf5; 408 v->ops->destroy = PetscViewerDestroy_HDF5; 409 v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5; 410 v->ops->flush = 0; 411 hdf5->btype = (PetscFileMode) -1; 412 hdf5->filename = 0; 413 hdf5->timestep = -1; 414 hdf5->groups = NULL; 415 416 /* ir and jc are deliberately swapped as MATLAB uses column-major format */ 417 ierr = PetscStrallocpy("jc", &hdf5->mataij_iname);CHKERRQ(ierr); 418 ierr = PetscStrallocpy("ir", &hdf5->mataij_jname);CHKERRQ(ierr); 419 ierr = PetscStrallocpy("data",&hdf5->mataij_aname);CHKERRQ(ierr); 420 ierr = PetscStrallocpy("MATLAB_sparse", &hdf5->mataij_cname);CHKERRQ(ierr); 421 422 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);CHKERRQ(ierr); 423 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);CHKERRQ(ierr); 424 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);CHKERRQ(ierr); 425 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);CHKERRQ(ierr); 426 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);CHKERRQ(ierr); 427 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetAIJNames_C",PetscViewerHDF5SetAIJNames_HDF5);CHKERRQ(ierr); 428 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5GetAIJNames_C",PetscViewerHDF5GetAIJNames_HDF5);CHKERRQ(ierr); 429 PetscFunctionReturn(0); 430 } 431 432 /*@C 433 PetscViewerHDF5Open - Opens a file for HDF5 input/output. 434 435 Collective on MPI_Comm 436 437 Input Parameters: 438 + comm - MPI communicator 439 . name - name of file 440 - type - type of file 441 $ FILE_MODE_WRITE - create new file for binary output 442 $ FILE_MODE_READ - open existing file for binary input 443 $ FILE_MODE_APPEND - open existing file for binary output 444 445 Output Parameter: 446 . hdf5v - PetscViewer for HDF5 input/output to use with the specified file 447 448 Options Database: 449 . -viewer_hdf5_base_dimension2 - turns on (true) or off (false) using a dimension of 2 in the HDF5 file even if the bs/dof of the vector is 1 450 . -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal 451 452 Level: beginner 453 454 Note: 455 This PetscViewer should be destroyed with PetscViewerDestroy(). 456 457 Concepts: HDF5 files 458 Concepts: PetscViewerHDF5^creating 459 460 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(), 461 PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(), 462 MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName() 463 @*/ 464 PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v) 465 { 466 PetscErrorCode ierr; 467 468 PetscFunctionBegin; 469 ierr = PetscViewerCreate(comm, hdf5v);CHKERRQ(ierr); 470 ierr = PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);CHKERRQ(ierr); 471 ierr = PetscViewerFileSetMode(*hdf5v, type);CHKERRQ(ierr); 472 ierr = PetscViewerFileSetName(*hdf5v, name);CHKERRQ(ierr); 473 PetscFunctionReturn(0); 474 } 475 476 /*@C 477 PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls 478 479 Not collective 480 481 Input Parameter: 482 . viewer - the PetscViewer 483 484 Output Parameter: 485 . file_id - The file id 486 487 Level: intermediate 488 489 .seealso: PetscViewerHDF5Open() 490 @*/ 491 PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id) 492 { 493 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 494 495 PetscFunctionBegin; 496 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 497 if (file_id) *file_id = hdf5->file_id; 498 PetscFunctionReturn(0); 499 } 500 501 /*@C 502 PetscViewerHDF5PushGroup - Set the current HDF5 group for output 503 504 Not collective 505 506 Input Parameters: 507 + viewer - the PetscViewer 508 - name - The group name 509 510 Level: intermediate 511 512 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup() 513 @*/ 514 PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char *name) 515 { 516 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 517 GroupList *groupNode; 518 PetscErrorCode ierr; 519 520 PetscFunctionBegin; 521 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 522 PetscValidCharPointer(name,2); 523 ierr = PetscNew(&groupNode);CHKERRQ(ierr); 524 ierr = PetscStrallocpy(name, (char**) &groupNode->name);CHKERRQ(ierr); 525 526 groupNode->next = hdf5->groups; 527 hdf5->groups = groupNode; 528 PetscFunctionReturn(0); 529 } 530 531 /*@ 532 PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value 533 534 Not collective 535 536 Input Parameter: 537 . viewer - the PetscViewer 538 539 Level: intermediate 540 541 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup() 542 @*/ 543 PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer) 544 { 545 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 546 GroupList *groupNode; 547 PetscErrorCode ierr; 548 549 PetscFunctionBegin; 550 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 551 if (!hdf5->groups) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop"); 552 groupNode = hdf5->groups; 553 hdf5->groups = hdf5->groups->next; 554 ierr = PetscFree(groupNode->name);CHKERRQ(ierr); 555 ierr = PetscFree(groupNode);CHKERRQ(ierr); 556 PetscFunctionReturn(0); 557 } 558 559 /*@C 560 PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with PetscViewerHDF5PushGroup()/PetscViewerHDF5PopGroup(). 561 If none has been assigned, returns NULL. 562 563 Not collective 564 565 Input Parameter: 566 . viewer - the PetscViewer 567 568 Output Parameter: 569 . name - The group name 570 571 Level: intermediate 572 573 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5OpenGroup() 574 @*/ 575 PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name) 576 { 577 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data; 578 579 PetscFunctionBegin; 580 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 581 PetscValidPointer(name,2); 582 if (hdf5->groups) *name = hdf5->groups->name; 583 else *name = NULL; 584 PetscFunctionReturn(0); 585 } 586 587 /*@ 588 PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by PetscViewerHDF5GetGroup(), 589 and return this group's ID and file ID. 590 If PetscViewerHDF5GetGroup() yields NULL, then group ID is file ID. 591 592 Not collective 593 594 Input Parameter: 595 . viewer - the PetscViewer 596 597 Output Parameter: 598 + fileId - The HDF5 file ID 599 - groupId - The HDF5 group ID 600 601 Level: intermediate 602 603 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 604 @*/ 605 PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId) 606 { 607 hid_t file_id, group; 608 htri_t found; 609 const char *groupName = NULL; 610 PetscErrorCode ierr; 611 612 PetscFunctionBegin; 613 ierr = PetscViewerHDF5GetFileId(viewer, &file_id);CHKERRQ(ierr); 614 ierr = PetscViewerHDF5GetGroup(viewer, &groupName);CHKERRQ(ierr); 615 /* Open group */ 616 if (groupName) { 617 PetscBool root; 618 619 ierr = PetscStrcmp(groupName, "/", &root);CHKERRQ(ierr); 620 PetscStackCall("H5Lexists",found = H5Lexists(file_id, groupName, H5P_DEFAULT)); 621 if (!root && (found <= 0)) { 622 PetscStackCallHDF5Return(group,H5Gcreate2,(file_id, groupName, 0, H5P_DEFAULT, H5P_DEFAULT)); 623 PetscStackCallHDF5(H5Gclose,(group)); 624 } 625 PetscStackCallHDF5Return(group,H5Gopen2,(file_id, groupName, H5P_DEFAULT)); 626 } else group = file_id; 627 628 *fileId = file_id; 629 *groupId = group; 630 PetscFunctionReturn(0); 631 } 632 633 /*@ 634 PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time. 635 636 Not collective 637 638 Input Parameter: 639 . viewer - the PetscViewer 640 641 Level: intermediate 642 643 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep() 644 @*/ 645 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) 646 { 647 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 648 649 PetscFunctionBegin; 650 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 651 ++hdf5->timestep; 652 PetscFunctionReturn(0); 653 } 654 655 /*@ 656 PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep 657 of -1 disables blocking with timesteps. 658 659 Not collective 660 661 Input Parameters: 662 + viewer - the PetscViewer 663 - timestep - The timestep number 664 665 Level: intermediate 666 667 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 668 @*/ 669 PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) 670 { 671 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 672 673 PetscFunctionBegin; 674 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 675 hdf5->timestep = timestep; 676 PetscFunctionReturn(0); 677 } 678 679 /*@ 680 PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time. 681 682 Not collective 683 684 Input Parameter: 685 . viewer - the PetscViewer 686 687 Output Parameter: 688 . timestep - The timestep number 689 690 Level: intermediate 691 692 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep() 693 @*/ 694 PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) 695 { 696 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 697 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 700 PetscValidPointer(timestep,2); 701 *timestep = hdf5->timestep; 702 PetscFunctionReturn(0); 703 } 704 705 /*@C 706 PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name. 707 708 Not collective 709 710 Input Parameter: 711 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 712 713 Output Parameter: 714 . mtype - the MPI datatype (for example MPI_DOUBLE, ...) 715 716 Level: advanced 717 718 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 719 @*/ 720 PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) 721 { 722 PetscFunctionBegin; 723 if (ptype == PETSC_INT) 724 #if defined(PETSC_USE_64BIT_INDICES) 725 *htype = H5T_NATIVE_LLONG; 726 #else 727 *htype = H5T_NATIVE_INT; 728 #endif 729 else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE; 730 else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG; 731 else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT; 732 else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_DOUBLE; 733 else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_DOUBLE; 734 else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT; 735 else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR; 736 else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR; 737 else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1); 738 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype"); 739 PetscFunctionReturn(0); 740 } 741 742 /*@C 743 PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name 744 745 Not collective 746 747 Input Parameter: 748 . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...) 749 750 Output Parameter: 751 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 752 753 Level: advanced 754 755 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 756 @*/ 757 PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) 758 { 759 PetscFunctionBegin; 760 #if defined(PETSC_USE_64BIT_INDICES) 761 if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG; 762 else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT; 763 #else 764 if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT; 765 #endif 766 else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE; 767 else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG; 768 else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT; 769 else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT; 770 else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR; 771 else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR; 772 else if (htype == H5T_C_S1) *ptype = PETSC_STRING; 773 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype"); 774 PetscFunctionReturn(0); 775 } 776 777 /*@C 778 PetscViewerHDF5WriteAttribute - Write an attribute 779 780 Input Parameters: 781 + viewer - The HDF5 viewer 782 . parent - The parent name 783 . name - The attribute name 784 . datatype - The attribute type 785 - value - The attribute value 786 787 Level: advanced 788 789 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute() 790 @*/ 791 PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value) 792 { 793 hid_t h5, dataspace, obj, attribute, dtype; 794 PetscBool has; 795 PetscErrorCode ierr; 796 797 PetscFunctionBegin; 798 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 799 PetscValidPointer(parent, 2); 800 PetscValidPointer(name, 3); 801 PetscValidPointer(value, 4); 802 803 ierr = PetscViewerHDF5HasAttribute(viewer, parent, name, &has);CHKERRQ(ierr); 804 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 805 if (datatype == PETSC_STRING) { 806 size_t len; 807 ierr = PetscStrlen((const char *) value, &len);CHKERRQ(ierr); 808 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 809 } 810 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 811 PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR)); 812 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 813 if (has) { 814 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 815 } else { 816 PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT)); 817 } 818 PetscStackCallHDF5(H5Awrite,(attribute, dtype, value)); 819 if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype)); 820 PetscStackCallHDF5(H5Aclose,(attribute)); 821 PetscStackCallHDF5(H5Oclose,(obj)); 822 PetscStackCallHDF5(H5Sclose,(dataspace)); 823 PetscFunctionReturn(0); 824 } 825 826 /*@C 827 PetscViewerHDF5ReadAttribute - Read an attribute 828 829 Input Parameters: 830 + viewer - The HDF5 viewer 831 . parent - The parent name 832 . name - The attribute name 833 - datatype - The attribute type 834 835 Output Parameter: 836 . value - The attribute value 837 838 Level: advanced 839 840 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute() 841 @*/ 842 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, void *value) 843 { 844 hid_t h5, obj, attribute, atype, dtype; 845 PetscErrorCode ierr; 846 847 PetscFunctionBegin; 848 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 849 PetscValidPointer(parent, 2); 850 PetscValidPointer(name, 3); 851 PetscValidPointer(value, 4); 852 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 853 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 854 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 855 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 856 if (datatype == PETSC_STRING) { 857 size_t len; 858 PetscStackCallHDF5Return(atype,H5Aget_type,(attribute)); 859 PetscStackCallHDF5Return(len,H5Tget_size,(atype)); 860 PetscStackCallHDF5(H5Tclose,(atype)); 861 ierr = PetscMalloc((len+1) * sizeof(char *), &value);CHKERRQ(ierr); 862 } 863 PetscStackCallHDF5(H5Aread,(attribute, dtype, value)); 864 PetscStackCallHDF5(H5Aclose,(attribute)); 865 /* H5Oclose can be used to close groups, datasets, or committed datatypes */ 866 PetscStackCallHDF5(H5Oclose,(obj)); 867 PetscFunctionReturn(0); 868 } 869 870 static PetscErrorCode PetscViewerHDF5HasObject_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype) 871 { 872 hid_t h5; 873 htri_t exists; 874 PetscInt i,n; 875 char **hierarchy; 876 char buf[PETSC_MAX_PATH_LEN]=""; 877 PetscErrorCode ierr; 878 879 PetscFunctionBegin; 880 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 881 PetscValidCharPointer(name, 2); 882 if (has) { 883 PetscValidIntPointer(has, 3); 884 *has = PETSC_FALSE; 885 } 886 if (otype) { 887 PetscValidIntPointer(otype, 4); 888 *otype = H5O_TYPE_UNKNOWN; 889 } 890 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 891 892 /* 893 Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing. 894 Hence, each of them needs to be tested separately: 895 1) whether it's a valid link 896 2) whether this link resolves to an object 897 See H5Oexists_by_name() documentation. 898 */ 899 ierr = PetscStrToArray(name,'/',&n,&hierarchy);CHKERRQ(ierr); 900 if (!n) { 901 /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */ 902 if (has) *has = PETSC_TRUE; 903 if (otype) *otype = H5O_TYPE_GROUP; 904 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 905 PetscFunctionReturn(0); 906 } 907 for (i=0; i<n; i++) { 908 ierr = PetscStrcat(buf,"/");CHKERRQ(ierr); 909 ierr = PetscStrcat(buf,hierarchy[i]);CHKERRQ(ierr); 910 PetscStackCallHDF5Return(exists,H5Lexists,(h5, buf, H5P_DEFAULT)); 911 if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, buf, H5P_DEFAULT)); 912 if (!exists) { 913 if (createGroup) { 914 hid_t group; 915 PetscStackCallHDF5Return(group,H5Gcreate2,(h5, buf, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)); 916 PetscStackCallHDF5(H5Gclose,(group)); 917 exists = PETSC_TRUE; 918 } else break; 919 } 920 } 921 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 922 923 /* If the object exists, get its type */ 924 if (exists && otype) { 925 H5O_info_t info; 926 927 PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT)); 928 *otype = info.type; 929 } 930 if (has) *has = exists; 931 PetscFunctionReturn(0); 932 } 933 934 /*@ 935 PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file 936 937 Input Parameters: 938 + viewer - The HDF5 viewer 939 - obj - The named object 940 941 Output Parameter: 942 . has - Flag for dataset existence; PETSC_FALSE for unnamed object 943 944 Level: advanced 945 946 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute() 947 @*/ 948 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) 949 { 950 H5O_type_t type; 951 PetscErrorCode ierr; 952 953 PetscFunctionBegin; 954 *has = PETSC_FALSE; 955 if (obj->name) { 956 ierr = PetscViewerHDF5HasObject_Internal(viewer, obj->name, PETSC_FALSE, has, &type);CHKERRQ(ierr); 957 *has = (type == H5O_TYPE_DATASET) ? PETSC_TRUE : PETSC_FALSE; 958 } 959 PetscFunctionReturn(0); 960 } 961 962 /*@C 963 PetscViewerHDF5HasAttribute - Check whether an attribute exists 964 965 Input Parameters: 966 + viewer - The HDF5 viewer 967 . parent - The parent name 968 - name - The attribute name 969 970 Output Parameter: 971 . has - Flag for attribute existence 972 973 Level: advanced 974 975 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasObject() 976 @*/ 977 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 978 { 979 hid_t h5, dataset; 980 htri_t hhas; 981 PetscBool exists; 982 H5O_type_t type; 983 PetscErrorCode ierr; 984 985 PetscFunctionBegin; 986 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 987 PetscValidPointer(parent, 2); 988 PetscValidPointer(name, 3); 989 PetscValidPointer(has, 4); 990 *has = PETSC_FALSE; 991 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 992 ierr = PetscViewerHDF5HasObject_Internal(viewer, parent, PETSC_FALSE, &exists, &type);CHKERRQ(ierr); 993 if (!exists || type != H5O_TYPE_DATASET) PetscFunctionReturn(0); 994 PetscStackCallHDF5Return(dataset, H5Dopen2, (h5, parent, H5P_DEFAULT)); 995 PetscStackCallHDF5Return(hhas, H5Aexists, (dataset, name)); 996 PetscStackCallHDF5(H5Dclose,(dataset)); 997 *has = hhas ? PETSC_TRUE : PETSC_FALSE; 998 PetscFunctionReturn(0); 999 } 1000 1001 static PetscErrorCode PetscViewerHDF5ReadInitialize_Private(PetscViewer viewer, const char name[], HDF5ReadCtx *ctx) 1002 { 1003 HDF5ReadCtx h=NULL; 1004 const char *groupname=NULL; 1005 char vecgroup[PETSC_MAX_PATH_LEN]; 1006 PetscErrorCode ierr; 1007 1008 PetscFunctionBegin; 1009 ierr = PetscNew(&h);CHKERRQ(ierr); 1010 ierr = PetscViewerHDF5OpenGroup(viewer, &h->file, &h->group);CHKERRQ(ierr); 1011 PetscStackCallHDF5Return(h->dataset,H5Dopen2,(h->group, name, H5P_DEFAULT)); 1012 PetscStackCallHDF5Return(h->dataspace,H5Dget_space,(h->dataset)); 1013 ierr = PetscViewerHDF5GetTimestep(viewer, &h->timestep);CHKERRQ(ierr); 1014 ierr = PetscViewerHDF5GetGroup(viewer,&groupname);CHKERRQ(ierr); 1015 ierr = PetscSNPrintf(vecgroup,PETSC_MAX_PATH_LEN,"%s/%s",groupname ? groupname : "",name);CHKERRQ(ierr); 1016 ierr = PetscViewerHDF5HasAttribute(viewer,vecgroup,"complex",&h->complexVal);CHKERRQ(ierr); 1017 /* MATLAB stores column vectors horizontally */ 1018 ierr = PetscViewerHDF5HasAttribute(viewer,vecgroup,"MATLAB_class",&h->horizontal);CHKERRQ(ierr); 1019 /* Create property list for collective dataset read */ 1020 PetscStackCallHDF5Return(h->plist,H5Pcreate,(H5P_DATASET_XFER)); 1021 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 1022 PetscStackCallHDF5(H5Pset_dxpl_mpio,(h->plist, H5FD_MPIO_COLLECTIVE)); 1023 #endif 1024 /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */ 1025 *ctx = h; 1026 PetscFunctionReturn(0); 1027 } 1028 1029 static PetscErrorCode PetscViewerHDF5ReadFinalize_Private(PetscViewer viewer, HDF5ReadCtx *ctx) 1030 { 1031 HDF5ReadCtx h; 1032 PetscErrorCode ierr; 1033 1034 PetscFunctionBegin; 1035 h = *ctx; 1036 PetscStackCallHDF5(H5Pclose,(h->plist)); 1037 if (h->group != h->file) PetscStackCallHDF5(H5Gclose,(h->group)); 1038 PetscStackCallHDF5(H5Sclose,(h->dataspace)); 1039 PetscStackCallHDF5(H5Dclose,(h->dataset)); 1040 ierr = PetscFree(*ctx);CHKERRQ(ierr); 1041 PetscFunctionReturn(0); 1042 } 1043 1044 static PetscErrorCode PetscViewerHDF5ReadSizes_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout *map_) 1045 { 1046 int rdim, dim; 1047 hsize_t dims[4]; 1048 PetscInt bsInd, lenInd, bs, len, N; 1049 PetscLayout map; 1050 PetscErrorCode ierr; 1051 1052 PetscFunctionBegin; 1053 if (!(*map_)) { 1054 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)viewer),map_);CHKERRQ(ierr); 1055 } 1056 map = *map_; 1057 /* calculate expected number of dimensions */ 1058 dim = 0; 1059 if (ctx->timestep >= 0) ++dim; 1060 ++dim; /* length in blocks */ 1061 if (ctx->complexVal) ++dim; 1062 /* get actual number of dimensions in dataset */ 1063 PetscStackCallHDF5Return(rdim,H5Sget_simple_extent_dims,(ctx->dataspace, dims, NULL)); 1064 /* calculate expected dimension indices */ 1065 lenInd = 0; 1066 if (ctx->timestep >= 0) ++lenInd; 1067 bsInd = lenInd + 1; 1068 ctx->dim2 = PETSC_FALSE; 1069 if (rdim == dim) { 1070 bs = 1; /* support vectors stored as 1D array */ 1071 } else if (rdim == dim+1) { 1072 bs = (PetscInt) dims[bsInd]; 1073 if (bs == 1) ctx->dim2 = PETSC_TRUE; /* vector with blocksize of 1, still stored as 2D array */ 1074 } else { 1075 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Dimension of array in file %d not %d as expected", rdim, dim); 1076 } 1077 len = dims[lenInd]; 1078 if (ctx->horizontal) { 1079 if (len != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot have horizontal array with number of rows > 1. In case of MATLAB MAT-file, vectors must be saved as column vectors."); 1080 len = bs; 1081 bs = 1; 1082 } 1083 N = (PetscInt) len*bs; 1084 1085 /* Set Vec sizes,blocksize,and type if not already set */ 1086 if (map->bs < 0) { 1087 ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr); 1088 } else if (map->bs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Block size of array in file is %D, not %D as expected",bs,map->bs); 1089 if (map->N < 0) { 1090 ierr = PetscLayoutSetSize(map, N);CHKERRQ(ierr); 1091 } else if (map->N != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Global size of array in file is %D, not %D as expected",N,map->N); 1092 PetscFunctionReturn(0); 1093 } 1094 1095 static PetscErrorCode PetscViewerHDF5ReadSelectHyperslab_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout map, hid_t *memspace) 1096 { 1097 hsize_t count[4], offset[4]; 1098 int dim; 1099 PetscInt bs, n, low; 1100 PetscErrorCode ierr; 1101 1102 PetscFunctionBegin; 1103 /* Compute local size and ownership range */ 1104 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1105 ierr = PetscLayoutGetBlockSize(map, &bs);CHKERRQ(ierr); 1106 ierr = PetscLayoutGetLocalSize(map, &n);CHKERRQ(ierr); 1107 ierr = PetscLayoutGetRange(map, &low, NULL);CHKERRQ(ierr); 1108 1109 /* Each process defines a dataset and reads it from the hyperslab in the file */ 1110 dim = 0; 1111 if (ctx->timestep >= 0) { 1112 count[dim] = 1; 1113 offset[dim] = ctx->timestep; 1114 ++dim; 1115 } 1116 if (ctx->horizontal) { 1117 count[dim] = 1; 1118 offset[dim] = 0; 1119 ++dim; 1120 } 1121 { 1122 ierr = PetscHDF5IntCast(n/bs, &count[dim]);CHKERRQ(ierr); 1123 ierr = PetscHDF5IntCast(low/bs, &offset[dim]);CHKERRQ(ierr); 1124 ++dim; 1125 } 1126 if (bs > 1 || ctx->dim2) { 1127 if (PetscUnlikely(ctx->horizontal)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "cannot have horizontal array with blocksize > 1"); 1128 count[dim] = bs; 1129 offset[dim] = 0; 1130 ++dim; 1131 } 1132 if (ctx->complexVal) { 1133 count[dim] = 2; 1134 offset[dim] = 0; 1135 ++dim; 1136 } 1137 PetscStackCallHDF5Return(*memspace,H5Screate_simple,(dim, count, NULL)); 1138 PetscStackCallHDF5(H5Sselect_hyperslab,(ctx->dataspace, H5S_SELECT_SET, offset, NULL, count, NULL)); 1139 PetscFunctionReturn(0); 1140 } 1141 1142 static PetscErrorCode PetscViewerHDF5ReadArray_Private(PetscViewer viewer, HDF5ReadCtx h, hid_t datatype, hid_t memspace, void *arr) 1143 { 1144 PetscFunctionBegin; 1145 PetscStackCallHDF5(H5Dread,(h->dataset, datatype, memspace, h->dataspace, h->plist, arr)); 1146 PetscFunctionReturn(0); 1147 } 1148 1149 PetscErrorCode PetscViewerHDF5Load(PetscViewer viewer, const char *name, PetscLayout map, hid_t datatype, void **newarr) 1150 { 1151 HDF5ReadCtx h=NULL; 1152 hid_t memspace=0; 1153 size_t unitsize; 1154 void *arr; 1155 PetscErrorCode ierr; 1156 1157 PetscFunctionBegin; 1158 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1159 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1160 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1161 ierr = PetscViewerHDF5ReadSelectHyperslab_Private(viewer, h, map, &memspace);CHKERRQ(ierr); 1162 1163 #if defined(PETSC_USE_COMPLEX) 1164 if (!h->complexVal) { 1165 H5T_class_t clazz = H5Tget_class(datatype); 1166 if (clazz == H5T_FLOAT) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"File contains real numbers but PETSc is configured for complex. The conversion is not yet implemented. Configure with --with-scalar-type=real."); 1167 } 1168 #else 1169 if (h->complexVal) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"File contains complex numbers but PETSc not configured for them. Configure with --with-scalar-type=complex."); 1170 #endif 1171 unitsize = H5Tget_size(datatype); 1172 if (h->complexVal) unitsize *= 2; 1173 if (unitsize <= 0 || unitsize > PetscMax(sizeof(PetscInt),sizeof(PetscScalar))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Sanity check failed: HDF5 function H5Tget_size(datatype) returned suspicious value %D",unitsize); 1174 ierr = PetscMalloc(map->n*unitsize, &arr);CHKERRQ(ierr); 1175 1176 ierr = PetscViewerHDF5ReadArray_Private(viewer, h, datatype, memspace, arr);CHKERRQ(ierr); 1177 PetscStackCallHDF5(H5Sclose,(memspace)); 1178 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1179 *newarr = arr; 1180 PetscFunctionReturn(0); 1181 } 1182 1183 /*@C 1184 PetscViewerHDF5ReadSizes - Read block size and global size of a vector (Vec or IS) stored in an HDF5 file. 1185 1186 Input Parameters: 1187 + viewer - The HDF5 viewer 1188 - name - The vector name 1189 1190 Output Parameter: 1191 + bs - block size 1192 - N - global size 1193 1194 Note: 1195 A vector is stored as an HDF5 dataspace with 1-4 dimensions in this order: 1196 1) # timesteps (optional), 2) # blocks, 3) # elements per block (optional), 4) real and imaginary part (only for complex). 1197 1198 A vectors can be stored as a 2D dataspace even if its blocksize is 1; see PetscViewerHDF5SetBaseDimension2(). 1199 1200 Level: advanced 1201 1202 .seealso: PetscViewerHDF5Open(), VecLoad(), ISLoad(), VecGetSize(), ISGetSize(), PetscViewerHDF5SetBaseDimension2() 1203 @*/ 1204 PetscErrorCode PetscViewerHDF5ReadSizes(PetscViewer viewer, const char name[], PetscInt *bs, PetscInt *N) 1205 { 1206 HDF5ReadCtx h=NULL; 1207 PetscLayout map=NULL; 1208 PetscErrorCode ierr; 1209 1210 PetscFunctionBegin; 1211 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1212 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1213 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1214 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1215 if (bs) *bs = map->bs; 1216 if (N) *N = map->N; 1217 ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1218 PetscFunctionReturn(0); 1219 } 1220 1221 /* 1222 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that 1223 is attached to a communicator, in this case the attribute is a PetscViewer. 1224 */ 1225 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID; 1226 1227 /*@C 1228 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator. 1229 1230 Collective on MPI_Comm 1231 1232 Input Parameter: 1233 . comm - the MPI communicator to share the HDF5 PetscViewer 1234 1235 Level: intermediate 1236 1237 Options Database Keys: 1238 . -viewer_hdf5_filename <name> 1239 1240 Environmental variables: 1241 . PETSC_VIEWER_HDF5_FILENAME 1242 1243 Notes: 1244 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return 1245 an error code. The HDF5 PetscViewer is usually used in the form 1246 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm)); 1247 1248 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy() 1249 @*/ 1250 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) 1251 { 1252 PetscErrorCode ierr; 1253 PetscBool flg; 1254 PetscViewer viewer; 1255 char fname[PETSC_MAX_PATH_LEN]; 1256 MPI_Comm ncomm; 1257 1258 PetscFunctionBegin; 1259 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1260 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) { 1261 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,0); 1262 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1263 } 1264 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg); 1265 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1266 if (!flg) { /* PetscViewer not yet created */ 1267 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 1268 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1269 if (!flg) { 1270 ierr = PetscStrcpy(fname,"output.h5"); 1271 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1272 } 1273 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer); 1274 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1275 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 1276 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1277 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer); 1278 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1279 } 1280 ierr = PetscCommDestroy(&ncomm); 1281 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1282 PetscFunctionReturn(viewer); 1283 } 1284