Actual source code: hdf5v.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  1: #include <petsc/private/viewerimpl.h>    /*I   "petscsys.h"   I*/
  2: #include <petscviewerhdf5.h>    /*I   "petscviewerhdf5.h"   I*/

  4: typedef struct GroupList {
  5:   const char       *name;
  6:   struct GroupList *next;
  7: } GroupList;

  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;

 21: static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v)
 22: {
 23:   PetscErrorCode   ierr;
 24:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data;

 27:   PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");
 28:   PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);
 29:   PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);
 30:   PetscOptionsTail();
 31:   return(0);
 32: }

 36: static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
 37: {
 38:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data;
 39:   PetscErrorCode   ierr;

 42:   PetscFree(hdf5->filename);
 43:   if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
 44:   return(0);
 45: }

 49: PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
 50: {
 51:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
 52:   PetscErrorCode   ierr;

 55:   PetscViewerFileClose_HDF5(viewer);
 56:   while (hdf5->groups) {
 57:     GroupList *tmp = hdf5->groups->next;

 59:     PetscFree(hdf5->groups->name);
 60:     PetscFree(hdf5->groups);
 61:     hdf5->groups = tmp;
 62:   }
 63:   PetscFree(hdf5);
 64:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);
 65:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);
 66:   return(0);
 67: }

 71: PetscErrorCode  PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
 72: {
 73:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

 77:   hdf5->btype = type;
 78:   return(0);
 79: }

 83: PetscErrorCode  PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg)
 84: {
 85:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

 88:   hdf5->basedimension2 = flg;
 89:   return(0);
 90: }

 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.

 98:     Logically Collective on PetscViewer

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

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


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.

111:   Level: intermediate

113: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()

115: @*/
116: PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg)
117: {

122:   PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));
123:   return(0);
124: }

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.

132:     Logically Collective on PetscViewer

134:   Input Parameter:
135: .  viewer - the PetscViewer, must be of type HDF5

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

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.

143:   Level: intermediate

145: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()

147: @*/
148: PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg)
149: {
150:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

154:   *flg = hdf5->basedimension2;
155:   return(0);
156: }

160: PetscErrorCode  PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg)
161: {
162:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

165:   hdf5->spoutput = flg;
166:   return(0);
167: }

171: /*@C
172:      PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
173:        compiled with double precision PetscReal.

175:     Logically Collective on PetscViewer

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

181:   Options Database:
182: .  -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision


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).

188:   Level: intermediate

190: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
191:           PetscReal

193: @*/
194: PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg)
195: {

200:   PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));
201:   return(0);
202: }

206: /*@C
207:      PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
208:        compiled with double precision PetscReal.

210:     Logically Collective on PetscViewer

212:   Input Parameter:
213: .  viewer - the PetscViewer, must be of type HDF5

215:   Output Parameter:
216: .  flg - if PETSC_TRUE the data will be written to disk with single precision

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).

221:   Level: intermediate

223: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
224:           PetscReal

226: @*/
227: PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg)
228: {
229:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

233:   *flg = hdf5->spoutput;
234:   return(0);
235: }

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;

249:   PetscStrallocpy(name, &hdf5->filename);
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:   return(0);
272: }

276: PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v)
277: {
278:   PetscViewer_HDF5 *hdf5;
279:   PetscErrorCode   ierr;

282:   PetscNewLog(v,&hdf5);

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;

293:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);
294:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);
295:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);
296:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);
297:   return(0);
298: }

302: /*@C
303:    PetscViewerHDF5Open - Opens a file for HDF5 input/output.

305:    Collective on MPI_Comm

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

315:    Output Parameter:
316: .  hdf5v - PetscViewer for HDF5 input/output to use with the specified file

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

322:    Level: beginner

324:    Note:
325:    This PetscViewer should be destroyed with PetscViewerDestroy().

327:    Concepts: HDF5 files
328:    Concepts: PetscViewerHDF5^creating

330: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), 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: {

339:   PetscViewerCreate(comm, hdf5v);
340:   PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);
341:   PetscViewerFileSetMode(*hdf5v, type);
342:   PetscViewerFileSetName(*hdf5v, name);
343:   return(0);
344: }

348: /*@C
349:   PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls

351:   Not collective

353:   Input Parameter:
354: . viewer - the PetscViewer

356:   Output Parameter:
357: . file_id - The file id

359:   Level: intermediate

361: .seealso: PetscViewerHDF5Open()
362: @*/
363: PetscErrorCode  PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
364: {
365:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

369:   if (file_id) *file_id = hdf5->file_id;
370:   return(0);
371: }

375: /*@C
376:   PetscViewerHDF5PushGroup - Set the current HDF5 group for output

378:   Not collective

380:   Input Parameters:
381: + viewer - the PetscViewer
382: - name - The group name

384:   Level: intermediate

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;

397:   PetscMalloc(sizeof(GroupList), &groupNode);
398:   PetscStrallocpy(name, (char**) &groupNode->name);

400:   groupNode->next = hdf5->groups;
401:   hdf5->groups    = groupNode;
402:   return(0);
403: }

407: /*@
408:   PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value

410:   Not collective

412:   Input Parameter:
413: . viewer - the PetscViewer

415:   Level: intermediate

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;

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:   PetscFree(groupNode->name);
431:   PetscFree(groupNode);
432:   return(0);
433: }

437: /*@C
438:   PetscViewerHDF5GetGroup - Get the current HDF5 group for output. If none has been assigned, returns NULL.

440:   Not collective

442:   Input Parameter:
443: . viewer - the PetscViewer

445:   Output Parameter:
446: . name - The group name

448:   Level: intermediate

450: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup()
451: @*/
452: PetscErrorCode  PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name)
453: {
454:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;

459:   if (hdf5->groups) *name = hdf5->groups->name;
460:   else *name = NULL;
461:   return(0);
462: }

466: /*@
467:   PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time.

469:   Not collective

471:   Input Parameter:
472: . viewer - the PetscViewer

474:   Level: intermediate

476: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep()
477: @*/
478: PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer)
479: {
480:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

484:   ++hdf5->timestep;
485:   return(0);
486: }

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.

494:   Not collective

496:   Input Parameters:
497: + viewer - the PetscViewer
498: - timestep - The timestep number

500:   Level: intermediate

502: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
503: @*/
504: PetscErrorCode  PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep)
505: {
506:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

510:   hdf5->timestep = timestep;
511:   return(0);
512: }

516: /*@
517:   PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.

519:   Not collective

521:   Input Parameter:
522: . viewer - the PetscViewer

524:   Output Parameter:
525: . timestep - The timestep number

527:   Level: intermediate

529: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep()
530: @*/
531: PetscErrorCode  PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep)
532: {
533:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

538:   *timestep = hdf5->timestep;
539:   return(0);
540: }

544: /*@C
545:   PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.

547:   Not collective

549:   Input Parameter:
550: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)

552:   Output Parameter:
553: . mtype - the MPI datatype (for example MPI_DOUBLE, ...)

555:   Level: advanced

557: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
558: @*/
559: PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype)
560: {
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:   return(0);
579: }

583: /*@C
584:   PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name

586:   Not collective

588:   Input Parameter:
589: . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...)

591:   Output Parameter:
592: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)

594:   Level: advanced

596: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
597: @*/
598: PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype)
599: {
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:   return(0);
616: }

620: /*@
621:  PetscViewerHDF5WriteAttribute - Write a scalar attribute

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

630:   Level: advanced

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;

644:   PetscDataTypeToHDF5DataType(datatype, &dtype);
645:   if (datatype == PETSC_STRING) {
646:     size_t len;
647:     PetscStrlen((const char *) value, &len);
648:     PetscStackCallHDF5(H5Tset_size,(dtype, len+1));
649:   }
650:   PetscViewerHDF5GetFileId(viewer, &h5);
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:   return(0);
665: }

669: /*@
670:  PetscViewerHDF5ReadAttribute - Read a scalar attribute

672:   Input Parameters:
673: + viewer - The HDF5 viewer
674: . parent - The parent name
675: . name   - The attribute name
676: - datatype - The attribute type

678:   Output Parameter:
679: . value    - The attribute value

681:   Level: advanced

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;

695:   PetscDataTypeToHDF5DataType(datatype, &dtype);
696:   PetscViewerHDF5GetFileId(viewer, &h5);
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:   return(0);
709: }

713: static PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, const char name[], H5O_type_t otype, PetscBool *has)
714: {
715:   hid_t          h5;

722:   *has = PETSC_FALSE;
723:   PetscViewerHDF5GetFileId(viewer, &h5);
724:   if (H5Lexists(h5, name, H5P_DEFAULT)) {
725:     H5O_info_t info;
726:     hid_t      obj;

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:   return(0);
734: }

738: /*@
739:  PetscViewerHDF5HasAttribute - Check whether a scalar attribute exists

741:   Input Parameters:
742: + viewer - The HDF5 viewer
743: . parent - The parent name
744: - name   - The attribute name

746:   Output Parameter:
747: . has    - Flag for attribute existence

749:   Level: advanced

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;

765:   *has = PETSC_FALSE;
766:   PetscViewerHDF5GetFileId(viewer, &h5);
767:   PetscViewerHDF5HasObject(viewer, parent, H5O_TYPE_DATASET, &exists);
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) return(0);
775:     PetscStackCall("H5Aexists",hhas = H5Aexists(dataset, name));
776:     if (hhas < 0) {
777:       PetscStackCallHDF5(H5Dclose,(dataset));
778:       return(0);
779:     }
780:     PetscStackCallHDF5(H5Dclose,(dataset));
781:     *has = hhas ? PETSC_TRUE : PETSC_FALSE;
782:   }
783:   return(0);
784: }

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;

794: /*@C
795:   PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator.

797:   Collective on MPI_Comm

799:   Input Parameter:
800: . comm - the MPI communicator to share the HDF5 PetscViewer

802:   Level: intermediate

804:   Options Database Keys:
805: . -viewer_hdf5_filename <name>

807:   Environmental variables:
808: . PETSC_VIEWER_HDF5_FILENAME

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));

815: .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy()
816: @*/
817: PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm)
818: {
820:   PetscBool      flg;
821:   PetscViewer    viewer;
822:   char           fname[PETSC_MAX_PATH_LEN];
823:   MPI_Comm       ncomm;

826:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
827:   if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
828:     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," ");return(0);}
830:   }
831:   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," ");return(0);}
833:   if (!flg) { /* PetscViewer not yet created */
834:     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," ");return(0);}
836:     if (!flg) {
837:       PetscStrcpy(fname,"output.h5");
838:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
839:     }
840:     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," ");return(0);}
842:     PetscObjectRegisterDestroy((PetscObject)viewer);
843:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
844:     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," ");return(0);}
846:   }
847:   PetscCommDestroy(&ncomm);
848:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
849:   PetscFunctionReturn(viewer);
850: }