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 *has, H5O_type_t *otype) 871 { 872 hid_t h5; 873 htri_t exists; 874 PetscErrorCode ierr; 875 876 PetscFunctionBegin; 877 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 878 PetscValidCharPointer(name, 2); 879 PetscValidIntPointer(has, 3); 880 PetscValidIntPointer(otype, 4); 881 *has = PETSC_FALSE; 882 *otype = H5O_TYPE_UNKNOWN; 883 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 884 PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT)); 885 if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT)); 886 if (exists) { 887 H5O_info_t info; 888 hid_t obj; 889 890 *has = PETSC_TRUE; 891 PetscStackCallHDF5Return(obj,H5Oopen,(h5, name, H5P_DEFAULT)); 892 PetscStackCallHDF5(H5Oget_info,(obj, &info)); 893 *otype = info.type; 894 PetscStackCallHDF5(H5Oclose,(obj)); 895 } 896 PetscFunctionReturn(0); 897 } 898 899 /*@ 900 PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file 901 902 Input Parameters: 903 + viewer - The HDF5 viewer 904 - obj - The named object 905 906 Output Parameter: 907 . has - Flag for dataset existence; PETSC_FALSE for unnamed object 908 909 Level: advanced 910 911 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute() 912 @*/ 913 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) 914 { 915 H5O_type_t type; 916 PetscErrorCode ierr; 917 918 PetscFunctionBegin; 919 *has = PETSC_FALSE; 920 if (obj->name) { 921 ierr = PetscViewerHDF5HasObject_Internal(viewer, obj->name, has, &type);CHKERRQ(ierr); 922 *has = (type == H5O_TYPE_DATASET) ? PETSC_TRUE : PETSC_FALSE; 923 } 924 PetscFunctionReturn(0); 925 } 926 927 /*@C 928 PetscViewerHDF5HasAttribute - Check whether an attribute exists 929 930 Input Parameters: 931 + viewer - The HDF5 viewer 932 . parent - The parent name 933 - name - The attribute name 934 935 Output Parameter: 936 . has - Flag for attribute existence 937 938 Level: advanced 939 940 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasObject() 941 @*/ 942 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 943 { 944 hid_t h5, dataset; 945 htri_t hhas; 946 PetscBool exists; 947 H5O_type_t type; 948 PetscErrorCode ierr; 949 950 PetscFunctionBegin; 951 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 952 PetscValidPointer(parent, 2); 953 PetscValidPointer(name, 3); 954 PetscValidPointer(has, 4); 955 *has = PETSC_FALSE; 956 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 957 ierr = PetscViewerHDF5HasObject_Internal(viewer, parent, &exists, &type);CHKERRQ(ierr); 958 if (!exists || type != H5O_TYPE_DATASET) PetscFunctionReturn(0); 959 PetscStackCallHDF5Return(dataset, H5Dopen2, (h5, parent, H5P_DEFAULT)); 960 PetscStackCallHDF5Return(hhas, H5Aexists, (dataset, name)); 961 PetscStackCallHDF5(H5Dclose,(dataset)); 962 *has = hhas ? PETSC_TRUE : PETSC_FALSE; 963 PetscFunctionReturn(0); 964 } 965 966 static PetscErrorCode PetscViewerHDF5ReadInitialize_Private(PetscViewer viewer, const char name[], HDF5ReadCtx *ctx) 967 { 968 HDF5ReadCtx h=NULL; 969 const char *groupname=NULL; 970 char vecgroup[PETSC_MAX_PATH_LEN]; 971 PetscErrorCode ierr; 972 973 PetscFunctionBegin; 974 ierr = PetscNew(&h);CHKERRQ(ierr); 975 ierr = PetscViewerHDF5OpenGroup(viewer, &h->file, &h->group);CHKERRQ(ierr); 976 PetscStackCallHDF5Return(h->dataset,H5Dopen2,(h->group, name, H5P_DEFAULT)); 977 PetscStackCallHDF5Return(h->dataspace,H5Dget_space,(h->dataset)); 978 ierr = PetscViewerHDF5GetTimestep(viewer, &h->timestep);CHKERRQ(ierr); 979 ierr = PetscViewerHDF5GetGroup(viewer,&groupname);CHKERRQ(ierr); 980 ierr = PetscSNPrintf(vecgroup,PETSC_MAX_PATH_LEN,"%s/%s",groupname ? groupname : "",name);CHKERRQ(ierr); 981 ierr = PetscViewerHDF5HasAttribute(viewer,vecgroup,"complex",&h->complexVal);CHKERRQ(ierr); 982 /* MATLAB stores column vectors horizontally */ 983 ierr = PetscViewerHDF5HasAttribute(viewer,vecgroup,"MATLAB_class",&h->horizontal);CHKERRQ(ierr); 984 /* Create property list for collective dataset read */ 985 PetscStackCallHDF5Return(h->plist,H5Pcreate,(H5P_DATASET_XFER)); 986 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 987 PetscStackCallHDF5(H5Pset_dxpl_mpio,(h->plist, H5FD_MPIO_COLLECTIVE)); 988 #endif 989 /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */ 990 *ctx = h; 991 PetscFunctionReturn(0); 992 } 993 994 static PetscErrorCode PetscViewerHDF5ReadFinalize_Private(PetscViewer viewer, HDF5ReadCtx *ctx) 995 { 996 HDF5ReadCtx h; 997 PetscErrorCode ierr; 998 999 PetscFunctionBegin; 1000 h = *ctx; 1001 PetscStackCallHDF5(H5Pclose,(h->plist)); 1002 if (h->group != h->file) PetscStackCallHDF5(H5Gclose,(h->group)); 1003 PetscStackCallHDF5(H5Sclose,(h->dataspace)); 1004 PetscStackCallHDF5(H5Dclose,(h->dataset)); 1005 ierr = PetscFree(*ctx);CHKERRQ(ierr); 1006 PetscFunctionReturn(0); 1007 } 1008 1009 static PetscErrorCode PetscViewerHDF5ReadSizes_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout *map_) 1010 { 1011 int rdim, dim; 1012 hsize_t dims[4]; 1013 PetscInt bsInd, lenInd, bs, len, N; 1014 PetscLayout map; 1015 PetscErrorCode ierr; 1016 1017 PetscFunctionBegin; 1018 if (!(*map_)) { 1019 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)viewer),map_);CHKERRQ(ierr); 1020 } 1021 map = *map_; 1022 /* calculate expected number of dimensions */ 1023 dim = 0; 1024 if (ctx->timestep >= 0) ++dim; 1025 ++dim; /* length in blocks */ 1026 if (ctx->complexVal) ++dim; 1027 /* get actual number of dimensions in dataset */ 1028 PetscStackCallHDF5Return(rdim,H5Sget_simple_extent_dims,(ctx->dataspace, dims, NULL)); 1029 /* calculate expected dimension indices */ 1030 lenInd = 0; 1031 if (ctx->timestep >= 0) ++lenInd; 1032 bsInd = lenInd + 1; 1033 ctx->dim2 = PETSC_FALSE; 1034 if (rdim == dim) { 1035 bs = 1; /* support vectors stored as 1D array */ 1036 } else if (rdim == dim+1) { 1037 bs = (PetscInt) dims[bsInd]; 1038 if (bs == 1) ctx->dim2 = PETSC_TRUE; /* vector with blocksize of 1, still stored as 2D array */ 1039 } else { 1040 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Dimension of array in file %d not %d as expected", rdim, dim); 1041 } 1042 len = dims[lenInd]; 1043 if (ctx->horizontal) { 1044 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."); 1045 len = bs; 1046 bs = 1; 1047 } 1048 N = (PetscInt) len*bs; 1049 1050 /* Set Vec sizes,blocksize,and type if not already set */ 1051 if (map->bs < 0) { 1052 ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr); 1053 } 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); 1054 if (map->N < 0) { 1055 ierr = PetscLayoutSetSize(map, N);CHKERRQ(ierr); 1056 } 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); 1057 PetscFunctionReturn(0); 1058 } 1059 1060 static PetscErrorCode PetscViewerHDF5ReadSelectHyperslab_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout map, hid_t *memspace) 1061 { 1062 hsize_t count[4], offset[4]; 1063 int dim; 1064 PetscInt bs, n, low; 1065 PetscErrorCode ierr; 1066 1067 PetscFunctionBegin; 1068 /* Compute local size and ownership range */ 1069 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1070 ierr = PetscLayoutGetBlockSize(map, &bs);CHKERRQ(ierr); 1071 ierr = PetscLayoutGetLocalSize(map, &n);CHKERRQ(ierr); 1072 ierr = PetscLayoutGetRange(map, &low, NULL);CHKERRQ(ierr); 1073 1074 /* Each process defines a dataset and reads it from the hyperslab in the file */ 1075 dim = 0; 1076 if (ctx->timestep >= 0) { 1077 count[dim] = 1; 1078 offset[dim] = ctx->timestep; 1079 ++dim; 1080 } 1081 if (ctx->horizontal) { 1082 count[dim] = 1; 1083 offset[dim] = 0; 1084 ++dim; 1085 } 1086 { 1087 ierr = PetscHDF5IntCast(n/bs, &count[dim]);CHKERRQ(ierr); 1088 ierr = PetscHDF5IntCast(low/bs, &offset[dim]);CHKERRQ(ierr); 1089 ++dim; 1090 } 1091 if (bs > 1 || ctx->dim2) { 1092 if (PetscUnlikely(ctx->horizontal)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "cannot have horizontal array with blocksize > 1"); 1093 count[dim] = bs; 1094 offset[dim] = 0; 1095 ++dim; 1096 } 1097 if (ctx->complexVal) { 1098 count[dim] = 2; 1099 offset[dim] = 0; 1100 ++dim; 1101 } 1102 PetscStackCallHDF5Return(*memspace,H5Screate_simple,(dim, count, NULL)); 1103 PetscStackCallHDF5(H5Sselect_hyperslab,(ctx->dataspace, H5S_SELECT_SET, offset, NULL, count, NULL)); 1104 PetscFunctionReturn(0); 1105 } 1106 1107 static PetscErrorCode PetscViewerHDF5ReadArray_Private(PetscViewer viewer, HDF5ReadCtx h, hid_t datatype, hid_t memspace, void *arr) 1108 { 1109 PetscFunctionBegin; 1110 PetscStackCallHDF5(H5Dread,(h->dataset, datatype, memspace, h->dataspace, h->plist, arr)); 1111 PetscFunctionReturn(0); 1112 } 1113 1114 PetscErrorCode PetscViewerHDF5Load(PetscViewer viewer, const char *name, PetscLayout map, hid_t datatype, void **newarr) 1115 { 1116 HDF5ReadCtx h=NULL; 1117 hid_t memspace=0; 1118 size_t unitsize; 1119 void *arr; 1120 PetscErrorCode ierr; 1121 1122 PetscFunctionBegin; 1123 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1124 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1125 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1126 ierr = PetscViewerHDF5ReadSelectHyperslab_Private(viewer, h, map, &memspace);CHKERRQ(ierr); 1127 1128 #if defined(PETSC_USE_COMPLEX) 1129 if (!h->complexVal) { 1130 H5T_class_t clazz = H5Tget_class(datatype); 1131 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."); 1132 } 1133 #else 1134 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."); 1135 #endif 1136 unitsize = H5Tget_size(datatype); 1137 if (h->complexVal) unitsize *= 2; 1138 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); 1139 ierr = PetscMalloc(map->n*unitsize, &arr);CHKERRQ(ierr); 1140 1141 ierr = PetscViewerHDF5ReadArray_Private(viewer, h, datatype, memspace, arr);CHKERRQ(ierr); 1142 PetscStackCallHDF5(H5Sclose,(memspace)); 1143 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1144 *newarr = arr; 1145 PetscFunctionReturn(0); 1146 } 1147 1148 /*@C 1149 PetscViewerHDF5ReadSizes - Read block size and global size of a vector (Vec or IS) stored in an HDF5 file. 1150 1151 Input Parameters: 1152 + viewer - The HDF5 viewer 1153 - name - The vector name 1154 1155 Output Parameter: 1156 + bs - block size 1157 - N - global size 1158 1159 Note: 1160 A vector is stored as an HDF5 dataspace with 1-4 dimensions in this order: 1161 1) # timesteps (optional), 2) # blocks, 3) # elements per block (optional), 4) real and imaginary part (only for complex). 1162 1163 A vectors can be stored as a 2D dataspace even if its blocksize is 1; see PetscViewerHDF5SetBaseDimension2(). 1164 1165 Level: advanced 1166 1167 .seealso: PetscViewerHDF5Open(), VecLoad(), ISLoad(), VecGetSize(), ISGetSize(), PetscViewerHDF5SetBaseDimension2() 1168 @*/ 1169 PetscErrorCode PetscViewerHDF5ReadSizes(PetscViewer viewer, const char name[], PetscInt *bs, PetscInt *N) 1170 { 1171 HDF5ReadCtx h=NULL; 1172 PetscLayout map=NULL; 1173 PetscErrorCode ierr; 1174 1175 PetscFunctionBegin; 1176 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1177 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1178 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1179 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1180 if (bs) *bs = map->bs; 1181 if (N) *N = map->N; 1182 ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1183 PetscFunctionReturn(0); 1184 } 1185 1186 /* 1187 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that 1188 is attached to a communicator, in this case the attribute is a PetscViewer. 1189 */ 1190 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID; 1191 1192 /*@C 1193 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator. 1194 1195 Collective on MPI_Comm 1196 1197 Input Parameter: 1198 . comm - the MPI communicator to share the HDF5 PetscViewer 1199 1200 Level: intermediate 1201 1202 Options Database Keys: 1203 . -viewer_hdf5_filename <name> 1204 1205 Environmental variables: 1206 . PETSC_VIEWER_HDF5_FILENAME 1207 1208 Notes: 1209 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return 1210 an error code. The HDF5 PetscViewer is usually used in the form 1211 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm)); 1212 1213 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy() 1214 @*/ 1215 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) 1216 { 1217 PetscErrorCode ierr; 1218 PetscBool flg; 1219 PetscViewer viewer; 1220 char fname[PETSC_MAX_PATH_LEN]; 1221 MPI_Comm ncomm; 1222 1223 PetscFunctionBegin; 1224 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1225 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) { 1226 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,0); 1227 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1228 } 1229 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg); 1230 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1231 if (!flg) { /* PetscViewer not yet created */ 1232 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 1233 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1234 if (!flg) { 1235 ierr = PetscStrcpy(fname,"output.h5"); 1236 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1237 } 1238 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer); 1239 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1240 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 1241 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1242 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer); 1243 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1244 } 1245 ierr = PetscCommDestroy(&ncomm); 1246 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1247 PetscFunctionReturn(viewer); 1248 } 1249