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