Actual source code: hdf5v.c
petsc-3.10.5 2019-03-28
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: }