376 lines
9.5 KiB
C
376 lines
9.5 KiB
C
#include <string.h>
|
|
|
|
#include "h5core/h5_core.h"
|
|
#include "h5_core_private.h"
|
|
|
|
/*
|
|
Assign unique global indices to vertices.
|
|
*/
|
|
static h5_err_t
|
|
assign_global_vertex_indices (
|
|
h5_file_t* const f
|
|
) {
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
if (t->leaf_level < 0) return H5_SUCCESS; /* no level defined */
|
|
|
|
/*
|
|
simple in serial runs: global_id = local_id
|
|
*/
|
|
h5_loc_idx_t local_idx = (t->leaf_level == 0) ?
|
|
0 : t->num_vertices[t->leaf_level-1];
|
|
for (local_idx = 0;
|
|
local_idx < t->num_vertices[t->num_leaf_levels-1];
|
|
local_idx++) {
|
|
t->vertices[local_idx].idx = local_idx;
|
|
}
|
|
|
|
return H5_SUCCESS;
|
|
}
|
|
|
|
/*!
|
|
Assign unique global indices to new elements.
|
|
*/
|
|
static h5_err_t
|
|
assign_glb_elem_indices (
|
|
h5_file_t* const f
|
|
) {
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
if (t->leaf_level < 0) return H5_SUCCESS; /* no level defined */
|
|
|
|
/*
|
|
simple in serial runs: global index = local index
|
|
*/
|
|
h5_loc_idx_t loc_idx = (t->leaf_level == 0) ? 0 : t->num_elems[t->leaf_level-1];
|
|
|
|
for (; loc_idx < t->num_elems[t->leaf_level]; loc_idx++) {
|
|
h5tpriv_set_loc_elem_glb_idx (f, loc_idx, loc_idx);
|
|
}
|
|
|
|
return H5_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
h5t_lvl_idx_t
|
|
h5t_add_level (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5t_lvl_idx_t, "f=0x%p", f);
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
if (f->mode == H5_O_RDONLY) {
|
|
H5_CORE_API_LEAVE (h5priv_handle_file_mode_error(f->mode));
|
|
}
|
|
|
|
/* t->num_leaf_levels will be set to zero on file creation(!) */
|
|
if ((t->cur_mesh < 0) || (t->num_leaf_levels == -1)) {
|
|
H5_CORE_API_LEAVE (h5tpriv_error_undef_mesh ());
|
|
}
|
|
t->leaf_level = t->num_leaf_levels++;
|
|
t->num_loaded_levels = t->num_leaf_levels;
|
|
t->dsinfo_num_vertices.dims[0] = t->num_leaf_levels;
|
|
t->dsinfo_num_elems.dims[0] = t->num_leaf_levels;
|
|
t->dsinfo_num_elems_on_leaf_level.dims[0] = t->num_leaf_levels;
|
|
|
|
ssize_t num_bytes = t->num_leaf_levels*sizeof (h5_size_t);
|
|
TRY (t->num_vertices = h5_alloc (t->num_vertices, num_bytes));
|
|
t->num_vertices[t->leaf_level] = -1;
|
|
|
|
TRY (t->num_elems = h5_alloc (t->num_elems, num_bytes));
|
|
t->num_elems[t->leaf_level] = -1;
|
|
TRY ( t->num_elems_on_leaf_level = h5_alloc (
|
|
t->num_elems_on_leaf_level, num_bytes));
|
|
t->num_elems_on_leaf_level[t->leaf_level] = -1;
|
|
|
|
if (t->leaf_level == 0) {
|
|
/* nothing stored yet */
|
|
t->last_stored_vid = -1;
|
|
t->last_stored_eid = -1;
|
|
}
|
|
|
|
H5_CORE_API_RETURN (t->leaf_level);
|
|
}
|
|
|
|
/*!
|
|
Allocate memory for (more) vertices.
|
|
*/
|
|
h5_err_t
|
|
h5t_begin_store_vertices (
|
|
h5_file_t* const f,
|
|
const h5_size_t num
|
|
) {
|
|
H5_CORE_API_ENTER2 (h5_err_t,
|
|
"f=0x%p, num=%llu",
|
|
f, (long long unsigned)num);
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
if (t->leaf_level < 0) {
|
|
H5_CORE_API_LEAVE (h5tpriv_error_undef_level());
|
|
}
|
|
h5_size_t cur_num_vertices = (t->leaf_level > 0 ?
|
|
t->num_vertices[t->leaf_level-1] : 0);
|
|
t->num_vertices[t->leaf_level] = cur_num_vertices+num;
|
|
t->dsinfo_vertices.dims[0] = cur_num_vertices+num;
|
|
H5_CORE_API_RETURN (h5tpriv_alloc_num_vertices (f, cur_num_vertices+num));
|
|
}
|
|
|
|
h5_loc_idx_t
|
|
h5t_store_vertex (
|
|
h5_file_t* const f, /*!< file handle */
|
|
const h5_glb_idx_t glb_id, /*!< global vertex id from mesher or -1 */
|
|
const h5_float64_t P[3] /*!< coordinates */
|
|
) {
|
|
H5_CORE_API_ENTER3 (h5_loc_idx_t,
|
|
"f=0x%p, glb=id=%lld, P=0x%p",
|
|
f,
|
|
(long long)glb_id,
|
|
P);
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
/*
|
|
more than allocated
|
|
*/
|
|
if (t->last_stored_vid+1 >= t->num_vertices[t->leaf_level])
|
|
H5_CORE_API_LEAVE (HANDLE_H5_OVERFLOW_ERR(
|
|
t->num_vertices[t->leaf_level]));
|
|
|
|
/*
|
|
missing call to add the first level
|
|
*/
|
|
if (t->leaf_level < 0)
|
|
H5_CORE_API_LEAVE (h5tpriv_error_undef_level());
|
|
|
|
h5_loc_idx_t local_idx = ++t->last_stored_vid;
|
|
h5_loc_vertex_t *vertex = &t->vertices[local_idx];
|
|
vertex->idx = glb_id; /* ID from mesher, replaced later!*/
|
|
memcpy (&vertex->P, P, sizeof (vertex->P));
|
|
H5_CORE_API_RETURN (local_idx);
|
|
}
|
|
|
|
h5_err_t
|
|
h5t_end_store_vertices (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5_err_t, "f=0x%p", f);
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
t->num_vertices[t->leaf_level] = t->last_stored_vid+1;
|
|
TRY (assign_global_vertex_indices (f));
|
|
TRY (h5tpriv_rebuild_vertex_indices_mapping (f));
|
|
H5_CORE_API_RETURN (H5_SUCCESS);
|
|
}
|
|
|
|
/*!
|
|
Initialize everything so that we can begin to store elements.
|
|
|
|
\param[in] f file handle
|
|
\param[in] num number of elements to add
|
|
*/
|
|
h5_err_t
|
|
h5t_begin_store_elems (
|
|
h5_file_t* const f,
|
|
const h5_size_t num
|
|
) {
|
|
H5_CORE_API_ENTER2 (h5_err_t,
|
|
"f=0x%p, num=%llu",
|
|
f, (long long unsigned)num);
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
size_t cur = t->leaf_level > 0 ? t->num_elems[t->leaf_level-1] : 0;
|
|
size_t new = num + cur;
|
|
t->num_elems[t->leaf_level] = new;
|
|
t->dsinfo_elems.dims[0] = new;
|
|
|
|
t->num_elems_on_leaf_level[t->leaf_level] = t->leaf_level > 0 ?
|
|
num + t->num_elems_on_leaf_level[t->leaf_level-1] : num;
|
|
/*
|
|
We allocate a hash table for a minimum of 2^21 edges to
|
|
avoid resizing.
|
|
*/
|
|
size_t nel = 2097152 > 5*new ? 2097152 : 5*new;
|
|
TRY (h5tpriv_resize_te_htab (f, nel));
|
|
H5_CORE_API_RETURN (h5tpriv_alloc_elems (f, cur, new));
|
|
}
|
|
|
|
|
|
/*!
|
|
Store element. The vertices are given via their local indices.
|
|
|
|
\param[in] f File handle.
|
|
\param[in] elem_idx_of_parent Local indexd of the parent element
|
|
or \c -1.
|
|
\param[in] vertices Local vertex indices defining the
|
|
tetrahedron.
|
|
*/
|
|
h5_loc_idx_t
|
|
h5t_store_elem (
|
|
h5_file_t* const f,
|
|
const h5_loc_idx_t parent_idx,
|
|
const h5_loc_idx_t* vertex_indices
|
|
) {
|
|
H5_CORE_API_ENTER3 (h5_loc_idx_t,
|
|
"f=0x%p, parent_idx=%lld, vertex_indices=0x%p",
|
|
f,
|
|
(long long)parent_idx,
|
|
vertex_indices);
|
|
h5t_fdata_t* t = f->t;
|
|
|
|
/* level set? */
|
|
if (t->leaf_level < 0)
|
|
H5_CORE_API_LEAVE (
|
|
h5tpriv_error_undef_level());
|
|
|
|
/* more than allocated? */
|
|
if ( t->last_stored_eid+1 >= t->num_elems[t->leaf_level] )
|
|
H5_CORE_API_LEAVE (
|
|
HANDLE_H5_OVERFLOW_ERR (t->num_elems[t->leaf_level]));
|
|
|
|
/* check parent id */
|
|
if ((t->leaf_level == 0 && parent_idx != -1) ||
|
|
(t->leaf_level > 0 && parent_idx < 0) ||
|
|
(t->leaf_level > 0
|
|
&& parent_idx >= t->num_elems[t->leaf_level-1])
|
|
) {
|
|
H5_CORE_API_LEAVE (
|
|
HANDLE_H5_PARENT_ID_ERR (parent_idx));
|
|
}
|
|
|
|
/* store elem data (but neighbors) */
|
|
h5_loc_idx_t elem_idx = ++t->last_stored_eid;
|
|
h5tpriv_set_loc_elem_parent_idx (f, elem_idx, parent_idx);
|
|
h5tpriv_set_loc_elem_child_idx (f, elem_idx, -1);
|
|
h5tpriv_set_loc_elem_level_idx (f, elem_idx, t->leaf_level);
|
|
|
|
// get ptr to local vertices store
|
|
h5_loc_idx_t* loc_vertex_indices = h5tpriv_get_loc_elem_vertex_indices (
|
|
f, elem_idx);
|
|
int num_vertices = h5tpriv_ref_elem_get_num_vertices (t);
|
|
memcpy (loc_vertex_indices, vertex_indices,
|
|
sizeof (*vertex_indices)*num_vertices);
|
|
h5tpriv_sort_local_vertex_indices (f, loc_vertex_indices, num_vertices);
|
|
|
|
/* add edges to map edges -> elements */
|
|
h5_loc_idx_t face_idx;
|
|
int num_faces = h5tpriv_ref_elem_get_num_edges (t);
|
|
for (face_idx = 0; face_idx < num_faces; face_idx++) {
|
|
// add edges to neighbour struct
|
|
TRY (h5tpriv_search_te2 (f, face_idx, elem_idx, NULL));
|
|
}
|
|
H5_CORE_API_RETURN (elem_idx);
|
|
}
|
|
|
|
h5_err_t
|
|
h5t_end_store_elems (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5_err_t, "f=0x%p", f);
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
t->num_elems[t->leaf_level] = t->last_stored_eid+1;
|
|
|
|
/* assign global indices to new indices */
|
|
TRY (assign_glb_elem_indices (f));
|
|
|
|
/* rebuild map: global index -> local_index */
|
|
TRY (h5tpriv_rebuild_elem_indices_mapping (f));
|
|
|
|
/* mesh specific finalize */
|
|
TRY (t->methods.store->end_store_elems (f));
|
|
|
|
H5_CORE_API_RETURN (H5_SUCCESS);
|
|
}
|
|
|
|
/*
|
|
Mark entity for further processing (e.g. refinement).
|
|
*/
|
|
h5_err_t
|
|
h5t_mark_entity (
|
|
h5_file_t* const f,
|
|
const h5_loc_id_t entity_id
|
|
) {
|
|
H5_CORE_API_ENTER2 (h5_err_t, "f=0x%p, entity_id=%llu",
|
|
f, (long long unsigned)entity_id);
|
|
h5t_fdata_t* const t = f->t;
|
|
H5_CORE_API_RETURN (h5priv_insert_idlist (&t->marked_entities, entity_id, -1));
|
|
}
|
|
|
|
/*
|
|
Refine previously marked elements.
|
|
*/
|
|
h5_err_t
|
|
h5t_refine_marked_elems (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5_err_t, "f=0x%p", f);
|
|
h5t_fdata_t* const t = f->t;
|
|
int i;
|
|
for (i = 0; i < t->marked_entities->num_items; i++) {
|
|
TRY (h5tpriv_refine_elem (f, t->marked_entities->items[i]));
|
|
}
|
|
H5_CORE_API_RETURN (H5_SUCCESS);
|
|
}
|
|
|
|
h5_err_t
|
|
h5t_post_refine (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5_err_t, "f=0x%p", f);
|
|
h5t_fdata_t* const t = f->t;
|
|
TRY (h5t_end_store_vertices (f));
|
|
TRY (h5t_end_store_elems (f));
|
|
H5_CORE_API_RETURN (h5priv_free_idlist (&t->marked_entities));
|
|
}
|
|
|
|
h5_err_t
|
|
h5t_begin_refine_elems (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5_err_t, "f=0x%p", f);
|
|
h5t_fdata_t* const t = f->t;
|
|
|
|
/*
|
|
Pre-allocate space for items to avoid allocating small pieces of
|
|
memory.
|
|
*/
|
|
TRY (h5priv_alloc_idlist (&t->marked_entities, 2048));
|
|
H5_CORE_API_RETURN (H5_SUCCESS);
|
|
}
|
|
|
|
h5_err_t
|
|
h5t_end_refine_elems (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5_err_t, "f=0x%p", f);
|
|
TRY (h5t_pre_refine (f));
|
|
TRY (h5t_refine_marked_elems (f));
|
|
TRY (h5t_post_refine (f));
|
|
H5_CORE_API_RETURN (H5_SUCCESS);
|
|
}
|
|
|
|
#if 0
|
|
// index set for DUNE
|
|
h5_err_t
|
|
h5t_create_index_set (
|
|
h5_file_t* const f
|
|
) {
|
|
H5_CORE_API_ENTER1 (h5_err_t, "f=0x%p", f);
|
|
int codim;
|
|
int dim = h5tpriv_ref_elem_get_dim (f->t);
|
|
// todo: check tagset already exist
|
|
TRY (h5t_add_mtagset (f, "__IndexSet__", H5_INT64_T));
|
|
|
|
for (codim = 0; codim <= dim; codim++) {
|
|
h5_glb_idx_t idx = 0;
|
|
h5t_leaf_iterator_t it;
|
|
h5_glb_id_t entity_id;
|
|
TRY (h5t_init_leaf_iterator (f, (h5t_iterator_t*)&it, codim));
|
|
while ((entity_id = it.iter(f, (h5t_iterator_t*)&it)) >= 0) {
|
|
TRY (h5t_set_mtag_by_name (f, "__IndexSet__", entity_id, 1, &idx));
|
|
}
|
|
}
|
|
H5_CORE_API_RETURN (H5_SUCCESS);
|
|
}
|
|
#endif
|