From 5eb841ecdf61c652e4731bd91d8917f6fcecd48b Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Fri, 13 Nov 2009 21:48:01 +0000 Subject: [PATCH] tag implementation, bugfixes ... --- .gitattributes | 5 + src/h5_core/h5t_core.h | 79 ++++ src/h5_core/h5t_core_private.h | 21 + src/h5_core/h5t_tags.c | 797 +++++++++++++++++++++++++++++++++ src/h5_core/h5t_tags.h | 19 + src/h5_core/h5t_tags_private.h | 86 ++++ 6 files changed, 1007 insertions(+) create mode 100644 src/h5_core/h5t_core.h create mode 100644 src/h5_core/h5t_core_private.h create mode 100644 src/h5_core/h5t_tags.c create mode 100644 src/h5_core/h5t_tags.h create mode 100644 src/h5_core/h5t_tags_private.h diff --git a/.gitattributes b/.gitattributes index e6fc3f2..202e2b7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -421,6 +421,8 @@ src/h5_core/h5t_boundaries.h -text src/h5_core/h5t_boundaries_private.h -text src/h5_core/h5t_consts.c -text src/h5_core/h5t_consts_private.h -text +src/h5_core/h5t_core.h -text +src/h5_core/h5t_core_private.h -text src/h5_core/h5t_errorhandling.c -text src/h5_core/h5t_errorhandling_private.h -text src/h5_core/h5t_hsearch.c -text @@ -441,6 +443,9 @@ src/h5_core/h5t_retrieve_private.h -text src/h5_core/h5t_storemesh.c -text src/h5_core/h5t_storemesh.h -text src/h5_core/h5t_storemesh_private.h -text +src/h5_core/h5t_tags.c -text +src/h5_core/h5t_tags.h -text +src/h5_core/h5t_tags_private.h -text src/h5_core/h5t_types_private.h -text src/h5_core/h5u_errorhandling_private.h -text src/h5_core/h5u_readwrite.c -text diff --git a/src/h5_core/h5t_core.h b/src/h5_core/h5t_core.h new file mode 100644 index 0000000..3c2e278 --- /dev/null +++ b/src/h5_core/h5t_core.h @@ -0,0 +1,79 @@ +#ifndef __H5T_CORE_H +#define __H5T_CORE_H + +#include "h5t_adjacencies.h" +#include "h5t_boundaries.h" +#include "h5t_inquiry.h" +#include "h5t_map.h" +#include "h5t_openclose.h" +#include "h5t_readwrite.h" +#include "h5t_retrieve.h" +#include "h5t_storemesh.h" +#include "h5t_tags.h" + +/* + ID's: 64bit + + Vertices: + 000100vv tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt + 3V TT TT TT TT TT TT + + Edges: + 00100eee tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt + 2E TT TT TT TT TT TT + + Trinagles: + 001100dd tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt + 1D TT TT TT TT TT TT + + Tets: + 01000000 tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt tttttttt + 00 TT TT TT TT TT TT + +*/ +#define H5T_ELEM_MASK ( (h5_id_t) (ULLONG_MAX >> 8) ) +#define H5T_ETYPE_MASK ( 7ull << (sizeof(h5_id_t)*8-4) ) +#define H5T_COMPONENT_MASK (~H5T_ELEM_MASK) +#define H5T_COMPONENT_ID_MASK (15ull << (sizeof(h5_id_t)*7) ) + +#define H5T_ETYPE_VERTEX ((h5_id_t)1) +#define H5T_ETYPE_EDGE ((h5_id_t)2) +#define H5T_ETYPE_TRIANGLE ((h5_id_t)3) +#define H5T_ETYPE_TET ((h5_id_t)4) + +#define _h5t_set_entity_type( type, elem_idx ) \ + ( \ + ((h5_id_t)(type) << (sizeof(h5_id_t)*8-4)) | \ + ((h5_id_t)(elem_idx)) \ + ) +#define _h5t_get_entity_type( entity_id ) \ + ((entity_id & H5T_ETYPE_MASK) >> (sizeof(h5_id_t)*8-4)) + + + +#define _h5t_build_id( type, comp_idx, elem_idx ) \ + ( \ + ((h5_id_t)(type) << (sizeof(h5_id_t)*8-4)) | \ + ((h5_id_t)(comp_idx) << (sizeof(h5_id_t)*7)) | \ + ((h5_id_t)(elem_idx) & H5T_ELEM_MASK) \ + ) + +#define _h5t_build_vertex_id( comp_idx, elem_idx ) \ + ( _h5t_build_id ( H5T_ETYPE_VERTEX, comp_idx, elem_idx ) ) + +#define _h5t_build_edge_id( comp_idx, elem_idx ) \ + ( _h5t_build_id ( H5T_ETYPE_EDGE, comp_idx, elem_idx ) ) + +#define _h5t_build_triangle_id( comp_idx, elem_idx ) \ + ( _h5t_build_id ( H5T_ETYPE_TRIANGLE, comp_idx, elem_idx ) ) + +#define _h5t_build_elem_id( elem_idx ) \ + ( _h5t_build_id ( f->t->mesh_type, 0, elem_idx ) ) + +#define _h5t_get_face_id( entity_id ) \ + ( (entity_id & H5T_COMPONENT_ID_MASK) >> (sizeof(h5_id_t)*7) ) + +#define _h5t_get_elem_idx( entity_id ) \ + ( entity_id & H5T_ELEM_MASK ) + +#endif diff --git a/src/h5_core/h5t_core_private.h b/src/h5_core/h5t_core_private.h new file mode 100644 index 0000000..7f62865 --- /dev/null +++ b/src/h5_core/h5t_core_private.h @@ -0,0 +1,21 @@ +#ifndef __H5T_CORE_PRIVATE_H +#define __H5T_CORE_PRIVATE_H + +#define H5T_CONTAINER_GRPNAME "Topo" + +#include "h5t_adjacencies_private.h" +#include "h5t_boundaries_private.h" +#include "h5t_consts_private.h" +#include "h5t_errorhandling_private.h" +#include "h5t_hsearch_private.h" +#include "h5t_map_private.h" +#include "h5t_readwrite_private.h" +#include "h5t_storemesh_private.h" +#include "h5t_tags_private.h" + +#include "h5t_types_private.h" + +#include "h5t_retrieve_private.h" + + +#endif diff --git a/src/h5_core/h5t_tags.c b/src/h5_core/h5t_tags.c new file mode 100644 index 0000000..77d89be --- /dev/null +++ b/src/h5_core/h5t_tags.c @@ -0,0 +1,797 @@ +#include +#include +#include + +#include "h5_core/h5_core.h" +#include "h5_core/h5_core_private.h" + +/* + To discuss: + - read tagsets on demand + */ + +/* + Initialize a tag container + */ + +static h5_err_t +_init_container ( + h5_file_t * const f, + const size_t ntags, + h5t_tagcontainer_t * container + ) { + container->names = _h5_calloc ( f, ntags, sizeof(char*) ); + TRY ( _h5_hcreate_string_keyed ( f, ntags, &container->sets ) ); + return H5_SUCCESS; +} +/* + Initialize tag container for current mesh and level. + */ +h5_err_t +_h5t_init_mtagsets ( + h5_file_t * const f, + size_t ntags + ) { + return _init_container ( f, ntags, &f->t->mtags ); +} + +/* + Release all tag values for a specific element + */ +static h5_err_t +_release_tagvals_of_elem ( + h5_file_t * const f, + h5t_tagsel_t *el_vals + ) { + unsigned int i = 0; + for ( i = 0; i < el_vals->size; i++ ) { + TRY ( _h5_free ( f, el_vals->valp[i] ) ); + } + return H5_SUCCESS; +} + +/* + Release a tag-set + */ +static h5_err_t +_release_tagset ( + h5_file_t * const f, + const void *__set + ) { + h5t_tagset_t *set = *(h5t_tagset_t**)__set; + unsigned int i; + for ( i = 0; i < set->num_elems; i++ ) { + if ( set->elems[i] != NULL ) { + TRY ( _release_tagvals_of_elem ( f, set->elems[i] ) ); + } + } + TRY ( _h5_free ( f, set->name ) ); + TRY ( _h5_free ( f, set ) ); + return H5_SUCCESS; +} + +/* + Release all sets in given container + */ +static h5_err_t +_release_container ( + h5_file_t * const f, + h5t_tagcontainer_t * container + ) { + TRY ( _h5_hwalk ( f, &container->sets, _release_tagset ) ); + TRY ( _h5_free ( f, container->names ) ); + + return H5_SUCCESS; +} + +/* + Release mesh tag-sets +*/ +h5_err_t +_h5t_release_tags ( + h5_file_t * const f + ) { + h5t_fdata_t *t = f->t; + TRY ( _release_container ( f, &t->mtags ) ); + + return H5_SUCCESS; +} + +/*! + Add tag to current mesh. + + \param[in] f File handle + \param[in] name name of tag + \param[in] type type + \param[out] tag pointer to tag object if != 0 + + \return H5_SUCCESS or error code +*/ +h5_err_t +_h5t_add_mtagset ( + h5_file_t * const f, + char * name, + h5_id_t type, + h5t_tagset_t **rtagset + ) { + h5t_fdata_t *t = f->t; + + /* + Initialize data structure for m-tagsets, if not already done. + */ + if ( t->mtags.names == NULL ) { + TRY ( _h5t_init_mtagsets ( f, 521 ) ); + } + /* + ToDo: Resize! + */ + + if ( ( name == NULL ) || ( name[0] == '\0' ) ) { + return h5_error ( + f, + H5_ERR_INVAL, + "Invalid name" ); + } + /* + @TODO@ check: + - tagset with name doesn't already exist + */ + if ( type != H5_INT64_T && type != H5_FLOAT64_T ) { + return h5_error ( f, H5_ERR_INVAL, + "Unsupported data type." ); + } + /* + create new tagset + */ + h5t_tagset_t *tagset = NULL; + size_t size = (t->num_elems[t->num_levels-1] - 1) * sizeof(*tagset->elems) + + sizeof(*tagset); + TRY ( (tagset = _h5_calloc ( f, 1, size ) ) ); + + TRY ( ( tagset->name = _h5_calloc ( f, 1, strlen(name)+1 ) ) ); + strcpy ( tagset->name, name ); + tagset->type = type; + tagset->num_elems = t->num_elems[t->num_levels-1]; + /* + add tagset to hash of tagsets + */ + void *__retval = NULL; + TRY ( _h5_hsearch ( f, tagset, H5_ENTER, &__retval, &t->mtags.sets ) ); + + t->mtags.changed = 1; + t->mtags.names[t->mtags.num_sets] = tagset->name; + t->mtags.num_sets++; + + if ( rtagset != 0 ) *rtagset = tagset; + return H5_SUCCESS; +} + +h5_err_t +h5t_add_mtagset ( + h5_file_t * const f, + char * name, + h5_id_t type + ) { + return _h5t_add_mtagset ( f, name, type, 0 ); +} + +/*! + Remove a tagset from the current mesh. + + \param[in] f file handle + \param[in] name name of tagset to remove + + \return H5_SUCCESS or error code + */ +h5_err_t +h5t_remove_mtagset ( + h5_file_t *const f, + char name[] + ) { + /* + - release all m-tags + - release pointer array + - remove tagset with NAME from m-tagsets dictionary + - remove HDF5 dataset + */ + return -2; +} + + +h5_size_t +h5t_get_num_mtagsets ( + h5_file_t *const f + ) { + h5t_fdata_t *t = f->t; + return t->mtags.num_sets; +} + +/*! + Get available tagset in current mesh. + + \param[in] f file handle + \param[out] names names of available tagsets + + \return Number of mesh tag-sets + */ +h5_size_t +h5t_get_mtagsets ( + h5_file_t *const f, + char **names[] + ) { + h5t_fdata_t *t = f->t; + *names = t->mtags.names; + return t->mtags.num_sets; +} + +h5_err_t +h5t_open_mtagset ( + h5_file_t *const f, + const char *name, + h5t_tagset_t **retval + ) { + h5t_fdata_t *t = f->t; + void *__retval = NULL; + TRY ( _h5_hsearch ( f, &name, H5_FIND, &__retval, + &t->mtags.sets ) ); + *retval = (h5t_tagset_t*)__retval; + return H5_SUCCESS; +} + +/*! + Get type of tagset in current mesh. + + \param[in] f file handle + \param[in] name name of tagset + + \return type or error code + */ +h5_id_t +h5t_get_mtagset_type_by_name ( + h5_file_t *const f, + char *name + ) { + h5t_tagset_t *tagset; + TRY ( h5t_open_mtagset ( f, name, &tagset ) ); + return tagset->type; +} + +/*! + Get information about a tagset + + \param[in] f file handle + \param[in] idx index of tagset we want information about + \param[out] name name of tag-set + \param[out] type type of tag-set + */ +h5_size_t +h5t_get_mtagset_info ( + h5_file_t *const f, + h5_id_t idx, + char **name, + h5_id_t *type + ) { + h5t_fdata_t *t = f->t; + *name = t->mtags.names[idx]; + void *__retval = NULL; + _h5_hsearch ( f, t->mtags.names[idx], H5_FIND, &__retval, + &t->mtags.sets ); + h5t_tagset_t *retval = (h5t_tagset_t*)__retval; + *type = retval->type; + return H5_SUCCESS; +} + +/*! + Set tag for entity in current mesh. + + \param[in] f file handle + \param[in] tagset pointer to tagset + \param[in] id local id of entity + \param[in] size size of value + \param[in] val tag value + + \return H5_SUCCESS or error code + */ +h5_err_t +_h5t_set_mtag ( + h5_file_t *const f, + h5t_tagset_t *tagset, + const h5_id_t id, + const size_t size, + void *val + ) { + size_t offs[5] = { 14, 0, 4, 10, 14 }; + h5_id_t el_idx = _h5t_get_elem_idx ( id ); + h5_id_t eoe_id = _h5t_get_face_id ( id ); + h5_id_t type_id = _h5t_get_entity_type ( id ); + if ( tagset->elems[el_idx] == NULL ) { + /* + alloc new structure to store all tags for this element + and the given name + */ + TRY ( ( tagset->elems[el_idx] = _h5_calloc ( + f, + 1, + sizeof(*tagset->elems[el_idx] ) ) ) ); + memset ( tagset->elems[el_idx]->idx, -1, + sizeof(tagset->elems[el_idx]->idx) ); + } + h5t_tagsel_t *tagselem = tagset->elems[el_idx]; + size_t i = offs[type_id]+eoe_id; + + /* + new tag value? + */ + if ( tagselem->idx[i] < 0 ) { + /* + Set new index of pointer to value + and increment number of values. + */ + size_t k = tagselem->idx[i] = tagselem->size++; + /* + We have to resize (actually not, if this is the first value, + but to keep things simple ...) + */ + size_t num_bytes = sizeof(*tagselem) + + (tagselem->size-1) * sizeof(void*); + TRY ( ( tagset->elems[el_idx] = _h5_alloc ( + f, tagselem, num_bytes ) ) ); + tagselem = tagset->elems[el_idx]; + /* + we will allocate the memory later. + */ + tagselem->valp[k] = NULL; + } + + /* + (re-)allocate memory for value and assign + */ + size_t num_bytes = (size-1) * sizeof(h5_float64_t) + sizeof(h5t_tagval_t); + size_t k = tagselem->idx[i]; + TRY ( ( tagselem->valp[k] = _h5_alloc ( + f, tagselem->valp[k], num_bytes ) ) ); + h5t_tagval_t *tagval = tagselem->valp[k]; + tagval->size = size; + memcpy ( &tagval->vals, val, size*sizeof(h5_float64_t) ); + tagset->changed = 1; + return H5_SUCCESS; +} + +/*! + Set tag for entity in current mesh. + + \param[in] f file handle + \param[in] name names of tagset + \param[in] id local id of entity + \param[in] size size of value + \param[in] val tag value + + \return H5_SUCCESS or error code + */ +h5_err_t +h5t_set_mtag_by_name ( + h5_file_t *const f, + char name[], + const h5_id_t id, + const size_t size, + void *val + ) { + h5t_tagset_t *tagset; + TRY ( h5t_open_mtagset ( f, name, &tagset ) ); + return _h5t_set_mtag ( f, tagset, id, size, val ); +} + +/*! + Get tag for entity in current mesh. + + \param[in] f file handle + \param[in] name names of tagset + \param[in] id id of entity + \param[out] size dimension of value + \param[out] val tag value + + \return H5_SUCCESS or error code + */ +h5_err_t +h5t_get_mtag ( + h5_file_t *const f, + const h5t_tagset_t *tagset, + const h5_id_t id, + size_t *size, + void *val + ) { + h5_id_t el_idx = _h5t_get_elem_idx ( id ); + h5_id_t subentity_id = _h5t_get_face_id ( id ); + h5_id_t type_id = _h5t_get_entity_type ( id ); + + if ( tagset->elems[el_idx] == NULL ) { + return H5_NOK; /* no tags for this element */ + } + h5t_tagsel_t *tagselem = tagset->elems[el_idx]; + size_t offs[5] = { 14, 0, 4, 10, 14 }; + size_t i = offs[type_id]+subentity_id; + + if ( tagselem->idx[i] < 0 ) { + return H5_NOK; /* no value set for this subentity */ + } + size_t k = tagselem->idx[i]; + h5t_tagval_t *tagval = tagselem->valp[k]; + + *size = tagval->size; + memcpy ( val, &tagval->vals, *size * sizeof(h5_float64_t) ); + + return H5_SUCCESS; +} + +/*! + Get tag for entity in current mesh. + + \param[in] f file handle + \param[in] name names of tagset + \param[in] id id of entity + \param[out] size dimension of value + \param[out] val tag value + + \return H5_SUCCESS or error code + */ +h5_err_t +h5t_get_mtag_by_name ( + h5_file_t *const f, + const char name[], + const h5_id_t id, + size_t *size, + void *val + ) { + h5t_tagset_t *tagset; + TRY ( h5t_open_mtagset ( f, name, &tagset ) ); + return h5t_get_mtag ( f, tagset, id, size, val ); +} + +h5_err_t +h5t_remove_mtag ( + h5_file_t *const f, + h5t_tagset_t *tagset, + const h5_id_t id + ) { + h5_id_t el_idx = _h5t_get_elem_idx ( id ); + h5_id_t subentity_id = _h5t_get_face_id ( id ); + h5_id_t type_id = _h5t_get_entity_type ( id ); + + if ( tagset->elems[el_idx] == NULL ) { + return H5_SUCCESS; /* no tags for this element */ + } + h5t_tagsel_t *tagselem = tagset->elems[el_idx]; + size_t offs[5] = { 14, 0, 4, 10, 14 }; + size_t i = offs[type_id]+subentity_id; + + if ( tagselem->idx[i] < 0 ) { + return H5_SUCCESS; /* no value set for this subentity */ + } + size_t k = tagselem->idx[i]; + h5t_tagval_t *tagval = tagselem->valp[k]; + TRY ( _h5_free ( f, tagval ) ); + return H5_SUCCESS; +} + +/*! + Remove tag for entity in current mesh. + + \param[in] f file handle + \param[in] name names of tagset + \param[in] id id of entity +*/ +h5_err_t +h5t_remove_mtag_by_name ( + h5_file_t *const f, + const char name[], + const h5_id_t id + ) { + h5t_tagset_t *tagset; + TRY ( h5t_open_mtagset ( f, name, &tagset ) ); + return h5t_remove_mtag ( f, tagset, id ); +} + +static hid_t +_open_space_all ( + h5_file_t * const f, + hid_t dataset_id + ) { + return H5S_ALL; +} + +/* + Store given tagset. + */ +static h5_err_t +_write_tagset ( + h5_file_t * const f, + hid_t loc_id, + h5t_tagset_t *tagset + ) { + h5t_fdata_t *t = f->t; + hid_t group_id; + /* + alloc memory + */ + h5t_tag_idx_t *elems; + size_t idx_elem; + size_t num_elems = t->num_elems[t->num_levels-1]; + TRY ( ( elems = _h5_calloc ( + f, num_elems+1, sizeof(*elems) ) ) ); + + h5t_tag_idx_t *entities; + size_t idx_entity = 0; + size_t num_entities = 0; + size_t max_entities = num_elems+1; + TRY ( ( entities = _h5_calloc ( + f, max_entities, sizeof(*entities) ) ) ); + + h5_int64_t *vals; + size_t idx_val = 0; + size_t num_vals = 0; + size_t max_vals = num_elems; + TRY ( ( vals = _h5_calloc ( + f, max_vals, sizeof(*vals) ) ) ); + + h5_id_t tmap[15] = { H5T_ETYPE_VERTEX, H5T_ETYPE_VERTEX, + H5T_ETYPE_VERTEX, H5T_ETYPE_VERTEX, + H5T_ETYPE_EDGE, H5T_ETYPE_EDGE, + H5T_ETYPE_EDGE, H5T_ETYPE_EDGE, + H5T_ETYPE_EDGE, H5T_ETYPE_EDGE, + H5T_ETYPE_TRIANGLE, H5T_ETYPE_TRIANGLE, + H5T_ETYPE_TRIANGLE, H5T_ETYPE_TRIANGLE, + H5T_ETYPE_TET }; + /* sub-entity indices */ + h5_id_t smap[15] = { 0, 1, 2, 3, /* vertices */ + 0, 1, 2, 3, 4, 5, /* edges */ + 0, 1, 2, 3, /* triangles */ + 0 }; /* tetrahedron */ + /* + build data structures in memory + */ + for ( idx_elem = 0; idx_elem < num_elems; idx_elem++ ) { + h5t_tagsel_t *tags_of_elem = tagset->elems[idx_elem]; + size_t num_subentities = 0; + h5_id_t start_idx_entities = idx_entity; + size_t i; + for ( i = 0; i < 15; i++ ) { + int k = tags_of_elem->idx[i]; + if ( k == -1 ) continue; + h5t_tagval_t *valp = tags_of_elem->valp[k]; + num_subentities++; + /* + append value to array of values + */ + if ( idx_val + valp->size > max_vals ) { + max_vals += num_elems; + TRY ( ( vals = _h5_alloc ( + f, vals, + max_vals*sizeof(*vals) ) ) ); + } + memcpy ( + vals+idx_val, + &valp->vals[0].i, + valp->size*sizeof(*vals) ); + + /* + append entity descriptor + */ + if ( idx_entity >= max_entities ) { + max_entities += num_elems; + TRY ( ( entities = _h5_alloc ( + f, entities, + max_entities*sizeof(*entities) ) + ) ); + } + h5_id_t type_id = tmap[i]; + h5_id_t sentity_id = smap[i]; + entities[idx_entity].eid = _h5t_build_id ( + type_id, sentity_id, idx_elem ); + entities[idx_entity].idx = idx_val; + idx_val += valp->size; + idx_entity++; + + } + /* append element descriptor */ + elems[idx_elem].eid = idx_elem; + elems[idx_elem].idx = start_idx_entities; + start_idx_entities += num_subentities; + } + num_entities = idx_entity; + num_vals = idx_val; + + elems[num_elems].eid = -1; + elems[num_elems].idx = num_entities; + entities[idx_entity].eid = -1; + entities[idx_entity].idx = num_vals; + + /* + write data + */ + TRY ( group_id = _h5_open_group ( f, loc_id, tagset->name ) ); + h5_dsinfo_t dsinfo; + memset ( &dsinfo, 0, sizeof(dsinfo) ); + dsinfo.rank = 1; + dsinfo.max_dims[0] = H5S_UNLIMITED; + dsinfo.chunk_dims[0] = 4096; + dsinfo.access_prop = H5P_DEFAULT; + + strcpy ( dsinfo.name, "elems" ); + dsinfo.dims[0] = num_elems + 1; + dsinfo.type_id = t->dtypes.h5t_tag_idx_t; + TRY( dsinfo.create_prop = _hdf_create_property ( f, + H5P_DATASET_CREATE ) ); + TRY( _hdf_set_chunk_property ( f, dsinfo.create_prop, dsinfo.rank, + dsinfo.chunk_dims ) ); + + TRY ( _h5_write_dataset_by_name ( + f, + group_id, + &dsinfo, + _open_space_all, _open_space_all, + elems ) ); + + strcpy ( dsinfo.name, "entities" ); + dsinfo.dims[0] = num_entities + 1; + + TRY ( _h5_write_dataset_by_name ( + f, + group_id, + &dsinfo, + _open_space_all, _open_space_all, + entities ) ); + + strcpy ( dsinfo.name, "values" ); + dsinfo.dims[0] = num_vals; + dsinfo.type_id = t->dtypes.h5_int64_t; + + TRY ( _h5_write_dataset_by_name ( + f, + group_id, + &dsinfo, + _open_space_all, _open_space_all, + vals ) ); + + return H5_SUCCESS; +} + +/* + Store given tag container. Write only changed tag-sets. + */ +static h5_err_t +_write_container ( + h5_file_t * const f, + h5t_tagcontainer_t *container + ) { + size_t idx; + for ( idx = 0; idx < container->num_sets; idx++ ) { + void *__retval; + TRY ( _h5_hsearch ( f, + &container->names[idx], + H5_FIND, + &__retval, + &container->sets ) ); + h5t_tagset_t *tagset = (h5t_tagset_t*)__retval; + if ( tagset->changed ) { + TRY ( _write_tagset ( + f, + container->group_id, + tagset ) ); + } + } + return H5_SUCCESS; +} + + +/* + Store mesh tags container + */ +h5_err_t +_h5t_write_mtags ( + h5_file_t *const f + ) { + h5t_fdata_t *t = f->t; + TRY ( t->mtags.group_id = _h5_open_group ( f, t->mesh_gid, "Tags" ) ); + return _write_container ( f, &f->t->mtags ); +} + +static h5_err_t +_read_tagset ( + h5_file_t * const f, + hid_t loc_id, + hsize_t idx + ) { + h5t_fdata_t *t = f->t; + char *name; + h5_id_t type; + hid_t group_id; + hid_t dset_id; + TRY ( _hdf_get_objname_by_idx_in_group ( f, loc_id, idx, &name ) ); + TRY ( group_id = _hdf_open_group ( f, loc_id, name ) ); + + /* + read datasets: "elems", "entities" and "values" + */ + h5t_tag_idx_t *elems; + size_t num_elems = 0; + + TRY ( dset_id = _hdf_open_dataset ( f, group_id, "elems" ) ); + TRY ( num_elems = _hdf_get_npoints_of_dataset ( f, dset_id ) ); + TRY ( elems = _h5_calloc ( f, num_elems, sizeof(*elems) ) ); + h5_dsinfo_t dsinfo; + memset ( &dsinfo, 0, sizeof(dsinfo) ); + dsinfo.type_id = t->dtypes.h5t_tag_idx_t; + TRY ( _h5_read_dataset ( + f, + dset_id, + &dsinfo, + _open_space_all, _open_space_all, + elems ) ); + TRY ( _hdf_close_dataset ( f, dset_id ) ); + num_elems--; + + h5t_tag_idx_t *entities; + size_t idx_entity = 0; + size_t num_entities = 0; + TRY ( dset_id = _hdf_open_dataset ( f, group_id, "entities" ) ); + TRY ( num_entities = _hdf_get_npoints_of_dataset ( f, dset_id ) ); + TRY ( entities = _h5_calloc ( f, num_entities, sizeof(*entities) ) ); + TRY ( _h5_read_dataset ( + f, + dset_id, + &dsinfo, + _open_space_all, _open_space_all, + entities ) ); + TRY ( _hdf_close_dataset ( f, dset_id ) ); + num_entities--; + + h5_int64_t *vals; + size_t num_vals = 0; + TRY ( dset_id = _hdf_open_dataset ( f, group_id, "values" ) ); + TRY ( num_vals = _hdf_get_npoints_of_dataset ( f, dset_id ) ); + TRY ( vals = _h5_calloc ( f, num_vals, sizeof(*vals) ) ); + TRY ( dsinfo.type_id = _hdf_get_dataset_type ( f, dset_id ) ); + TRY ( _h5_read_dataset ( + f, + dset_id, + &dsinfo, + _open_space_all, _open_space_all, + vals ) ); + TRY ( _hdf_close_dataset ( f, dset_id ) ); + type = h5_normalize_h5_type ( f, dsinfo.type_id ); + /* + add tagset and set values + */ + h5t_tagset_t *tagset; + TRY ( _h5t_add_mtagset ( f, name, type, &tagset ) ); + for ( idx_entity = 0; idx_entity < num_entities; idx_entity++ ) { + h5t_tag_idx_t *entity = &entities[idx_entity]; + size_t dim = (entity+1)->idx - entity->idx; + TRY ( _h5t_set_mtag ( + f, + tagset, + entity->eid, + dim, + &vals[entity->idx] ) ); + } + + return H5_SUCCESS; +} + +h5_err_t +_h5t_read_tag_container ( + h5_file_t * const f, + h5t_tagcontainer_t *container + ) { + size_t num_sets; + TRY ( ( num_sets = _hdf_get_num_objs_in_group ( + f, container->group_id ) ) ); + hsize_t idx; + + for ( idx = 0; idx < num_sets; idx++ ) { + TRY ( _read_tagset ( f, container->group_id, idx ) ); + } + + return H5_SUCCESS; +} + diff --git a/src/h5_core/h5t_tags.h b/src/h5_core/h5t_tags.h new file mode 100644 index 0000000..6e7ae39 --- /dev/null +++ b/src/h5_core/h5t_tags.h @@ -0,0 +1,19 @@ +#ifndef __H5T_TAGS_H +#define __H5T_TAGS_H + +h5_err_t h5t_add_mtagset ( h5_file_t *const f, char name[], h5_id_t id ); +h5_err_t h5t_remove_mtagset ( h5_file_t *const f, char name[] ); +h5_size_t h5t_get_num_mtagsets ( h5_file_t *const f ); +h5_size_t h5t_get_mtagsets ( h5_file_t *const f, char **names[] ); +h5_err_t h5t_get_mtagset_info ( h5_file_t *const f, const h5_id_t idx, + char **names, h5_id_t *type ); +h5_id_t h5t_get_mtagset_type_by_name ( h5_file_t *const f, char name[] ); + +h5_err_t h5t_set_mtag_by_name ( h5_file_t *const f, char name[], const h5_id_t id, + const size_t dims, void *value ); +h5_err_t h5t_get_mtag_by_name ( h5_file_t *const f, const char name[], + const h5_id_t id, size_t *dims, void *value ); +h5_err_t h5t_remove_mtag_by_name ( h5_file_t *const f, const char name[], + const h5_id_t id ); + +#endif diff --git a/src/h5_core/h5t_tags_private.h b/src/h5_core/h5t_tags_private.h new file mode 100644 index 0000000..c813550 --- /dev/null +++ b/src/h5_core/h5t_tags_private.h @@ -0,0 +1,86 @@ +#ifndef __H5T_TAGS_PRIVATE_H +#define __H5T_TAGS_PRIVATE_H + +/* + * Tags can be assigned to all entities of a mesh + * Tag values are arrays of int64 or float64 + * Complex numbers can be stored as array of float64 with even dimension + * Tags are addressed via a name and the entity. + * Tags with the same name are called a "tagset" + * Tagsets can be used to store time/step-constant data. These tagsets are + called "m-tagsets" and are assigned directly to a mesh. + * Tagsets can be used to store data which may change from step to step. + These tagsets are called "s-tagsets" and are assigned to a mesh and a + (time-)step. + */ + + +/* + Tags are addressed via name and entity id. We access a tag very indirect: + First we lookup for the name of the tagset in a hash table. The value of the + hash entry gives us information about the data type stored in this tagset, + whether this tagset has been changed or not and a pointer to another data + structure. This data structure keeps information about tags within the given + tagset per element. + */ + + +/* + Structure to store a tag value +*/ +typedef struct { + size_t size; + union { + h5_float64_t f; + h5_int64_t i; + } vals[1]; +} h5t_tagval_t; + + +/* + Structure with pointers to the tag values of a given tagset of an element. + We use idx as an index into valp: + valp[idx[0]] ... valp[idx[3]] are pointing to the tag values of vertex 0 ... 3 + valp[idx[4]] ... valp[idx[9]] are pointing to the tag values of edge 0 ... 5 + valp[idx[10]] ... valp[idx[13]] are pointing to the tag values of triangle 0 ... 3 + valp[idx[14]] points to the tag value of the elements itself. + + If idx[k] is equal -1, no tag has been assigned to the appropriate entity. +*/ +typedef struct { + signed char size; /* size of valp */ + signed char idx[15]; + h5t_tagval_t *valp[1]; +} h5t_tagsel_t; + + +typedef struct h5t_tagset { + char * name; + unsigned int changed; /* flag tagset changed, ... */ + unsigned int num_elems; + h5_id_t type; /* int64 or float64 */ + h5t_tagsel_t *elems[1]; +} h5t_tagset_t; + +/* + Structure for hash table of tagsets + */ +typedef struct { + unsigned int changed; /* flag container changed */ + hid_t group_id; + hsize_t num_sets; /* number of tagsets */ + char **names; /* fast access via index */ + h5_hashtable_t sets; +} h5t_tagcontainer_t; + + +typedef struct { + h5_id_t eid ; + h5_id_t idx; +} h5t_tag_idx_t; + +h5_err_t _h5t_write_mtags ( h5_file_t *const f ); +h5_err_t _h5t_release_tags ( h5_file_t * const f ); +h5_err_t _h5t_read_tag_container ( h5_file_t * const f, + h5t_tagcontainer_t *container ); +#endif