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