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