Actual source code: hdf5v.c

petsc-3.10.5 2019-03-28
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;

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

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

 32: static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer)
 33: {
 34:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data;
 35:   PetscErrorCode   ierr;

 38:   PetscFree(hdf5->filename);
 39:   if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
 40:   return(0);
 41: }

 43: PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer)
 44: {
 45:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
 46:   PetscErrorCode   ierr;

 49:   PetscViewerFileClose_HDF5(viewer);
 50:   while (hdf5->groups) {
 51:     GroupList *tmp = hdf5->groups->next;

 53:     PetscFree(hdf5->groups->name);
 54:     PetscFree(hdf5->groups);
 55:     hdf5->groups = tmp;
 56:   }
 57:   PetscFree(hdf5);
 58:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);
 59:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);
 60:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);
 61:   return(0);
 62: }

 64: PetscErrorCode  PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type)
 65: {
 66:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

 70:   hdf5->btype = type;
 71:   return(0);
 72: }

 74: PetscErrorCode  PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg)
 75: {
 76:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

 79:   hdf5->basedimension2 = flg;
 80:   return(0);
 81: }

 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.

 87:     Logically Collective on PetscViewer

 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

 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


 97:   Notes:
 98:     Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
 99:          of one when the dimension is lower. Others think the option is crazy.

101:   Level: intermediate

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

105: @*/
106: PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg)
107: {

112:   PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));
113:   return(0);
114: }

116: /*@
117:      PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a
118:        dimension of 2.

120:     Logically Collective on PetscViewer

122:   Input Parameter:
123: .  viewer - the PetscViewer, must be of type HDF5

125:   Output Parameter:
126: .  flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1

128:   Notes:
129:     Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof
130:          of one when the dimension is lower. Others think the option is crazy.

132:   Level: intermediate

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

136: @*/
137: PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg)
138: {
139:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

143:   *flg = hdf5->basedimension2;
144:   return(0);
145: }

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

152:   hdf5->spoutput = flg;
153:   return(0);
154: }

156: /*@
157:      PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
158:        compiled with double precision PetscReal.

160:     Logically Collective on PetscViewer

162:   Input Parameters:
163: +  viewer - the PetscViewer; if it is not hdf5 then this command is ignored
164: -  flg - if PETSC_TRUE the data will be written to disk with single precision

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


170:   Notes:
171:     Setting this option does not make any difference if PETSc is compiled with single precision
172:          in the first place. It does not affect reading datasets (HDF5 handle this internally).

174:   Level: intermediate

176: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
177:           PetscReal

179: @*/
180: PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg)
181: {

186:   PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));
187:   return(0);
188: }

190: /*@
191:      PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
192:        compiled with double precision PetscReal.

194:     Logically Collective on PetscViewer

196:   Input Parameter:
197: .  viewer - the PetscViewer, must be of type HDF5

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

202:   Notes:
203:     Setting this option does not make any difference if PETSc is compiled with single precision
204:          in the first place. It does not affect reading datasets (HDF5 handle this internally).

206:   Level: intermediate

208: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
209:           PetscReal

211: @*/
212: PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg)
213: {
214:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

218:   *flg = hdf5->spoutput;
219:   return(0);
220: }

222: PetscErrorCode  PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[])
223: {
224:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
225: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
226:   MPI_Info          info = MPI_INFO_NULL;
227: #endif
228:   hid_t             plist_id;
229:   PetscErrorCode    ierr;

232:   if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
233:   if (hdf5->filename) {PetscFree(hdf5->filename);}
234:   PetscStrallocpy(name, &hdf5->filename);
235:   /* Set up file access property list with parallel I/O access */
236:   PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS));
237: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
238:   PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), info));
239: #endif
240:   /* Create or open the file collectively */
241:   switch (hdf5->btype) {
242:   case FILE_MODE_READ:
243:     PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id));
244:     break;
245:   case FILE_MODE_APPEND:
246:     PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id));
247:     break;
248:   case FILE_MODE_WRITE:
249:     PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id));
250:     break;
251:   default:
252:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
253:   }
254:   if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name);
255:   PetscStackCallHDF5(H5Pclose,(plist_id));
256:   return(0);
257: }

259: static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name)
260: {
261:   PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data;

264:   *name = vhdf5->filename;
265:   return(0);
266: }

268: /*MC
269:    PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file


272: .seealso:  PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET,
273:            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING,
274:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
275:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()

277:   Level: beginner
278: M*/

280: PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v)
281: {
282:   PetscViewer_HDF5 *hdf5;
283:   PetscErrorCode   ierr;

286:   PetscNewLog(v,&hdf5);

288:   v->data                = (void*) hdf5;
289:   v->ops->destroy        = PetscViewerDestroy_HDF5;
290:   v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5;
291:   v->ops->flush          = 0;
292:   hdf5->btype            = (PetscFileMode) -1;
293:   hdf5->filename         = 0;
294:   hdf5->timestep         = -1;
295:   hdf5->groups           = NULL;

297:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);
298:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);
299:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);
300:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);
301:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);
302:   return(0);
303: }

305: /*@C
306:    PetscViewerHDF5Open - Opens a file for HDF5 input/output.

308:    Collective on MPI_Comm

310:    Input Parameters:
311: +  comm - MPI communicator
312: .  name - name of file
313: -  type - type of file
314: $    FILE_MODE_WRITE - create new file for binary output
315: $    FILE_MODE_READ - open existing file for binary input
316: $    FILE_MODE_APPEND - open existing file for binary output

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

321:   Options Database:
322: .  -viewer_hdf5_base_dimension2 - turns on (true) or off (false) using a dimension of 2 in the HDF5 file even if the bs/dof of the vector is 1
323: .  -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal

325:    Level: beginner

327:    Note:
328:    This PetscViewer should be destroyed with PetscViewerDestroy().

330:    Concepts: HDF5 files
331:    Concepts: PetscViewerHDF5^creating

333: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(),
334:           PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(),
335:           MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName()
336: @*/
337: PetscErrorCode  PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v)
338: {

342:   PetscViewerCreate(comm, hdf5v);
343:   PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);
344:   PetscViewerFileSetMode(*hdf5v, type);
345:   PetscViewerFileSetName(*hdf5v, name);
346:   return(0);
347: }

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

352:   Not collective

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

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

360:   Level: intermediate

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

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

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

377:   Not collective

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

383:   Level: intermediate

385: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup()
386: @*/
387: PetscErrorCode  PetscViewerHDF5PushGroup(PetscViewer viewer, const char *name)
388: {
389:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
390:   GroupList        *groupNode;
391:   PetscErrorCode   ierr;

396:   PetscNew(&groupNode);
397:   PetscStrallocpy(name, (char**) &groupNode->name);

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

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

407:   Not collective

409:   Input Parameter:
410: . viewer - the PetscViewer

412:   Level: intermediate

414: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup()
415: @*/
416: PetscErrorCode  PetscViewerHDF5PopGroup(PetscViewer viewer)
417: {
418:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
419:   GroupList        *groupNode;
420:   PetscErrorCode   ierr;

424:   if (!hdf5->groups) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop");
425:   groupNode    = hdf5->groups;
426:   hdf5->groups = hdf5->groups->next;
427:   PetscFree(groupNode->name);
428:   PetscFree(groupNode);
429:   return(0);
430: }

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

435:   Not collective

437:   Input Parameter:
438: . viewer - the PetscViewer

440:   Output Parameter:
441: . name - The group name

443:   Level: intermediate

445: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup()
446: @*/
447: PetscErrorCode  PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name)
448: {
449:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;

454:   if (hdf5->groups) *name = hdf5->groups->name;
455:   else *name = NULL;
456:   return(0);
457: }

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

462:   Not collective

464:   Input Parameter:
465: . viewer - the PetscViewer

467:   Level: intermediate

469: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep()
470: @*/
471: PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer)
472: {
473:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

477:   ++hdf5->timestep;
478:   return(0);
479: }

481: /*@
482:   PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep
483:   of -1 disables blocking with timesteps.

485:   Not collective

487:   Input Parameters:
488: + viewer - the PetscViewer
489: - timestep - The timestep number

491:   Level: intermediate

493: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
494: @*/
495: PetscErrorCode  PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep)
496: {
497:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

501:   hdf5->timestep = timestep;
502:   return(0);
503: }

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

508:   Not collective

510:   Input Parameter:
511: . viewer - the PetscViewer

513:   Output Parameter:
514: . timestep - The timestep number

516:   Level: intermediate

518: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep()
519: @*/
520: PetscErrorCode  PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep)
521: {
522:   PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;

527:   *timestep = hdf5->timestep;
528:   return(0);
529: }

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

534:   Not collective

536:   Input Parameter:
537: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)

539:   Output Parameter:
540: . mtype - the MPI datatype (for example MPI_DOUBLE, ...)

542:   Level: advanced

544: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
545: @*/
546: PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype)
547: {
549:   if (ptype == PETSC_INT)
550: #if defined(PETSC_USE_64BIT_INDICES)
551:                                        *htype = H5T_NATIVE_LLONG;
552: #else
553:                                        *htype = H5T_NATIVE_INT;
554: #endif
555:   else if (ptype == PETSC_DOUBLE)      *htype = H5T_NATIVE_DOUBLE;
556:   else if (ptype == PETSC_LONG)        *htype = H5T_NATIVE_LONG;
557:   else if (ptype == PETSC_SHORT)       *htype = H5T_NATIVE_SHORT;
558:   else if (ptype == PETSC_ENUM)        *htype = H5T_NATIVE_DOUBLE;
559:   else if (ptype == PETSC_BOOL)        *htype = H5T_NATIVE_DOUBLE;
560:   else if (ptype == PETSC_FLOAT)       *htype = H5T_NATIVE_FLOAT;
561:   else if (ptype == PETSC_CHAR)        *htype = H5T_NATIVE_CHAR;
562:   else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR;
563:   else if (ptype == PETSC_STRING)      *htype = H5Tcopy(H5T_C_S1);
564:   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype");
565:   return(0);
566: }

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

571:   Not collective

573:   Input Parameter:
574: . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...)

576:   Output Parameter:
577: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)

579:   Level: advanced

581: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
582: @*/
583: PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype)
584: {
586: #if defined(PETSC_USE_64BIT_INDICES)
587:   if      (htype == H5T_NATIVE_INT)    *ptype = PETSC_LONG;
588:   else if (htype == H5T_NATIVE_LLONG)  *ptype = PETSC_INT;
589: #else
590:   if      (htype == H5T_NATIVE_INT)    *ptype = PETSC_INT;
591: #endif
592:   else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE;
593:   else if (htype == H5T_NATIVE_LONG)   *ptype = PETSC_LONG;
594:   else if (htype == H5T_NATIVE_SHORT)  *ptype = PETSC_SHORT;
595:   else if (htype == H5T_NATIVE_FLOAT)  *ptype = PETSC_FLOAT;
596:   else if (htype == H5T_NATIVE_CHAR)   *ptype = PETSC_CHAR;
597:   else if (htype == H5T_NATIVE_UCHAR)  *ptype = PETSC_CHAR;
598:   else if (htype == H5T_C_S1)          *ptype = PETSC_STRING;
599:   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype");
600:   return(0);
601: }

603: /*@C
604:  PetscViewerHDF5WriteAttribute - Write a scalar attribute

606:   Input Parameters:
607: + viewer - The HDF5 viewer
608: . parent - The parent name
609: . name   - The attribute name
610: . datatype - The attribute type
611: - value    - The attribute value

613:   Level: advanced

615: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute()
616: @*/
617: PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value)
618: {
619:   hid_t          h5, dataspace, obj, attribute, dtype;

627:   PetscDataTypeToHDF5DataType(datatype, &dtype);
628:   if (datatype == PETSC_STRING) {
629:     size_t len;
630:     PetscStrlen((const char *) value, &len);
631:     PetscStackCallHDF5(H5Tset_size,(dtype, len+1));
632:   }
633:   PetscViewerHDF5GetFileId(viewer, &h5);
634:   PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR));
635:   PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT));
636: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
637:   PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT));
638: #else
639:   PetscStackCallHDF5Return(attribute,H5Acreate,(obj, name, dtype, dataspace, H5P_DEFAULT));
640: #endif
641:   PetscStackCallHDF5(H5Awrite,(attribute, dtype, value));
642:   if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype));
643:   PetscStackCallHDF5(H5Aclose,(attribute));
644:   PetscStackCallHDF5(H5Oclose,(obj));
645:   PetscStackCallHDF5(H5Sclose,(dataspace));
646:   return(0);
647: }

649: /*@C
650:  PetscViewerHDF5ReadAttribute - Read a scalar attribute

652:   Input Parameters:
653: + viewer - The HDF5 viewer
654: . parent - The parent name
655: . name   - The attribute name
656: - datatype - The attribute type

658:   Output Parameter:
659: . value    - The attribute value

661:   Level: advanced

663: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute()
664: @*/
665: PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, void *value)
666: {
667:   hid_t          h5, obj, attribute, atype, dtype;

675:   PetscDataTypeToHDF5DataType(datatype, &dtype);
676:   PetscViewerHDF5GetFileId(viewer, &h5);
677:   PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT));
678:   PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name));
679:   PetscStackCallHDF5Return(atype,H5Aget_type,(attribute));
680:   if (datatype == PETSC_STRING) {
681:     size_t len;

683:     PetscStackCallHDF5Return(len,H5Tget_size,(atype));
684:     PetscStackCallHDF5(H5Tclose,(atype));
685:     PetscMalloc((len+1) * sizeof(char *), &value);
686:   }
687:   PetscStackCallHDF5(H5Aread,(attribute, dtype, value));
688:   PetscStackCallHDF5(H5Aclose,(attribute));
689:   PetscStackCallHDF5(H5Dclose,(obj));
690:   return(0);
691: }

693: static PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, const char name[], H5O_type_t otype, PetscBool *has)
694: {
695:   hid_t          h5;

702:   *has = PETSC_FALSE;
703:   PetscViewerHDF5GetFileId(viewer, &h5);
704:   if (H5Lexists(h5, name, H5P_DEFAULT)) {
705:     H5O_info_t info;
706:     hid_t      obj;

708:     PetscStackCallHDF5Return(obj,H5Oopen,(h5, name, H5P_DEFAULT));
709:     PetscStackCallHDF5(H5Oget_info,(obj, &info));
710:     if (otype == info.type) *has = PETSC_TRUE;
711:     PetscStackCallHDF5(H5Oclose,(obj));
712:   }
713:   return(0);
714: }

716: /*@C
717:  PetscViewerHDF5HasAttribute - Check whether a scalar attribute exists

719:   Input Parameters:
720: + viewer - The HDF5 viewer
721: . parent - The parent name
722: - name   - The attribute name

724:   Output Parameter:
725: . has    - Flag for attribute existence

727:   Level: advanced

729: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute()
730: @*/
731: PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has)
732: {
733:   hid_t          h5, dataset;
734:   htri_t         hhas;
735:   PetscBool      exists;

743:   *has = PETSC_FALSE;
744:   PetscViewerHDF5GetFileId(viewer, &h5);
745:   PetscViewerHDF5HasObject(viewer, parent, H5O_TYPE_DATASET, &exists);
746:   if (exists) {
747: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
748:     PetscStackCall("H5Dopen2",dataset = H5Dopen2(h5, parent, H5P_DEFAULT));
749: #else
750:     PetscStackCall("H5Dopen",dataset = H5Dopen(h5, parent));
751: #endif
752:     if (dataset < 0) return(0);
753:     PetscStackCall("H5Aexists",hhas = H5Aexists(dataset, name));
754:     if (hhas < 0) {
755:       PetscStackCallHDF5(H5Dclose,(dataset));
756:       return(0);
757:     }
758:     PetscStackCallHDF5(H5Dclose,(dataset));
759:     *has = hhas ? PETSC_TRUE : PETSC_FALSE;
760:   }
761:   return(0);
762: }

764: /*
765:   The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that
766:   is attached to a communicator, in this case the attribute is a PetscViewer.
767: */
768: PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID;

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

773:   Collective on MPI_Comm

775:   Input Parameter:
776: . comm - the MPI communicator to share the HDF5 PetscViewer

778:   Level: intermediate

780:   Options Database Keys:
781: . -viewer_hdf5_filename <name>

783:   Environmental variables:
784: . PETSC_VIEWER_HDF5_FILENAME

786:   Notes:
787:   Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return
788:   an error code.  The HDF5 PetscViewer is usually used in the form
789: $       XXXView(XXX object, PETSC_VIEWER_HDF5_(comm));

791: .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy()
792: @*/
793: PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm)
794: {
796:   PetscBool      flg;
797:   PetscViewer    viewer;
798:   char           fname[PETSC_MAX_PATH_LEN];
799:   MPI_Comm       ncomm;

802:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
803:   if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
804:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,0);
805:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
806:   }
807:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg);
808:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
809:   if (!flg) { /* PetscViewer not yet created */
810:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
811:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
812:     if (!flg) {
813:       PetscStrcpy(fname,"output.h5");
814:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
815:     }
816:     PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer);
817:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
818:     PetscObjectRegisterDestroy((PetscObject)viewer);
819:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
820:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer);
821:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
822:   }
823:   PetscCommDestroy(&ncomm);
824:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
825:   PetscFunctionReturn(viewer);
826: }