Actual source code: hdf5v.c
petsc-3.9.4 2018-09-11
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: 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.
100: Level: intermediate
102: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
104: @*/
105: PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg)
106: {
111: PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));
112: return(0);
113: }
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.
119: Logically Collective on PetscViewer
121: Input Parameter:
122: . viewer - the PetscViewer, must be of type HDF5
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
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.
130: Level: intermediate
132: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
134: @*/
135: PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg)
136: {
137: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
141: *flg = hdf5->basedimension2;
142: return(0);
143: }
145: PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg)
146: {
147: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
150: hdf5->spoutput = flg;
151: return(0);
152: }
154: /*@
155: PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is
156: compiled with double precision PetscReal.
158: Logically Collective on PetscViewer
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
164: Options Database:
165: . -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision
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).
171: Level: intermediate
173: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
174: PetscReal
176: @*/
177: PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg)
178: {
183: PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));
184: return(0);
185: }
187: /*@
188: PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is
189: compiled with double precision PetscReal.
191: Logically Collective on PetscViewer
193: Input Parameter:
194: . viewer - the PetscViewer, must be of type HDF5
196: Output Parameter:
197: . flg - if PETSC_TRUE the data will be written to disk with single precision
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).
202: Level: intermediate
204: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
205: PetscReal
207: @*/
208: PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg)
209: {
210: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
214: *flg = hdf5->spoutput;
215: return(0);
216: }
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;
228: if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id));
229: if (hdf5->filename) {PetscFree(hdf5->filename);}
230: PetscStrallocpy(name, &hdf5->filename);
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: return(0);
253: }
255: static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name)
256: {
257: PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data;
260: *name = vhdf5->filename;
261: return(0);
262: }
264: /*MC
265: PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file
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()
273: Level: beginner
274: M*/
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,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);
295: PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);
296: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);
297: PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);
298: return(0);
299: }
301: /*@C
302: PetscViewerHDF5Open - Opens a file for HDF5 input/output.
304: Collective on MPI_Comm
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
314: Output Parameter:
315: . hdf5v - PetscViewer for HDF5 input/output to use with the specified file
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
321: Level: beginner
323: Note:
324: This PetscViewer should be destroyed with PetscViewerDestroy().
326: Concepts: HDF5 files
327: Concepts: PetscViewerHDF5^creating
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: {
338: PetscViewerCreate(comm, hdf5v);
339: PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);
340: PetscViewerFileSetMode(*hdf5v, type);
341: PetscViewerFileSetName(*hdf5v, name);
342: return(0);
343: }
345: /*@C
346: PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls
348: Not collective
350: Input Parameter:
351: . viewer - the PetscViewer
353: Output Parameter:
354: . file_id - The file id
356: Level: intermediate
358: .seealso: PetscViewerHDF5Open()
359: @*/
360: PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id)
361: {
362: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
366: if (file_id) *file_id = hdf5->file_id;
367: return(0);
368: }
370: /*@C
371: PetscViewerHDF5PushGroup - Set the current HDF5 group for output
373: Not collective
375: Input Parameters:
376: + viewer - the PetscViewer
377: - name - The group name
379: Level: intermediate
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;
392: PetscNew(&groupNode);
393: PetscStrallocpy(name, (char**) &groupNode->name);
395: groupNode->next = hdf5->groups;
396: hdf5->groups = groupNode;
397: return(0);
398: }
400: /*@
401: PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value
403: Not collective
405: Input Parameter:
406: . viewer - the PetscViewer
408: Level: intermediate
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;
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: PetscFree(groupNode->name);
424: PetscFree(groupNode);
425: return(0);
426: }
428: /*@C
429: PetscViewerHDF5GetGroup - Get the current HDF5 group for output. If none has been assigned, returns NULL.
431: Not collective
433: Input Parameter:
434: . viewer - the PetscViewer
436: Output Parameter:
437: . name - The group name
439: Level: intermediate
441: .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup()
442: @*/
443: PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name)
444: {
445: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data;
450: if (hdf5->groups) *name = hdf5->groups->name;
451: else *name = NULL;
452: return(0);
453: }
455: /*@
456: PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time.
458: Not collective
460: Input Parameter:
461: . viewer - the PetscViewer
463: Level: intermediate
465: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep()
466: @*/
467: PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer)
468: {
469: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
473: ++hdf5->timestep;
474: return(0);
475: }
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.
481: Not collective
483: Input Parameters:
484: + viewer - the PetscViewer
485: - timestep - The timestep number
487: Level: intermediate
489: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep()
490: @*/
491: PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep)
492: {
493: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
497: hdf5->timestep = timestep;
498: return(0);
499: }
501: /*@
502: PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time.
504: Not collective
506: Input Parameter:
507: . viewer - the PetscViewer
509: Output Parameter:
510: . timestep - The timestep number
512: Level: intermediate
514: .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep()
515: @*/
516: PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep)
517: {
518: PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data;
523: *timestep = hdf5->timestep;
524: return(0);
525: }
527: /*@C
528: PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name.
530: Not collective
532: Input Parameter:
533: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)
535: Output Parameter:
536: . mtype - the MPI datatype (for example MPI_DOUBLE, ...)
538: Level: advanced
540: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
541: @*/
542: PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype)
543: {
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: return(0);
562: }
564: /*@C
565: PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name
567: Not collective
569: Input Parameter:
570: . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...)
572: Output Parameter:
573: . ptype - the PETSc datatype name (for example PETSC_DOUBLE)
575: Level: advanced
577: .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType()
578: @*/
579: PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype)
580: {
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: return(0);
597: }
599: /*@C
600: PetscViewerHDF5WriteAttribute - Write a scalar attribute
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
609: Level: advanced
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;
623: PetscDataTypeToHDF5DataType(datatype, &dtype);
624: if (datatype == PETSC_STRING) {
625: size_t len;
626: PetscStrlen((const char *) value, &len);
627: PetscStackCallHDF5(H5Tset_size,(dtype, len+1));
628: }
629: PetscViewerHDF5GetFileId(viewer, &h5);
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: return(0);
643: }
645: /*@C
646: PetscViewerHDF5ReadAttribute - Read a scalar attribute
648: Input Parameters:
649: + viewer - The HDF5 viewer
650: . parent - The parent name
651: . name - The attribute name
652: - datatype - The attribute type
654: Output Parameter:
655: . value - The attribute value
657: Level: advanced
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;
671: PetscDataTypeToHDF5DataType(datatype, &dtype);
672: PetscViewerHDF5GetFileId(viewer, &h5);
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;
679: PetscStackCallHDF5Return(len,H5Tget_size,(atype));
680: PetscStackCallHDF5(H5Tclose,(atype));
681: PetscMalloc((len+1) * sizeof(char *), &value);
682: }
683: PetscStackCallHDF5(H5Aread,(attribute, dtype, value));
684: PetscStackCallHDF5(H5Aclose,(attribute));
685: PetscStackCallHDF5(H5Dclose,(obj));
686: return(0);
687: }
689: static PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, const char name[], H5O_type_t otype, PetscBool *has)
690: {
691: hid_t h5;
698: *has = PETSC_FALSE;
699: PetscViewerHDF5GetFileId(viewer, &h5);
700: if (H5Lexists(h5, name, H5P_DEFAULT)) {
701: H5O_info_t info;
702: hid_t obj;
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: return(0);
710: }
712: /*@C
713: PetscViewerHDF5HasAttribute - Check whether a scalar attribute exists
715: Input Parameters:
716: + viewer - The HDF5 viewer
717: . parent - The parent name
718: - name - The attribute name
720: Output Parameter:
721: . has - Flag for attribute existence
723: Level: advanced
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;
739: *has = PETSC_FALSE;
740: PetscViewerHDF5GetFileId(viewer, &h5);
741: PetscViewerHDF5HasObject(viewer, parent, H5O_TYPE_DATASET, &exists);
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) return(0);
749: PetscStackCall("H5Aexists",hhas = H5Aexists(dataset, name));
750: if (hhas < 0) {
751: PetscStackCallHDF5(H5Dclose,(dataset));
752: return(0);
753: }
754: PetscStackCallHDF5(H5Dclose,(dataset));
755: *has = hhas ? PETSC_TRUE : PETSC_FALSE;
756: }
757: return(0);
758: }
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;
766: /*@C
767: PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator.
769: Collective on MPI_Comm
771: Input Parameter:
772: . comm - the MPI communicator to share the HDF5 PetscViewer
774: Level: intermediate
776: Options Database Keys:
777: . -viewer_hdf5_filename <name>
779: Environmental variables:
780: . PETSC_VIEWER_HDF5_FILENAME
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));
787: .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy()
788: @*/
789: PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm)
790: {
792: PetscBool flg;
793: PetscViewer viewer;
794: char fname[PETSC_MAX_PATH_LEN];
795: MPI_Comm ncomm;
798: PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
799: if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) {
800: 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," ");return(0);}
802: }
803: 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," ");return(0);}
805: if (!flg) { /* PetscViewer not yet created */
806: 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," ");return(0);}
808: if (!flg) {
809: PetscStrcpy(fname,"output.h5");
810: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
811: }
812: 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," ");return(0);}
814: PetscObjectRegisterDestroy((PetscObject)viewer);
815: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
816: 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," ");return(0);}
818: }
819: PetscCommDestroy(&ncomm);
820: if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
821: PetscFunctionReturn(viewer);
822: }