40 #include <boost/scoped_array.hpp> 44 #include "Hdf5DataWriter.hpp" 48 #include "OutputFileHandler.hpp" 50 #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()),
74 mSinglePermutation(nullptr),
75 mDoublePermutation(nullptr),
76 mUseOptimalChunkSizeAlgorithm(true),
78 mChunkTargetSize(0x20000),
81 mCacheFirstTimeStep(0u)
92 EXCEPTION(
"You are asking to delete a file and then extend it, change arguments to constructor.");
98 EXCEPTION(
"Adding new data only makes sense when extending an existing file");
127 H5Sget_simple_extent_dims(variables_dataspace,
mDatasetDims, dataset_max_sizes);
128 H5Sclose(variables_dataspace);
131 if (dataset_max_sizes[0] != H5S_UNLIMITED)
135 EXCEPTION(
"Tried to open a datafile for extending which doesn't have an unlimited dimension.");
150 hid_t attribute_type = H5Aget_type(attribute_id);
151 hid_t attribute_space = H5Aget_space(attribute_id);
153 H5Sget_simple_extent_dims(attribute_space, &attr_dataspace_dim,
nullptr);
154 unsigned num_columns = H5Sget_simple_extent_npoints(attribute_space);
157 char* string_array = (
char*)malloc(
sizeof(
char) * MAX_STRING_SIZE * (int)num_columns);
158 H5Aread(attribute_id, attribute_type, string_array);
161 for (
unsigned index = 0; index < num_columns; index++)
164 std::string column_name_unit(&string_array[MAX_STRING_SIZE * index]);
167 size_t name_length = column_name_unit.find(
'(');
168 size_t unit_length = column_name_unit.find(
')') - name_length - 1;
173 var.
mVariableUnits = column_name_unit.substr(name_length + 1, unit_length);
179 H5Tclose(attribute_type);
180 H5Sclose(attribute_space);
181 H5Aclose(attribute_id);
189 H5Sget_simple_extent_dims(timestep_dataspace, &num_timesteps,
nullptr);
190 H5Sclose(timestep_dataspace);
196 if (attribute_id < 0)
200 EXCEPTION(
"Extending old-format files isn't supported.");
205 attribute_type = H5Aget_type(attribute_id);
206 attribute_space = H5Aget_space(attribute_id);
207 unsigned is_data_complete;
208 H5Aread(attribute_id, H5T_NATIVE_UINT, &is_data_complete);
210 H5Tclose(attribute_type);
211 H5Sclose(attribute_space);
212 H5Aclose(attribute_id);
224 attribute_type = H5Aget_type(attribute_id);
225 attribute_space = H5Aget_space(attribute_id);
228 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.");
295 EXCEPTION(
"Hdf5DataWriter could not open " + file_name +
" , as it does not exist.");
300 hid_t fapl = H5Pcreate(H5P_FILE_ACCESS);
301 H5Pset_fapl_mpio(fapl, PETSC_COMM_WORLD, MPI_INFO_NULL);
309 std::string attempting_to;
312 mFileId = H5Fopen(file_name.c_str(), H5F_ACC_RDWR, fapl);
313 attempting_to =
"open";
317 hid_t fcpl = H5Pcreate(H5P_FILE_CREATE);
351 mFileId = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, fcpl, fapl);
366 attempting_to =
"create";
375 EXCEPTION(
"Hdf5DataWriter could not " << attempting_to <<
" " << file_name <<
" , H5F" << attempting_to <<
" error code = " <<
mFileId);
383 EXCEPTION(
"Cannot define variables when not in Define mode");
385 if (dimensionSize < 1)
387 EXCEPTION(
"Fixed dimension must be at least 1 long");
391 EXCEPTION(
"Fixed dimension already set");
406 unsigned vector_size = rNodesToOuputOriginalIndices.size();
408 for (
unsigned index = 0; index < vector_size - 1; index++)
410 if (rNodesToOuputOriginalIndices[index] >= rNodesToOuputOriginalIndices[index + 1])
412 EXCEPTION(
"Input should be monotonic increasing");
416 if ((
int)rNodesToOuputOriginalIndices.back() >= vecSize || (int)rNodesToOuputPermutedIndices.back() >= vecSize)
418 EXCEPTION(
"Vector size doesn't match nodes to output");
438 std::vector<std::pair <unsigned, unsigned> > indices;
443 std::sort(indices.begin(),indices.end());
465 const std::string& rVariableUnits)
469 EXCEPTION(
"Cannot define variables when not in Define mode");
476 for (
unsigned index = 0; index <
mVariables.size(); index++)
478 if (
mVariables[index].mVariableName == rVariableName)
480 EXCEPTION(
"Variable name already exists");
501 if (rName.length() == 0)
503 EXCEPTION(
"Variable name not allowed: may not be blank.");
510 for (
unsigned i = 0; i < rName.length(); i++)
512 if (!isalnum(rName[i]) && !(rName[i] ==
'_'))
514 std::string error =
"Variable name/units '" + rName +
"' not allowed: may only contain alphanumeric characters or '_'.";
530 EXCEPTION(
"Cannot end define mode. No variables have been defined.");
536 EXCEPTION(
"Cannot end define mode. One fixed dimension should be defined.");
551 dataset_max_dims[0] = H5S_UNLIMITED;
555 dataset_max_dims[0] = 1;
570 hid_t cparms = H5Pcreate(H5P_DATASET_CREATE);
574 H5P_DEFAULT, cparms, H5P_DEFAULT);
580 const unsigned MAX_STRING_SIZE = 100;
582 hid_t colspace = H5Screate_simple(1, columns,
nullptr);
585 char* col_data = (
char*)malloc(
mVariables.size() *
sizeof(char) * MAX_STRING_SIZE);
587 char* col_data_offset = col_data;
588 for (
unsigned var = 0; var <
mVariables.size(); var++)
590 std::string full_name =
mVariables[var].mVariableName +
"(" +
mVariables[var].mVariableUnits +
")";
591 strcpy(col_data_offset, full_name.c_str());
592 col_data_offset +=
sizeof(char) * MAX_STRING_SIZE;
596 hid_t string_type = H5Tcopy(H5T_C_S1);
597 H5Tset_size(string_type, MAX_STRING_SIZE);
599 H5P_DEFAULT, H5P_DEFAULT);
602 H5Awrite(attr, string_type, col_data);
611 colspace = H5Screate_simple(1, columns,
nullptr);
613 H5P_DEFAULT, H5P_DEFAULT);
617 H5Awrite(attr, H5T_NATIVE_UINT, &is_data_complete);
627 colspace = H5Screate_simple(1, columns,
nullptr);
629 H5P_DEFAULT, H5P_DEFAULT);
644 hsize_t time_dataset_max_dims[1] = { H5S_UNLIMITED };
650 hsize_t time_chunk_dims[1] = { 128u };
651 hid_t time_cparms = H5Pcreate(H5P_DATASET_CREATE);
652 H5Pset_chunk(time_cparms, 1, time_chunk_dims);
654 hid_t time_filespace = H5Screate_simple(1, time_dataset_dims, time_dataset_max_dims);
664 H5P_DEFAULT, time_cparms, H5P_DEFAULT);
668 hid_t one_column_space = H5Screate_simple(1, &one,
nullptr);
672 H5P_DEFAULT, H5P_DEFAULT);
676 H5P_DEFAULT, H5P_DEFAULT);
679 char unit_string[MAX_STRING_SIZE];
681 H5Awrite(unit_attr, string_type, unit_string);
684 char name_string[MAX_STRING_SIZE];
686 H5Awrite(name_attr, string_type, name_string);
689 H5Pclose(time_cparms);
690 H5Sclose(one_column_space);
693 H5Sclose(time_filespace);
701 const unsigned MAX_PROVENANCE_STRING_SIZE = 1023;
702 hid_t long_string_type = H5Tcopy(H5T_C_S1);
703 H5Tset_size(long_string_type, MAX_PROVENANCE_STRING_SIZE);
704 hsize_t prov_columns[1] = { 1 };
705 hid_t provenance_space = H5Screate_simple(1, prov_columns,
nullptr);
706 char* provenance_data = (
char*)malloc(
sizeof(
char) * MAX_PROVENANCE_STRING_SIZE);
710 hid_t prov_attr = H5Acreate(
mVariablesDatasetId,
"Chaste Provenance", long_string_type, provenance_space,
711 H5P_DEFAULT, H5P_DEFAULT);
714 H5Awrite(prov_attr, long_string_type, provenance_data);
717 free(provenance_data);
718 H5Sclose(provenance_space);
726 EXCEPTION(
"Cannot write data while in define mode.");
730 VecGetSize(petscVector, &vector_size);
734 EXCEPTION(
"Vector size doesn't match fixed dimension");
742 EXCEPTION(
"Cached writes must write all variables at once.");
747 EXCEPTION(
"Cached writes require an unlimited dimension.");
754 Vec output_petsc_vector;
760 output_petsc_vector = petscVector;
766 VecDuplicate(petscVector, &output_petsc_vector);
773 hid_t memspace, hyperslab_space;
777 memspace = H5Screate_simple(1, v_size,
nullptr);
783 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset_dims,
nullptr, count,
nullptr);
787 memspace = H5Screate(H5S_NULL);
788 hyperslab_space = H5Screate(H5S_NULL);
792 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
793 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
795 double* p_petsc_vector;
796 VecGetArray(output_petsc_vector, &p_petsc_vector);
807 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector);
813 boost::scoped_array<double> local_data(
new double[
mNumberOwned]);
825 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, local_data.get());
829 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
832 H5Sclose(hyperslab_space);
833 H5Pclose(property_list_id);
835 if (petscVector != output_petsc_vector)
846 EXCEPTION(
"Cannot write data while in define mode.");
849 if (variableIDs.size() <= 1)
851 EXCEPTION(
"The PutStripedVector method requires at least two variables ID. If only one is needed, use PutVector method instead");
854 const unsigned NUM_STRIPES = variableIDs.size();
861 EXCEPTION(
"Cached writes must write all variables at once.");
866 EXCEPTION(
"Cached writes require an unlimited dimension.");
870 int firstVariableID = variableIDs[0];
873 for (
unsigned i = 1; i < variableIDs.size(); i++)
875 if (variableIDs[i] - variableIDs[i - 1] != 1)
877 EXCEPTION(
"Columns should be consecutive. Try reordering them.");
882 VecGetSize(petscVector, &vector_size);
886 EXCEPTION(
"Vector size doesn't match fixed dimension");
892 Vec output_petsc_vector;
898 output_petsc_vector = petscVector;
904 VecDuplicate(petscVector, &output_petsc_vector);
910 hid_t memspace, hyperslab_space;
914 memspace = H5Screate_simple(1, v_size,
nullptr);
922 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, start, stride, number_blocks, block_size);
926 memspace = H5Screate(H5S_NULL);
927 hyperslab_space = H5Screate(H5S_NULL);
931 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
932 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
934 double* p_petsc_vector;
935 VecGetArray(output_petsc_vector, &p_petsc_vector);
946 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector);
951 if (variableIDs.size() < 3)
954 boost::scoped_array<double> local_data(
new double[
mNumberOwned * NUM_STRIPES]);
958 local_data[NUM_STRIPES * i] = p_petsc_vector[local_node_number * NUM_STRIPES];
959 local_data[NUM_STRIPES * i + 1] = p_petsc_vector[local_node_number * NUM_STRIPES + 1];
969 H5Dwrite(
mVariablesDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, local_data.get());
974 EXCEPTION(
"The PutStripedVector functionality for incomplete data is supported for only 2 stripes");
978 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
981 H5Sclose(hyperslab_space);
982 H5Pclose(property_list_id);
984 if (petscVector != output_petsc_vector)
1001 if (!any_nonempty_caches)
1012 hid_t memspace, hyperslab_space;
1016 memspace = H5Screate_simple(1, v_size,
nullptr);
1023 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, start,
nullptr, count,
nullptr);
1027 memspace = H5Screate(H5S_NULL);
1028 hyperslab_space = H5Screate(H5S_NULL);
1032 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
1033 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
1040 H5Sclose(hyperslab_space);
1041 H5Pclose(property_list_id);
1051 EXCEPTION(
"Cannot write data while in define mode.");
1056 EXCEPTION(
"PutUnlimitedVariable() called but no unlimited dimension has been set");
1069 hid_t memspace = H5Screate_simple(1, size,
nullptr);
1075 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset,
nullptr, count,
nullptr);
1077 H5Dwrite(
mUnlimitedDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, H5P_DEFAULT, &value);
1079 H5Sclose(hyperslab_space);
1107 const std::string& rVariableUnits,
1108 unsigned estimatedLength)
1112 EXCEPTION(
"Unlimited dimension already set. Cannot be defined twice");
1117 EXCEPTION(
"Cannot define variables when not in Define mode");
1130 EXCEPTION(
"Trying to advance along an unlimited dimension without having defined any");
1181 for (
unsigned index = 0; index <
mVariables.size(); index++)
1183 if (
mVariables[index].mVariableName == rVariableName)
1191 EXCEPTION(
"Variable does not exist in hdf5 definitions.");
1200 EXCEPTION(
"Cannot define permutation when not in Define mode");
1203 if (rPermutation.empty())
1216 std::set<unsigned> permutation_pigeon_hole;
1219 bool identity_map =
true;
1222 permutation_pigeon_hole.insert(rPermutation[i]);
1223 if (identity_map && i != rPermutation[i])
1225 identity_map =
false;
1241 if (permutation_pigeon_hole.count(i) != 1u)
1243 EXCEPTION(
"Permutation vector doesn't contain a valid permutation");
1251 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x 1259 for (
unsigned row_index =
mLo; row_index <
mHi; row_index++)
1265 MatSetValue(
mSinglePermutation, row_index, rPermutation[row_index], 1.0, INSERT_VALUES);
1267 unsigned bi_index = 2 * row_index;
1268 unsigned perm_index = 2 * rPermutation[row_index];
1286 const unsigned& rNodesPerChunk,
1287 const unsigned& rVariablesPerChunk)
1310 bool all_one_chunk =
true;
1311 unsigned chunk_size_in_bytes = 8u;
1325 all_one_chunk = all_one_chunk && divisors[i] == 1u;
1328 *pChunkSizeInBytes = chunk_size_in_bytes;
1329 *pAllOneChunk = all_one_chunk;
1338 unsigned target_size = 0;
1339 unsigned chunk_size_in_bytes;
1349 while ( chunk_size_in_bytes < target_size_in_bytes && !all_one_chunk);
1352 if (chunk_size_in_bytes > target_size_in_bytes && !all_one_chunk)
1385 EXCEPTION(
"Cannot set chunk target size when not in define mode.");
1407 EXCEPTION(
"Alignment parameter can only be set for new HDF5 files.");
1412 EXCEPTION(
"Cannot set alignment parameter when not in define mode.");
void ComputeIncompleteOffset()
std::string GetAbsolutePath() const
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 mUnlimitedDimensionUnit
#define EXCEPTION(message)
void CalculateChunkDims(unsigned targetSize, unsigned *pChunkSizeInBytes, bool *pAllOneChunk)
hid_t mVariablesDatasetId
std::vector< unsigned > mIncompletePermIndices
hid_t mUnlimitedDatasetId
void SetTargetChunkSize(hsize_t targetSize)
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 GetLocalOwnership() const
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)
void PutVector(int variableID, Vec petscVector)
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()
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)