1 #include <petsc/private/viewerimpl.h> /*I "petscsys.h" I*/ 2 #include <petscviewerhdf5.h> /*I "petscviewerhdf5.h" I*/ 3 4 typedef struct GroupList { 5 const char *name; 6 struct GroupList *next; 7 } GroupList; 8 9 typedef struct { 10 char *filename; 11 PetscFileMode btype; 12 hid_t file_id; 13 PetscInt timestep; 14 GroupList *groups; 15 PetscBool basedimension2; /* save vectors and DMDA vectors with a dimension of at least 2 even if the bs/dof is 1 */ 16 PetscBool spoutput; /* write data in single precision even if PETSc is compiled with double precision PetscReal */ 17 } PetscViewer_HDF5; 18 19 static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v) 20 { 21 PetscErrorCode ierr; 22 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data; 23 24 PetscFunctionBegin; 25 ierr = PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");CHKERRQ(ierr); 26 ierr = PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);CHKERRQ(ierr); 27 ierr = PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);CHKERRQ(ierr); 28 ierr = PetscOptionsTail();CHKERRQ(ierr); 29 PetscFunctionReturn(0); 30 } 31 32 static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer) 33 { 34 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data; 35 PetscErrorCode ierr; 36 37 PetscFunctionBegin; 38 ierr = PetscFree(hdf5->filename);CHKERRQ(ierr); 39 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 40 PetscFunctionReturn(0); 41 } 42 43 PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer) 44 { 45 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 46 PetscErrorCode ierr; 47 48 PetscFunctionBegin; 49 ierr = PetscViewerFileClose_HDF5(viewer);CHKERRQ(ierr); 50 while (hdf5->groups) { 51 GroupList *tmp = hdf5->groups->next; 52 53 ierr = PetscFree(hdf5->groups->name);CHKERRQ(ierr); 54 ierr = PetscFree(hdf5->groups);CHKERRQ(ierr); 55 hdf5->groups = tmp; 56 } 57 ierr = PetscFree(hdf5);CHKERRQ(ierr); 58 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr); 59 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr); 60 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type) 65 { 66 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 67 68 PetscFunctionBegin; 69 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 70 hdf5->btype = type; 71 PetscFunctionReturn(0); 72 } 73 74 PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg) 75 { 76 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 77 78 PetscFunctionBegin; 79 hdf5->basedimension2 = flg; 80 PetscFunctionReturn(0); 81 } 82 83 /*@ 84 PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a 85 dimension of 2. 86 87 Logically Collective on PetscViewer 88 89 Input Parameters: 90 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored 91 - flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1 92 93 Options Database: 94 . -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 95 96 97 Notes: 98 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof 99 of one when the dimension is lower. Others think the option is crazy. 100 101 Level: intermediate 102 103 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen() 104 105 @*/ 106 PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg) 107 { 108 PetscErrorCode ierr; 109 110 PetscFunctionBegin; 111 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 112 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr); 113 PetscFunctionReturn(0); 114 } 115 116 /*@ 117 PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a 118 dimension of 2. 119 120 Logically Collective on PetscViewer 121 122 Input Parameter: 123 . viewer - the PetscViewer, must be of type HDF5 124 125 Output Parameter: 126 . flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1 127 128 Notes: 129 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof 130 of one when the dimension is lower. Others think the option is crazy. 131 132 Level: intermediate 133 134 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen() 135 136 @*/ 137 PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg) 138 { 139 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 140 141 PetscFunctionBegin; 142 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 143 *flg = hdf5->basedimension2; 144 PetscFunctionReturn(0); 145 } 146 147 PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg) 148 { 149 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 150 151 PetscFunctionBegin; 152 hdf5->spoutput = flg; 153 PetscFunctionReturn(0); 154 } 155 156 /*@ 157 PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is 158 compiled with double precision PetscReal. 159 160 Logically Collective on PetscViewer 161 162 Input Parameters: 163 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored 164 - flg - if PETSC_TRUE the data will be written to disk with single precision 165 166 Options Database: 167 . -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision 168 169 170 Notes: 171 Setting this option does not make any difference if PETSc is compiled with single precision 172 in the first place. It does not affect reading datasets (HDF5 handle this internally). 173 174 Level: intermediate 175 176 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(), 177 PetscReal 178 179 @*/ 180 PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg) 181 { 182 PetscErrorCode ierr; 183 184 PetscFunctionBegin; 185 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 186 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr); 187 PetscFunctionReturn(0); 188 } 189 190 /*@ 191 PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is 192 compiled with double precision PetscReal. 193 194 Logically Collective on PetscViewer 195 196 Input Parameter: 197 . viewer - the PetscViewer, must be of type HDF5 198 199 Output Parameter: 200 . flg - if PETSC_TRUE the data will be written to disk with single precision 201 202 Notes: 203 Setting this option does not make any difference if PETSc is compiled with single precision 204 in the first place. It does not affect reading datasets (HDF5 handle this internally). 205 206 Level: intermediate 207 208 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(), 209 PetscReal 210 211 @*/ 212 PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg) 213 { 214 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 215 216 PetscFunctionBegin; 217 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 218 *flg = hdf5->spoutput; 219 PetscFunctionReturn(0); 220 } 221 222 PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[]) 223 { 224 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 225 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 226 MPI_Info info = MPI_INFO_NULL; 227 #endif 228 hid_t plist_id; 229 PetscErrorCode ierr; 230 231 PetscFunctionBegin; 232 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 233 if (hdf5->filename) {ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);} 234 ierr = PetscStrallocpy(name, &hdf5->filename);CHKERRQ(ierr); 235 /* Set up file access property list with parallel I/O access */ 236 PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS)); 237 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 238 PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), info)); 239 #endif 240 /* Create or open the file collectively */ 241 switch (hdf5->btype) { 242 case FILE_MODE_READ: 243 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id)); 244 break; 245 case FILE_MODE_APPEND: 246 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id)); 247 break; 248 case FILE_MODE_WRITE: 249 PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id)); 250 break; 251 default: 252 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 253 } 254 if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name); 255 PetscStackCallHDF5(H5Pclose,(plist_id)); 256 PetscFunctionReturn(0); 257 } 258 259 static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name) 260 { 261 PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data; 262 263 PetscFunctionBegin; 264 *name = vhdf5->filename; 265 PetscFunctionReturn(0); 266 } 267 268 /*MC 269 PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file 270 271 272 .seealso: PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET, 273 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING, 274 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, 275 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType() 276 277 Level: beginner 278 M*/ 279 280 PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v) 281 { 282 PetscViewer_HDF5 *hdf5; 283 PetscErrorCode ierr; 284 285 PetscFunctionBegin; 286 ierr = PetscNewLog(v,&hdf5);CHKERRQ(ierr); 287 288 v->data = (void*) hdf5; 289 v->ops->destroy = PetscViewerDestroy_HDF5; 290 v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5; 291 v->ops->flush = 0; 292 hdf5->btype = (PetscFileMode) -1; 293 hdf5->filename = 0; 294 hdf5->timestep = -1; 295 hdf5->groups = NULL; 296 297 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);CHKERRQ(ierr); 298 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);CHKERRQ(ierr); 299 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);CHKERRQ(ierr); 300 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);CHKERRQ(ierr); 301 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);CHKERRQ(ierr); 302 PetscFunctionReturn(0); 303 } 304 305 /*@C 306 PetscViewerHDF5Open - Opens a file for HDF5 input/output. 307 308 Collective on MPI_Comm 309 310 Input Parameters: 311 + comm - MPI communicator 312 . name - name of file 313 - type - type of file 314 $ FILE_MODE_WRITE - create new file for binary output 315 $ FILE_MODE_READ - open existing file for binary input 316 $ FILE_MODE_APPEND - open existing file for binary output 317 318 Output Parameter: 319 . hdf5v - PetscViewer for HDF5 input/output to use with the specified file 320 321 Options Database: 322 . -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 323 . -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal 324 325 Level: beginner 326 327 Note: 328 This PetscViewer should be destroyed with PetscViewerDestroy(). 329 330 Concepts: HDF5 files 331 Concepts: PetscViewerHDF5^creating 332 333 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(), 334 PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(), 335 MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName() 336 @*/ 337 PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v) 338 { 339 PetscErrorCode ierr; 340 341 PetscFunctionBegin; 342 ierr = PetscViewerCreate(comm, hdf5v);CHKERRQ(ierr); 343 ierr = PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);CHKERRQ(ierr); 344 ierr = PetscViewerFileSetMode(*hdf5v, type);CHKERRQ(ierr); 345 ierr = PetscViewerFileSetName(*hdf5v, name);CHKERRQ(ierr); 346 PetscFunctionReturn(0); 347 } 348 349 /*@C 350 PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls 351 352 Not collective 353 354 Input Parameter: 355 . viewer - the PetscViewer 356 357 Output Parameter: 358 . file_id - The file id 359 360 Level: intermediate 361 362 .seealso: PetscViewerHDF5Open() 363 @*/ 364 PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id) 365 { 366 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 367 368 PetscFunctionBegin; 369 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 370 if (file_id) *file_id = hdf5->file_id; 371 PetscFunctionReturn(0); 372 } 373 374 /*@C 375 PetscViewerHDF5PushGroup - Set the current HDF5 group for output 376 377 Not collective 378 379 Input Parameters: 380 + viewer - the PetscViewer 381 - name - The group name 382 383 Level: intermediate 384 385 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 386 @*/ 387 PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char *name) 388 { 389 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 390 GroupList *groupNode; 391 PetscErrorCode ierr; 392 393 PetscFunctionBegin; 394 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 395 PetscValidCharPointer(name,2); 396 ierr = PetscNew(&groupNode);CHKERRQ(ierr); 397 ierr = PetscStrallocpy(name, (char**) &groupNode->name);CHKERRQ(ierr); 398 399 groupNode->next = hdf5->groups; 400 hdf5->groups = groupNode; 401 PetscFunctionReturn(0); 402 } 403 404 /*@ 405 PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value 406 407 Not collective 408 409 Input Parameter: 410 . viewer - the PetscViewer 411 412 Level: intermediate 413 414 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup() 415 @*/ 416 PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer) 417 { 418 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 419 GroupList *groupNode; 420 PetscErrorCode ierr; 421 422 PetscFunctionBegin; 423 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 424 if (!hdf5->groups) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop"); 425 groupNode = hdf5->groups; 426 hdf5->groups = hdf5->groups->next; 427 ierr = PetscFree(groupNode->name);CHKERRQ(ierr); 428 ierr = PetscFree(groupNode);CHKERRQ(ierr); 429 PetscFunctionReturn(0); 430 } 431 432 /*@C 433 PetscViewerHDF5GetGroup - Get the current HDF5 group for output. If none has been assigned, returns NULL. 434 435 Not collective 436 437 Input Parameter: 438 . viewer - the PetscViewer 439 440 Output Parameter: 441 . name - The group name 442 443 Level: intermediate 444 445 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup() 446 @*/ 447 PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name) 448 { 449 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data; 450 451 PetscFunctionBegin; 452 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 453 PetscValidPointer(name,2); 454 if (hdf5->groups) *name = hdf5->groups->name; 455 else *name = NULL; 456 PetscFunctionReturn(0); 457 } 458 459 PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId) 460 { 461 hid_t file_id, group; 462 htri_t found; 463 const char *groupName = NULL; 464 PetscErrorCode ierr; 465 466 PetscFunctionBegin; 467 ierr = PetscViewerHDF5GetFileId(viewer, &file_id);CHKERRQ(ierr); 468 ierr = PetscViewerHDF5GetGroup(viewer, &groupName);CHKERRQ(ierr); 469 /* Open group */ 470 if (groupName) { 471 PetscBool root; 472 473 ierr = PetscStrcmp(groupName, "/", &root);CHKERRQ(ierr); 474 PetscStackCall("H5Lexists",found = H5Lexists(file_id, groupName, H5P_DEFAULT)); 475 if (!root && (found <= 0)) { 476 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800) 477 PetscStackCallHDF5Return(group,H5Gcreate2,(file_id, groupName, 0, H5P_DEFAULT, H5P_DEFAULT)); 478 #else /* deprecated HDF5 1.6 API */ 479 PetscStackCallHDF5Return(group,H5Gcreate,(file_id, groupName, 0)); 480 #endif 481 PetscStackCallHDF5(H5Gclose,(group)); 482 } 483 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800) 484 PetscStackCallHDF5Return(group,H5Gopen2,(file_id, groupName, H5P_DEFAULT)); 485 #else 486 PetscStackCallHDF5Return(group,H5Gopen,(file_id, groupName)); 487 #endif 488 } else group = file_id; 489 490 *fileId = file_id; 491 *groupId = group; 492 PetscFunctionReturn(0); 493 } 494 495 /*@ 496 PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time. 497 498 Not collective 499 500 Input Parameter: 501 . viewer - the PetscViewer 502 503 Level: intermediate 504 505 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep() 506 @*/ 507 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) 508 { 509 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 510 511 PetscFunctionBegin; 512 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 513 ++hdf5->timestep; 514 PetscFunctionReturn(0); 515 } 516 517 /*@ 518 PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep 519 of -1 disables blocking with timesteps. 520 521 Not collective 522 523 Input Parameters: 524 + viewer - the PetscViewer 525 - timestep - The timestep number 526 527 Level: intermediate 528 529 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 530 @*/ 531 PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) 532 { 533 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 534 535 PetscFunctionBegin; 536 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 537 hdf5->timestep = timestep; 538 PetscFunctionReturn(0); 539 } 540 541 /*@ 542 PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time. 543 544 Not collective 545 546 Input Parameter: 547 . viewer - the PetscViewer 548 549 Output Parameter: 550 . timestep - The timestep number 551 552 Level: intermediate 553 554 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep() 555 @*/ 556 PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) 557 { 558 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 559 560 PetscFunctionBegin; 561 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 562 PetscValidPointer(timestep,2); 563 *timestep = hdf5->timestep; 564 PetscFunctionReturn(0); 565 } 566 567 /*@C 568 PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name. 569 570 Not collective 571 572 Input Parameter: 573 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 574 575 Output Parameter: 576 . mtype - the MPI datatype (for example MPI_DOUBLE, ...) 577 578 Level: advanced 579 580 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 581 @*/ 582 PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) 583 { 584 PetscFunctionBegin; 585 if (ptype == PETSC_INT) 586 #if defined(PETSC_USE_64BIT_INDICES) 587 *htype = H5T_NATIVE_LLONG; 588 #else 589 *htype = H5T_NATIVE_INT; 590 #endif 591 else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE; 592 else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG; 593 else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT; 594 else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_DOUBLE; 595 else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_DOUBLE; 596 else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT; 597 else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR; 598 else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR; 599 else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1); 600 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype"); 601 PetscFunctionReturn(0); 602 } 603 604 /*@C 605 PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name 606 607 Not collective 608 609 Input Parameter: 610 . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...) 611 612 Output Parameter: 613 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 614 615 Level: advanced 616 617 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 618 @*/ 619 PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) 620 { 621 PetscFunctionBegin; 622 #if defined(PETSC_USE_64BIT_INDICES) 623 if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG; 624 else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT; 625 #else 626 if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT; 627 #endif 628 else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE; 629 else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG; 630 else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT; 631 else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT; 632 else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR; 633 else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR; 634 else if (htype == H5T_C_S1) *ptype = PETSC_STRING; 635 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype"); 636 PetscFunctionReturn(0); 637 } 638 639 /*@C 640 PetscViewerHDF5WriteAttribute - Write a scalar attribute 641 642 Input Parameters: 643 + viewer - The HDF5 viewer 644 . parent - The parent name 645 . name - The attribute name 646 . datatype - The attribute type 647 - value - The attribute value 648 649 Level: advanced 650 651 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute() 652 @*/ 653 PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value) 654 { 655 hid_t h5, dataspace, obj, attribute, dtype; 656 PetscErrorCode ierr; 657 658 PetscFunctionBegin; 659 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 660 PetscValidPointer(parent, 2); 661 PetscValidPointer(name, 3); 662 PetscValidPointer(value, 4); 663 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 664 if (datatype == PETSC_STRING) { 665 size_t len; 666 ierr = PetscStrlen((const char *) value, &len);CHKERRQ(ierr); 667 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 668 } 669 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 670 PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR)); 671 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 672 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800) 673 PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT)); 674 #else 675 PetscStackCallHDF5Return(attribute,H5Acreate,(obj, name, dtype, dataspace, H5P_DEFAULT)); 676 #endif 677 PetscStackCallHDF5(H5Awrite,(attribute, dtype, value)); 678 if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype)); 679 PetscStackCallHDF5(H5Aclose,(attribute)); 680 PetscStackCallHDF5(H5Oclose,(obj)); 681 PetscStackCallHDF5(H5Sclose,(dataspace)); 682 PetscFunctionReturn(0); 683 } 684 685 /*@C 686 PetscViewerHDF5ReadAttribute - Read a scalar attribute 687 688 Input Parameters: 689 + viewer - The HDF5 viewer 690 . parent - The parent name 691 . name - The attribute name 692 - datatype - The attribute type 693 694 Output Parameter: 695 . value - The attribute value 696 697 Level: advanced 698 699 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute() 700 @*/ 701 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, void *value) 702 { 703 hid_t h5, obj, attribute, atype, dtype; 704 PetscErrorCode ierr; 705 706 PetscFunctionBegin; 707 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 708 PetscValidPointer(parent, 2); 709 PetscValidPointer(name, 3); 710 PetscValidPointer(value, 4); 711 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 712 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 713 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 714 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 715 PetscStackCallHDF5Return(atype,H5Aget_type,(attribute)); 716 if (datatype == PETSC_STRING) { 717 size_t len; 718 719 PetscStackCallHDF5Return(len,H5Tget_size,(atype)); 720 PetscStackCallHDF5(H5Tclose,(atype)); 721 ierr = PetscMalloc((len+1) * sizeof(char *), &value);CHKERRQ(ierr); 722 } 723 PetscStackCallHDF5(H5Aread,(attribute, dtype, value)); 724 PetscStackCallHDF5(H5Aclose,(attribute)); 725 PetscStackCallHDF5(H5Dclose,(obj)); 726 PetscFunctionReturn(0); 727 } 728 729 static PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, const char name[], H5O_type_t otype, PetscBool *has) 730 { 731 hid_t h5; 732 PetscErrorCode ierr; 733 734 PetscFunctionBegin; 735 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 736 PetscValidPointer(name, 2); 737 PetscValidPointer(has, 3); 738 *has = PETSC_FALSE; 739 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 740 if (H5Lexists(h5, name, H5P_DEFAULT)) { 741 H5O_info_t info; 742 hid_t obj; 743 744 PetscStackCallHDF5Return(obj,H5Oopen,(h5, name, H5P_DEFAULT)); 745 PetscStackCallHDF5(H5Oget_info,(obj, &info)); 746 if (otype == info.type) *has = PETSC_TRUE; 747 PetscStackCallHDF5(H5Oclose,(obj)); 748 } 749 PetscFunctionReturn(0); 750 } 751 752 /*@C 753 PetscViewerHDF5HasAttribute - Check whether a scalar attribute exists 754 755 Input Parameters: 756 + viewer - The HDF5 viewer 757 . parent - The parent name 758 - name - The attribute name 759 760 Output Parameter: 761 . has - Flag for attribute existence 762 763 Level: advanced 764 765 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute() 766 @*/ 767 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 768 { 769 hid_t h5, dataset; 770 htri_t hhas; 771 PetscBool exists; 772 PetscErrorCode ierr; 773 774 PetscFunctionBegin; 775 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 776 PetscValidPointer(parent, 2); 777 PetscValidPointer(name, 3); 778 PetscValidPointer(has, 4); 779 *has = PETSC_FALSE; 780 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 781 ierr = PetscViewerHDF5HasObject(viewer, parent, H5O_TYPE_DATASET, &exists);CHKERRQ(ierr); 782 if (exists) { 783 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800) 784 PetscStackCall("H5Dopen2",dataset = H5Dopen2(h5, parent, H5P_DEFAULT)); 785 #else 786 PetscStackCall("H5Dopen",dataset = H5Dopen(h5, parent)); 787 #endif 788 if (dataset < 0) PetscFunctionReturn(0); 789 PetscStackCall("H5Aexists",hhas = H5Aexists(dataset, name)); 790 if (hhas < 0) { 791 PetscStackCallHDF5(H5Dclose,(dataset)); 792 PetscFunctionReturn(0); 793 } 794 PetscStackCallHDF5(H5Dclose,(dataset)); 795 *has = hhas ? PETSC_TRUE : PETSC_FALSE; 796 } 797 PetscFunctionReturn(0); 798 } 799 800 /* 801 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that 802 is attached to a communicator, in this case the attribute is a PetscViewer. 803 */ 804 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID; 805 806 /*@C 807 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator. 808 809 Collective on MPI_Comm 810 811 Input Parameter: 812 . comm - the MPI communicator to share the HDF5 PetscViewer 813 814 Level: intermediate 815 816 Options Database Keys: 817 . -viewer_hdf5_filename <name> 818 819 Environmental variables: 820 . PETSC_VIEWER_HDF5_FILENAME 821 822 Notes: 823 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return 824 an error code. The HDF5 PetscViewer is usually used in the form 825 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm)); 826 827 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy() 828 @*/ 829 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) 830 { 831 PetscErrorCode ierr; 832 PetscBool flg; 833 PetscViewer viewer; 834 char fname[PETSC_MAX_PATH_LEN]; 835 MPI_Comm ncomm; 836 837 PetscFunctionBegin; 838 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 839 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) { 840 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,0); 841 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 842 } 843 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg); 844 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 845 if (!flg) { /* PetscViewer not yet created */ 846 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 847 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 848 if (!flg) { 849 ierr = PetscStrcpy(fname,"output.h5"); 850 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 851 } 852 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer); 853 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 854 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 855 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 856 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer); 857 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 858 } 859 ierr = PetscCommDestroy(&ncomm); 860 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 861 PetscFunctionReturn(viewer); 862 } 863