XdmfHDF5Writer.cpp 4.82 KB
Newer Older
1
2
3
// Kenneth Leiter
// Xdmf Smart Pointer Test

4
#include <hdf5.h>
5
6
7
8
9
#include <sstream>
#include "XdmfArray.hpp"
#include "XdmfItem.hpp"
#include "XdmfHDF5Writer.hpp"

10
11
12
13
14
15
16
/**
 * PIMPL
 */
class XdmfHDF5Writer::XdmfHDF5WriterImpl {

public:

17
	XdmfHDF5WriterImpl(std::string & hdf5FilePath) :
18
19
20
21
22
23
24
25
26
27
28
29
30
		mHDF5Handle(H5Fcreate("output.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)),
		mHeavyFileName("output.h5")
	{
	};
	~XdmfHDF5WriterImpl()
	{
		herr_t status = H5Fclose(mHDF5Handle);
	};
	std::vector<std::string> mDataHierarchy;
	hid_t mHDF5Handle;
	std::string mHeavyFileName;
};

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class XdmfHDF5Writer::GetHDF5Type : public boost::static_visitor <hid_t> {
public:

	GetHDF5Type()
	{
	}

	hid_t getHDF5Type(const char * const) const
	{
		return H5T_NATIVE_CHAR;
	}

	hid_t getHDF5Type(const short * const) const
	{
		return H5T_NATIVE_SHORT;
	}

	hid_t getHDF5Type(const int * const) const
	{
		return H5T_NATIVE_INT;
	}

	hid_t getHDF5Type(const long * const) const
	{
		return H5T_NATIVE_LONG;
	}

	hid_t getHDF5Type(const float * const) const
	{
		return H5T_NATIVE_FLOAT;
	}

	hid_t getHDF5Type(const double * const) const
	{
		return H5T_NATIVE_DOUBLE;
	}

	hid_t getHDF5Type(const unsigned char * const) const
	{
		return H5T_NATIVE_UCHAR;
	}

	hid_t getHDF5Type(const unsigned short * const) const
	{
		return H5T_NATIVE_USHORT;
	}

	hid_t getHDF5Type(const unsigned int * const) const
	{
		return H5T_NATIVE_UINT;
	}

	template<typename T>
	hid_t operator()(const boost::shared_ptr<std::vector<T> > & array) const
	{
		return this->getHDF5Type(&(array.get()->operator[](0)));
	}

	template<typename T>
	hid_t operator()(const boost::shared_array<const T> & array) const
	{
		return this->getHDF5Type(array.get());
	}
};

XdmfHDF5Writer::XdmfHDF5Writer(std::string & hdf5FilePath) :
	mImpl(new XdmfHDF5WriterImpl(hdf5FilePath))
98
99
100
101
102
103
{
	std::cout << "Created XdmfHDF5Writer " << this << std::endl;
}

XdmfHDF5Writer::~XdmfHDF5Writer()
{
104
	delete mImpl;
105
106
107
108
109
	std::cout << "Deleted XdmfHDF5Writer " << this << std::endl;
}

std::string XdmfHDF5Writer::createHDF5Group(std::stringstream & groupPath, int index)
{
110
111
	groupPath << "/" << mImpl->mDataHierarchy[index];
	hid_t handle = H5Gopen(mImpl->mHDF5Handle, groupPath.str().c_str(), H5P_DEFAULT);
112
113
114
	if(handle < 0)
	{
		// Open failed, create a new group
115
		handle = H5Gcreate(mImpl->mHDF5Handle, groupPath.str().c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
116
117
118
119
	}
	H5Gclose(handle);

	// + 2 because the last value in mDataHierarchy == dataset name
120
	if(index + 2 < mImpl->mDataHierarchy.size())
121
122
123
124
125
126
127
128
	{
		return createHDF5Group(groupPath, index + 1);
	}
	return groupPath.str().c_str();
}

std::string XdmfHDF5Writer::getHDF5GroupHandle()
{
129
	if(mImpl->mDataHierarchy.size() > 1)
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
	{
		// Save old error handler and turn off error handling for now
		H5E_auto_t old_func;
		void* old_client_data;
		H5Eget_auto(0, &old_func, &old_client_data);
		H5Eset_auto2(0, NULL, NULL);

		std::stringstream emptyPath;
		std::string handle = createHDF5Group(emptyPath);

		// Restore previous error handler
		H5Eset_auto2(0, old_func, old_client_data);

		return handle;
	}
	return "";
}

void XdmfHDF5Writer::popDataHierarchy()
{
150
	mImpl->mDataHierarchy.pop_back();
151
152
153
154
155
156
157
158
}

void XdmfHDF5Writer::pushDataHierarchy(const XdmfItem & item)
{
	const std::map<std::string, std::string> itemProperties = item.getItemProperties();
	std::map<std::string, std::string>::const_iterator name = itemProperties.find("Name");
	if(name == itemProperties.end())
	{
159
		mImpl->mDataHierarchy.push_back(item.getItemTag());
160
161
162
	}
	else
	{
163
		mImpl->mDataHierarchy.push_back(name->second);
164
165
166
167
168
	}
}

std::string XdmfHDF5Writer::visit(XdmfArray & array, boost::shared_ptr<Loki::BaseVisitor> visitor)
{
169
170
	hid_t datatype = -1;
	if(array.mHaveArray)
171
	{
172
		datatype = boost::apply_visitor(GetHDF5Type(), array.mArray);
173
	}
174
	else if(array.mHaveArrayPointer)
175
	{
176
		datatype = boost::apply_visitor(GetHDF5Type(), array.mArrayPointer);
177
178
	}

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
	if(datatype != -1)
	{
		herr_t status;
		hsize_t size = array.getSize();
		hid_t dataspace = H5Screate_simple(1, &size, NULL);
		hid_t handle = mImpl->mHDF5Handle;
		std::string groupName = getHDF5GroupHandle();
		if(groupName.compare("") != 0)
		{
			handle = H5Gopen(mImpl->mHDF5Handle, groupName.c_str(), H5P_DEFAULT);
		}

		hid_t dataset = H5Dcreate(handle, mImpl->mDataHierarchy.back().c_str(), datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
		status = H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, array.getValuesPointer());
		if(groupName.compare("") != 0)
		{
			H5Gclose(handle);
		}
		status = H5Dclose(dataset);
		status = H5Sclose(dataspace);

		std::stringstream dataSetName;
		dataSetName << mImpl->mHeavyFileName << ":" << groupName << "/" << mImpl->mDataHierarchy.back();
		return dataSetName.str();
	}
	return "";
205
206
207
208
209
210
211
212
}

void XdmfHDF5Writer::visit(XdmfItem & item, boost::shared_ptr<Loki::BaseVisitor> visitor)
{
	this->pushDataHierarchy(item);
	item.traverse(visitor);
	this->popDataHierarchy();
}