42 #include <boost/scoped_array.hpp>
44 #include "Hdf5DataWriter.hpp"
47 #include "OutputFileHandler.hpp"
49 #include "Version.hpp"
53 const std::string& rDirectory,
54 const std::string& rBaseName,
57 std::string datasetName)
59 mrVectorFactory(rVectorFactory),
60 mCleanDirectory(cleanDirectory),
61 mUseExistingFile(extendData),
62 mIsInDefineMode(true),
63 mIsFixedDimensionSet(false),
64 mEstimatedUnlimitedLength(1u),
65 mFileFixedDimensionSize(0u),
66 mDataFixedDimensionSize(0u),
67 mLo(mrVectorFactory.GetLow()),
68 mHi(mrVectorFactory.GetHigh()),
72 mUseMatrixForIncompleteData(false),
74 mSinglePermutation(NULL),
75 mDoublePermutation(NULL),
76 mSingleIncompleteOutputMatrix(NULL),
77 mDoubleIncompleteOutputMatrix(NULL),
78 mUseOptimalChunkSizeAlgorithm(true),
90 EXCEPTION(
"You are asking to delete a file and then extend it, change arguments to constructor.");
96 EXCEPTION(
"Adding new data only makes sense when extending an existing file");
125 H5Sget_simple_extent_dims(variables_dataspace,
mDatasetDims, dataset_max_sizes);
126 H5Sclose(variables_dataspace);
129 if (dataset_max_sizes[0] != H5S_UNLIMITED)
133 EXCEPTION(
"Tried to open a datafile for extending which doesn't have an unlimited dimension.");
148 hid_t attribute_type = H5Aget_type(attribute_id);
149 hid_t attribute_space = H5Aget_space(attribute_id);
150 hsize_t attr_dataspace_dim;
151 H5Sget_simple_extent_dims(attribute_space, &attr_dataspace_dim, NULL);
152 unsigned num_columns = H5Sget_simple_extent_npoints(attribute_space);
155 char* string_array = (
char *)malloc(
sizeof(
char)*MAX_STRING_SIZE*(int)num_columns);
156 H5Aread(attribute_id, attribute_type, string_array);
159 for (
unsigned index=0; index<num_columns; index++)
162 std::string column_name_unit(&string_array[MAX_STRING_SIZE*index]);
165 size_t name_length = column_name_unit.find(
'(');
166 size_t unit_length = column_name_unit.find(
')') - name_length - 1;
171 var.
mVariableUnits = column_name_unit.substr(name_length+1, unit_length);
177 H5Tclose(attribute_type);
178 H5Sclose(attribute_space);
179 H5Aclose(attribute_id);
186 hsize_t num_timesteps;
187 H5Sget_simple_extent_dims(timestep_dataspace, &num_timesteps, NULL);
188 H5Sclose(timestep_dataspace);
193 if (attribute_id < 0)
195 #define COVERAGE_IGNORE
197 EXCEPTION(
"Extending old-format files isn't supported.");
198 #undef COVERAGE_IGNORE
202 attribute_type = H5Aget_type(attribute_id);
203 attribute_space = H5Aget_space(attribute_id);
204 unsigned is_data_complete;
205 H5Aread(attribute_id, H5T_NATIVE_UINT, &is_data_complete);
207 H5Tclose(attribute_type);
208 H5Sclose(attribute_space);
209 H5Aclose(attribute_id);
221 attribute_type = H5Aget_type(attribute_id);
222 attribute_space = H5Aget_space(attribute_id);
225 unsigned num_node_indices = H5Sget_simple_extent_npoints(attribute_space);
233 H5Tclose(attribute_type);
234 H5Sclose(attribute_space);
235 H5Aclose(attribute_id);
247 EXCEPTION(
"Unable to extend an incomplete data file at present.");
288 EXCEPTION(
"Hdf5DataWriter could not open " + file_name +
" , as it does not exist.");
293 hid_t fapl = H5Pcreate(H5P_FILE_ACCESS);
294 H5Pset_fapl_mpio(fapl, PETSC_COMM_WORLD, MPI_INFO_NULL);
302 std::string attempting_to;
305 mFileId = H5Fopen(file_name.c_str(), H5F_ACC_RDWR, fapl);
306 attempting_to =
"open";
313 hid_t fcpl = H5Pcreate(H5P_FILE_CREATE);
344 mFileId = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, fcpl, fapl);
359 attempting_to =
"create";
368 EXCEPTION(
"Hdf5DataWriter could not " << attempting_to <<
" " << file_name <<
369 " , H5F" << attempting_to <<
" error code = " <<
mFileId);
377 EXCEPTION(
"Cannot define variables when not in Define mode");
379 if (dimensionSize < 1)
381 EXCEPTION(
"Fixed dimension must be at least 1 long");
385 EXCEPTION(
"Fixed dimension already set");
400 unsigned vector_size = rNodesToOuput.size();
402 for (
unsigned index=0; index < vector_size-1; index++)
404 if (rNodesToOuput[index] >= rNodesToOuput[index+1])
406 EXCEPTION(
"Input should be monotonic increasing");
410 if ((
int) rNodesToOuput.back() >= vecSize)
412 EXCEPTION(
"Vector size doesn't match nodes to output");
425 unsigned vector_size = rNodesToOuput.size();
427 for (
unsigned index=0; index < vector_size-1; index++)
429 if (rNodesToOuput[index] >= rNodesToOuput[index+1])
431 EXCEPTION(
"Input should be monotonic increasing");
435 if ((
int) rNodesToOuput.back() >= vecSize)
437 EXCEPTION(
"Vector size doesn't match nodes to output");
463 unsigned bi_index = 2*row_index;
464 unsigned perm_index = 2*rNodesToOuput[row_index];
500 const std::string& rVariableUnits)
504 EXCEPTION(
"Cannot define variables when not in Define mode");
511 for (
unsigned index=0; index<
mVariables.size(); index++)
513 if (
mVariables[index].mVariableName == rVariableName)
515 EXCEPTION(
"Variable name already exists");
536 if (rName.length() == 0)
538 EXCEPTION(
"Variable name not allowed: may not be blank.");
545 for (
unsigned i=0; i<rName.length(); i++)
547 if (!isalnum(rName[i]) && !(rName[i]==
'_'))
549 std::string error =
"Variable name/units '" + rName +
"' not allowed: may only contain alphanumeric characters or '_'.";
565 EXCEPTION(
"Cannot end define mode. No variables have been defined.");
571 EXCEPTION(
"Cannot end define mode. One fixed dimension should be defined.");
586 dataset_max_dims[0] = H5S_UNLIMITED;
590 dataset_max_dims[0] = 1;
602 hid_t cparms = H5Pcreate (H5P_DATASET_CREATE);
611 const unsigned MAX_STRING_SIZE = 100;
613 hid_t colspace = H5Screate_simple(1, columns, NULL);
616 char* col_data = (
char*) malloc(
mVariables.size() *
sizeof(char) * MAX_STRING_SIZE);
618 char* col_data_offset = col_data;
619 for (
unsigned var=0; var<
mVariables.size(); var++)
621 std::string full_name =
mVariables[var].mVariableName +
"(" +
mVariables[var].mVariableUnits +
")";
622 strcpy (col_data_offset, full_name.c_str());
623 col_data_offset +=
sizeof(char) * MAX_STRING_SIZE;
627 hid_t string_type = H5Tcopy(H5T_C_S1);
628 H5Tset_size(string_type, MAX_STRING_SIZE );
629 hid_t attr = H5Acreate(
mVariablesDatasetId,
"Variable Details", string_type, colspace, H5P_DEFAULT);
632 H5Awrite(attr, string_type, col_data);
641 colspace = H5Screate_simple(1, columns, NULL);
642 attr = H5Acreate(
mVariablesDatasetId,
"IsDataComplete", H5T_NATIVE_UINT, colspace, H5P_DEFAULT);
646 H5Awrite(attr, H5T_NATIVE_UINT, &is_data_complete);
656 colspace = H5Screate_simple(1, columns, NULL);
672 hsize_t time_dataset_max_dims[1] = {H5S_UNLIMITED};
678 hsize_t time_chunk_dims[1] = {128u};
679 hid_t time_cparms = H5Pcreate (H5P_DATASET_CREATE);
680 H5Pset_chunk( time_cparms, 1, time_chunk_dims);
682 hid_t time_filespace = H5Screate_simple(1, time_dataset_dims, time_dataset_max_dims);
695 hid_t one_column_space = H5Screate_simple(1, &one, NULL);
698 hid_t unit_attr = H5Acreate(
mUnlimitedDatasetId,
"Unit", string_type, one_column_space, H5P_DEFAULT);
701 hid_t name_attr = H5Acreate(
mUnlimitedDatasetId,
"Name", string_type, one_column_space, H5P_DEFAULT);
704 char unit_string[MAX_STRING_SIZE];
706 H5Awrite(unit_attr, string_type, unit_string);
709 char name_string[MAX_STRING_SIZE];
711 H5Awrite(name_attr, string_type, name_string);
714 H5Pclose(time_cparms);
715 H5Sclose(one_column_space);
718 H5Sclose(time_filespace);
726 const unsigned MAX_PROVENANCE_STRING_SIZE = 1023;
727 hid_t long_string_type = H5Tcopy(H5T_C_S1);
728 H5Tset_size(long_string_type, MAX_PROVENANCE_STRING_SIZE );
729 hsize_t prov_columns[1] = {1};
730 hid_t provenance_space = H5Screate_simple(1, prov_columns, NULL);
731 char* provenance_data = (
char*) malloc(
sizeof(
char) * MAX_PROVENANCE_STRING_SIZE);
735 hid_t prov_attr = H5Acreate(
mVariablesDatasetId,
"Chaste Provenance", long_string_type, provenance_space, H5P_DEFAULT);
738 H5Awrite(prov_attr, long_string_type, provenance_data);
741 free(provenance_data);
742 H5Sclose(provenance_space);
750 EXCEPTION(
"Cannot write data while in define mode.");
754 VecGetSize(petscVector, &vector_size);
758 EXCEPTION(
"Vector size doesn't match fixed dimension");
764 Vec output_petsc_vector;
770 output_petsc_vector = petscVector;
776 VecDuplicate(petscVector, &output_petsc_vector);
787 memspace = H5Screate_simple(1, v_size, NULL);
796 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
797 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
799 H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, offset_dims, NULL, count, NULL);
801 double* p_petsc_vector;
802 VecGetArray(output_petsc_vector, &p_petsc_vector);
806 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, p_petsc_vector);
818 double* p_petsc_vector_incomplete;
819 VecGetArray(output_petsc_vector, &p_petsc_vector_incomplete);
820 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, p_petsc_vector_incomplete);
825 boost::scoped_array<double> local_data(
new double[
mNumberOwned]);
831 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, local_data.get());
835 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
837 H5Pclose(property_list_id);
838 H5Sclose(file_dataspace);
844 if (petscVector != output_petsc_vector)
855 EXCEPTION(
"Cannot write data while in define mode.");
858 if (variableIDs.size() <= 1)
860 EXCEPTION(
"The PutStripedVector method requires at least two variables ID. If only one is needed, use PutVector method instead");
863 const unsigned NUM_STRIPES=variableIDs.size();
865 int firstVariableID=variableIDs[0];
868 for (
unsigned i = 1; i < variableIDs.size(); i++)
870 if (variableIDs[i]-variableIDs[i-1] != 1)
872 EXCEPTION(
"Columns should be consecutive. Try reordering them.");
877 VecGetSize(petscVector, &vector_size);
881 EXCEPTION(
"Vector size doesn't match fixed dimension");
887 Vec output_petsc_vector;
893 output_petsc_vector = petscVector;
899 VecDuplicate(petscVector, &output_petsc_vector);
909 memspace = H5Screate_simple(1, v_size, NULL);
916 hsize_t number_blocks[
DATASET_DIMS] = {1, 1, NUM_STRIPES};
919 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, start, stride, number_blocks, block_size);
922 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
923 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
925 double* p_petsc_vector;
926 VecGetArray(output_petsc_vector, &p_petsc_vector);
930 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector);
934 if (variableIDs.size() < 3)
944 double* p_petsc_vector_incomplete;
945 VecGetArray(output_petsc_vector, &p_petsc_vector_incomplete);
947 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector_incomplete);
952 boost::scoped_array<double> local_data(
new double[
mNumberOwned*NUM_STRIPES]);
956 local_data[NUM_STRIPES*i] = p_petsc_vector[ local_node_number*NUM_STRIPES ];
957 local_data[NUM_STRIPES*i+1] = p_petsc_vector[ local_node_number*NUM_STRIPES + 1];
960 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, local_data.get());
965 EXCEPTION(
"The PutStripedVector functionality for incomplete data is supported for only 2 stripes");
969 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
971 H5Sclose(hyperslab_space);
976 H5Pclose(property_list_id);
978 if (petscVector != output_petsc_vector)
989 EXCEPTION(
"Cannot write data while in define mode.");
994 EXCEPTION(
"PutUnlimitedVariable() called but no unlimited dimension has been set");
1006 hsize_t size[1] = {1};
1007 hid_t memspace = H5Screate_simple(1, size, NULL);
1010 hsize_t count[1] = {1};
1013 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset, NULL, count, NULL);
1015 H5Dwrite(
mUnlimitedDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, H5P_DEFAULT, &value);
1017 H5Sclose(hyperslab_space);
1040 const std::string& rVariableUnits,
1041 unsigned estimatedLength)
1045 EXCEPTION(
"Unlimited dimension already set. Cannot be defined twice");
1050 EXCEPTION(
"Cannot define variables when not in Define mode");
1063 EXCEPTION(
"Trying to advance along an unlimited dimension without having defined any");
1083 #if H5_VERS_MAJOR>=1 && H5_VERS_MINOR>=8 // HDF5 1.8+
1109 for (
unsigned index=0; index<
mVariables.size(); index++)
1111 if (
mVariables[index].mVariableName == rVariableName)
1119 EXCEPTION(
"Variable does not exist in hdf5 definitions.");
1128 EXCEPTION(
"Cannot define permutation when not in Define mode");
1131 if (rPermutation.empty())
1139 EXCEPTION(
"Permutation doesn't match the expected problem size");
1143 std::set<unsigned> permutation_pigeon_hole;
1146 bool identity_map =
true;
1149 permutation_pigeon_hole.insert(rPermutation[i]);
1150 if (identity_map && i != rPermutation[i])
1152 identity_map =
false;
1168 if (permutation_pigeon_hole.count(i) != 1u)
1170 EXCEPTION(
"Permutation vector doesn't contain a valid permutation");
1178 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
1186 for (
unsigned row_index=
mLo; row_index<
mHi; row_index++)
1192 MatSetValue(
mSinglePermutation, row_index, rPermutation[row_index], 1.0, INSERT_VALUES);
1194 unsigned bi_index = 2*row_index;
1195 unsigned perm_index = 2*rPermutation[row_index];
1213 const unsigned& rNodesPerChunk,
1214 const unsigned& rVariablesPerChunk)
1227 hsize_t num_chunks = 1;
1237 bool all_one_chunk =
true;
1238 unsigned chunk_size_in_bytes = 8u;
1252 all_one_chunk = all_one_chunk && divisors[i]==1u;
1255 *pChunkSizeInBytes = chunk_size_in_bytes;
1256 *pAllOneChunk = all_one_chunk;
1270 const unsigned recommended_max_number_chunks = 75000;
1283 unsigned target_size_in_bytes = 1024*1024/8;
1285 unsigned target_size = 0;
1286 unsigned chunk_size_in_bytes;
1299 while ( chunk_size_in_bytes < target_size_in_bytes && !all_one_chunk);
1302 if ( chunk_size_in_bytes > target_size_in_bytes && !all_one_chunk )
1317 target_size_in_bytes *= 2;
void ComputeIncompleteOffset()
hsize_t CalculateNumberOfChunks()
bool ApplyPermutation(const std::vector< unsigned > &rPermutation, bool unsafeExtendingMode=false)
Hdf5DataWriter(DistributedVectorFactory &rVectorFactory, const std::string &rDirectory, const std::string &rBaseName, bool cleanDirectory=true, bool extendData=false, std::string datasetName="Data")
bool mUseOptimalChunkSizeAlgorithm
std::string mUnlimitedDimensionName
void CheckVariableName(const std::string &rName)
int GetVariableByName(const std::string &rVariableName)
unsigned CeilDivide(unsigned numerator, unsigned denominator)
void SetUnlimitedDatasetId()
std::string GetAbsolutePath() const
std::string mUnlimitedDimensionUnit
#define EXCEPTION(message)
void CalculateChunkDims(unsigned targetSize, unsigned *pChunkSizeInBytes, bool *pAllOneChunk)
hid_t mVariablesDatasetId
void DefineFixedDimensionUsingMatrix(const std::vector< unsigned > &rNodesToOuput, long vecSize)
hid_t mUnlimitedDatasetId
bool mUseMatrixForIncompleteData
bool DoesDatasetExist(const std::string &rDatasetName)
bool mIsFixedDimensionSet
hsize_t mDatasetDims[DATASET_DIMS]
void SetMainDatasetRawChunkCache()
void SetFixedChunkSize(const unsigned &rTimestepsPerChunk, const unsigned &rNodesPerChunk, const unsigned &rVariablesPerChunk)
unsigned mEstimatedUnlimitedLength
void AdvanceAlongUnlimitedDimension()
std::vector< unsigned > mIncompleteNodeIndices
DistributedVectorFactory & mrVectorFactory
hsize_t mFixedChunkSize[DATASET_DIMS]
int DefineVariable(const std::string &rVariableName, const std::string &rVariableUnits)
Mat mDoubleIncompleteOutputMatrix
void PutVector(int variableID, Vec petscVector)
unsigned GetLocalOwnership() const
std::string mVariableName
void DefineFixedDimension(long dimensionSize)
static std::string GetProvenanceString()
virtual ~Hdf5DataWriter()
Mat mSingleIncompleteOutputMatrix
void CheckUnitsName(const std::string &rName)
void PutStripedVector(std::vector< int > variableIDs, Vec petscVector)
std::string mVariableUnits
std::vector< DataWriterVariable > mVariables
bool mIsUnlimitedDimensionSet
void PutUnlimitedVariable(double value)
static const unsigned DATASET_DIMS
unsigned mDataFixedDimensionSize
long unsigned mCurrentTimeStep
hsize_t mChunkSize[DATASET_DIMS]
unsigned mFileFixedDimensionSize
virtual void EndDefineMode()
void DefineUnlimitedDimension(const std::string &rVariableName, const std::string &rVariableUnits, unsigned estimatedLength=1)