Commit a1e47c27 authored by Fabian.Wein's avatar Fabian.Wein
Browse files

Apply changes for third review round

parent 854e24f3
Pipeline #286787 waiting for manual action with stages
......@@ -35,35 +35,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace H5CFS
{
//-----------------------------------------------------------------------------
std::string GetObjNameByIdx(hid_t loc, hsize_t idx)
{
// We first obtain the length of the name, then by the same function write the name to a buffer
// and third copy it to a std::string we return. There is no shortcut possible
// nullptr for name gives the length
ssize_t name_len = H5Lget_name_by_idx(loc, ".", H5_INDEX_NAME, H5_ITER_NATIVE, idx, nullptr, 0, 0);
if(name_len < 0)
ssize_t nameLen = H5Lget_name_by_idx(loc, ".", H5_INDEX_NAME, H5_ITER_NATIVE, idx, nullptr, 0, 0);
if(nameLen < 0)
{
throw std::runtime_error("Was not able to determine name" );
}
// now, allocate buffer to get the name, we may not write to std::string data directly. std::make_unique is not C++11
// https://stackoverflow.com/questions/1042940/writing-directly-to-stdstring-internal-buffers
std::vector<char> buf(name_len+1); // the trailing NULL is written but not counted
std::vector<char> buf(nameLen+1); // the trailing NULL is written but not counted
if(H5Lget_name_by_idx(loc, ".", H5_INDEX_NAME, H5_ITER_NATIVE, idx, buf.data(), name_len+1,0) < 0)
if(H5Lget_name_by_idx(loc, ".", H5_INDEX_NAME, H5_ITER_NATIVE, idx, buf.data(), nameLen+1,0) < 0)
{
throw std::runtime_error(std::string("error obtaining obj name with index ") + std::to_string(idx) + " of size " + std::to_string(name_len));
throw std::runtime_error(std::string("error obtaining obj name with index ") + std::to_string(idx) + " of size " + std::to_string(nameLen));
}
std::string name(buf.data());
return name;
}
hid_t OpenGroup(hid_t loc, const std::string& name, bool throw_exception)
//-----------------------------------------------------------------------------
hid_t OpenGroup(hid_t loc, const std::string& name, bool throwException)
{
hid_t ret = H5Gopen(loc, name.c_str(), H5P_DEFAULT);
if(ret < 0 && throw_exception)
if(ret < 0 && throwException)
{
throw std::runtime_error("cannot open group '" + name + "'");
}
......@@ -71,6 +73,7 @@ hid_t OpenGroup(hid_t loc, const std::string& name, bool throw_exception)
return ret;
}
//-----------------------------------------------------------------------------
hid_t OpenDataSet(hid_t loc, const std::string& name)
{
hid_t ret = H5Dopen(loc, name.c_str(), H5P_DEFAULT);
......@@ -82,7 +85,7 @@ hid_t OpenDataSet(hid_t loc, const std::string& name)
return ret;
}
//-----------------------------------------------------------------------------
H5G_info_t GetInfo(hid_t group_id)
{
H5G_info_t info;
......@@ -94,46 +97,51 @@ H5G_info_t GetInfo(hid_t group_id)
return info;
}
int GetDataSetSize(hid_t loc_id, const char *name)
//-----------------------------------------------------------------------------
int GetDataSetSize(hid_t loc_id, const char *dsetName)
{
int val = 0;
if(H5LTget_dataset_ndims(loc_id, name, &val) < 0)
if(H5LTget_dataset_ndims(loc_id, dsetName, &val) < 0)
{
throw std::runtime_error("cannot get size of data set '" + std::string(name) + "'");
throw std::runtime_error("cannot get size of data set '" + std::string(dsetName) + "'");
}
return val;
}
//-----------------------------------------------------------------------------
template<>
void ReadAttribute<int>(hid_t loc_id, const std::string& obj_name, const std::string& attr_name, int& data)
void ReadAttribute<int>(hid_t loc_id, const std::string& objName, const std::string& attrName, int& data)
{
if(H5LTget_attribute_int(loc_id, obj_name.c_str(), attr_name.c_str(), &data) < 0)
if(H5LTget_attribute_int(loc_id, objName.c_str(), attrName.c_str(), &data) < 0)
{
throw std::runtime_error(std::string("cannot read int attribute ") + obj_name + "/" + attr_name);
throw std::runtime_error(std::string("cannot read int attribute ") + objName + "/" + attrName);
}
}
//-----------------------------------------------------------------------------
template<>
void ReadAttribute<unsigned int>(hid_t loc_id, const std::string& obj_name, const std::string& attr_name, unsigned int& data)
void ReadAttribute<unsigned int>(hid_t loc_id, const std::string& objName, const std::string& attrName, unsigned int& data)
{
if(H5LTget_attribute_uint(loc_id, obj_name.c_str(), attr_name.c_str(), &data) < 0)
if(H5LTget_attribute_uint(loc_id, objName.c_str(), attrName.c_str(), &data) < 0)
{
throw std::runtime_error(std::string("cannot read uint attribute ") + obj_name + "/" + attr_name);
throw std::runtime_error(std::string("cannot read uint attribute ") + objName + "/" + attrName);
}
}
//-----------------------------------------------------------------------------
template<>
void ReadAttribute<double>(hid_t loc_id, const std::string& obj_name, const std::string& attr_name, double& data)
void ReadAttribute<double>(hid_t loc_id, const std::string& objName, const std::string& attrName, double& data)
{
if(H5LTget_attribute_double(loc_id, obj_name.c_str(), attr_name.c_str(), &data) < 0)
if(H5LTget_attribute_double(loc_id, objName.c_str(), attrName.c_str(), &data) < 0)
{
throw std::runtime_error(std::string("cannot read double attribute ") + obj_name + "/" + attr_name);
throw std::runtime_error(std::string("cannot read double attribute ") + objName + "/" + attrName);
}
}
//-----------------------------------------------------------------------------
template<>
void ReadAttribute<std::string>(hid_t loc_id, const std::string& obj_name, const std::string& attr_name, std::string& data)
void ReadAttribute<std::string>(hid_t loc_id, const std::string& objName, const std::string& attrName, std::string& data)
{
// H5LTget_attribute_string is a very poorly described function
// it has a char* data with OUT: Buffer with data.
......@@ -142,14 +150,15 @@ void ReadAttribute<std::string>(hid_t loc_id, const std::string& obj_name, const
// https://stackoverflow.com/questions/64467420/how-to-use-the-h5ltget-attribute-string-function
char* out = nullptr;
if(H5LTget_attribute_string(loc_id, obj_name.c_str(), attr_name.c_str(), reinterpret_cast<char*>(&out)) < 0) // see comment for cast
if(H5LTget_attribute_string(loc_id, objName.c_str(), attrName.c_str(), reinterpret_cast<char*>(&out)) < 0) // see comment for cast
{
throw std::runtime_error(std::string("cannot obtain string attribute value for ") + obj_name + "/" + attr_name);
throw std::runtime_error(std::string("cannot obtain string attribute value for ") + objName + "/" + attrName);
}
data = std::string(out);
}
//-----------------------------------------------------------------------------
std::vector<unsigned int> GetArrayDims(hid_t loc, const std::string& name)
{
hid_t set = OpenDataSet(loc, name);
......@@ -181,7 +190,7 @@ std::vector<unsigned int> GetArrayDims(hid_t loc, const std::string& name)
return ret;
}
//-----------------------------------------------------------------------------
unsigned int GetNumEntries(hid_t id, const std::string& name)
{
hid_t set = OpenDataSet(id, name);
......@@ -205,6 +214,7 @@ unsigned int GetNumEntries(hid_t id, const std::string& name)
return npoints;
}
//-----------------------------------------------------------------------------
template<>
void ReadDataSet<double>(hid_t loc, const std::string& name, double* out)
{
......@@ -215,6 +225,7 @@ void ReadDataSet<double>(hid_t loc, const std::string& name, double* out)
}
}
//-----------------------------------------------------------------------------
template<>
void ReadDataSet<int>(hid_t loc, const std::string& name, int* out)
{
......@@ -225,12 +236,14 @@ void ReadDataSet<int>(hid_t loc, const std::string& name, int* out)
}
}
//-----------------------------------------------------------------------------
template<>
void ReadDataSet<unsigned int>(hid_t loc, const std::string& name, unsigned int* out)
{
return ReadDataSet(loc, name, reinterpret_cast<int*>(out)); // no uint version in HL available :(
}
//-----------------------------------------------------------------------------
template<>
void ReadDataSet<std::string>(hid_t loc, const std::string& name, std::string* out)
{
......@@ -244,7 +257,7 @@ void ReadDataSet<std::string>(hid_t loc, const std::string& name, std::string* o
*out = std::string(buffer); // convert to string
}
//-----------------------------------------------------------------------------
template<typename TYPE>
TYPE ReadDataSet(hid_t loc, const std::string& name)
{
......@@ -254,7 +267,7 @@ TYPE ReadDataSet(hid_t loc, const std::string& name)
return val;
}
//-----------------------------------------------------------------------------
template<typename TYPE>
void ReadArray(hid_t loc, const std::string& name, std::vector<TYPE>& data)
{
......@@ -262,6 +275,7 @@ void ReadArray(hid_t loc, const std::string& name, std::vector<TYPE>& data)
ReadDataSet(loc, name, data.data()); // directly write to the vector data space
}
//-----------------------------------------------------------------------------
template<>
void ReadArray<std::string>(hid_t loc, const std::string& name, std::vector<std::string>& data)
{
......@@ -280,7 +294,7 @@ void ReadArray<std::string>(hid_t loc, const std::string& name, std::vector<std:
}
}
//-----------------------------------------------------------------------------
/** little helper to for root based key for simulation results. */
std::string GetMultiStepKey(unsigned int msStep, bool isHistory)
{
......@@ -292,12 +306,14 @@ std::string GetMultiStepKey(unsigned int msStep, bool isHistory)
return ss.str();
}
//-----------------------------------------------------------------------------
hid_t GetMultiStepGroup(hid_t root, unsigned int msStep, bool isHistory)
{
return OpenGroup(root, GetMultiStepKey(msStep, isHistory));
}
//-----------------------------------------------------------------------------
hid_t GetStepGroup(hid_t root, unsigned int msStep, unsigned int stepNum)
{
// no history but element/node result
......@@ -305,42 +321,42 @@ hid_t GetStepGroup(hid_t root, unsigned int msStep, unsigned int stepNum)
return OpenGroup(root, key);
}
//-----------------------------------------------------------------------------
std::string MapUnknownTypeAsString(EntityType t)
{
std::string definedOn;
switch(t)
{
case NODE:
case H5CFS::NODE:
definedOn = "Nodes";
break;
case EDGE:
case H5CFS::EDGE:
definedOn = "Edges";
break;
case FACE:
case H5CFS::FACE:
definedOn = "Faces";
break;
case ELEMENT:
case SURF_ELEM:
case H5CFS::ELEMENT:
case H5CFS::SURF_ELEM:
definedOn = "Elements";
break;
case PFEM:
case H5CFS::PFEM:
definedOn = "Nodes";
break;
case REGION:
case H5CFS::REGION:
definedOn = "Regions";
break;
case SURF_REGION:
case H5CFS::SURF_REGION:
definedOn = "ElementGroup";
break;
case NODE_GROUP:
case H5CFS::NODE_GROUP:
definedOn = "NodeGroup";
break;
case COIL:
case H5CFS::COIL:
definedOn = "Coils";
break;
case FREE:
case H5CFS::FREE:
definedOn = "Unknowns";
break;
}
......
......@@ -55,6 +55,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace H5CFS
{
/**
* openCFS element types
*/
typedef enum
{
ET_UNDEF = 0,
......@@ -79,6 +82,9 @@ typedef enum
ET_WEDGE18 = 18
} ElemType;
/**
* Number of nodes sorted by H5CFS::ElemType
*/
const std::array<int, 20> NUM_ELEM_NODES = {
0, // ET_UNDEF
1, // ET_POINT
......@@ -102,9 +108,9 @@ const std::array<int, 20> NUM_ELEM_NODES = {
14 // ET_PYRA14
};
//! Typedef describing the entryType of the result
//! This must be kept in sync with the values defined in
//! source/DataInOut/SimInOut/hdf5/hdf5io.cc.
/**
* openCFS entry types
*/
typedef enum
{
UNKNOWN = 0,
......@@ -114,9 +120,9 @@ typedef enum
STRING = 32
} EntryType;
//! Entity types a result is related to
//! This must be kept in sync with the values defined in
//! source/DataInOut/SimInOut/hdf5/hdf5io.cc.
/**
* openCFS entity types
*/
typedef enum
{
NODE = 1,
......@@ -132,7 +138,9 @@ typedef enum
FREE = 11
} EntityType;
//! Type of analysis
/**
* openCFS analysis type
*/
typedef enum
{
NO_ANALYSIS_TYPE = -1,
......@@ -145,23 +153,23 @@ typedef enum
EIGENVALUE = 7
} AnalysisType;
// =======================================================================
// HELPER CLASSES
// =======================================================================
//! Description of a result
/**
* Meta data of a result within the openCFS h5 file
*/
struct ResultInfo
{
std::string name;
std::string unit;
std::vector<std::string> dofNames;
EntryType entryType = UNKNOWN;
EntityType listType = FREE;
EntryType entryType = H5CFS::UNKNOWN;
EntityType listType = H5CFS::FREE;
std::string listName;
bool isHistory = false;
};
//! Result object itself
/**
* The values of a single openCFS result
*/
struct Result
{
std::shared_ptr<ResultInfo> resultInfo;
......@@ -170,98 +178,143 @@ struct Result
std::vector<double> imagVals;
};
//! Common I/O routines for accessing hdf5 files in CFS format
//! This helper fumctions provides convenience methods and abstractions from
//! the hdf5-native datatypes to native C++ ones, like e.g. reading and
//! writing arrays (int, double, string). It also allows the control
//! of the compression and chuncking settings of the hdf5 format.
//! Currently this api can treat 1D and 2D arrays
//! Get name of an object in a group with given index
//! This method retrieves the name of an object ob a group with given
//! index.
//! \note This methods replaces the buggy method
//! H5::H5Location::getObjnameByIdx(), which skips by default the last
//! character of the groupname
std::string GetObjNameByIdx(hid_t loc, hsize_t idx); // killme
/**
* Wrapper for H5 c-api H5Lget_name_by_idx
*
* Including memory and error management
* @throws std::runtime_error
*/
std::string GetObjNameByIdx(hid_t loc, hsize_t idx);
/** helper to open a group
* @param throw_exception throw an exception on error
* @return negtive if not found but not throw_exception */
hid_t OpenGroup(hid_t loc, const std::string& name, bool throw_exception = true);
/**
* Wrapper for H5 c-api H5Gopen
*
* @param throwException throw an exception on error
* @return negtive if not found but not throwException
* @throws std::runtime_error
*/
hid_t OpenGroup(hid_t loc, const std::string& name, bool throwException = true);
/** helper to open a dataset, throws exception */
/**
* Wrapper for H5 c-api H5Dopen
*
* @throws std::runtime_error
*/
hid_t OpenDataSet(hid_t loc, const std::string& name);
/** little helper returns the info struct */
/**
* Wrapper for H5 c-api H5Gget_info
*
* @throws std::runtime_error
*/
H5G_info_t GetInfo(hid_t group_id);
/** little helper for dataset ndims */
int GetDataSetSize(hid_t loc_id, const char* dset_name);
/**
* Wrapper for H5 c-api H5LTget_dataset_ndims
*
* @throws std::runtime_error
*/
int GetDataSetSize(hid_t loc_id, const char* dsetName);
/** read an attribute
/**
* Read h5 attribute via H5LTget_attribute_uint, and other types.
*
* Implemented via template specific implementations.
* @param loc_id group or file
* @param obj_name element of loc_id object
* @param data output */
* @param data output
* @throws std::runtime_error
*/
template <typename TYPE>
void ReadAttribute(
hid_t loc_id, const std::string& obj_name, const std::string& attr_name, TYPE& data);
hid_t loc_id, const std::string& obj_name, const std::string& attrName, TYPE& data);
/** convenience ReadAttribute which provides own variable space */
/**
* Convenience ReadAttribute which provides own variable space
*/
template <typename TYPE>
TYPE ReadAttribute(hid_t loc_id, const std::string& obj_name, const std::string& attr_name)
TYPE ReadAttribute(hid_t loc_id, const std::string& obj_name, const std::string& attrName)
{
TYPE val;
ReadAttribute(loc_id, obj_name, attr_name, val);
ReadAttribute(loc_id, obj_name, attrName, val);
return val;
}
/** read an attribute of the given group id
* @param data output */
/**
* Read an attribute of the given group id.
*
* Assumes the current object ('.')
* @see ReadAttribute
*/
template <typename TYPE>
TYPE ReadAttribute(hid_t loc_id, const std::string& attr_name)
TYPE ReadAttribute(hid_t loc_id, const std::string& attrName)
{
TYPE val;
ReadAttribute(loc_id, ".", attr_name, val); // object name is this name
ReadAttribute(loc_id, ".", attrName, val); // object name is this name
return val;
}
/** simple wrapper to the HL H5LTread_dataset_* functions */
/**
* Wrapper to the HL H5LTread_dataset_* functions
*
* Template instants for the types are implemented.
* @throws std::runtime_error
*/
template <typename TYPE>
void ReadDataSet(hid_t loc, const std::string& name, TYPE* out);
/** convenience variant of ReadDataSet with return value */
/**
* Convenience variant of ReadDataSet with return value
*
* @throws std::runtime_error
*/
template <typename TYPE>
TYPE ReadDataSet(hid_t loc, const std::string& name);
/** Retrieve rank and dimensionality of a dataset
* and return total number of entries in the dataset */
/**
* Retrieve rank and dimensionality of a dataset
*
* @return total number of entries in the dataset
* @throws std::runtime_error
*/
std::vector<unsigned int> GetArrayDims(hid_t loc, const std::string& name);
//! Return number of entries of a dataset / rray
/**
* Return number of entries of a dataset / array
*
* @throws std::runtime_error
*/
unsigned int GetNumEntries(hid_t id, const std::string& name);
//! Retrieve array data from a dataset
//! Read data from a an dataset of arbitrary dimension into a linear buffer
//! Note, that the memory has to be allocated from outside
/** Read data from a dataset into a stl vector */
/**
* Retrieve array data from a dataset
*
* Read data from a an dataset of arbitrary dimension into a linear buffer
* Read data from a dataset into a stl vector
* @throws std::runtime_error
*/
template <typename TYPE>
void ReadArray(hid_t loc, const std::string& name, std::vector<TYPE>& data);
/** Obtain grid result group for specified multisequence step.
/**
* Obtain grid result group for specified multisequence step.
*
* @param msStep 1-based multisequence step. There is always at least the first one.
* @param isHistory indicated region result instead of element/node result */
* @param isHistory indicated region result instead of element/node result
* @throws std::runtime_error
*/
hid_t GetMultiStepGroup(hid_t root, unsigned int msStep, bool isHistory);
/** Obtain grid result group for specified step in a given multistep element/node result
/**
* Obtain grid result group for specified step in a given multistep element/node result
*
* @param stepNum the 0-based step for nodal and element results
* @see GetMultiStepGroup() */
hid_t GetStepGroup(hid_t root, unsigned int msStep, unsigned int stepNum);
//! Map EntityUnknownType enum to string representation
/**
* Map EntityUnknownType enum to string representation
*/
std::string MapUnknownTypeAsString(EntityType t);
} // end of namespace H5CFS
......
......@@ -47,11 +47,11 @@ Hdf5Reader::~Hdf5Reader()
void Hdf5Reader::CloseFile()
{
if(main_file_ != -1)
if(mainFile_ != -1)
{
H5Gclose(main_root_);
H5Fclose(main_file_);
main_file_ = -1;
H5Gclose(mainRoot_);
H5Fclose(mainFile_);
mainFile_ = -1;
}
}
......@@ -63,17 +63,17 @@ void Hdf5Reader::LoadFile(const std::string& fileName)
baseDir_ = vtksys::SystemTools::GetParentDirectory(fileName_); // used to load external results
//! open file and store main group and mesh group
main_file_ = H5Fopen(fileName_.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
if(main_file_ < 0)
mainFile_ = H5Fopen(fileName_.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
if(mainFile_ < 0)
{
throw std::runtime_error(std::string("cannot open file ") + fileName_);
}
main_root_ = OpenGroup(main_file_, "/");
mesh_root_ = OpenGroup(main_root_, "Mesh");
mainRoot_ = OpenGroup(mainFile_, "/");
meshRoot_ = OpenGroup(mainRoot_, "Mesh");
// check for use of external files (uint to bool)
hasExternalFiles_ = ReadAttribute<unsigned int>(main_root_, "Results/Mesh","ExternalFiles") != 0;
hasExternalFiles_ = ReadAttribute<unsigned int>(mainRoot_, "Results/Mesh","ExternalFiles") != 0;
// read general mesh information
ReadMeshStats();
......@@ -81,24 +81,24 @@ void Hdf5Reader::LoadFile(const std::string& fileName)
unsigned int Hdf5Reader::GetDim() const
{
return H5CFS::ReadAttribute<unsigned int>(mesh_root_, "Dimension");
return H5CFS::ReadAttribute<unsigned int>(meshRoot_, "Dimension");
}
unsigned int Hdf5Reader::GetGridOrder() const