stardis

Perform coupled heat transfer calculations
git clone git://git.meso-star.fr/stardis.git
Log | Files | Refs | README | LICENSE

commit 53a4cdc26d934088a1ec5f43c1c9dd8685e5b234
parent 9d793c5596a1fcdc56422a481ad4d564362eaa36
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 21 Dec 2018 11:37:14 +0100

For saving purposes; has memleaks

Diffstat:
Mcmake/CMakeLists.txt | 8++++++++
Msrc/args.h | 2+-
Msrc/main.c | 6+++++-
Msrc/stardis-app.c | 702+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/stardis-app.h | 726++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/stardis-compute.c | 733++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
6 files changed, 1650 insertions(+), 527 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -72,8 +72,15 @@ if(CMAKE_COMPILER_IS_GNUCC) set(MATH_LIB m) endif() +# Default is right to left pow and log is natural log +# Build tinyExpr without closure support and with function_1 to function_3 support only +# (these ones cannot be disabled as predefined functions require them). +set(TE_DEFAULTS + "-DTE_POW_FROM_RIGHT -DTE_NAT_LOG -DTE_WITHOUT_CLOSURES -DTE_WITHOUT_FUNCTION_0 -DTE_MAX_FUNCTION_ARITY=3") + ADD_LIBRARY(tinyexpr STATIC ${TINYEXPR_SOURCE_DIR}/tinyexpr.c ${TINYEXPR_SOURCE_DIR}/tinyexpr.h) +set_target_properties(tinyexpr PROPERTIES COMPILE_FLAGS ${TE_DEFAULTS}) if(CMAKE_COMPILER_IS_GNUCC) set_target_properties(tinyexpr PROPERTIES COMPILE_FLAGS "-std=c99") endif() @@ -91,6 +98,7 @@ if(MSVC) endif() set_target_properties(sdis-app PROPERTIES + COMPILE_FLAGS ${TE_DEFAULTS} VERSION ${VERSION}) rcmake_copy_runtime_libraries(sdis-app) diff --git a/src/args.h b/src/args.h @@ -31,7 +31,7 @@ struct args{ char* camera; }; #define ARGS_DEFAULT__ {\ - NULL, NULL, 10000, SDIS_NTHREADS_DEFAULT,\ + NULL, NULL, 10000, 1,\ { { {0.0, 0.0, 0.0}, 0x7FF0000000000000 /* probe[3]=INF */}},\ PROBE_COMPUTE, 1.0, {300.0, 300.0}, NULL} static const struct args ARGS_DEFAULT = ARGS_DEFAULT__; diff --git a/src/main.c b/src/main.c @@ -20,7 +20,7 @@ int main(int argc, char** argv){ if (res != RES_OK) goto error; if (args.mode == DUMP_VTK){ - res = dump_vtk(stdout, &stardis.geometry, stardis.geometry.boundary_count); + res = dump_vtk(stdout, &stardis.geometry); if (res != RES_OK) goto error; goto exit; } @@ -30,7 +30,11 @@ int main(int argc, char** argv){ exit: stardis_release(&stardis); + mem_shutdown_proxy_allocator(&stardis.allocator); if((memsz = mem_allocated_size()) != 0) { + char dump[4096] = { '\0' }; + MEM_DUMP(&stardis.allocator, dump, sizeof(dump)); + fprintf(stderr, "%s\n", dump); fprintf(stderr, "Memory leaks: %lu Bytes\n", (unsigned long)memsz); } diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -4,8 +4,14 @@ #include <string.h> #include "stardis-app.h" -#define MEDIUM 0 -#define BOUNDARY 1 + +#include <rsys/hash_table.h> +#define HTABLE_NAME descriptions +#define HTABLE_KEY struct description +#define HTABLE_DATA unsigned +#define HTABLE_KEY_FUNCTOR_EQ eq_description +#define HTABLE_KEY_FUNCTOR_HASH hash_description +#include <rsys/hash_table.h> /******************************************************************************* * @@ -93,125 +99,315 @@ static char** split_line(char* a_str, const char a_delim) return result; } +#ifdef COMPILER_GCC +static char* +_strupr(char* s) +{ + char* tmp; + for (tmp = s; *tmp; ++tmp) *tmp = toupper((unsigned char)*tmp); + return s; +} +#endif + +/* Read medium line; should be one of: + * SOLID STL_filename lambda rho cp delta "Tinit(x,y,z)" "volumic_power(x,y,z,t)" + * FLUID STL_filename rho cp "Tinit(x,y,z)" +*/ static res_T -parse_medium_line(char* line, char** stl_filename, struct material* mat) +parse_medium_line(char* line, char** stl_filename, struct description* desc) { char* tk = NULL; res_T res = RES_OK; - tk = strtok(line," "); - *stl_filename = malloc(strlen(tk) + 1); - strcpy(*stl_filename,tk); - tk = strtok(NULL," "); - res = cstr_to_double(tk, &mat->lambda); - if (res != RES_OK || mat->lambda <= 0) { - fprintf(stderr, "Invalid lambda: %s\n", tk); - res = RES_BAD_ARG; - goto error; - } - tk = strtok(NULL," "); - res = cstr_to_double(tk, &mat->rho); - if (res != RES_OK || mat->rho <= 0) { - fprintf(stderr, "Invalid rho: %s\n", tk); - res = RES_BAD_ARG; - goto error; +#define CHK_TOK(tk, x) if(((tk) = (x)) == NULL) goto error + CHK_TOK(tk, _strupr(strtok(line, " "))); + if (strcmp(tk, "SOLID") == 0) { + desc->type = DESC_MAT_SOLID; + + CHK_TOK(tk, strtok(NULL, " ")); + *stl_filename = malloc(strlen(tk) + 1); + strcpy(*stl_filename, tk); + + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.solid.lambda); + if (res != RES_OK || desc->d.solid.lambda <= 0) { + fprintf(stderr, "Invalid lambda: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.solid.rho); + if (res != RES_OK || desc->d.solid.rho <= 0) { + fprintf(stderr, "Invalid rho: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.solid.cp); + if (res != RES_OK || desc->d.solid.cp <= 0) { + fprintf(stderr, "Invalid cp: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.solid.delta); + if (res != RES_OK || desc->d.solid.delta <= 0) { + fprintf(stderr, "Invalid delta: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, "\"")); + desc->d.solid.Tinit = malloc(strlen(tk) + 1); + strcpy(desc->d.solid.Tinit, tk); + CHK_TOK(tk, strtok(NULL, "\"")); + + CHK_TOK(tk, strtok(NULL, "\"")); + desc->d.solid.power = malloc(strlen(tk) + 1); + strcpy(desc->d.solid.power, tk); } - tk = strtok(NULL," "); - res = cstr_to_double(tk, &mat->cp); - if (res != RES_OK || mat->cp <= 0){ - fprintf(stderr, "Invalid cp: %s\n", tk); - res = RES_BAD_ARG; - goto error; + else if (strcmp(tk, "FLUID") == 0) { + desc->type = DESC_MAT_FLUID; + + CHK_TOK(tk, strtok(NULL, " ")); + *stl_filename = malloc(strlen(tk) + 1); + strcpy(*stl_filename, tk); + + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.fluid.rho); + if (res != RES_OK || desc->d.fluid.rho <= 0) { + fprintf(stderr, "Invalid rho: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.fluid.cp); + if (res != RES_OK || desc->d.fluid.cp <= 0) { + fprintf(stderr, "Invalid cp: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, "\"")); + desc->d.fluid.Tinit = malloc(strlen(tk) + 1); + strcpy(desc->d.fluid.Tinit, tk); } - tk = strtok(NULL," "); - res = cstr_to_double(tk, &mat->delta); - if (res != RES_OK || mat->delta <= 0){ - fprintf(stderr, "Invalid delta: %s\n", tk); + else { res = RES_BAD_ARG; - goto error; + printf("Invalid medium type: %s\n", tk); } - tk = strtok(NULL,"\""); - tk = strtok(NULL,"\""); - mat->Tinit = malloc(strlen(tk) + 1); - strcpy(mat->Tinit,tk); - - tk = strtok(NULL,"\""); - tk = strtok(NULL,"\""); - mat->power = malloc(strlen(tk) + 1); - strcpy(mat->power,tk); +#undef GET_TOK exit: return res; error: goto exit; } +/* Read boundary line; should be one of: +# H_BOUNDARY_FOR_SOLID STL_filename emissivity specular_fraction hc hc_max "T_env(x,y,z,t)" +# | H_BOUNDARY_FOR_FLUID STL_filename emissivity specular_fraction hc hc_max "T_env(x,y,z,t)" +# | T_BOUNDARY_FOR_SOLID STL_filename "T_value(x,y,z,t)" +# | T_BOUNDARY_FOR_FLUID STL_filename "T_value(x,y,z,t)" hc hc_max +# | F_BOUNDARY_FOR_SOLID STL_filename "F_value(x,y,z,t)" +# ; no F_BOUNDARY_FOR_FLUID + */ static res_T -parse_boundary_line(char* line, char** stl_filename, struct boundary* bound) +parse_boundary_line(char* line, char** stl_filename, struct description* desc) { char* tk = NULL; + int h_solid = 0, h_fluid = 0; + int t_solid = 0, t_fluid = 0; + int f_solid = 0; + int sf_connect = 0; res_T res = RES_OK; - tk = strtok(line," "); - *stl_filename = malloc(strlen(tk) + 1); - strcpy(*stl_filename,tk); - - tk = strtok(NULL," "); - res = cstr_to_double(tk, &bound->emissivity); - if (res != RES_OK || bound->emissivity < 0 || bound->emissivity > 1){ - fprintf(stderr, "Invalid emissivity: %s\n", tk); - res = RES_BAD_ARG; - goto error; +#define CHK_TOK(tk, x) if(((tk) = (x)) == NULL) goto error + CHK_TOK(tk, strtok(line, " ")); + h_solid = (0 == strcmp(tk, "H_BOUNDARY_FOR_SOLID")); + if (!h_solid) { + h_fluid = (0 == strcmp(tk, "H_BOUNDARY_FOR_FLUID")); + if (!h_fluid) { + t_solid = (0 == strcmp(tk, "T_BOUNDARY_FOR_SOLID")); + if (!t_solid) { + t_fluid = (0 == strcmp(tk, "T_BOUNDARY_FOR_FLUID")); + if (!t_fluid) { + f_solid = (0 == strcmp(tk, "F_BOUNDARY_FOR_SOLID")); + if (!f_solid) { + sf_connect = (0 == strcmp(tk, "SOLID_FLUID_CONNECTION")); + } + } + } + } } - tk = strtok(NULL," "); - res = cstr_to_double(tk, &bound->specular_fraction); - if (res != RES_OK || - bound->specular_fraction < 0.0 || bound->specular_fraction > 1.0){ - fprintf(stderr, "Invalid specular_fraction: %s\n", tk); - res = RES_BAD_ARG; - goto error; + if (h_solid || h_fluid) { + desc->type = h_solid ? DESC_BOUND_H_FOR_SOLID : DESC_BOUND_H_FOR_FLUID; + + /* The description is parsed the same way for both types */ + CHK_TOK(tk, strtok(NULL, " ")); + *stl_filename = malloc(strlen(tk) + 1); + strcpy(*stl_filename, tk); + + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.h_boundary.emissivity); + if (res != RES_OK || + desc->d.h_boundary.emissivity < 0 || desc->d.h_boundary.emissivity > 1) { + fprintf(stderr, "Invalid emissivity: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + desc->d.h_boundary.has_emissivity = (desc->d.h_boundary.emissivity > 0); + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.h_boundary.specular_fraction); + if (res != RES_OK + || desc->d.h_boundary.specular_fraction < 0.0 + || desc->d.h_boundary.specular_fraction > 1.0) { + fprintf(stderr, "Invalid specular_fraction: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.h_boundary.hc); + if (res != RES_OK || desc->d.h_boundary.hc < 0) { + fprintf(stderr, "Invalid hc value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + desc->d.h_boundary.has_hc = (desc->d.h_boundary.hc > 0); + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.h_boundary.hc_max); + if (res != RES_OK + || desc->d.h_boundary.hc_max < desc->d.h_boundary.hc + || desc->d.h_boundary.hc_max < 0) { + fprintf(stderr, "Invalid hc_max value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, "\"")); + desc->d.h_boundary.T = malloc(strlen(tk) + 1); + strcpy(desc->d.h_boundary.T, tk); } - - tk = strtok(NULL," "); - if (strcmp(tk,"h")==0 || strcmp(tk,"H")==0 ){ - tk = strtok(NULL," "); - res = cstr_to_double(tk, &bound->hc); - if (res != RES_OK || bound->hc < 0) { - fprintf(stderr, "Invalid value parameter: %s\n", tk); + else if (t_solid || t_fluid) { + desc->type = t_solid ? DESC_BOUND_T_FOR_SOLID : DESC_BOUND_T_FOR_FLUID; + + /* This part of the description is parsed the same way for both types */ + CHK_TOK(tk, strtok(NULL, " ")); + *stl_filename = malloc(strlen(tk) + 1); + strcpy(*stl_filename, tk); + + CHK_TOK(tk, strtok(NULL, "\"")); + desc->d.t_boundary.T = malloc(strlen(tk) + 1); + strcpy(desc->d.t_boundary.T, tk); + + /* Parse hc + hc_max only if fluid */ + if (t_fluid) { + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.t_boundary.hc); + if (res != RES_OK || desc->d.t_boundary.hc < 0) { + fprintf(stderr, "Invalid hc value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + desc->d.t_boundary.has_hc = (desc->d.t_boundary.hc > 0); + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.t_boundary.hc_max); + if (res != RES_OK + || desc->d.t_boundary.hc_max < desc->d.t_boundary.hc + || desc->d.t_boundary.hc_max < 0) { + fprintf(stderr, "Invalid hc_max value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + } + else desc->d.t_boundary.has_hc = 0; + } + else if (f_solid) { + desc->type = DESC_BOUND_F_FOR_SOLID; + + CHK_TOK(tk, strtok(NULL, " ")); + *stl_filename = malloc(strlen(tk) + 1); + strcpy(*stl_filename, tk); + + CHK_TOK(tk, strtok(NULL, "\"")); + desc->d.f_boundary.flux = malloc(strlen(tk) + 1); + strcpy(desc->d.f_boundary.flux, tk); + + /* Optional hc + hc_max */ + tk = strtok(NULL, " "); + if (tk) { + res = cstr_to_double(tk, &desc->d.f_boundary.hc); + if (res != RES_OK || desc->d.f_boundary.hc < 0) { + fprintf(stderr, "Invalid hc value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + desc->d.f_boundary.has_hc = (desc->d.f_boundary.hc > 0); + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.f_boundary.hc_max); + if (res != RES_OK + || desc->d.f_boundary.hc_max < desc->d.f_boundary.hc + || desc->d.f_boundary.hc_max < 0) { + fprintf(stderr, "Invalid hc_max value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + } + } + else if (sf_connect) { + desc->type = DESC_SOLID_FLUID_CONNECT; + + CHK_TOK(tk, strtok(NULL, " ")); + *stl_filename = malloc(strlen(tk) + 1); + strcpy(*stl_filename, tk); + + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.sf_connect.emissivity); + if (res != RES_OK || + desc->d.sf_connect.emissivity < 0 || desc->d.sf_connect.emissivity > 1) { + fprintf(stderr, "Invalid emissivity: %s\n", tk); res = RES_BAD_ARG; goto error; } - - tk = strtok(NULL,"\""); - tk = strtok(NULL,"\""); - bound->T = malloc(strlen(tk) + 1); - strcpy(bound->T,tk); - - } else if (strcmp(tk,"t")==0 || strcmp(tk,"T")==0 ){ - - tk = strtok(NULL,"\""); - tk = strtok(NULL,"\""); - bound->T = malloc(strlen(tk) + 1); - strcpy(bound->T,tk); - - } else if (strcmp(tk,"f")==0 || strcmp(tk,"F")==0 ){ - - tk = strtok(NULL,"\""); - tk = strtok(NULL,"\""); - bound->flux = malloc(strlen(tk) + 1); - strcpy(bound->flux,tk); - - } else { - fprintf(stderr,"unknown boundary type: %s\n", tk); + desc->d.sf_connect.has_emissivity = (desc->d.sf_connect.emissivity > 0); + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.sf_connect.specular_fraction); + if (res != RES_OK + || desc->d.sf_connect.specular_fraction < 0.0 + || desc->d.sf_connect.specular_fraction > 1.0) { + fprintf(stderr, "Invalid specular_fraction: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.sf_connect.hc); + if (res != RES_OK || desc->d.sf_connect.hc < 0) { + fprintf(stderr, "Invalid hc value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + desc->d.sf_connect.has_hc = (desc->d.sf_connect.hc > 0); + CHK_TOK(tk, strtok(NULL, " ")); + res = cstr_to_double(tk, &desc->d.h_boundary.hc_max); + if (res != RES_OK + || desc->d.h_boundary.hc_max < desc->d.h_boundary.hc + || desc->d.h_boundary.hc_max < 0) { + fprintf(stderr, "Invalid hc_max value: %s\n", tk); + res = RES_BAD_ARG; + goto error; + } + } + else { + printf("Invalid boundary type: %s", tk); + res = RES_BAD_ARG; goto error; } +#undef GET_TOK exit: return res; error: goto exit; } + static res_T read_vertices (struct sstl_desc* desc, @@ -248,132 +444,198 @@ read_vertices return res; } +static int +indices_to_key(unsigned3 key, const unsigned3 indices) +{ + int i, reversed = 0; + FOR_EACH(i, 0, 3) key[i] = indices[i]; + if (key[0] > key[1]) { + reversed = !reversed; + SWAP(unsigned, key[0], key[1]); + } + if (key[1] > key[2]) { + reversed = !reversed; + SWAP(unsigned, key[1], key[2]); + } + if (key[0] > key[1]) { + reversed = !reversed; + SWAP(unsigned, key[0], key[1]); + } + return reversed; +} + static res_T read_triangles - (int FLAG, - struct sstl_desc* desc, - struct htable_triangle* triangle2id, - unsigned* id2id, char** cl_type, - const unsigned* id, - struct triangle** tri_list) + (const struct sstl_desc* stl_desc, + struct htable_triangle* triangle2id, + const unsigned* id2id, + const int is_connection, + const unsigned desc_id, + struct triangle** tri_list) { res_T res = RES_OK; unsigned tri_index = 0; - (void)cl_type; - for (tri_index = 0; tri_index < desc->triangles_count; ++tri_index){ + for (tri_index = 0; tri_index < stl_desc->triangles_count; ++tri_index) { struct triangle tri = NULL_TRIANGLE; - unsigned *found_id = NULL; - - tri.sids[0] = tri.indices[0] = id2id[desc->indices[3*tri_index + 0]]; - tri.sids[1] = tri.indices[1] = id2id[desc->indices[3*tri_index + 1]]; - tri.sids[2] = tri.indices[2] = id2id[desc->indices[3*tri_index + 2]]; - - if(tri.sids[0] > tri.sids[1]) SWAP(unsigned, tri.sids[0], tri.sids[1]); - if(tri.sids[1] > tri.sids[2]) SWAP(unsigned, tri.sids[1], tri.sids[2]); - if(tri.sids[0] > tri.sids[1]) SWAP(unsigned, tri.sids[0], tri.sids[1]); - found_id = htable_triangle_find(triangle2id, &tri); - - if (found_id){ - if (FLAG==MEDIUM) (*tri_list)[*found_id].medium_back = *id; - if (FLAG==BOUNDARY) (*tri_list)[*found_id].bound_id = *id; + const unsigned *found_id = NULL; + unsigned id; + unsigned3 key; + int reversed; + enum sdis_side current_side = SDIS_FRONT; + unsigned* side_desc_ptr = NULL; + + tri.indices[0] = id2id[stl_desc->indices[3*tri_index + 0]]; + tri.indices[1] = id2id[stl_desc->indices[3*tri_index + 1]]; + tri.indices[2] = id2id[stl_desc->indices[3*tri_index + 2]]; + reversed = indices_to_key(key, tri.indices); + + /* Find triangle if already known, or insert it in known list */ + found_id = htable_triangle_find(triangle2id, &key); + if (found_id) { + struct triangle* original_tri; + int original_reversed; + id = *found_id; + original_tri = (*tri_list) + id; + original_reversed = indices_to_key(key, original_tri->indices); + current_side = (reversed == original_reversed) ? SDIS_FRONT : SDIS_BACK; + ASSERT(id < sa_size(*tri_list)); } else { size_t sz; - unsigned size; - if (FLAG==MEDIUM) tri.medium_front = *id; sz = htable_triangle_size_get(triangle2id); + ASSERT(sz == sa_size(*tri_list)); ASSERT(sz < UINT_MAX); - size = (unsigned)sz; - htable_triangle_set(triangle2id, &tri, &size); - /*printf("triangle %i %i %i\n added at index %i\n", SPLIT3(tri.indices), size);*/ + id = (unsigned)sz; + /* Store tri as described by stl_desc regardless of key order */ + htable_triangle_set(triangle2id, &key, &id); sa_push(*tri_list, tri); } + + if (is_connection) { + side_desc_ptr = &(*tri_list)[id].connection_description; + } + else { + /* Is the triangle in tri_list reversed wrt stl_desc? */ + side_desc_ptr = (current_side == SDIS_FRONT) ? + &(*tri_list)[id].front_description : &(*tri_list)[id].back_description; + } + if (*side_desc_ptr != UINT_MAX && *side_desc_ptr != desc_id) { + /* Already described with a different description! */ + fprintf(stderr, "Triangle %s with 2 different descriptions\n", + is_connection ? "connection" : "side"); + return RES_BAD_ARG; + } + /* Everithing is OK: store description */ + *side_desc_ptr = desc_id; } return res; } - static res_T read_stl -(char FLAG, - unsigned id, - char** stl_filename, - struct htable_vertex* vertex2id, - struct htable_triangle* triangle2id, - struct geometry* geometry) + (const unsigned desc_id, + const int is_connection, + const char** stl_filename, + struct htable_vertex* vertex2id, + struct htable_triangle* triangle2id, + struct stardis* stardis) { res_T res = RES_OK; struct sstl* sstl = NULL; - struct sstl_desc desc; + struct sstl_desc stl_desc; unsigned* id2id = NULL; - SSTL(create(NULL, NULL, 0, &sstl)); + if (!stl_filename) return RES_BAD_ARG; - SSTL(load(sstl, *stl_filename)); - SSTL(get_desc(sstl, &desc)); + SSTL(create(NULL, &stardis->allocator, 0, &sstl)); - read_vertices(&desc, vertex2id, &id2id, &geometry->vertex); - read_triangles(FLAG, &desc, triangle2id, id2id, NULL, &id, &geometry->triangle); - sa_release(id2id); + res = sstl_load(sstl, *stl_filename); + if (res != RES_OK) { + printf("Cannot read STL file: %s\n", *stl_filename); + goto error; + } + SSTL(get_desc(sstl, &stl_desc)); + res = read_vertices(&stl_desc, vertex2id, &id2id, &stardis->geometry.vertex); + if (res != RES_OK) goto error; + res = read_triangles(&stl_desc, triangle2id, id2id, is_connection, desc_id, + &stardis->geometry.triangle); + if (res != RES_OK) goto error; + +end: + sa_release(id2id); SSTL(ref_put(sstl)); return res; +error: + goto end; } - /******************************************************************************* * ******************************************************************************/ static res_T geometry_analyse -(const char* medium_filename, - const char* bc_filename, - struct geometry* geometry, - struct material** material, - struct boundary** boundary) + (const char* medium_filename, + const char* bc_filename, + struct stardis* stardis) { res_T res = RES_OK; FILE* input; char* line = NULL; + unsigned sz = (unsigned)sa_size(stardis->descriptions); struct htable_vertex vertex2id; struct htable_triangle triangle2id; + struct htable_descriptions descriptions; + int descriptions_table_initialised = 0; + unsigned desc_id; + unsigned *p_desc; + ASSERT(sz == sa_size(stardis->descriptions)); - /*init geometry*/ - *geometry = NULL_GEOMETRY; + stardis->geometry = NULL_GEOMETRY; - /*parse medium file*/ + /* parse medium files */ input = fopen(medium_filename,"r"); if (!input){ - fprintf(stderr,"Can not open %s\n", medium_filename); + fprintf(stderr,"Cannot open %s\n", medium_filename); res = RES_IO_ERR; goto error; } - htable_vertex_init(NULL, &vertex2id); - htable_triangle_init(NULL, &triangle2id); + htable_vertex_init(&stardis->allocator, &vertex2id); + htable_triangle_init(&stardis->allocator, &triangle2id); + htable_descriptions_init(&stardis->allocator, &descriptions); + descriptions_table_initialised = 1; /* loop on media */ while (read_line(&line, input)){ char* stl_filename = NULL; - struct material mat = NULL_MATERIAL; + struct description desc = NULL_DESCRIPTION__; - res = parse_medium_line(line, &stl_filename, &mat); + res = parse_medium_line(line, &stl_filename, &desc); if (res != RES_OK) goto error; - sa_push(*material,mat); - /*analyse medium stl*/ - res = read_stl(MEDIUM, geometry->medium_count, &stl_filename, - &vertex2id, &triangle2id, geometry); - if (res != RES_OK) goto error; + /* Deduplicate media: find if the same description already exists */ + p_desc = htable_descriptions_find(&descriptions, &desc); + if (!p_desc) { + sa_push(stardis->descriptions, desc); + desc_id = sz++; + ASSERT(sz == sa_size(stardis->descriptions)); + /* Register new medium description */ + htable_descriptions_set(&descriptions, &desc, &desc_id); + } else { + printf("Duplicate media description found: deduplicated.\n"); + desc_id = *p_desc; + } - geometry->medium_count += 1; + res = read_stl(sz-1, 0, &stl_filename, &vertex2id, &triangle2id, stardis); if (stl_filename) free(stl_filename); + if (res != RES_OK) goto error; } fclose(input); - /*parse boundary file*/ + /* parse boundary files */ input = fopen(bc_filename,"r"); if (!input){ - fprintf(stderr,"Can not open %s\n", bc_filename); + fprintf(stderr,"Cannot open %s\n", bc_filename); res = RES_IO_ERR; goto error; } @@ -381,24 +643,33 @@ geometry_analyse /* loop on boundaries */ while (read_line(&line, input)){ char* stl_filename = NULL; - struct boundary bound = NULL_BOUNDARY; - - res = parse_boundary_line(line, &stl_filename, &bound); - if (res != RES_OK) goto error; - sa_push(*boundary,bound); + struct description desc = NULL_DESCRIPTION__; - /*analyse medium stl*/ - res = read_stl(BOUNDARY, geometry->boundary_count, &stl_filename, - &vertex2id, &triangle2id, geometry); + res = parse_boundary_line(line, &stl_filename, &desc); if (res != RES_OK) goto error; - - geometry->boundary_count += 1; + + /* Deduplicate media: find if the same description already exists */ + p_desc = htable_descriptions_find(&descriptions, &desc); + if (!p_desc) { + sa_push(stardis->descriptions, desc); + desc_id = sz++; + ASSERT(sz == sa_size(stardis->descriptions)); + /* Register new boundary description */ + htable_descriptions_set(&descriptions, &desc, &desc_id); + } else { + printf("Duplicate boundary description found: deduplicated.\n"); + desc_id = *p_desc; + } + + res = read_stl(desc_id, 1, &stl_filename, &vertex2id, &triangle2id, stardis); if (stl_filename) free(stl_filename); + if (res != RES_OK) goto error; } - fclose(input); exit: + if(descriptions_table_initialised) + htable_descriptions_release(&descriptions); htable_vertex_release(&vertex2id); htable_triangle_release(&triangle2id); sa_release(line); @@ -408,27 +679,6 @@ error: } static res_T -check_consistency -(struct boundary* boundary, double* probe) -{ - res_T res = RES_OK; - size_t i = 0; - - for (i=0; i<sa_size(boundary); ++i){ - if ( boundary[i].T && strchr(boundary[i].T,'t') && probe[3] == INF) { - fprintf(stderr,"Transient boundary condition is inconsistent with INF time of the probe.\n"); - res = RES_BAD_ARG; - goto error; - } - } - -exit: - return res; -error: - goto exit; -} - -static res_T parse_camera (char* cam_param, struct camera* cam) { @@ -487,11 +737,12 @@ stardis_init { res_T res = RES_OK; + res = mem_init_proxy_allocator(&stardis->allocator, + &mem_default_allocator); + if (res != RES_OK) goto error; + res = geometry_analyse(args->medium_filename, - args->bc_filename, - &stardis->geometry, - &stardis->material, - &stardis->boundary); + args->bc_filename, stardis); if (res != RES_OK) goto error; stardis->N = args->N; @@ -504,59 +755,59 @@ stardis_init stardis->radiative_temp[0] = args->radiative_temp[0]; stardis->radiative_temp[1] = args->radiative_temp[1]; - if (args->mode == PROBE_COMPUTE){ - res = check_consistency(stardis->boundary, stardis->probe); - if (res != RES_OK) goto error; - } - if (args->mode == IR_COMPUTE){ res = parse_camera(args->camera, &stardis->camera); if (res != RES_OK) goto error; } + exit: return res; error: goto exit; } - -res_T +void stardis_release(struct stardis* stardis) { size_t i = 0; - res_T res = RES_OK; - - for (i=0; i<sa_size(stardis->material); ++i){ - free(stardis->material[i].Tinit); - free(stardis->material[i].power); - } - sa_release(stardis->material); - for (i=0; i<sa_size(stardis->boundary); ++i){ - free(stardis->boundary[i].T); - free(stardis->boundary[i].flux); + for (i=0; i<sa_size(stardis->descriptions); ++i) { + struct description* desc = &stardis->descriptions[i]; + switch (desc->type) { + case DESC_MAT_SOLID: + free(desc->d.solid.power); + free(desc->d.solid.Tinit); + break; + case DESC_MAT_FLUID: + free(desc->d.fluid.Tinit); + break; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + free(desc->d.h_boundary.T); + break; + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + free(desc->d.t_boundary.T); + break; + case DESC_BOUND_F_FOR_SOLID: + free(desc->d.f_boundary.flux); + break; + default: FATAL("Invalid type.\n"); + } } - sa_release(stardis->boundary); - - res = release_geometry(&stardis->geometry); - if (res != RES_OK) goto error; - -exit: - return res; -error: - goto exit; + sa_release(stardis->descriptions); + release_geometry(&stardis->geometry); } - +/* TODO: rewrite dump! */ res_T dump_vtk -(FILE* output, - const struct geometry* geometry, - unsigned nbound) + (FILE* output, + const struct geometry* geometry) { res_T res = RES_OK; - unsigned i,j = 0; + unsigned i; struct vertex* vtx = geometry->vertex; struct triangle* tri = geometry->triangle; @@ -576,22 +827,15 @@ dump_vtk fprintf(output,"3 %i %i %i\n",SPLIT3(tri[i].indices)); } fprintf(output,"\nCELL_DATA %i \n", (int)sa_size(tri)); - fprintf(output,"SCALARS medium_front float 1\n"); + fprintf(output,"SCALARS front_description float 1\n"); fprintf(output,"LOOKUP_TABLE default\n"); - for (i=0; i<sa_size(tri); ++i){ - fprintf(output,"%i\n",tri[i].medium_front); + for (i=0; i<sa_size(tri); ++i) { + fprintf(output,"%i\n",tri[i].front_description); } - fprintf(output,"SCALARS medium_back float 1\n"); + fprintf(output,"SCALARS back_description float 1\n"); fprintf(output,"LOOKUP_TABLE default\n"); - for (i=0; i<sa_size(tri); ++i){ - fprintf(output,"%i\n",tri[i].medium_back); - } - for (j=0; j<nbound; ++j){ - fprintf(output,"SCALARS bound_id float 1\n"); - fprintf(output,"LOOKUP_TABLE default\n"); - for (i=0; i<sa_size(tri); ++i){ - fprintf(output,"%i\n",tri[i].bound_id); - } + for (i=0; i<sa_size(tri); ++i) { + fprintf(output,"%i\n",tri[i].back_description); } exit: diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -20,6 +20,20 @@ free(ARRAY);\ } +/* Different types of descriptions */ +enum description_type { + DESC_MAT_SOLID, + DESC_MAT_FLUID, + DESC_BOUND_H_FOR_FLUID, + DESC_BOUND_H_FOR_SOLID, + DESC_BOUND_T_FOR_FLUID, + DESC_BOUND_T_FOR_SOLID, + DESC_BOUND_F_FOR_SOLID, + DESC_SOLID_FLUID_CONNECT, + DESCRIPTION_TYPE_COUNT__, + DESC_OUTSIDE +}; + struct vertex{ float xyz[3]; }; @@ -39,83 +53,709 @@ eq_vertex(const struct vertex* a, const struct vertex* b) #define HTABLE_KEY_FUNCTOR_EQ eq_vertex #include <rsys/hash_table.h> -struct triangle{ - unsigned indices[3]; - unsigned sids[3]; - unsigned medium_front; - unsigned medium_back; - unsigned bound_id; +typedef unsigned unsigned3[3]; +struct triangle { + unsigned3 indices; + unsigned front_description; + unsigned back_description; + unsigned connection_description; }; -#define NULL_TRIANGLE__ {{0, 0, 0}, {0, 0, 0}, UINT_MAX, UINT_MAX, UINT_MAX} +#define NULL_TRIANGLE__ {{0, 0, 0}, UINT_MAX, UINT_MAX, UINT_MAX } static const struct triangle NULL_TRIANGLE = NULL_TRIANGLE__; static char -eq_triangle(const struct triangle* a, const struct triangle* b) +eq_indices(const unsigned3* a, const unsigned3* b) { - return a->sids[0] == b->sids[0] - && a->sids[1] == b->sids[1] - && a->sids[2] == b->sids[2]; + return (*a)[0] == (*b)[0] && (*a)[1] == (*b)[1] && (*a)[2] == (*b)[2]; } -static size_t -hash_triangle(const struct triangle* tri) +static res_T +cp_indices(unsigned3* dst, const unsigned3* src) { - return hash_fnv64(tri->sids, sizeof(unsigned[3])); + int i; + FOR_EACH(i, 0, 3) (*dst)[i] = (*src)[i]; + return RES_OK; } -/* Declare the hash table that map a triangle to its index */ +/* Declare the hash table that maps a triangle id to its index */ #define HTABLE_NAME triangle #define HTABLE_DATA unsigned -#define HTABLE_KEY struct triangle -#define HTABLE_KEY_FUNCTOR_EQ eq_triangle -#define HTABLE_KEY_FUNCTOR_HASH hash_triangle +#define HTABLE_KEY unsigned3 +#define HTABLE_KEY_FUNCTOR_EQ eq_indices +#define HTABLE_KEY_FUNCTOR_COPY cp_indices #include <rsys/hash_table.h> -struct geometry{ +struct geometry { struct vertex* vertex; struct triangle* triangle; - unsigned medium_count; - unsigned boundary_count; + struct sdis_interface** interf_bytrg; struct sdis_interface** interfaces; }; -#define NULL_GEOMETRY__ {NULL, NULL, 0, 0, NULL} +#define NULL_GEOMETRY__ {NULL, NULL, NULL, NULL } static const struct geometry NULL_GEOMETRY = NULL_GEOMETRY__; -static inline res_T -release_geometry -(struct geometry* geom) +static inline void +release_geometry(struct geometry* geom) { - res_T res = RES_OK; + size_t i; + for (i = 0; i < sa_size(geom->interfaces); ++i) + SDIS(interface_ref_put(geom->interfaces[i])); + sa_release(geom->vertex); geom->vertex = NULL; + sa_release(geom->triangle); geom->triangle = NULL; + sa_release(geom->interfaces); geom->interfaces = NULL; + sa_release(geom->interf_bytrg); geom->interf_bytrg = NULL; +} + +struct mat_fluid { + unsigned fluid_id; + double rho; + double cp; + char* Tinit; +}; - sa_release(geom->vertex); - sa_release(geom->triangle); - sa_release(geom->interfaces); +static char +eq_fluid(const struct mat_fluid* a, const struct mat_fluid* b) +{ + if (a->fluid_id != b->fluid_id + || a->rho != b->rho + || a->cp != b->cp + || strcmp(a->Tinit, b->Tinit)) + return 0; + return 1; +} - return res; +static size_t +hash_fluid(const struct mat_fluid* key) +{ +#ifdef ARCH_32BITS + /* 32-bits Fowler/Noll/Vo hash function */ + const uint32_t FNV32_PRIME = + (uint32_t) (((uint32_t) 1 << 24) + ((uint32_t) 1 << 8) + 0x93); + const uint32_t OFFSET32_BASIS = 2166136261u; + uint32_t hash = OFFSET32_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->fluid_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->fluid_id)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->rho)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->rho)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->cp)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->cp)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, strlen(key->Tinit) * sizeof(*key->Tinit)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)key->Tinit)[i]); + hash = hash * FNV32_PRIME; + } + return hash; +#elif defined(ARCH_64BITS) + /* 64-bits Fowler/Noll/Vo hash function */ + const uint64_t FNV64_PRIME = + (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3); + const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u; + uint64_t hash = OFFSET64_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->fluid_id)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->fluid_id)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->rho)) { + hash = hash ^ (uint64_t) ((unsigned char)((const char*)&key->rho)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->cp)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->cp)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, strlen(key->Tinit)*sizeof(*key->Tinit)) { + hash = hash ^ (uint64_t)((unsigned char) ((const char*)key->Tinit)[i]); + hash = hash * FNV64_PRIME; + } + return hash; +#else +#error "Unexpected architecture" +#endif } -struct material{ +struct mat_solid { + unsigned solid_id; double lambda; double rho; double cp; double delta; char* Tinit; char* power; + int has_power; }; -#define NULL_MATERIAL__ {0.0 ,0.0 ,0.0, 0.0, NULL, NULL} -static const struct material NULL_MATERIAL = NULL_MATERIAL__; -struct boundary{ +static char +eq_solid(const struct mat_solid* a, const struct mat_solid* b) +{ + if (a->solid_id != b->solid_id + || a->lambda != b->lambda + || a->rho != b->rho + || a->cp != b->cp + || a->delta != b->delta + || strcmp(a->Tinit, b->Tinit) + || a->has_power != b->has_power) + return 0; + if (a->has_power && a->power != b->power) return 0; + return 1; +} + +static size_t +hash_solid(const struct mat_solid* key) +{ +#ifdef ARCH_32BITS + /* 32-bits Fowler/Noll/Vo hash function */ + const uint32_t FNV32_PRIME = + (uint32_t) (((uint32_t) 1 << 24) + ((uint32_t) 1 << 8) + 0x93); + const uint32_t OFFSET32_BASIS = 2166136261u; + uint32_t hash = OFFSET32_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->solid_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->solid_id)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->lambda)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->lambda)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->rho)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->rho)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->cp)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->cp)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->delta)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->delta)[i]); + hash = hash * FNV32_PRIME; +} + FOR_EACH(i, 0, strlen(key->Tinit) * sizeof(*key->Tinit)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)key->Tinit)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_power)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_power)[i]); + hash = hash * FNV32_PRIME; + } + if (!key->has_power) return hash; + FOR_EACH(i, 0, strlen(key->Tinit) * sizeof(*key->power)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) key->power)[i]); + hash = hash * FNV32_PRIME; + } + return hash; +#elif defined(ARCH_64BITS) + /* 64-bits Fowler/Noll/Vo hash function */ + const uint64_t FNV64_PRIME = + (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3); + const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u; + uint64_t hash = OFFSET64_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->solid_id)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->solid_id)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->lambda)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->lambda)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->rho)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->rho)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->cp)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->cp)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->delta)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->delta)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, strlen(key->Tinit) * sizeof(*key->Tinit)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)key->Tinit)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_power)) { + hash = hash ^ (uint64_t) ((unsigned char) ((const char*) &key->has_power)[i]); + hash = hash * FNV64_PRIME; + } + if (!key->has_power) return hash; + FOR_EACH(i, 0, strlen(key->power) * sizeof(*key->power)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)key->power)[i]); + hash = hash * FNV64_PRIME; + } + return hash; +#else +#error "Unexpected architecture" +#endif +} + +struct h_boundary { + unsigned mat_id; + double emissivity; + double specular_fraction; double hc; + double hc_max; char* T; + int has_emissivity, has_hc; +}; + +static char +eq_h_boundary + (const struct h_boundary* a, + const struct h_boundary* b) +{ + if (a->mat_id != b->mat_id + || a->specular_fraction != b->specular_fraction + || strcmp(a->T, b->T) + || a->has_emissivity != b->has_emissivity + || a->has_hc != b->has_hc) + return 0; + if (a->has_emissivity && a->emissivity != b->emissivity) return 0; + if (a->has_hc && (a->hc != b->hc || a->hc_max != b->hc_max)) return 0; + return 1; +} + +static size_t +hash_h_boundary(const struct h_boundary* key) +{ +#ifdef ARCH_32BITS + /* 32-bits Fowler/Noll/Vo hash function */ + const uint32_t FNV32_PRIME = + (uint32_t) (((uint32_t) 1 << 24) + ((uint32_t) 1 << 8) + 0x93); + const uint32_t OFFSET32_BASIS = 2166136261u; + uint32_t hash = OFFSET32_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->mat_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->emissivity)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->specular_fraction)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->specular_fraction)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, strlen(key->T) * sizeof(*key->T)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)key->T)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_emissivity)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->has_hc)[i]); + hash = hash * FNV32_PRIME; + } + if (!key->has_hc) return hash; + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->hc)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->hc_max)[i]); + hash = hash * FNV32_PRIME; + } + return hash; +#elif defined(ARCH_64BITS) + /* 64-bits Fowler/Noll/Vo hash function */ + const uint64_t FNV64_PRIME = + (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3); + const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u; + uint64_t hash = OFFSET64_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->mat_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->emissivity)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->specular_fraction)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->specular_fraction)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, strlen(key->T) * sizeof(*key->T)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)key->T)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_emissivity)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->has_hc)[i]); + hash = hash * FNV64_PRIME; + } + if (!key->has_hc) return hash; + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->hc)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->hc_max)[i]); + hash = hash * FNV64_PRIME; + } + return hash; +#else +#error "Unexpected architecture" +#endif +} + +struct t_boundary { + unsigned mat_id; + char* T; + struct te_expr* te_temperature; + double hc; + double hc_max; + int has_hc; +}; + +static char +eq_t_boundary + (const struct t_boundary* a, + const struct t_boundary* b, + const enum description_type type) +{ + ASSERT(type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID); + /* These fields are meaningful by both types */ + if (a->mat_id != b->mat_id || strcmp(a->T, b->T)) + return 0; + if (type != DESC_BOUND_T_FOR_FLUID) + return 1; + /* These ones are only relevant for fluids */ + if (a->has_hc != b->has_hc) + return 0; + if (a->has_hc && (a->hc != b->hc || a->hc_max != b->hc_max)) + return 0; + return 1; +} + +static size_t +hash_t_boundary + (const struct t_boundary* key, + const enum description_type type) +{ + ASSERT(type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID); +#ifdef ARCH_32BITS + /* 32-bits Fowler/Noll/Vo hash function */ + const uint32_t FNV32_PRIME = + (uint32_t) (((uint32_t) 1 << 24) + ((uint32_t) 1 << 8) + 0x93); + const uint32_t OFFSET32_BASIS = 2166136261u; + uint32_t hash = OFFSET32_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->mat_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->has_hc)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, strlen(key->T) * sizeof(*key->T)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) key->T)[i]); + hash = hash * FNV32_PRIME; + } + if (!key->has_hc) return hash; + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->hc)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc_max)[i]); + hash = hash * FNV32_PRIME; + } + return hash; +#elif defined(ARCH_64BITS) + /* 64-bits Fowler/Noll/Vo hash function */ + const uint64_t FNV64_PRIME = + (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3); + const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u; + uint64_t hash = OFFSET64_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->mat_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) &key->has_hc)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, strlen(key->T) * sizeof(*key->T)) { + hash = hash ^ (uint32_t) ((unsigned char) ((const char*) key->T)[i]); + hash = hash * FNV64_PRIME; + } + if (!key->has_hc) return hash; + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc_max)[i]); + hash = hash * FNV64_PRIME; + } + return hash; +#else +#error "Unexpected architecture" +#endif +} + +struct f_boundary { + unsigned mat_id; char* flux; + struct te_expr* te_flux; + double hc; + double hc_max; + int has_hc; +}; + +static char +eq_f_boundary(const struct f_boundary* a, const struct f_boundary* b) +{ + if (a->mat_id != b->mat_id + || strcmp(a->flux, b->flux) + || a->has_hc != b->has_hc) + return 0; + if (a->has_hc && (a->hc != b->hc || a->hc_max != b->hc_max)) return 0; + return 1; +} + +static size_t +hash_f_boundary(const struct f_boundary* key) +{ +#ifdef ARCH_32BITS + /* 32-bits Fowler/Noll/Vo hash function */ + const uint32_t FNV32_PRIME = + (uint32_t) (((uint32_t) 1 << 24) + ((uint32_t) 1 << 8) + 0x93); + const uint32_t OFFSET32_BASIS = 2166136261u; + uint32_t hash = OFFSET32_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->mat_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc_max)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, strlen(key->flux) * sizeof(*key->flux)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)key->flux)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_hc)[i]); + hash = hash * FNV32_PRIME; + } + return hash; +#elif defined(ARCH_64BITS) + /* 64-bits Fowler/Noll/Vo hash function */ + const uint64_t FNV64_PRIME = + (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3); + const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u; + uint64_t hash = OFFSET64_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->mat_id)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc_max)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, strlen(key->flux) * sizeof(*key->flux)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)key->flux)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_hc)[i]); + hash = hash * FNV64_PRIME; + } + return hash; +#else +#error "Unexpected architecture" +#endif +} + +struct solid_fluid_connect { double emissivity; double specular_fraction; + double hc; + double hc_max; + int has_emissivity, has_hc; }; -#define NULL_BOUNDARY__ {-1, NULL, NULL, 0.0 , 0.0} -static const struct boundary NULL_BOUNDARY = NULL_BOUNDARY__; -struct camera{ +static char +eq_sf_connect(const struct solid_fluid_connect* a, const struct solid_fluid_connect* b) +{ + return (char) (a->emissivity == b->emissivity + && a->specular_fraction == b->specular_fraction + && a->hc == b->hc + && a->hc_max == b->hc_max + && a->has_emissivity == b->has_emissivity + && a->has_hc == b->has_hc); +} + +static size_t +hash_sf_connect(const struct solid_fluid_connect* key) +{ +#ifdef ARCH_32BITS + /* 32-bits Fowler/Noll/Vo hash function */ + const uint32_t FNV32_PRIME = + (uint32_t) (((uint32_t) 1 << 24) + ((uint32_t) 1 << 8) + 0x93); + const uint32_t OFFSET32_BASIS = 2166136261u; + uint32_t hash = OFFSET32_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->emissivity)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->specular_fraction)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->specular_fraction)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc_max)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_emissivity)[i]); + hash = hash * FNV32_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_hc)[i]); + hash = hash * FNV32_PRIME; + } + return hash; +#elif defined(ARCH_64BITS) + /* 64-bits Fowler/Noll/Vo hash function */ + const uint64_t FNV64_PRIME = + (uint64_t) (((uint64_t) 1 << 40) + ((uint64_t) 1 << 8) + 0xB3); + const uint64_t OFFSET64_BASIS = (uint64_t) 14695981039346656037u; + uint64_t hash = OFFSET64_BASIS; + size_t i; + ASSERT(key); + FOR_EACH(i, 0, sizeof(key->emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->emissivity)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->specular_fraction)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->specular_fraction)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->hc_max)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->hc_max)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_emissivity)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_emissivity)[i]); + hash = hash * FNV64_PRIME; + } + FOR_EACH(i, 0, sizeof(key->has_hc)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->has_hc)[i]); + hash = hash * FNV64_PRIME; + } + return hash; +#else +#error "Unexpected architecture" +#endif +} + +struct description { + enum description_type type; + union d { + struct mat_fluid fluid; + struct mat_solid solid; + struct t_boundary t_boundary; + struct f_boundary f_boundary; + struct h_boundary h_boundary; + struct solid_fluid_connect sf_connect; + } d; +}; +#define NULL_DESCRIPTION__ {DESCRIPTION_TYPE_COUNT__ }; + +static char +eq_description(const struct description* a, const struct description* b) +{ + if (a->type != b->type) return 0; + switch (a->type) { + case DESC_MAT_SOLID: + return eq_solid(&a->d.solid, &b->d.solid); + case DESC_MAT_FLUID: + return eq_fluid(&a->d.fluid, &b->d.fluid); + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + return eq_h_boundary(&a->d.h_boundary, &b->d.h_boundary); + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + return eq_t_boundary(&a->d.t_boundary, &b->d.t_boundary, a->type); + case DESC_BOUND_F_FOR_SOLID: + return eq_f_boundary(&a->d.f_boundary, &b->d.f_boundary); + case DESC_SOLID_FLUID_CONNECT: + return eq_sf_connect(&a->d.sf_connect, &b->d.sf_connect); + default: FATAL("Invalid type.\n"); + } +} + +static size_t +hash_description(const struct description* key) +{ + switch (key->type) { + case DESC_MAT_SOLID: + return hash_solid(&key->d.solid); + case DESC_MAT_FLUID: + return hash_fluid(&key->d.fluid); + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + return hash_h_boundary(&key->d.h_boundary); + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + return hash_t_boundary(&key->d.t_boundary, key->type); + case DESC_BOUND_F_FOR_SOLID: + return hash_f_boundary(&key->d.f_boundary); + case DESC_SOLID_FLUID_CONNECT: + return hash_sf_connect(&key->d.sf_connect); + default: FATAL("Invalid type.\n"); + } +} + +struct camera { double pos[3]; double tgt[3]; double up[3]; @@ -126,10 +766,9 @@ struct camera{ #define NULL_CAMERA__ {{1,1,1},{0,0,0},{0,0,1},30,4,{640,480}} static const struct camera NULL_CAMERA = NULL_CAMERA__; -struct stardis{ +struct stardis { struct geometry geometry; - struct material* material; /*array of materials*/ - struct boundary* boundary; /*array of boundaries*/ + struct description* descriptions; /*array of materials and boundaries */ size_t N; /*number of MC realizations*/ unsigned nthreads; @@ -137,8 +776,9 @@ struct stardis{ double scale_factor; double radiative_temp[2]; struct camera camera; + struct mem_allocator allocator; }; -#define NULL_STARDIS__ {NULL_GEOMETRY__, NULL, NULL, 0, 0, {0,0,0,0}, 0, {300,300}, NULL_CAMERA__} +#define NULL_STARDIS__ {NULL_GEOMETRY__, NULL, 0, 0, {0,0,0,0}, 0, {300,300}, NULL_CAMERA__} static const struct stardis NULL_STARDIS = NULL_STARDIS__; extern res_T @@ -149,10 +789,10 @@ stardis_init extern res_T stardis_compute(struct stardis* stardis, enum stardis_mode mode); -extern res_T +void stardis_release(struct stardis* stardis); extern res_T -dump_vtk(FILE* output, const struct geometry* geometry, unsigned nbound); +dump_vtk(FILE* output, const struct geometry* geometry); #endif /*STARDIS-APP_H*/ diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -38,7 +38,32 @@ geometry_get_interface void* context) { struct geometry* geom = context; - *interf = geom->interfaces[itri]; + *interf = geom->interf_bytrg[itri]; +} + +static res_T +compile_expr_to_fn + (struct te_expr** f, + const char* math_expr, + const int t_allowed, + int* is_zero) +{ + te_variable vars[4] = { + TE_DEF_OFFSET("x", offsetof(struct sdis_rwalk_vertex, P[0])), + TE_DEF_OFFSET("y", offsetof(struct sdis_rwalk_vertex, P[1])), + TE_DEF_OFFSET("z", offsetof(struct sdis_rwalk_vertex, P[2])), + TE_DEF_OFFSET("t", offsetof(struct sdis_rwalk_vertex, time)) + }; + + ASSERT(math_expr); + *f = te_compile(math_expr, vars, t_allowed ? 4 : 3, NULL); + if (!*f) { + if (!t_allowed && te_compile(math_expr, vars, 4, NULL)) + printf("Expression use variable t and should not.\n"); + return RES_BAD_ARG; + } + if (is_zero) *is_zero = !((*f)->type == TE_CONSTANT && (*f)->v.value == 0); + return RES_OK; } /******************************************************************************* @@ -69,27 +94,22 @@ fluid_get_volumic_mass return fluid_props->rho; } -res_T -set_fluid_temperature_fn(struct fluid* fluid, const char* math_expr) +static double +fluid_get_temperature +(const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) { - te_variable vars[4] = { - TE_OFFSET("x", offsetof(struct sdis_rwalk_vertex, P[0])), - TE_OFFSET("y", offsetof(struct sdis_rwalk_vertex, P[1])), - TE_OFFSET("z", offsetof(struct sdis_rwalk_vertex, P[2])), - TE_OFFSET("t", offsetof(struct sdis_rwalk_vertex, time)) - }; - - ASSERT(math_expr); - fluid->temperature = te_compile(math_expr, vars, 4, NULL); - if(!fluid->temperature) return RES_BAD_ARG; - return RES_OK; + const struct fluid* fluid_props = sdis_data_cget(data); + return te_eval(fluid_props->temperature, vtx); } static double -fluid_get_temperature +fluid_get_tinit (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) { const struct fluid* fluid_props = sdis_data_cget(data); + if(vtx->time > 0) { + return -1; + } return te_eval(fluid_props->temperature, vtx); } @@ -161,24 +181,16 @@ solid_get_delta_boundary } #endif -res_T -set_solid_temperature_fn(struct solid* solid, const char* math_expr) +static double +solid_get_temperature +(const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) { - te_variable vars[4] = { - TE_OFFSET("x", offsetof(struct sdis_rwalk_vertex, P[0])), - TE_OFFSET("y", offsetof(struct sdis_rwalk_vertex, P[1])), - TE_OFFSET("z", offsetof(struct sdis_rwalk_vertex, P[2])), - TE_OFFSET("t", offsetof(struct sdis_rwalk_vertex, time)) - }; - - ASSERT(math_expr); - solid->t_init = te_compile(math_expr, vars, 4, NULL); - if (!solid->t_init) return RES_BAD_ARG; - return RES_OK; + const struct solid* solid_props = sdis_data_cget(data); + return te_eval(solid_props->t_init, vtx); } static double -solid_get_temperature +solid_get_tinit (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) { const struct solid* solid_props = sdis_data_cget(data); @@ -188,24 +200,6 @@ solid_get_temperature return te_eval(solid_props->t_init, vtx); } -res_T -set_solid_power_fn(struct solid* solid, const char* math_expr, int* has) -{ - te_variable vars[4] = { - TE_OFFSET("x", offsetof(struct sdis_rwalk_vertex, P[0])), - TE_OFFSET("y", offsetof(struct sdis_rwalk_vertex, P[1])), - TE_OFFSET("z", offsetof(struct sdis_rwalk_vertex, P[2])), - TE_OFFSET("t", offsetof(struct sdis_rwalk_vertex, time)) - }; - - ASSERT(math_expr); - solid->power = te_compile(math_expr, vars, 4, NULL); - if (!solid->power) return RES_BAD_ARG; - if(has) /* has power? */ - *has = !(solid->power->type == TE_CONSTANT && solid->power->v.value == 0); - return RES_OK; -} - static double solid_get_power (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) @@ -242,22 +236,6 @@ interface_get_convection_coef return interface_props->hc; } -res_T -set_interface_temperature_fn(struct intface* intface, const char* math_expr) -{ - te_variable vars[4] = { - TE_OFFSET("x", offsetof(struct sdis_interface_fragment, P[0])), - TE_OFFSET("y", offsetof(struct sdis_interface_fragment, P[1])), - TE_OFFSET("z", offsetof(struct sdis_interface_fragment, P[2])), - TE_OFFSET("t", offsetof(struct sdis_interface_fragment, time)) - }; - - ASSERT(math_expr); - intface->temperature = te_compile(math_expr, vars, 4, NULL); - if (!intface->temperature) return RES_BAD_ARG; - return RES_OK; -} - static double interface_get_temperature (const struct sdis_interface_fragment* frag, struct sdis_data* data) @@ -270,22 +248,6 @@ interface_get_temperature return te_eval(interface_props->temperature, frag); } -res_T -set_interface_flux_fn(struct intface* intface, const char* math_expr) -{ - te_variable vars[4] = { - TE_OFFSET("x", offsetof(struct sdis_interface_fragment, P[0])), - TE_OFFSET("y", offsetof(struct sdis_interface_fragment, P[1])), - TE_OFFSET("z", offsetof(struct sdis_interface_fragment, P[2])), - TE_OFFSET("t", offsetof(struct sdis_interface_fragment, time)) - }; - - ASSERT(math_expr); - intface->flux = te_compile(math_expr, vars, 4, NULL); - if (!intface->flux) return RES_BAD_ARG; - return RES_OK; -} - static double interface_get_flux (const struct sdis_interface_fragment* frag, struct sdis_data* data) @@ -314,7 +276,6 @@ interface_get_emissivity return interface_props->emissivity; } - static double interface_get_alpha (const struct sdis_interface_fragment* frag, struct sdis_data* data) @@ -324,31 +285,37 @@ interface_get_alpha return interface_props->alpha; } - static res_T select_probe_type -(const struct sdis_scene* scn, - const struct triangle* triangle, - const struct material* mat, - double pos[], - size_t* iprim, - double uv[]) + (const struct sdis_scene* scn, + const struct triangle* triangle, + const struct description* descriptions, + double pos[3], + size_t* iprim, + double uv[2]) { res_T res = RES_OK; size_t i = 0; - double projected_pos[3] = {0,0,0}; - double dp[3] = {0,0,0}; - double delta = 0; - for (i=0; i<sa_size(triangle); ++i){ - + for (i = 0; i < sa_size(triangle); ++i) { + double delta = 0, dp[3], projected_pos[3]; res = sdis_scene_boundary_project_position(scn, i, pos, uv); - + if (res != RES_OK) return res; res = sdis_scene_get_boundary_position(scn, i, uv, projected_pos); - + if (res != RES_OK) return res; d3_sub(dp, pos, projected_pos); - delta = mat[triangle[i].medium_front].delta; + if (triangle[i].front_description != UINT_MAX) { + const struct description *desc = descriptions + triangle[i].front_description; + if (desc->type == DESC_MAT_SOLID) delta = MMAX(desc->d.solid.delta, delta); + + } + if (triangle[i].back_description != UINT_MAX) { + const struct description *desc = descriptions + triangle[i].back_description; + if (desc->type == DESC_MAT_SOLID) delta = MMAX(desc->d.solid.delta, delta); + + } + if (d3_len(dp) < delta){ *iprim = i; fprintf(stderr,"The probe is very close to the primitive %llu.\n", @@ -400,183 +367,458 @@ dump_image(const struct sdis_accum_buffer* buf) /******************************************************************************* * ******************************************************************************/ - -res_T -stardis_compute(struct stardis* stardis, enum stardis_mode mode) + +struct int_descs { + unsigned front, back, connect; unsigned id; +}; +#define INT_DESCS_NULL__ { UINT_MAX, UINT_MAX, UINT_MAX }; +static const struct int_descs INT_DESCS_NULL = INT_DESCS_NULL__; + +static inline char +eq_desc(const struct int_descs* a, const struct int_descs* b) { - res_T res = RES_OK; - struct sdis_device* dev = NULL; - struct sdis_data* data = NULL; - struct solid* solid_props = NULL; - struct fluid* fluid_props = NULL; - struct sdis_solid_shader solid_shader = SDIS_SOLID_SHADER_NULL; - struct sdis_medium** solid_medium = NULL; - struct sdis_fluid_shader fluid_shader = SDIS_FLUID_SHADER_NULL; - struct sdis_medium** fluid_medium = NULL; - - struct sdis_interface_side_shader interface_shader_front = - SDIS_INTERFACE_SIDE_SHADER_NULL; - struct sdis_interface_side_shader interface_shader_back = - SDIS_INTERFACE_SIDE_SHADER_NULL; - struct sdis_interface_shader interface_shader_boundary = - SDIS_INTERFACE_SHADER_NULL; - struct sdis_interface_shader interface_shader_connection = - SDIS_INTERFACE_SHADER_NULL; - struct intface* interface_props = NULL; - struct sdis_interface** interfaces = NULL; + return (char)(a->front == b->front && a->back == b->back + && a->connect == b->connect); +} - struct sdis_scene* scn = NULL; - struct sdis_estimator* estimator = NULL; - struct sdis_mc temperature; - struct sdis_accum_buffer* buf = NULL; - struct sdis_camera* cam = NULL; +static INLINE size_t +hash_desc(struct int_descs const* key) +{ +#ifdef ARCH_32BITS + return (size_t)hash_fnv32(key, 3 * sizeof(unsigned)); +#elif defined(ARCH_64BITS) + return (size_t)hash_fnv64(key, 3 * sizeof(unsigned)); +#else +#error "Unexpected architecture" +#endif +} - int* bound2fluid = NULL; - double pos[3] = {0,0,0}; - double time[2] = { 0, 0}; - size_t nfailures; - unsigned i = 0; +#include <rsys/hash_table.h> +/* Declare the hash table that map a vertex to its index */ +#define HTABLE_NAME intface +#define HTABLE_DATA struct sdis_interface* +#define HTABLE_KEY struct int_descs +#define HTABLE_KEY_FUNCTOR_EQ eq_desc +#define HTABLE_KEY_FUNCTOR_HASH hash_desc +#include <rsys/hash_table.h> - SDIS(device_create(NULL, NULL, stardis->nthreads, 1, &dev)); +static res_T +create_fluid + (struct sdis_device* dev, + const double rho, + const double cp, + const int t_allowed, + const char* t_expr, + struct sdis_medium*** media_ptr, + sdis_medium_getter_T get_temp, + unsigned* out_id) +{ + struct sdis_fluid_shader fluid_shader = SDIS_FLUID_SHADER_NULL; + struct sdis_data* data = NULL; + struct fluid* fluid_props; + size_t sz; + res_T res = RES_OK; - /* Setup the fluid shader */ + ASSERT(dev && rho >= 0 && cp >= 0 && t_expr && media_ptr && out_id); fluid_shader.calorific_capacity = fluid_get_calorific_capacity; fluid_shader.volumic_mass = fluid_get_volumic_mass; - fluid_shader.temperature = fluid_get_temperature; - - /* create fluid for each hc boundary */ - for (i=0; i<stardis->geometry.boundary_count; ++i){ - SDIS(data_create(dev, sizeof(struct fluid), ALIGNOF(struct fluid), - release_fluid_data, &data)); - fluid_props = sdis_data_get(data); /* Fetch the allocated memory space */ - fluid_props->cp = 0; - fluid_props->rho = 0; - res = set_fluid_temperature_fn(fluid_props, stardis->boundary[i].T); - if (res != RES_OK) { - fprintf(stderr, "Invalid temperature expression: %s\n", stardis->boundary[i].T); - goto error; - } - SDIS(fluid_create(dev, &fluid_shader, data, sa_add(fluid_medium, 1))); - SDIS(data_ref_put(data)); data = NULL; - if (stardis->boundary[i].hc > -1) { - size_t sz = sa_size(fluid_medium) - 1; - ASSERT(sz < INT_MAX); - sa_push(bound2fluid, (int)sz); - } else { - sa_push(bound2fluid, 0); - } + fluid_shader.temperature = get_temp; + res = sdis_data_create(dev, sizeof(struct fluid), ALIGNOF(struct fluid), + release_fluid_data, &data); + if (res != RES_OK) goto error; + fluid_props = sdis_data_get(data); /* Fetch the allocated memory space */ + fluid_props->cp = cp; + fluid_props->rho = rho; + res = compile_expr_to_fn(&fluid_props->temperature, t_expr, t_allowed, NULL); + if (res != RES_OK) { + fprintf(stderr, "Invalid initial temperature expression: %s\n", + t_expr); + goto error; } + res = sdis_fluid_create(dev, &fluid_shader, data, sa_add(*media_ptr, 1)); + if (res != RES_OK) goto error; + sz = sa_size(*media_ptr) - 1; + ASSERT(sz < INT_MAX); + *out_id = (unsigned)sz; - /* Setup the solid shader */ +end: + if (data) SDIS(data_ref_put(data)); + return res; +error: + goto end; +} + +static res_T +create_solid + (struct sdis_device* dev, + const double lambda, + const double rho, + const double cp, + const double delta, + const int t_allowed, + const char* t_expr, /* Can be NULL if get_temp is NULL */ + const char* power_expr, /* Can be NULL */ + struct sdis_medium*** media_ptr, + sdis_medium_getter_T get_temp, /* Can be NULL */ + int* out_has_power, /* Can be NULL */ + unsigned* out_id) +{ + struct sdis_solid_shader solid_shader = SDIS_SOLID_SHADER_NULL; + struct sdis_data* data = NULL; + struct solid* solid_props; + size_t sz; + res_T res = RES_OK; + + ASSERT(dev && lambda >= 0 && rho >= 0 && cp >= 0 && delta > 0 + && media_ptr && out_id); + ASSERT(t_expr || !get_temp); solid_shader.calorific_capacity = solid_get_calorific_capacity; solid_shader.thermal_conductivity = solid_get_thermal_conductivity; solid_shader.volumic_mass = solid_get_volumic_mass; - solid_shader.delta_solid = solid_get_delta; + solid_shader.delta_solid = solid_get_delta; #if Stardis_VERSION_MINOR == 3 solid_shader.delta_boundary = solid_get_delta_boundary; #endif - solid_shader.temperature = solid_get_temperature; - - /* Create the solid medium */ - for (i=0; i<stardis->geometry.medium_count; ++i){ - /* Create and setup the solid physical properties */ - int has; - SDIS(data_create(dev, sizeof(struct solid), ALIGNOF(struct solid), - release_solid_data, &data)); - solid_props = sdis_data_get(data); /* Fetch the allocated memory space */ - solid_props->cp = stardis->material[i].cp; - solid_props->lambda = stardis->material[i].lambda; - solid_props->rho = stardis->material[i].rho; - solid_props->delta = stardis->material[i].delta; - solid_props->power = NULL; /* just in case we go to error */ - res = set_solid_temperature_fn(solid_props, stardis->material[i].Tinit); + solid_shader.temperature = get_temp; + res = sdis_data_create(dev, sizeof(struct solid), ALIGNOF(struct solid), + release_solid_data, &data); + if (res != RES_OK) goto error; + + solid_props = sdis_data_get(data); /* Fetch the allocated memory space */ + solid_props->lambda = lambda; + solid_props->rho = rho; + solid_props->cp = cp; + solid_props->delta = delta; + solid_props->power = NULL; /* just in case we go to error */ + if (t_expr) { + res = compile_expr_to_fn(&solid_props->t_init, t_expr, t_allowed, NULL); if (res != RES_OK) { fprintf(stderr, "Invalid initial temperature expression: %s\n", - stardis->material[i].Tinit); + t_expr); goto error; } - res = set_solid_power_fn(solid_props, stardis->material[i].power, &has); + } + if (power_expr) { + int has_power; + res = compile_expr_to_fn(&solid_props->power, power_expr, 1, &has_power); if (res != RES_OK) { fprintf(stderr, "Invalid volumic power expression: %s\n", - stardis->material[i].power); + power_expr); goto error; } - if (has) solid_shader.volumic_power = solid_get_power; - SDIS(solid_create(dev, &solid_shader, data, sa_add(solid_medium, 1))); - SDIS(data_ref_put(data)); data = NULL; + if (out_has_power) *out_has_power = has_power; + if(has_power) solid_shader.volumic_power = solid_get_power; + } + else { + if (out_has_power) *out_has_power = 0; + } + res = sdis_solid_create(dev, &solid_shader, data, sa_add(*media_ptr, 1)); + if (res != RES_OK) goto error; + sz = sa_size(*media_ptr) - 1; + ASSERT(sz < INT_MAX); + *out_id = (unsigned)sz; + +end: + if (data) SDIS(data_ref_put(data)); + return res; +error: + goto end; +} + +res_T +stardis_compute(struct stardis* stardis, enum stardis_mode mode) +{ + res_T res = RES_OK; + struct sdis_device* dev = NULL; + struct sdis_medium** media = NULL; + struct sdis_interface** interfaces = NULL; + struct sdis_interface** interf_bytrg = NULL; + + struct sdis_scene* scn = NULL; + struct sdis_estimator* estimator = NULL; + struct sdis_mc temperature; + struct sdis_accum_buffer* buf = NULL; + struct sdis_camera* cam = NULL; + + struct htable_intface htable_interfaces; unsigned int_cpt = 0; + double pos[3] = {0,0,0}; + double time[2] = { 0, 0}; + size_t nfailures; + unsigned i = 0; + const int t_allowed = stardis->probe[3] < INF; /* Can condition use the variable t? */ + + res = sdis_device_create(NULL, &stardis->allocator, stardis->nthreads, 1, &dev); + if (res != RES_OK) goto error; + + /* Create media and property holders found in descriptions */ + for (i = 0; i < sa_size(stardis->descriptions); ++i) { + struct description* desc = stardis->descriptions + i; + + switch (desc->type) { + case DESC_BOUND_H_FOR_SOLID: + /* Create an external fluid */ + res = create_fluid(dev, 1, 1, t_allowed, desc->d.h_boundary.T, &media, + fluid_get_temperature, &desc->d.h_boundary.mat_id); + if (res != RES_OK) goto error; + break; + case DESC_BOUND_H_FOR_FLUID: + /* Create an external solid */ + res = create_solid(dev, 1, 1, 1, 1, t_allowed, desc->d.h_boundary.T, + NULL, &media, solid_get_temperature, NULL, &desc->d.h_boundary.mat_id); + if (res != RES_OK) goto error; + break; + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + ASSERT(desc->d.t_boundary.T != NULL); + res = compile_expr_to_fn(&desc->d.t_boundary.te_temperature, + desc->d.t_boundary.T, 1, NULL); + if (res != RES_OK) { + fprintf(stderr, "Invalid boundary temperature expression: %s\n", + desc->d.h_boundary.T); + goto error; + } + /* Create an external solid */ + res = create_solid(dev, 1, 1, 1, 1, t_allowed, NULL, NULL, &media, NULL, + NULL, &desc->d.t_boundary.mat_id); + if (res != RES_OK) goto error; + break; + case DESC_BOUND_F_FOR_SOLID: + ASSERT(desc->d.f_boundary.flux != NULL); + res = compile_expr_to_fn(&desc->d.f_boundary.te_flux, + desc->d.f_boundary.flux, 1, NULL); + if (res != RES_OK) { + fprintf(stderr, "Invalid boundary flux expression: %s\n", + desc->d.h_boundary.T); + goto error; + } + /* Create an external solid */ + res = create_solid(dev, 1, 1, 1, 1, t_allowed, NULL, NULL, &media, NULL, + NULL, &desc->d.f_boundary.mat_id); + if (res != RES_OK) goto error; + break; + case DESC_SOLID_FLUID_CONNECT: + ASSERT(desc->d.sf_connect.specular_fraction >= 0 + && desc->d.sf_connect.specular_fraction <= 1); + ASSERT(desc->d.sf_connect.emissivity >= 0); + ASSERT(desc->d.sf_connect.hc >= 0); + break; + case DESC_MAT_SOLID: + res = create_solid(dev, + stardis->descriptions[i].d.solid.lambda, + stardis->descriptions[i].d.solid.rho, + stardis->descriptions[i].d.solid.cp, + stardis->descriptions[i].d.solid.delta, + t_allowed, + stardis->descriptions[i].d.solid.Tinit, + stardis->descriptions[i].d.solid.power, + &media, + solid_get_tinit, + &stardis->descriptions[i].d.solid.has_power, + &desc->d.solid.solid_id); + if (res != RES_OK) goto error; + break; + case DESC_MAT_FLUID: + res = create_fluid(dev, + stardis->descriptions[i].d.fluid.rho, + stardis->descriptions[i].d.fluid.cp, + t_allowed, + stardis->descriptions[i].d.fluid.Tinit, + &media, + fluid_get_tinit, + &desc->d.fluid.fluid_id); + if (res != RES_OK) goto error; + break; + default: FATAL("Invalid type.\n"); + } } - /* Setup the interface shader */ - interface_shader_front.temperature = interface_get_temperature; - interface_shader_front.flux = interface_get_flux; - interface_shader_front.emissivity = NULL; - interface_shader_front.specular_fraction = NULL; - - interface_shader_back.temperature = interface_get_temperature; - interface_shader_back.flux = NULL; - interface_shader_back.emissivity = interface_get_emissivity; - interface_shader_back.specular_fraction = interface_get_alpha; - - interface_shader_boundary.convection_coef = interface_get_convection_coef; - interface_shader_boundary.front = interface_shader_front; - interface_shader_boundary.back = interface_shader_back; - - for (i=0; i<sa_size(stardis->geometry.triangle); ++i){ - unsigned bound_id = stardis->geometry.triangle[i].bound_id; - - if (bound_id != UINT_MAX){ /* boundary interface */ - double hc = stardis->boundary[bound_id].hc; - char* T = stardis->boundary[bound_id].T; - char* flux = stardis->boundary[bound_id].flux; - double emissivity = - stardis->boundary[stardis->geometry.triangle[i].bound_id].emissivity; - double alpha = - stardis->boundary[stardis->geometry.triangle[i].bound_id].specular_fraction; - - SDIS(data_create(dev, sizeof(struct intface), ALIGNOF(struct intface), + /* Create interfaces */ + htable_intface_init(&stardis->allocator, &htable_interfaces); + for (i=0; i<sa_size(stardis->geometry.triangle); ++i) { + struct triangle *trg = stardis->geometry.triangle + i; + struct int_descs int_descs = INT_DESCS_NULL; + struct sdis_interface** p_intface; + struct sdis_interface* intface; + struct sdis_medium* front_med = NULL; + struct sdis_medium* back_med = NULL; + struct sdis_interface_side_shader* fluid_side_shader = NULL; + unsigned fd = trg->front_description; + unsigned bd = trg->back_description; + unsigned cd = trg->connection_description; + int fluid_count = 0, solid_count = 0; + int solid_fluid_connection_count = 0, connection_count = 0, boundary_count = 0; + + /* Create key */ + int_descs.front = fd; + int_descs.back = bd; + int_descs.connect = trg->connection_description; + + /* Search if interface already exists, or create it */ + p_intface = htable_intface_find(&htable_interfaces, &int_descs); + if (p_intface) { + intface = *p_intface; + } + else { + /* create new interface and register */ + struct sdis_data* data = NULL; + struct sdis_interface_shader interface_shader = SDIS_INTERFACE_SHADER_NULL; + struct intface* interface_props = NULL; + int front_defined = (fd != UINT_MAX); + int back_defined = (bd != UINT_MAX); + int connect_defined = (cd != UINT_MAX); + int incoherent = 0; + int_descs.id = int_cpt++; + + SDIS(data_create(dev, sizeof(struct intface), ALIGNOF(struct intface), release_interface_data, &data)); interface_props = sdis_data_get(data); - if (hc > -1) { - interface_props->hc = hc; - interface_props->temperature = NULL; - interface_props->flux = NULL; - } else if (T != NULL){ - interface_props->flux = NULL; - res = set_interface_temperature_fn(interface_props, T); - if (res != RES_OK) { - fprintf(stderr, "Invalid temperature expression: %s\n", T); - goto error; + interface_props->temperature = NULL; + interface_props->flux = NULL; + + if (front_defined) { + switch (stardis->descriptions[fd].type) { + case DESC_MAT_SOLID: + solid_count++; + front_med = media[fd]; + break; + case DESC_MAT_FLUID: + fluid_count++; + front_med = media[fd]; + fluid_side_shader = &interface_shader.front; + break; + default: FATAL("Invalid type.\n"); } - } else if (flux != NULL){ - interface_props->temperature = NULL; - res = set_interface_flux_fn(interface_props, flux); - if (res != RES_OK) { - fprintf(stderr, "Invalid flux expression: %s\n", flux); - goto error; + } + if (back_defined) { + switch (stardis->descriptions[bd].type) { + case DESC_MAT_SOLID: + solid_count++; + back_med = media[bd]; + break; + case DESC_MAT_FLUID: + fluid_count++; + back_med = media[bd]; + fluid_side_shader = &interface_shader.back; + break; + default: FATAL("Invalid type.\n"); } } - interface_props->emissivity = emissivity; - interface_props->alpha = alpha; - SDIS(interface_create(dev, - solid_medium[stardis->geometry.triangle[i].medium_front], - fluid_medium[bound2fluid[bound_id]], - &interface_shader_boundary, data, sa_add(interfaces,1))); - SDIS(data_ref_put(data)); data = NULL; + if (connect_defined) { + const struct description* connect = stardis->descriptions + cd; + unsigned ext_id; + switch (connect->type) { + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + /* One among front and back should be defined, the other undefined; + * if not will raise an error below */ + ext_id = connect->d.h_boundary.mat_id; /* External material id */ + ASSERT(ext_id < sa_size(media)); + ASSERT(sdis_medium_get_type(media[ext_id]) == + (connect->type == DESC_BOUND_H_FOR_SOLID ? SDIS_FLUID : SDIS_SOLID)); + if (front_defined && back_defined) incoherent = 1; + connection_count++; + boundary_count++; + if (front_defined) back_med = media[ext_id]; + else front_med = media[ext_id]; + interface_shader.convection_coef = interface_get_convection_coef; + interface_shader.convection_coef_upper_bound = connect->d.h_boundary.hc_max; + interface_props->hc = connect->d.h_boundary.hc; + interface_props->emissivity = connect->d.h_boundary.emissivity; + interface_props->alpha = connect->d.h_boundary.specular_fraction; + break; + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + /* One among front and back should be defined, the other undefined; + * if not will raise an error below */ + ext_id = connect->d.t_boundary.mat_id; /* External material id */ + ASSERT(ext_id < sa_size(media)); + ASSERT(sdis_medium_get_type(media[ext_id]) == SDIS_SOLID); + if (front_defined && back_defined) incoherent = 1; + connection_count++; + boundary_count++; + if (front_defined) back_med = media[ext_id]; + else front_med = media[ext_id]; + ASSERT(connect->d.t_boundary.te_temperature); + interface_props->temperature = connect->d.t_boundary.te_temperature; + if (connect->d.t_boundary.has_hc) { + ASSERT(connect->type == DESC_BOUND_T_FOR_FLUID); + interface_shader.convection_coef = interface_get_convection_coef; + interface_shader.convection_coef_upper_bound = connect->d.t_boundary.hc_max; + interface_props->hc = connect->d.t_boundary.hc; + } + break; + case DESC_BOUND_F_FOR_SOLID: + /* One among front and back should be defined, the other undefined; + * if not will raise an error below */ + connection_count++; + /* Reuse same solid for the external side */ + if (front_defined) { + ASSERT(!back_defined); + back_med = front_med; + interface_shader.front.flux = interface_get_flux; + } + else { + ASSERT(back_defined); + front_med = back_med; + interface_shader.back.flux = interface_get_flux; + } + ASSERT(connect->d.f_boundary.te_flux); + interface_props->flux = connect->d.f_boundary.te_flux; + break; + case DESC_SOLID_FLUID_CONNECT: + /* Both front and back should be defined; + * if not will raise an error below */ + connection_count++; + solid_fluid_connection_count++; + ASSERT(fluid_side_shader); + if (connect->d.sf_connect.has_hc) { + interface_shader.convection_coef = interface_get_convection_coef; + interface_shader.convection_coef_upper_bound = connect->d.sf_connect.hc_max; + interface_props->hc = connect->d.sf_connect.hc; + } + if (connect->d.sf_connect.has_emissivity) { + fluid_side_shader->emissivity = interface_get_emissivity; + interface_props->emissivity = connect->d.sf_connect.emissivity; + interface_props->alpha = connect->d.sf_connect.specular_fraction; + } + break; + default: FATAL("Invalid type.\n"); + } + } + + if(fluid_count == 2 + || fluid_count + solid_count + connection_count < 2 + || boundary_count ? + (fluid_count + solid_count != 1) : (fluid_count + solid_count != 2) + || (solid_fluid_connection_count && (fluid_count != 1 || solid_count != 1))) + incoherent = 1; + if (incoherent) { + /* Incoherent triangle description */ + if(fluid_count == 2) + fprintf(stderr, "Incoherent triangle description\n"); + res = RES_BAD_ARG; + goto error; + } - } else { /* solid/solid interface */ - SDIS(interface_create(dev, - solid_medium[stardis->geometry.triangle[i].medium_front], - solid_medium[stardis->geometry.triangle[i].medium_back], - &interface_shader_connection, NULL, sa_add(interfaces,1))); + res = sdis_interface_create(dev, front_med, back_med, + &interface_shader, data, &intface); + if (res != RES_OK) goto error; + SDIS(data_ref_put(data)); data = NULL; + res = htable_intface_set(&htable_interfaces, &int_descs, &intface); + if (res != RES_OK) goto error; + sa_push(interfaces, intface); } + sa_push(interf_bytrg, intface); } + stardis->geometry.interf_bytrg = interf_bytrg; stardis->geometry.interfaces = interfaces; - SDIS(scene_create(dev, + res = sdis_scene_create(dev, sa_size(stardis->geometry.triangle), geometry_get_indices, geometry_get_interface, sa_size(stardis->geometry.vertex), - geometry_get_position, &stardis->geometry, &scn)); + geometry_get_position, &stardis->geometry, &scn); + if (res != RES_OK) goto error; if (mode == IR_COMPUTE){ @@ -627,7 +869,7 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) res = select_probe_type(scn, stardis->geometry.triangle, - stardis->material, + stardis->descriptions, pos, &iprim, uv); @@ -670,23 +912,9 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) } end: - for (i=0; i<sa_size(solid_medium); ++i){ - SDIS(medium_ref_put(solid_medium[i])); - } - sa_release(solid_medium); - - for (i=0; i<sa_size(fluid_medium); ++i){ - SDIS(medium_ref_put(fluid_medium[i])); - } - sa_release(fluid_medium); - - for (i=0; i<sa_size(interfaces); ++i){ - SDIS(interface_ref_put(interfaces[i])); - } - sa_release(interfaces); - stardis->geometry.interfaces = NULL; - - sa_release(bound2fluid); + for (i=0; i<sa_size(media); ++i) + SDIS(medium_ref_put(media[i])); + sa_release(media); if (cam) SDIS(camera_ref_put(cam)); if (buf) SDIS(accum_buffer_ref_put(buf)); @@ -696,6 +924,5 @@ end: return res; error: - if(data) SDIS(data_ref_put(data)); goto end; }