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,
60 mrVectorFactory(rVectorFactory),
61 mCleanDirectory(cleanDirectory),
62 mUseExistingFile(extendData),
63 mIsInDefineMode(true),
64 mIsFixedDimensionSet(false),
65 mEstimatedUnlimitedLength(1u),
66 mFileFixedDimensionSize(0u),
67 mDataFixedDimensionSize(0u),
68 mLo(mrVectorFactory.GetLow()),
69 mHi(mrVectorFactory.GetHigh()),
73 mUseMatrixForIncompleteData(false),
75 mSinglePermutation(nullptr),
76 mDoublePermutation(nullptr),
77 mSingleIncompleteOutputMatrix(nullptr),
78 mDoubleIncompleteOutputMatrix(nullptr),
79 mUseOptimalChunkSizeAlgorithm(true),
81 mChunkTargetSize(0x20000),
84 mCacheFirstTimeStep(0u)
95 EXCEPTION(
"You are asking to delete a file and then extend it, change arguments to constructor.");
101 EXCEPTION(
"Adding new data only makes sense when extending an existing file");
130 H5Sget_simple_extent_dims(variables_dataspace,
mDatasetDims, dataset_max_sizes);
131 H5Sclose(variables_dataspace);
134 if (dataset_max_sizes[0] != H5S_UNLIMITED)
138 EXCEPTION(
"Tried to open a datafile for extending which doesn't have an unlimited dimension.");
153 hid_t attribute_type = H5Aget_type(attribute_id);
154 hid_t attribute_space = H5Aget_space(attribute_id);
156 H5Sget_simple_extent_dims(attribute_space, &attr_dataspace_dim,
nullptr);
157 unsigned num_columns = H5Sget_simple_extent_npoints(attribute_space);
160 char* string_array = (
char *)malloc(
sizeof(
char)*MAX_STRING_SIZE*(int)num_columns);
161 H5Aread(attribute_id, attribute_type, string_array);
164 for (
unsigned index=0; index<num_columns; index++)
167 std::string column_name_unit(&string_array[MAX_STRING_SIZE*index]);
170 size_t name_length = column_name_unit.find(
'(');
171 size_t unit_length = column_name_unit.find(
')') - name_length - 1;
176 var.
mVariableUnits = column_name_unit.substr(name_length+1, unit_length);
182 H5Tclose(attribute_type);
183 H5Sclose(attribute_space);
184 H5Aclose(attribute_id);
192 H5Sget_simple_extent_dims(timestep_dataspace, &num_timesteps,
nullptr);
193 H5Sclose(timestep_dataspace);
199 if (attribute_id < 0)
203 EXCEPTION(
"Extending old-format files isn't supported.");
208 attribute_type = H5Aget_type(attribute_id);
209 attribute_space = H5Aget_space(attribute_id);
210 unsigned is_data_complete;
211 H5Aread(attribute_id, H5T_NATIVE_UINT, &is_data_complete);
213 H5Tclose(attribute_type);
214 H5Sclose(attribute_space);
215 H5Aclose(attribute_id);
227 attribute_type = H5Aget_type(attribute_id);
228 attribute_space = H5Aget_space(attribute_id);
231 unsigned num_node_indices = H5Sget_simple_extent_npoints(attribute_space);
239 H5Tclose(attribute_type);
240 H5Sclose(attribute_space);
241 H5Aclose(attribute_id);
253 EXCEPTION(
"Unable to extend an incomplete data file at present.");
258 H5Pget_chunk(dcpl, DATASET_DIMS,
mChunkSize );
303 EXCEPTION(
"Hdf5DataWriter could not open " + file_name +
" , as it does not exist.");
308 hid_t fapl = H5Pcreate(H5P_FILE_ACCESS);
309 H5Pset_fapl_mpio(fapl, PETSC_COMM_WORLD, MPI_INFO_NULL);
317 std::string attempting_to;
320 mFileId = H5Fopen(file_name.c_str(), H5F_ACC_RDWR, fapl);
321 attempting_to =
"open";
325 hid_t fcpl = H5Pcreate(H5P_FILE_CREATE);
359 mFileId = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, fcpl, fapl);
374 attempting_to =
"create";
383 EXCEPTION(
"Hdf5DataWriter could not " << attempting_to <<
" " << file_name <<
384 " , H5F" << attempting_to <<
" error code = " <<
mFileId);
392 EXCEPTION(
"Cannot define variables when not in Define mode");
394 if (dimensionSize < 1)
396 EXCEPTION(
"Fixed dimension must be at least 1 long");
400 EXCEPTION(
"Fixed dimension already set");
415 unsigned vector_size = rNodesToOuput.size();
417 for (
unsigned index=0; index < vector_size-1; index++)
419 if (rNodesToOuput[index] >= rNodesToOuput[index+1])
421 EXCEPTION(
"Input should be monotonic increasing");
425 if ((
int) rNodesToOuput.back() >= vecSize)
427 EXCEPTION(
"Vector size doesn't match nodes to output");
440 unsigned vector_size = rNodesToOuput.size();
442 for (
unsigned index=0; index < vector_size-1; index++)
444 if (rNodesToOuput[index] >= rNodesToOuput[index+1])
446 EXCEPTION(
"Input should be monotonic increasing");
450 if ((
int) rNodesToOuput.back() >= vecSize)
452 EXCEPTION(
"Vector size doesn't match nodes to output");
478 unsigned bi_index = 2*row_index;
479 unsigned perm_index = 2*rNodesToOuput[row_index];
515 const std::string& rVariableUnits)
519 EXCEPTION(
"Cannot define variables when not in Define mode");
526 for (
unsigned index=0; index<
mVariables.size(); index++)
528 if (
mVariables[index].mVariableName == rVariableName)
530 EXCEPTION(
"Variable name already exists");
551 if (rName.length() == 0)
553 EXCEPTION(
"Variable name not allowed: may not be blank.");
560 for (
unsigned i=0; i<rName.length(); i++)
562 if (!isalnum(rName[i]) && !(rName[i]==
'_'))
564 std::string error =
"Variable name/units '" + rName +
"' not allowed: may only contain alphanumeric characters or '_'.";
580 EXCEPTION(
"Cannot end define mode. No variables have been defined.");
586 EXCEPTION(
"Cannot end define mode. One fixed dimension should be defined.");
601 dataset_max_dims[0] = H5S_UNLIMITED;
605 dataset_max_dims[0] = 1;
620 hid_t cparms = H5Pcreate (H5P_DATASET_CREATE);
624 H5P_DEFAULT, cparms, H5P_DEFAULT);
630 const unsigned MAX_STRING_SIZE = 100;
632 hid_t colspace = H5Screate_simple(1, columns,
nullptr);
635 char* col_data = (
char*) malloc(
mVariables.size() *
sizeof(char) * MAX_STRING_SIZE);
637 char* col_data_offset = col_data;
638 for (
unsigned var=0; var<
mVariables.size(); var++)
640 std::string full_name =
mVariables[var].mVariableName +
"(" +
mVariables[var].mVariableUnits +
")";
641 strcpy (col_data_offset, full_name.c_str());
642 col_data_offset +=
sizeof(char) * MAX_STRING_SIZE;
646 hid_t string_type = H5Tcopy(H5T_C_S1);
647 H5Tset_size(string_type, MAX_STRING_SIZE );
649 H5P_DEFAULT, H5P_DEFAULT);
652 H5Awrite(attr, string_type, col_data);
661 colspace = H5Screate_simple(1, columns,
nullptr);
663 H5P_DEFAULT, H5P_DEFAULT);
667 H5Awrite(attr, H5T_NATIVE_UINT, &is_data_complete);
677 colspace = H5Screate_simple(1, columns,
nullptr);
679 H5P_DEFAULT, H5P_DEFAULT);
694 hsize_t time_dataset_max_dims[1] = {H5S_UNLIMITED};
700 hsize_t time_chunk_dims[1] = {128u};
701 hid_t time_cparms = H5Pcreate (H5P_DATASET_CREATE);
702 H5Pset_chunk( time_cparms, 1, time_chunk_dims);
704 hid_t time_filespace = H5Screate_simple(1, time_dataset_dims, time_dataset_max_dims);
714 H5P_DEFAULT, time_cparms, H5P_DEFAULT);
718 hid_t one_column_space = H5Screate_simple(1, &one,
nullptr);
722 H5P_DEFAULT, H5P_DEFAULT);
726 H5P_DEFAULT, H5P_DEFAULT);
729 char unit_string[MAX_STRING_SIZE];
731 H5Awrite(unit_attr, string_type, unit_string);
734 char name_string[MAX_STRING_SIZE];
736 H5Awrite(name_attr, string_type, name_string);
739 H5Pclose(time_cparms);
740 H5Sclose(one_column_space);
743 H5Sclose(time_filespace);
751 const unsigned MAX_PROVENANCE_STRING_SIZE = 1023;
752 hid_t long_string_type = H5Tcopy(H5T_C_S1);
753 H5Tset_size(long_string_type, MAX_PROVENANCE_STRING_SIZE );
755 hid_t provenance_space = H5Screate_simple(1, prov_columns,
nullptr);
756 char* provenance_data = (
char*) malloc(
sizeof(
char) * MAX_PROVENANCE_STRING_SIZE);
760 hid_t prov_attr = H5Acreate(
mVariablesDatasetId,
"Chaste Provenance", long_string_type, provenance_space,
761 H5P_DEFAULT, H5P_DEFAULT);
764 H5Awrite(prov_attr, long_string_type, provenance_data);
767 free(provenance_data);
768 H5Sclose(provenance_space);
776 EXCEPTION(
"Cannot write data while in define mode.");
780 VecGetSize(petscVector, &vector_size);
784 EXCEPTION(
"Vector size doesn't match fixed dimension");
792 EXCEPTION(
"Cached writes must write all variables at once.");
797 EXCEPTION(
"Cached writes require an unlimited dimension.");
804 Vec output_petsc_vector;
810 output_petsc_vector = petscVector;
816 VecDuplicate(petscVector, &output_petsc_vector);
823 hid_t memspace, hyperslab_space;
827 memspace = H5Screate_simple(1, v_size,
nullptr);
833 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset_dims,
nullptr, count,
nullptr);
837 memspace = H5Screate(H5S_NULL);
838 hyperslab_space = H5Screate(H5S_NULL);
842 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
843 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
845 double* p_petsc_vector;
846 VecGetArray(output_petsc_vector, &p_petsc_vector);
857 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector);
870 double* p_petsc_vector_incomplete;
871 VecGetArray(output_petsc_vector, &p_petsc_vector_incomplete);
880 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector_incomplete);
886 boost::scoped_array<double> local_data(
new double[
mNumberOwned]);
899 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, local_data.get());
904 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
907 H5Sclose(hyperslab_space);
908 H5Pclose(property_list_id);
910 if (petscVector != output_petsc_vector)
921 EXCEPTION(
"Cannot write data while in define mode.");
924 if (variableIDs.size() <= 1)
926 EXCEPTION(
"The PutStripedVector method requires at least two variables ID. If only one is needed, use PutVector method instead");
929 const unsigned NUM_STRIPES=variableIDs.size();
936 EXCEPTION(
"Cached writes must write all variables at once.");
941 EXCEPTION(
"Cached writes require an unlimited dimension.");
945 int firstVariableID=variableIDs[0];
948 for (
unsigned i = 1; i < variableIDs.size(); i++)
950 if (variableIDs[i]-variableIDs[i-1] != 1)
952 EXCEPTION(
"Columns should be consecutive. Try reordering them.");
957 VecGetSize(petscVector, &vector_size);
961 EXCEPTION(
"Vector size doesn't match fixed dimension");
967 Vec output_petsc_vector;
973 output_petsc_vector = petscVector;
979 VecDuplicate(petscVector, &output_petsc_vector);
985 hid_t memspace, hyperslab_space;
989 memspace = H5Screate_simple(1, v_size,
nullptr);
997 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, start, stride, number_blocks, block_size);
1001 memspace = H5Screate(H5S_NULL);
1002 hyperslab_space = H5Screate(H5S_NULL);
1006 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
1007 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
1009 double* p_petsc_vector;
1010 VecGetArray(output_petsc_vector, &p_petsc_vector);
1021 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector);
1026 if (variableIDs.size() < 3)
1036 double* p_petsc_vector_incomplete;
1037 VecGetArray(output_petsc_vector, &p_petsc_vector_incomplete);
1046 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector_incomplete);
1052 boost::scoped_array<double> local_data(
new double[
mNumberOwned*NUM_STRIPES]);
1056 local_data[NUM_STRIPES*i] = p_petsc_vector[ local_node_number*NUM_STRIPES ];
1057 local_data[NUM_STRIPES*i+1] = p_petsc_vector[ local_node_number*NUM_STRIPES + 1];
1067 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, local_data.get());
1073 EXCEPTION(
"The PutStripedVector functionality for incomplete data is supported for only 2 stripes");
1077 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
1080 H5Sclose(hyperslab_space);
1081 H5Pclose(property_list_id);
1083 if (petscVector != output_petsc_vector)
1100 if (!any_nonempty_caches)
1111 hid_t memspace, hyperslab_space;
1115 memspace = H5Screate_simple(1, v_size,
nullptr);
1122 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, start,
nullptr, count,
nullptr);
1126 memspace = H5Screate(H5S_NULL);
1127 hyperslab_space = H5Screate(H5S_NULL);
1131 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
1132 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
1139 H5Sclose(hyperslab_space);
1140 H5Pclose(property_list_id);
1150 EXCEPTION(
"Cannot write data while in define mode.");
1155 EXCEPTION(
"PutUnlimitedVariable() called but no unlimited dimension has been set");
1168 hid_t memspace = H5Screate_simple(1, size,
nullptr);
1174 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset,
nullptr, count,
nullptr);
1176 H5Dwrite(
mUnlimitedDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, H5P_DEFAULT, &value);
1178 H5Sclose(hyperslab_space);
1206 const std::string& rVariableUnits,
1207 unsigned estimatedLength)
1211 EXCEPTION(
"Unlimited dimension already set. Cannot be defined twice");
1216 EXCEPTION(
"Cannot define variables when not in Define mode");
1229 EXCEPTION(
"Trying to advance along an unlimited dimension without having defined any");
1280 for (
unsigned index=0; index<
mVariables.size(); index++)
1282 if (
mVariables[index].mVariableName == rVariableName)
1290 EXCEPTION(
"Variable does not exist in hdf5 definitions.");
1299 EXCEPTION(
"Cannot define permutation when not in Define mode");
1302 if (rPermutation.empty())
1310 EXCEPTION(
"Permutation doesn't match the expected problem size");
1314 std::set<unsigned> permutation_pigeon_hole;
1317 bool identity_map =
true;
1320 permutation_pigeon_hole.insert(rPermutation[i]);
1321 if (identity_map && i != rPermutation[i])
1323 identity_map =
false;
1339 if (permutation_pigeon_hole.count(i) != 1u)
1341 EXCEPTION(
"Permutation vector doesn't contain a valid permutation");
1349 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
1357 for (
unsigned row_index=
mLo; row_index<
mHi; row_index++)
1363 MatSetValue(
mSinglePermutation, row_index, rPermutation[row_index], 1.0, INSERT_VALUES);
1365 unsigned bi_index = 2*row_index;
1366 unsigned perm_index = 2*rPermutation[row_index];
1384 const unsigned& rNodesPerChunk,
1385 const unsigned& rVariablesPerChunk)
1408 bool all_one_chunk =
true;
1409 unsigned chunk_size_in_bytes = 8u;
1423 all_one_chunk = all_one_chunk && divisors[i]==1u;
1426 *pChunkSizeInBytes = chunk_size_in_bytes;
1427 *pAllOneChunk = all_one_chunk;
1436 unsigned target_size = 0;
1437 unsigned chunk_size_in_bytes;
1447 while ( chunk_size_in_bytes < target_size_in_bytes && !all_one_chunk);
1450 if (chunk_size_in_bytes > target_size_in_bytes && !all_one_chunk)
1483 EXCEPTION(
"Cannot set chunk target size when not in define mode.");
1505 EXCEPTION(
"Alignment parameter can only be set for new HDF5 files.");
1510 EXCEPTION(
"Cannot set alignment parameter when not in define mode.");
void ComputeIncompleteOffset()
hsize_t CalculateNumberOfChunks()
bool ApplyPermutation(const std::vector< unsigned > &rPermutation, bool unsafeExtendingMode=false)
bool mUseOptimalChunkSizeAlgorithm
std::string mUnlimitedDimensionName
void CheckVariableName(const std::string &rName)
const bool mUseExistingFile
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
void SetTargetChunkSize(hsize_t targetSize)
bool mUseMatrixForIncompleteData
bool DoesDatasetExist(const std::string &rDatasetName)
bool mIsFixedDimensionSet
hsize_t mDatasetDims[DATASET_DIMS]
const bool mCleanDirectory
void SetMainDatasetRawChunkCache()
void SetFixedChunkSize(const unsigned &rTimestepsPerChunk, const unsigned &rNodesPerChunk, const unsigned &rVariablesPerChunk)
unsigned mEstimatedUnlimitedLength
long unsigned mCacheFirstTimeStep
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
std::vector< double > mDataCache
void DefineFixedDimension(long dimensionSize)
Hdf5DataWriter(DistributedVectorFactory &rVectorFactory, const std::string &rDirectory, const std::string &rBaseName, bool cleanDirectory=true, bool extendData=false, std::string datasetName="Data", bool useCache=false)
void SetAlignment(hsize_t alignment)
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)