stardis

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

commit 4350f88693db871b487a1482edd84d1fe7b9e17b
parent 580c13150738b78675bcf046dbd9b98a35d8ac63
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Mon, 20 May 2019 15:42:33 +0200

Add Green computation and output

Diffstat:
Msrc/args.h | 92+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/main.c | 2+-
Msrc/stardis-app.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/stardis-app.h | 58++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/stardis-compute.c | 798+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
5 files changed, 779 insertions(+), 247 deletions(-)

diff --git a/src/args.h b/src/args.h @@ -11,17 +11,27 @@ #include <sdis_version.h> enum stardis_mode { - PROBE_COMPUTE, - MEDIUM_COMPUTE, - BOUNDARY_COMPUTE, - IR_COMPUTE, - DUMP_VTK, - UNDEF_MODE + UNDEF_MODE = 0, + PROBE_COMPUTE = BIT(0), + MEDIUM_COMPUTE = BIT(1), + BOUNDARY_COMPUTE = BIT(2), + GREEN_MODE = BIT(3), + IR_COMPUTE = BIT(4), + DUMP_VTK = BIT(5), + COMPUTE_MODES = PROBE_COMPUTE | MEDIUM_COMPUTE | BOUNDARY_COMPUTE | IR_COMPUTE | DUMP_VTK }; -static const char MODE_OPTION[UNDEF_MODE] = { - 'p', 'm', 'b', 'R', 'd' -}; +static char mode_option(const enum stardis_mode m) { + int found = 0; + char res = '?'; + if (m & PROBE_COMPUTE) { found++; res = 'p'; } + if (m & MEDIUM_COMPUTE) { found++; res = 'm'; } + if (m & BOUNDARY_COMPUTE) { found++; res = 'b'; } + if (m & IR_COMPUTE) { found++; res = 'R'; } + if (m & DUMP_VTK) { found++; res = 'd'; } + ASSERT(found == 1); + return res; +} enum dump_path_type { DUMP_NONE = 0, @@ -67,7 +77,7 @@ print_help(char* prog) printf("usage: \n%s -M MEDIUM.txt -B BOUNDARY.txt\n", prog); printf("[ -p X,Y,Z,TIME | -m MEDIUM_NAME,TIME | -d | -b SURFACE.vtk,TIME\n"); printf(" | -R t=TIME:spp=SPP:fov=FOV:up=XUP,YUP,ZUP:pos=X,Y,Z:tgt=XT,YT,ZT:img=WxH ]\n"); - printf("[-s SCALE_FACTOR] [-D {all | error | success}] -d\n"); + printf("[ -g] [-s SCALE_FACTOR] [-D {all | error | success}] -d\n"); printf("[-n NUM_OF_REALIZATIONS] [-t NUM_OF_THREADS]\n"); printf("[-r AMBIENT_RAD_TEMP:REFERENCE_TEMP]\n"); printf("\n -h: print this help.\n"); @@ -82,21 +92,21 @@ print_help(char* prog) printf("\nExclusive arguments\n"); printf("-------------------\n"); printf("\n -p X:Y:Z:TIME:\n"); - printf(" compute the temperature at the given probe.\n"); + printf(" Compute the temperature at the given probe.\n"); printf(" The probe must be in a medium. If some boundary conditions are\n"); - printf(" time-dependant, TIME can not be INF.\n"); + printf(" time-dependant, TIME cannot be INF.\n"); printf("\n -m MEDIUM_NAME,TIME:\n"); - printf(" compute the mean temperature in a given medium at a given time.\n"); - printf(" If some boundary conditions are time-dependant, TIME can not be INF.\n"); + printf(" Compute the mean temperature in a given medium at a given time.\n"); + printf(" If some boundary conditions are time-dependant, TIME cannot be INF.\n"); printf("\n -d:\n"); - printf(" dump the geometry in VTK format with medium front/back id and\n"); + printf(" Dump the geometry in VTK format with medium front/back id and\n"); printf(" boundary id.\n"); printf("\n -b SURFACE.vtk,TIME:\n"); - printf(" compute the mean temperature on a given 2D shape at a given time.\n"); + printf(" Compute the mean temperature on a given 2D shape at a given time.\n"); printf(" Mean temperature is computed on the front sides of the primitives\n"); printf(" listed in SURFACE.vtk. These primitives are not added to the geometry,\n"); printf(" but must be already known. The shape doesn't need to be connex.\n"); - printf(" If some boundary conditions are time-dependant, TIME can not be INF.\n"); + printf(" If some boundary conditions are time-dependant, TIME cannot be INF.\n"); printf("\n -R t=TIME:spp=SPP:fov=FOV:up=XUP,YUP,ZUP:pos=X,Y,Z:tgt=XT,YT,ZT:img=WxH:\n"); printf(" The infra-red rendering mode.\n"); printf(" t is the rendering time (default: INF).\n"); @@ -108,20 +118,24 @@ print_help(char* prog) printf(" img is the resolution (default: 640x480).\n"); printf("\nOptionnal arguments\n"); printf("-------------------\n"); + printf("\n -g:\n"); + printf(" Compute the green function.\n"); + printf(" Must be used in conjonction with one the -p, -m or -b options.\n"); + printf(" Provided TIME is silently ignored.\n"); printf("\n -s SCALE_FACTOR:\n"); printf(" default value: 1.0.\n"); printf("\n -D { all | error | success }:\n"); printf(" dump paths in VTK format.\n"); printf("\n -n NUM_OF_REALIZATIONS:\n"); - printf(" number of Monte-Carlo realizations.\n"); + printf(" Number of Monte-Carlo realizations.\n"); printf(" default value: 10000.\n"); printf("\n -t NUM_OF_THREADS:\n"); - printf(" default value: all threads available.\n"); + printf(" Number of threads; default value is all threads available.\n"); printf("\n -r AMBIENT_RAD_TEMP,REFERENCE_TEMP:\n"); printf(" Parameters for the radiative transfer.\n"); printf(" AMBIENT_RAD_TEMP is the ambient radiative temperature .\n"); - printf(" REFERENCE_TEMP is the temperature used for the linearization.\n"); - printf(" of theradiative transfer.\n"); + printf(" REFERENCE_TEMP is the temperature used for the linearization\n"); + printf(" of the radiative transfer.\n"); } @@ -138,13 +152,17 @@ parse_args(const int argc, char** argv, struct args* args) goto error; } - while((opt = getopt(argc, argv, "hn:t:b:B:M:m:p:dD:s:r:R:")) != -1) { + while((opt = getopt(argc, argv, "hgn:t:b:B:M:m:p:dD:s:r:R:")) != -1) { switch(opt) { case 'h': print_help(argv[0]); args->just_help = 1; goto exit; + case 'g': + args->mode |= GREEN_MODE; + break; + case 'n': { args->N = strtoull(optarg, NULL, 10); if (args->N <= 0) { @@ -174,13 +192,13 @@ parse_args(const int argc, char** argv, struct args* args) break; case 'p': - if (args->mode != UNDEF_MODE) { + if (args->mode & COMPUTE_MODES) { res = RES_BAD_ARG; fprintf(stderr, "Cannot specify multiple modes: -%c and -%c\n", - (char)opt, MODE_OPTION[args->mode]); + (char)opt, mode_option(args->mode)); goto error; } - args->mode = PROBE_COMPUTE; + args->mode |= PROBE_COMPUTE; cstr_to_list_double(optarg, ',', args->u.probe, &len, 4); if(len != 4 || res != RES_OK) { @@ -193,13 +211,13 @@ parse_args(const int argc, char** argv, struct args* args) case 'b': { int err = 0; char *ptr; - if (args->mode != UNDEF_MODE) { + if (args->mode & COMPUTE_MODES) { res = RES_BAD_ARG; fprintf(stderr, "Cannot specify multiple modes: -%c and -%c\n", - (char)opt, MODE_OPTION[args->mode]); + (char)opt, mode_option(args->mode)); goto error; } - args->mode = BOUNDARY_COMPUTE; + args->mode |= BOUNDARY_COMPUTE; ptr = strrchr(optarg, ','); /* Single ',' allowed */ if (ptr != strchr(optarg, ',')) @@ -219,13 +237,13 @@ parse_args(const int argc, char** argv, struct args* args) } case 'm': { char* ptr; - if (args->mode != UNDEF_MODE) { + if (args->mode & COMPUTE_MODES) { res = RES_BAD_ARG; fprintf(stderr, "Cannot specify multiple modes: -%c and -%c\n", - (char)opt, MODE_OPTION[args->mode]); + (char)opt, mode_option(args->mode)); goto error; } - args->mode = MEDIUM_COMPUTE; + args->mode |= MEDIUM_COMPUTE; ptr = strpbrk(optarg, ","); if (! ptr || ptr == optarg) res = RES_BAD_ARG; @@ -240,13 +258,13 @@ parse_args(const int argc, char** argv, struct args* args) } case 'd': - if (args->mode != UNDEF_MODE) { + if (args->mode & COMPUTE_MODES) { res = RES_BAD_ARG; fprintf(stderr, "Cannot specify multiple modes: -%c and -%c\n", - (char)opt, MODE_OPTION[args->mode]); + (char)opt, mode_option(args->mode)); goto error; } - args->mode = DUMP_VTK; + args->mode |= DUMP_VTK; break; case 'D': @@ -286,13 +304,13 @@ parse_args(const int argc, char** argv, struct args* args) break; case 'R': - if (args->mode != UNDEF_MODE) { + if (args->mode & COMPUTE_MODES) { res = RES_BAD_ARG; fprintf(stderr, "Cannot specify multiple modes: -%c and -%c\n", - (char)opt, MODE_OPTION[args->mode]); + (char)opt, mode_option(args->mode)); goto error; } - args->mode = IR_COMPUTE; + args->mode |= IR_COMPUTE; args->camera = optarg; break; } diff --git a/src/main.c b/src/main.c @@ -20,7 +20,7 @@ int main(int argc, char** argv){ res = stardis_init(&args, &stardis); if (res != RES_OK) goto error; - if (args.mode == DUMP_VTK) { + if (args.mode & DUMP_VTK) { res = dump_vtk(stdout, &stardis.geometry); if (res != RES_OK) goto error; goto exit; diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -135,12 +135,12 @@ parse_medium_line(char* line, char** stl_filename, struct description* desc) desc->type = DESC_MAT_SOLID; CHK_TOK(strtok(NULL, " "), "medium name"); - if (strlen(tk) >= sizeof(desc->name)) { + if (strlen(tk) >= sizeof(desc->d.solid.name)) { fprintf(stderr, "Medium name is too long: %s\n", tk); res = RES_BAD_ARG; goto exit; } - strncpy(desc->name, tk, sizeof(desc->name)); + strncpy(desc->d.solid.name, tk, sizeof(desc->d.solid.name)); CHK_TOK(strtok(NULL, " "), "file name"); *stl_filename = malloc(strlen(tk) + 1); @@ -177,8 +177,9 @@ parse_medium_line(char* line, char** stl_filename, struct description* desc) /* Depending of the number of spaces before '"' strtok should * be called once or twice */ CHK_TOK(strtok(NULL, "\""), "Tinit"); - if(*(tk + strspn(tk, " \t")) == '\0') + if (*(tk + strspn(tk, " \t")) == '\0') { CHK_TOK(strtok(NULL, "\""), "Tinit"); + } desc->d.solid.Tinit = malloc(strlen(tk) + 1); strcpy(desc->d.solid.Tinit, tk); /* Closing " fot Tinit; can return NULL if line ends just after "Tinit" */ @@ -203,12 +204,12 @@ parse_medium_line(char* line, char** stl_filename, struct description* desc) desc->type = DESC_MAT_FLUID; CHK_TOK(strtok(NULL, " "), "medium name"); - if (strlen(tk) >= sizeof(desc->name)) { + if (strlen(tk) >= sizeof(desc->d.fluid.name)) { fprintf(stderr, "Medium name is too long: %s\n", tk); res = RES_BAD_ARG; goto exit; } - strncpy(desc->name, tk, sizeof(desc->name)); + strncpy(desc->d.fluid.name, tk, sizeof(desc->d.fluid.name)); CHK_TOK(strtok(NULL, " "), "file name"); *stl_filename = malloc(strlen(tk) + 1); @@ -231,8 +232,9 @@ parse_medium_line(char* line, char** stl_filename, struct description* desc) /* Depending of the number of spaces before '"' strtok should * be called once or twice */ CHK_TOK(strtok(NULL, "\""), "Tinit"); - if (*(tk + strspn(tk, " \t")) == '\0') + if (*(tk + strspn(tk, " \t")) == '\0') { CHK_TOK(strtok(NULL, "\""), "Tinit"); + } desc->d.fluid.Tinit = malloc(strlen(tk) + 1); strcpy(desc->d.fluid.Tinit, tk); } @@ -247,12 +249,13 @@ 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)" +# H_BOUNDARY_FOR_SOLID Boundary_name STL_filename emissivity specular_fraction hc hc_max "T_env(x,y,z,t)" +# | H_BOUNDARY_FOR_FLUID Boundary_name STL_filename emissivity specular_fraction hc hc_max "T_env(x,y,z,t)" +# | T_BOUNDARY_FOR_SOLID Boundary_name STL_filename "T_value(x,y,z,t)" +# | T_BOUNDARY_FOR_FLUID Boundary_name STL_filename "T_value(x,y,z,t)" hc hc_max +# | F_BOUNDARY_FOR_SOLID Boundary_name STL_filename "F_value(x,y,z,t)" # ; no F_BOUNDARY_FOR_FLUID +# | SOLID_FLUID_CONNECTION Connection_name STL_filename emissivity specular_fraction hc hc_max */ static res_T parse_boundary_line(char* line, char** stl_filename, struct description* desc) @@ -286,9 +289,18 @@ parse_boundary_line(char* line, char** stl_filename, struct description* desc) } } } + if (h_solid || h_fluid) { desc->type = h_solid ? DESC_BOUND_H_FOR_SOLID : DESC_BOUND_H_FOR_FLUID; + CHK_TOK(strtok(NULL, " "), "boundary name"); + if (strlen(tk) >= sizeof(desc->d.h_boundary.name)) { + fprintf(stderr, "Boundary name is too long: %s\n", tk); + res = RES_BAD_ARG; + goto exit; + } + strncpy(desc->d.h_boundary.name, tk, sizeof(desc->d.h_boundary.name)); + /* The description is parsed the same way for both types */ CHK_TOK(strtok(NULL, " "), "file name"); *stl_filename = malloc(strlen(tk) + 1); @@ -332,14 +344,23 @@ parse_boundary_line(char* line, char** stl_filename, struct description* desc) /* Depending of the number of spaces before '"' strtok should * be called once or twice */ CHK_TOK(strtok(NULL, "\""), "temperature"); - if (*(tk + strspn(tk, " \t")) == '\0') + if (*(tk + strspn(tk, " \t")) == '\0') { CHK_TOK(strtok(NULL, "\""), "temperature"); + } desc->d.h_boundary.T = malloc(strlen(tk) + 1); strcpy(desc->d.h_boundary.T, tk); } else if (t_solid || t_fluid) { desc->type = t_solid ? DESC_BOUND_T_FOR_SOLID : DESC_BOUND_T_FOR_FLUID; + CHK_TOK(strtok(NULL, " "), "boundary name"); + if (strlen(tk) >= sizeof(desc->d.t_boundary.name)) { + fprintf(stderr, "Boundary name is too long: %s\n", tk); + res = RES_BAD_ARG; + goto exit; + } + strncpy(desc->d.t_boundary.name, tk, sizeof(desc->d.t_boundary.name)); + /* This part of the description is parsed the same way for both types */ CHK_TOK(strtok(NULL, " "), "file name"); *stl_filename = malloc(strlen(tk) + 1); @@ -348,8 +369,9 @@ parse_boundary_line(char* line, char** stl_filename, struct description* desc) /* Depending of the number of spaces before '"' strtok should * be called once or twice */ CHK_TOK(strtok(NULL, "\""), "temperature"); - if (*(tk + strspn(tk, " \t")) == '\0') + if (*(tk + strspn(tk, " \t")) == '\0') { CHK_TOK(strtok(NULL, "\""), "temperature"); + } desc->d.t_boundary.T = malloc(strlen(tk) + 1); strcpy(desc->d.t_boundary.T, tk); @@ -378,6 +400,14 @@ parse_boundary_line(char* line, char** stl_filename, struct description* desc) else if (f_solid) { desc->type = DESC_BOUND_F_FOR_SOLID; + CHK_TOK(strtok(NULL, " "), "boundary name"); + if (strlen(tk) >= sizeof(desc->d.f_boundary.name)) { + fprintf(stderr, "Boundary name is too long: %s\n", tk); + res = RES_BAD_ARG; + goto exit; + } + strncpy(desc->d.f_boundary.name, tk, sizeof(desc->d.f_boundary.name)); + CHK_TOK(strtok(NULL, " "), "file name"); *stl_filename = malloc(strlen(tk) + 1); strcpy(*stl_filename, tk); @@ -385,8 +415,9 @@ parse_boundary_line(char* line, char** stl_filename, struct description* desc) /* Depending of the number of spaces before '"' strtok should * be called once or twice */ CHK_TOK(strtok(NULL, "\""), "flux"); - if (*(tk + strspn(tk, " \t")) == '\0') + if (*(tk + strspn(tk, " \t")) == '\0') { CHK_TOK(strtok(NULL, "\""), "flux"); + } desc->d.f_boundary.flux = malloc(strlen(tk) + 1); strcpy(desc->d.f_boundary.flux, tk); @@ -414,6 +445,14 @@ parse_boundary_line(char* line, char** stl_filename, struct description* desc) else if (sf_connect) { desc->type = DESC_SOLID_FLUID_CONNECT; + CHK_TOK(strtok(NULL, " "), "boundary name"); + if (strlen(tk) >= sizeof(desc->d.sf_connect.name)) { + fprintf(stderr, "Boundary name is too long: %s\n", tk); + res = RES_BAD_ARG; + goto exit; + } + strncpy(desc->d.sf_connect.name, tk, sizeof(desc->d.sf_connect.name)); + CHK_TOK(strtok(NULL, " "), "file name"); *stl_filename = malloc(strlen(tk) + 1); strcpy(*stl_filename, tk); @@ -453,8 +492,7 @@ parse_boundary_line(char* line, char** stl_filename, struct description* desc) res = RES_BAD_ARG; goto exit; } - } - else { + } else { fprintf(stderr, "Invalid boundary type: %s", tk); res = RES_BAD_ARG; goto exit; @@ -897,14 +935,14 @@ stardis_init if (args->dump_paths & DUMP_SUCCESS) stardis->dump_paths |= SDIS_HEAT_PATH_SUCCEED; - if (args->mode == IR_COMPUTE){ + if (args->mode & IR_COMPUTE){ res = parse_camera(args->camera, &stardis->camera); if (res != RES_OK) goto error; } - else if (args->mode == MEDIUM_COMPUTE) { + else if (args->mode & MEDIUM_COMPUTE) { strcpy(stardis->solve_name, args->medium_name); } - else if (args->mode == BOUNDARY_COMPUTE) { + else if (args->mode & BOUNDARY_COMPUTE) { strcpy(stardis->solve_name, args->solve_boundary_filename); } diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -122,7 +122,7 @@ release_geometry(struct geometry* geom) } struct mat_fluid { - char name[16]; + char name[32]; unsigned fluid_id; double rho; double cp; @@ -217,7 +217,7 @@ hash_fluid(const struct mat_fluid* key) } struct mat_solid { - char name[16]; + char name[32]; unsigned solid_id; double lambda; double rho; @@ -355,6 +355,7 @@ hash_solid(const struct mat_solid* key) } struct h_boundary { + char name[32]; unsigned mat_id; double emissivity; double specular_fraction; @@ -373,7 +374,8 @@ print_h_boundary ASSERT(stream && b && (type == DESC_BOUND_H_FOR_SOLID || type == DESC_BOUND_H_FOR_FLUID)); fprintf(stream, - "H boundary for %s: emissivity=%g specular_fraction=%g hc=%g hc_max=%g T='%s'\n", + "H boundary %s for %s: emissivity=%g specular_fraction=%g hc=%g hc_max=%g T='%s'\n", + b->name, (type == DESC_BOUND_H_FOR_SOLID ? "solid" : "fluid"), (b->has_emissivity ? b->emissivity : 0), (b->has_emissivity ? b->specular_fraction : 0), @@ -388,6 +390,7 @@ eq_h_boundary const struct h_boundary* b) { if (a->mat_id != b->mat_id + || strcmp(a->name, b->name) || a->specular_fraction != b->specular_fraction || strcmp(a->T, b->T) || a->has_emissivity != b->has_emissivity @@ -409,6 +412,10 @@ hash_h_boundary(const struct h_boundary* key) uint32_t hash = OFFSET32_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->name)[i]); + hash = hash * FNV32_PRIME; + } FOR_EACH(i, 0, sizeof(key->mat_id)) { hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); hash = hash * FNV32_PRIME; @@ -451,6 +458,10 @@ hash_h_boundary(const struct h_boundary* key) uint64_t hash = OFFSET64_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->name)[i]); + hash = hash * FNV64_PRIME; + } FOR_EACH(i, 0, sizeof(key->mat_id)) { hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); hash = hash * FNV64_PRIME; @@ -491,6 +502,7 @@ hash_h_boundary(const struct h_boundary* key) } struct t_boundary { + char name[32]; unsigned mat_id; char* T; struct te_expr* te_temperature; @@ -508,7 +520,8 @@ print_t_boundary ASSERT(stream && b && (type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID)); fprintf(stream, - "T boundary for %s: hc=%g hc_max=%g T='%s'\n", + "T boundary %s for %s: hc=%g hc_max=%g T='%s'\n", + b->name, (type == DESC_BOUND_T_FOR_SOLID ? "solid" : "fluid"), (b->has_hc ? b->hc : 0), (b->has_hc ? b->hc_max : 0), @@ -523,6 +536,8 @@ eq_t_boundary { ASSERT(type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID); /* These fields are meaningful by both types */ + if (strcmp(a->name, b->name)) + return 0; if (a->mat_id != b->mat_id || strcmp(a->T, b->T)) return 0; if (type != DESC_BOUND_T_FOR_FLUID) @@ -550,6 +565,10 @@ hash_t_boundary uint32_t hash = OFFSET32_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->name)[i]); + hash = hash * FNV32_PRIME; + } FOR_EACH(i, 0, sizeof(key->mat_id)) { hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); hash = hash * FNV32_PRIME; @@ -580,6 +599,10 @@ hash_t_boundary uint64_t hash = OFFSET64_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->name)[i]); + hash = hash * FNV64_PRIME; + } FOR_EACH(i, 0, sizeof(key->mat_id)) { hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); hash = hash * FNV64_PRIME; @@ -608,6 +631,7 @@ hash_t_boundary } struct f_boundary { + char name[32]; unsigned mat_id; char* flux; struct te_expr* te_flux; @@ -624,7 +648,8 @@ print_f_boundary { ASSERT(stream && b && type == DESC_BOUND_F_FOR_SOLID); (void)type; fprintf(stream, - "F boundary for SOLID: hc=%g hc_max=%g flux='%s'\n", + "F boundary %s for SOLID: hc=%g hc_max=%g flux='%s'\n", + b->name, (b->has_hc ? b->hc : 0), (b->has_hc ? b->hc_max : 0), (b->flux ? b->flux : "0")); @@ -634,6 +659,7 @@ static char eq_f_boundary(const struct f_boundary* a, const struct f_boundary* b) { if (a->mat_id != b->mat_id + || strcmp(a->name, b->name) || strcmp(a->flux, b->flux) || a->has_hc != b->has_hc) return 0; @@ -652,6 +678,10 @@ hash_f_boundary(const struct f_boundary* key) uint32_t hash = OFFSET32_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->name)[i]); + hash = hash * FNV32_PRIME; + } FOR_EACH(i, 0, sizeof(key->mat_id)) { hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); hash = hash * FNV32_PRIME; @@ -681,6 +711,10 @@ hash_f_boundary(const struct f_boundary* key) uint64_t hash = OFFSET64_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->name)[i]); + hash = hash * FNV64_PRIME; + } FOR_EACH(i, 0, sizeof(key->mat_id)) { hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->mat_id)[i]); hash = hash * FNV64_PRIME; @@ -708,6 +742,7 @@ hash_f_boundary(const struct f_boundary* key) } struct solid_fluid_connect { + char name[32]; double emissivity; double specular_fraction; double hc; @@ -718,7 +753,8 @@ struct solid_fluid_connect { static char eq_sf_connect(const struct solid_fluid_connect* a, const struct solid_fluid_connect* b) { - return (char) (a->emissivity == b->emissivity + return (char)(!strcmp(a->name, b->name) + && a->emissivity == b->emissivity && a->specular_fraction == b->specular_fraction && a->hc == b->hc && a->hc_max == b->hc_max @@ -737,6 +773,10 @@ hash_sf_connect(const struct solid_fluid_connect* key) uint32_t hash = OFFSET32_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint32_t)((unsigned char)((const char*)&key->name)[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; @@ -770,6 +810,10 @@ hash_sf_connect(const struct solid_fluid_connect* key) uint64_t hash = OFFSET64_BASIS; size_t i; ASSERT(key); + FOR_EACH(i, 0, sizeof(key->name)) { + hash = hash ^ (uint64_t)((unsigned char)((const char*)&key->name)[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; @@ -801,7 +845,6 @@ hash_sf_connect(const struct solid_fluid_connect* key) } struct description { - char name[16]; enum description_type type; union d { struct mat_fluid fluid; @@ -816,7 +859,6 @@ struct description { FINLINE void init_description(struct description* desc) { ASSERT(desc); - desc->name[0] = '\0'; desc->type = DESCRIPTION_TYPE_COUNT__; } diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -15,6 +15,13 @@ #define HTABLE_KEY unsigned #include <rsys/hash_table.h> +/* A type to limit variable use in tinyexpr expressions */ +enum var_prohibited_t { + ALL_VARS_ALLOWED = 0, + T_PROHIBITED = BIT(1), + XYZ_PROHIBITED = BIT(2) +}; + static void geometry_get_position (const size_t ivert, @@ -53,7 +60,7 @@ static res_T compile_expr_to_fn (struct te_expr** f, const char* math_expr, - const int t_allowed, + const enum var_prohibited_t prohibited, int* is_zero) { te_variable vars[4] = { @@ -62,12 +69,15 @@ compile_expr_to_fn TE_DEF_OFFSET("z", offsetof(struct sdis_rwalk_vertex, P[2])), TE_DEF_OFFSET("t", offsetof(struct sdis_rwalk_vertex, time)) }; - + int fst = 0, lst = 4; ASSERT(math_expr); - *f = te_compile(math_expr, vars, t_allowed ? 4 : 3, NULL); + if (prohibited & XYZ_PROHIBITED) fst = 3; + if(prohibited & T_PROHIBITED) lst = 3; + *f = te_compile(math_expr, vars+fst, lst-fst, NULL); if (!*f) { - if (!t_allowed && te_compile(math_expr, vars, 4, NULL)) - fprintf(stderr, "Expression use variable t and should not.\n"); + if ((prohibited != ALL_VARS_ALLOWED) + && te_compile(math_expr, vars, 4, NULL)) + fprintf(stderr, "Expression %s use a probibited variable.\n", math_expr); return RES_BAD_ARG; } if (is_zero) *is_zero = !((*f)->type == TE_CONSTANT && (*f)->v.value == 0); @@ -80,8 +90,13 @@ compile_expr_to_fn struct fluid { double cp; /* Calorific capacity */ double rho; /* Volumic mass */ + /* Compute mode */ + int is_green, is_outside; + double t0; /* TinyExpr stuff to compute temperature */ struct te_expr *temperature; + /* ID */ + unsigned id; }; static double @@ -115,7 +130,7 @@ 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) { + if (fluid_props->is_green || vtx->time > fluid_props->t0) { return -1; } return te_eval(fluid_props->temperature, vtx); @@ -136,9 +151,14 @@ struct solid { double lambda; /* Conductivity */ double rho; /* Volumic mass */ double delta; /* Numerical parameter */ + /* Compute mode */ + int is_green, is_outside; + double t0; /* TinyExpr stuff to compute temperature & power */ struct te_expr *t_init; struct te_expr *power; + /* ID */ + unsigned id; }; static double @@ -213,7 +233,7 @@ solid_get_tinit (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) { const struct solid* solid_props = sdis_data_cget(data); - if (vtx->time > 0) { + if (solid_props->is_green || vtx->time > solid_props->t0) { return -1; } return te_eval(solid_props->t_init, vtx); @@ -245,6 +265,8 @@ struct intface { /* TinyExpr stuff to compute temperature & flux */ struct te_expr *temperature; struct te_expr *flux; + /* IDs */ + unsigned front_boundary_id, back_boundary_id; }; static double @@ -426,7 +448,9 @@ create_fluid (struct sdis_device* dev, const double rho, const double cp, - const int t_allowed, + const enum var_prohibited_t prohibited, + const int is_green, + const int is_outside, const char* t_expr, struct sdis_medium*** media_ptr, sdis_medium_getter_T get_temp, @@ -445,10 +469,17 @@ create_fluid res = sdis_data_create(dev, sizeof(struct fluid), ALIGNOF(struct fluid), release_fluid_data, &data); if (res != RES_OK) goto error; + + sz = sa_size(*media_ptr); + ASSERT(sz < INT_MAX); 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); + fluid_props->is_green = is_green; + fluid_props->is_outside = is_outside; + fluid_props->t0 = 0; + fluid_props->id = (unsigned)sz; + res = compile_expr_to_fn(&fluid_props->temperature, t_expr, prohibited, NULL); if (res != RES_OK) { fprintf(stderr, "Invalid initial temperature expression: %s\n", t_expr); @@ -456,9 +487,7 @@ create_fluid } 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; + *out_id = fluid_props->id; end: if (data) SDIS(data_ref_put(data)); @@ -474,7 +503,9 @@ create_solid const double rho, const double cp, const double delta, - const int t_allowed, + const enum var_prohibited_t prohibited, + const int is_green, + const int is_outside, const char* t_expr, /* Can be NULL if not used by getter */ const char* power_expr, /* Can be NULL */ struct sdis_medium*** media_ptr, @@ -502,6 +533,8 @@ create_solid release_solid_data, &data); if (res != RES_OK) goto error; + sz = sa_size(*media_ptr); + ASSERT(sz < INT_MAX); solid_props = sdis_data_get(data); /* Fetch the allocated memory space */ solid_props->lambda = lambda; solid_props->rho = rho; @@ -509,8 +542,12 @@ create_solid solid_props->delta = delta; solid_props->t_init = NULL; solid_props->power = NULL; + solid_props->is_green = is_green; + solid_props->is_outside = is_outside; + solid_props->t0 = 0; + solid_props->id = (unsigned)sz; if (t_expr) { - res = compile_expr_to_fn(&solid_props->t_init, t_expr, t_allowed, NULL); + res = compile_expr_to_fn(&solid_props->t_init, t_expr, prohibited, NULL); if (res != RES_OK) { fprintf(stderr, "Invalid initial temperature expression: %s\n", t_expr); @@ -533,9 +570,7 @@ create_solid } 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; + *out_id = solid_props->id; end: if (data) SDIS(data_ref_put(data)); @@ -751,6 +786,188 @@ dump_path return RES_OK; } +static res_T +print_power_term + (struct sdis_medium* mdm, + const double power_term, + void* ctx) +{ + struct sdis_data* data = NULL; + enum sdis_medium_type type; + unsigned id; + struct description* desc = ctx; + + CHK(mdm && ctx); + + data = sdis_medium_get_data(mdm); + type = sdis_medium_get_type(mdm); + + switch (type) { + case SDIS_FLUID: { + FATAL("Unexpected power term in fluid"); +#if 0 + struct fluid* d__ = sdis_data_get(data); + id = d__->id; + desc = (struct description*)ctx + id; + ASSERT(id == desc->d.fluid.fluid_id); + printf("\tF\t%u\t%g", id, power_term); + break; +#endif + } + case SDIS_SOLID: { + struct solid* d__ = sdis_data_get(data); + id = d__->id; + desc = (struct description*)ctx + id; + ASSERT(id == desc->d.solid.solid_id); + printf("\tS\t%u\t%g", id, power_term); + break; + } + default: FATAL("Unreachable code.\n"); break; + } + return RES_OK; +} + +static res_T +print_flux_term + (struct sdis_interface* interf, + const enum sdis_side side, + const double flux_term, + void* ctx) +{ + struct sdis_data* data = NULL; + struct intface* d__; + unsigned id; + struct description* desc; + + CHK(interf && ctx); + + data = sdis_interface_get_data(interf); + d__ = sdis_data_get(data); + id = (side == SDIS_FRONT) ? d__->front_boundary_id : d__->back_boundary_id; + desc = (struct description*)ctx + id; + + switch (desc->type) { + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + FATAL("Cannot have a flux term here.\n"); break; + case DESC_BOUND_F_FOR_SOLID: + ASSERT(id == desc->d.f_boundary.mat_id); + printf("\t%u\t%g", id, flux_term); + break; + default: FATAL("Unreachable code.\n"); break; + } + return RES_OK; +} + +static res_T +print_sample + (struct sdis_green_path* path, + void* ctx) +{ + struct sdis_point pt = SDIS_POINT_NULL; + struct sdis_data* data = NULL; + enum sdis_medium_type type; + struct description* desc; + unsigned id; + size_t pcount, fcount; + res_T res = RES_OK; + CHK(path && ctx); + + res = sdis_green_path_get_limit_point(path, &pt); + if (res != RES_OK) goto error; + + + /* For each path, prints: + * # end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n + * with: + * - end = end_type end_id; end_type = T | H | X | R | F | S + * - power_term_i = power_type_i power_id_i factor_i + * - flux_term_i = flux_id_i factor_i + */ + + switch (pt.type) { + case SDIS_FRAGMENT: { + struct intface* d__; + data = sdis_interface_get_data(pt.data.itfrag.intface); + d__ = sdis_data_get(data); + id = (pt.data.itfrag.fragment.side == SDIS_FRONT) + ? d__->front_boundary_id : d__->back_boundary_id; + ASSERT(id != UINT_MAX); + desc = (struct description*)ctx + id; + switch (desc->type) { + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + ASSERT(id == desc->d.t_boundary.mat_id); + printf("T\t%u", id); + break; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + ASSERT(id == desc->d.h_boundary.mat_id); + printf("H\t%u", id); + break; + case DESC_BOUND_F_FOR_SOLID: + ASSERT(id == desc->d.f_boundary.mat_id); + printf("X\t%u", id); + break; + default: FATAL("Unreachable code.\n"); break; + } + break; + } + case SDIS_VERTEX: + type = sdis_medium_get_type(pt.data.mdmvert.medium); + data = sdis_medium_get_data(pt.data.mdmvert.medium); + if (pt.data.mdmvert.vertex.P[0] == INF) { + /* Radiative output */ + printf("R %u", (unsigned)sa_size(ctx)); + } + else if (type == SDIS_FLUID) { + struct fluid* d__ = sdis_data_get(data); + id = d__->id; + desc = (struct description*)ctx + id; + ASSERT(id == desc->d.fluid.fluid_id); + if (d__->is_outside) + /* If outside the model and in a fluid with known temperature, + * its a fluid attached to a H boundary */ + printf("H\t%u", id); + /* In a standard fluid with known temperature */ + else printf("F\t%u", id); + + } else { + struct solid* d__ = sdis_data_get(data); + ASSERT(type == SDIS_SOLID); + id = d__->id; + desc = (struct description*)ctx + id; + ASSERT(id == desc->d.solid.solid_id); + desc = (struct description*)ctx + id; + ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */ + printf("S\t%u", id); + } + break; + default: FATAL("Unreachable code.\n"); break; + } + + res = sdis_green_function_get_power_terms_count(path, &pcount); + if (res != RES_OK) goto error; + + res = sdis_green_function_get_flux_terms_count(path, &fcount); + if (res != RES_OK) goto error; + + printf("\t%zu\t%zu", pcount, fcount); + + res = sdis_green_path_for_each_power_term(path, print_power_term, ctx); + if (res != RES_OK) goto error; + + res = sdis_green_path_for_each_flux_term(path, print_flux_term, ctx); + if (res != RES_OK) goto error; + + printf("\n"); + +error: + return res; +} + res_T stardis_compute(struct stardis* stardis, enum stardis_mode mode) { @@ -772,8 +989,9 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) double pos[3] = { 0,0,0 }; double time[2] = { 0, 0 }; size_t nfailures; + size_t smed_count = 0, fmed_count = 0, + tbound_count = 0, hbound_count = 0, fbound_count = 0, sfconnect_count = 0; 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; @@ -781,22 +999,31 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) /* Create media and property holders found in descriptions */ for (i = 0; i < sa_size(stardis->descriptions); ++i) { struct description* desc = stardis->descriptions + i; + /* Base prohibition; additional restrictions apply for media */ + enum var_prohibited_t prohibited = + ((stardis->probe[3] < INF) | (mode & GREEN_MODE)) + ? T_PROHIBITED : ALL_VARS_ALLOWED; 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); + hbound_count++; + res = create_fluid(dev, 1, 1, prohibited, (mode & GREEN_MODE), 1, + 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, INF, 1, 1, 1, t_allowed, desc->d.h_boundary.T, - NULL, &media, solid_get_temperature, NULL, &desc->d.h_boundary.mat_id); + hbound_count++; + res = create_solid(dev, INF, 1, 1, 1, prohibited, (mode & GREEN_MODE), 1, + 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: + tbound_count++; 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); @@ -806,11 +1033,13 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) goto error; } /* Create an external solid */ - res = create_solid(dev, 1, 1, 1, 1, t_allowed, NULL, NULL, &media, - solid_dont_get_temperature, NULL, &desc->d.t_boundary.mat_id); + res = create_solid(dev, 1, 1, 1, 1, prohibited, (mode & GREEN_MODE), 1, + NULL, NULL, &media, solid_dont_get_temperature, NULL, + &desc->d.t_boundary.mat_id); if (res != RES_OK) goto error; break; case DESC_BOUND_F_FOR_SOLID: + fbound_count++; 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); @@ -820,42 +1049,48 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) 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); + res = create_solid(dev, 1, 1, 1, 1, prohibited, (mode & GREEN_MODE), 1, + NULL, NULL, &media, solid_dont_get_temperature, NULL, + &desc->d.f_boundary.mat_id); if (res != RES_OK) goto error; break; case DESC_SOLID_FLUID_CONNECT: + sfconnect_count++; 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: + smed_count++; + if (mode & GREEN_MODE) prohibited |= T_PROHIBITED | XYZ_PROHIBITED; 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, + prohibited, + (mode & GREEN_MODE), 0, 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); - strcpy(desc->d.solid.name, desc->name); if (res != RES_OK) goto error; break; case DESC_MAT_FLUID: + fmed_count++; + if (mode & GREEN_MODE) prohibited |= T_PROHIBITED | XYZ_PROHIBITED; res = create_fluid(dev, stardis->descriptions[i].d.fluid.rho, stardis->descriptions[i].d.fluid.cp, - t_allowed, + prohibited, + (mode & GREEN_MODE), 0, stardis->descriptions[i].d.fluid.Tinit, &media, fluid_get_tinit, &desc->d.fluid.fluid_id); - strcpy(desc->d.fluid.name, desc->name); if (res != RES_OK) goto error; break; default: FATAL("Invalid type.\n"); @@ -902,6 +1137,8 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) interface_props = sdis_data_get(data); interface_props->temperature = NULL; interface_props->flux = NULL; + interface_props->front_boundary_id = UINT_MAX; + interface_props->back_boundary_id = UINT_MAX; if (front_defined) { switch (stardis->descriptions[fd].type) { @@ -957,6 +1194,9 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) goto error; } def_medium = front_defined ? front_med : back_med; + if (front_defined) + interface_props->front_boundary_id = cd; + else interface_props->back_boundary_id = cd; } switch (connect->type) { case DESC_BOUND_H_FOR_FLUID: @@ -1128,179 +1368,373 @@ stardis_compute(struct stardis* stardis, enum stardis_mode mode) res = create_edge_file_if(scn, &stardis->allocator); if (res != RES_OK) goto error; - if (mode == IR_COMPUTE) { - size_t width = (size_t)stardis->camera.img[0]; - size_t height = (size_t)stardis->camera.img[1]; - - /* Setup the camera */ - SDIS(camera_create(dev, &cam)); - SDIS(camera_set_proj_ratio(cam, (double)width / (double)height)); - SDIS(camera_set_fov(cam, MDEG2RAD(stardis->camera.fov))); - SDIS(camera_look_at(cam, - stardis->camera.pos, - stardis->camera.tgt, - stardis->camera.up)); - - /* Create the accum buffer */ - SDIS(accum_buffer_create(dev, width, height, &buf)); - - /* Launch the simulation */ - res = sdis_solve_camera(scn, - cam, - stardis->camera.u.time, - stardis->scale_factor, - stardis->radiative_temp[0], - stardis->radiative_temp[1], - width, - height, - (size_t)stardis->camera.spp, - sdis_accum_buffer_write, - buf); - if (res != RES_OK) goto error; + if (mode & GREEN_MODE) { + struct sdis_green_function* green = NULL; + size_t ok_count, failed_count; + ASSERT((mode & PROBE_COMPUTE) + || (mode & BOUNDARY_COMPUTE) || (mode & MEDIUM_COMPUTE)); + + if (mode & PROBE_COMPUTE) { + double uv[2] = { 0,0 }; + size_t iprim = SIZE_MAX; + /* Launch the probe simulation */ + pos[0] = stardis->probe[0]; + pos[1] = stardis->probe[1]; + pos[2] = stardis->probe[2]; + + res = select_probe_type(scn, + stardis->geometry.triangle, + stardis->descriptions, + pos, + &iprim, + uv); + if (res != RES_OK) goto error; - /* Write the image */ - dump_image(buf); - } - else if (mode == PROBE_COMPUTE) { - double uv[2] = { 0,0 }; - size_t iprim = SIZE_MAX; - /* Launch the probe simulation */ - pos[0] = stardis->probe[0]; - pos[1] = stardis->probe[1]; - pos[2] = stardis->probe[2]; - time[0] = time[1] = stardis->probe[3]; - - res = select_probe_type(scn, - stardis->geometry.triangle, - stardis->descriptions, - pos, - &iprim, - uv); - if (res != RES_OK) goto error; + if (iprim == SIZE_MAX) { + res = sdis_solve_probe_green_function(scn, + stardis->N, + pos, + stardis->scale_factor, + stardis->radiative_temp[0], + stardis->radiative_temp[1], + &green); + } else { + res = sdis_solve_probe_boundary_green_function(scn, + stardis->N, + iprim, + uv, + SDIS_FRONT, + stardis->scale_factor, + stardis->radiative_temp[0], + stardis->radiative_temp[1], + &green); + } + } + else if (mode & BOUNDARY_COMPUTE) { + ASSERT(sa_size(stardis->boundary.primitives) + == sa_size(stardis->boundary.sides)); + if (sa_size(stardis->boundary.sides) == 0) { + fprintf(stderr, "Cannot solve boundary %s (empty geometry)\n", + stardis->solve_name); + } - if (iprim == SIZE_MAX) { - res = sdis_solve_probe(scn, + res = sdis_solve_boundary_green_function(scn, stardis->N, - pos, - time, + stardis->boundary.primitives, + stardis->boundary.sides, + sa_size(stardis->boundary.sides), stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], - stardis->dump_paths, - &estimator); - } else { - res = sdis_solve_probe_boundary(scn, + &green); + } + else if (mode & MEDIUM_COMPUTE) { + size_t sz, ii; + struct sdis_medium* medium = NULL; + /* Find medium */ + sz = sa_size(stardis->descriptions); + FOR_EACH(ii, 0, sz) { + struct description* desc = stardis->descriptions + ii; + if (desc->type == DESC_MAT_SOLID) { + if (0 == strcmp(stardis->solve_name, desc->d.solid.name)) { + ASSERT(sa_size(media) > ii); + medium = media[ii]; + break; + } + } + else if (desc->type == DESC_MAT_FLUID) { + if (0 == strcmp(stardis->solve_name, desc->d.fluid.name)) { + ASSERT(sa_size(media) > ii); + medium = media[ii]; + break; + } + } + } + if (medium == NULL) { + /* Not found */ + fprintf(stderr, "Cannot solve medium %s (unknown medium)\n", + stardis->solve_name); + res = RES_BAD_ARG; + goto error; + } + res = sdis_solve_medium_green_function(scn, stardis->N, - iprim, - uv, - time, - SDIS_FRONT, + medium, stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], - stardis->dump_paths, - &estimator); + &green); } - } - else if (mode == MEDIUM_COMPUTE) { - size_t sz, ii; - struct sdis_medium* medium = NULL; - /* Find medium */ - sz = sa_size(stardis->descriptions); - FOR_EACH(ii, 0, sz) { - struct description* desc = stardis->descriptions + ii; - if (desc->type == DESC_MAT_SOLID) { - if (0 == strcmp(stardis->solve_name, desc->d.solid.name)) { - ASSERT(sa_size(media) > ii); - medium = media[ii]; - break; - } + if (res != RES_OK) goto error; + + /* Output the green function */ + CHK(sdis_green_function_get_invalid_paths_count(green, &failed_count) == RES_OK); + CHK(sdis_green_function_get_paths_count(green, &ok_count) == RES_OK); + + /* Output counts */ + printf("---BEGIN GREEN---\n"); + printf("# #solids #fluids #t_boundaries #h_boundaries #f_boundaries #ok #failures\n"); + printf("%zu %zu %zu %zu %zu %zu %zu\n", + smed_count, fmed_count, + tbound_count, hbound_count, fbound_count, + ok_count, failed_count); + + /* List Media */ + if (smed_count) { + printf("# Solids\n"); + printf("# ID Name lambda rho cp power\n"); + FOR_EACH(i, 0, (unsigned)sa_size(stardis->descriptions)) { + struct description* desc = stardis->descriptions + i; + struct mat_solid* sl; + if (desc->type != DESC_MAT_SOLID) continue; + sl = &desc->d.solid; + printf("%u\t%s\t%g\t%g\t%g\t%s\n", + i, sl->name, sl->lambda, sl->rho, sl->cp, (sl->has_power ? sl->power : "0")); } - else if (desc->type == DESC_MAT_FLUID) { - if (0 == strcmp(stardis->solve_name, desc->d.fluid.name)) { - ASSERT(sa_size(media) > ii); - medium = media[ii]; - break; - } + } + if (fmed_count) { + printf("# Fluids\n"); + printf("# ID Name rho cp\n"); + FOR_EACH(i, 0, sa_size(stardis->descriptions)) { + struct description* desc = stardis->descriptions + i; + struct mat_fluid* fl; + fl = &desc->d.fluid; + printf("%u\t%s\t%g\t%g\n", i, fl->name, fl->rho, fl->cp); } } - if (medium == NULL) { - /* Not found */ - fprintf(stderr, "Cannot solve medium %s (unknown medium)\n", - stardis->solve_name); - res = RES_BAD_ARG; - goto error; + + /* List Boundaries */ + if (tbound_count) { + printf("# T Boundaries\n"); + printf("# ID Name temperature\n"); + FOR_EACH(i, 0, sa_size(stardis->descriptions)) { + struct description* desc = stardis->descriptions + i; + struct t_boundary* bd; + if (desc->type != DESC_BOUND_T_FOR_SOLID + && desc->type != DESC_BOUND_T_FOR_FLUID) continue; + bd = &desc->d.t_boundary; + printf("%u\t%s\t%s\n", i, bd->name, bd->T); + } } - time[0] = time[1] = stardis->probe[3]; - res = sdis_solve_medium(scn, - stardis->N, - medium, - time, - stardis->scale_factor, - stardis->radiative_temp[0], - stardis->radiative_temp[1], - stardis->dump_paths, - &estimator); - } else if (mode == BOUNDARY_COMPUTE) { - ASSERT(sa_size(stardis->boundary.primitives) - == sa_size(stardis->boundary.sides)); - if (sa_size(stardis->boundary.sides) == 0) { - fprintf(stderr, "Cannot solve boundary %s (empty geometry)\n", - stardis->solve_name); + if (hbound_count) { + printf("# H Boundaries\n"); + printf("# ID Name emissivity specular_fraction hc hc_max T_env\n"); + FOR_EACH(i, 0, sa_size(stardis->descriptions)) { + struct description* desc = stardis->descriptions + i; + struct h_boundary* bd; + if (desc->type != DESC_BOUND_H_FOR_SOLID + && desc->type != DESC_BOUND_H_FOR_FLUID) continue; + bd = &desc->d.h_boundary; + printf("%u\t%s\t%g\t%g\t%g\t%g\t%s\n", + i, bd->name, (bd->has_emissivity ? bd->emissivity : 0), + (bd->has_emissivity ? bd->specular_fraction : 0), + (bd->has_hc ? bd->hc : 0), (bd->has_hc ? bd->hc_max : 0), bd->T); + } } + if (fbound_count) { + printf("# F Boundaries\n"); + printf("# ID Name hc hc_max\n"); + FOR_EACH(i, 0, sa_size(stardis->descriptions)) { + struct description* desc = stardis->descriptions + i; + struct f_boundary* bd; + if (desc->type != DESC_BOUND_F_FOR_SOLID) continue; + bd = &desc->d.f_boundary; + printf("%u\t%s\t%g\t%g\n", + i, bd->name, (bd->has_hc ? bd->hc : 0), (bd->has_hc ? bd->hc_max : 0)); + } + } + + /* Radiative Temperatures */ + printf("# Radiative Temperatures\n"); + printf("# ID Rad_Temp Lin_Temp\n"); + printf("%u\t%g\t%g\n", (unsigned)sa_size(stardis->descriptions), + stardis->radiative_temp[0], stardis->radiative_temp[1]); - time[0] = time[1] = stardis->probe[3]; - res = sdis_solve_boundary(scn, - stardis->N, - stardis->boundary.primitives, - stardis->boundary.sides, - sa_size(stardis->boundary.sides), - time, - stardis->scale_factor, - stardis->radiative_temp[0], - stardis->radiative_temp[1], - stardis->dump_paths, - &estimator); + printf("# Samples\n"); + printf("# end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n\n"); + printf("# end = end_type end_id; end_type = T | H | X | R | F | S\n"); + printf("# power_term_i = power_type_i power_id_i factor_i\n"); + printf("# flux_term_i = flux_id_i factor_i\n"); + sdis_green_function_for_each_path(green, print_sample, stardis->descriptions); + printf("---END GREEN---\n"); + + CHK(sdis_green_function_ref_put(green) == RES_OK); } else { - CHK(0); - } - if (res != RES_OK) goto error; - if (mode == PROBE_COMPUTE - || mode == MEDIUM_COMPUTE - || mode == BOUNDARY_COMPUTE) { - /* Fetch the estimation data */ - SDIS(estimator_get_temperature(estimator, &temperature)); - SDIS(estimator_get_failure_count(estimator, &nfailures)); - - /* Print the results */ - switch (mode) { - case PROBE_COMPUTE: - printf("Temperature at t=[%g, %g, %g, %g] = %g +/- %g\n", - pos[0], pos[1], pos[2], time[0], - temperature.E, /* Expected value */ - temperature.SE); /* Standard error */ - break; - case MEDIUM_COMPUTE: - printf("Temperature in medium %s at t=%g = %g +/- %g\n", - stardis->solve_name, time[0], - temperature.E, /* Expected value */ - temperature.SE); /* Standard error */ - break; - case BOUNDARY_COMPUTE: - printf("Temperature at boundary %s at t=%g = %g +/- %g\n", - stardis->solve_name, time[0], - temperature.E, /* Expected value */ - temperature.SE); /* Standard error */ - break; - default: FATAL("Invalid mode."); + if (mode & IR_COMPUTE) { + size_t width = (size_t)stardis->camera.img[0]; + size_t height = (size_t)stardis->camera.img[1]; + + /* Setup the camera */ + SDIS(camera_create(dev, &cam)); + SDIS(camera_set_proj_ratio(cam, (double)width / (double)height)); + SDIS(camera_set_fov(cam, MDEG2RAD(stardis->camera.fov))); + SDIS(camera_look_at(cam, + stardis->camera.pos, + stardis->camera.tgt, + stardis->camera.up)); + + /* Create the accum buffer */ + SDIS(accum_buffer_create(dev, width, height, &buf)); + + /* Launch the simulation */ + res = sdis_solve_camera(scn, + cam, + stardis->camera.u.time, + stardis->scale_factor, + stardis->radiative_temp[0], + stardis->radiative_temp[1], + width, + height, + (size_t)stardis->camera.spp, + sdis_accum_buffer_write, + buf); + if (res != RES_OK) goto error; + + /* Write the image */ + dump_image(buf); + } + else if (mode & PROBE_COMPUTE) { + double uv[2] = { 0,0 }; + size_t iprim = SIZE_MAX; + /* Launch the probe simulation */ + pos[0] = stardis->probe[0]; + pos[1] = stardis->probe[1]; + pos[2] = stardis->probe[2]; + time[0] = time[1] = stardis->probe[3]; + + res = select_probe_type(scn, + stardis->geometry.triangle, + stardis->descriptions, + pos, + &iprim, + uv); + if (res != RES_OK) goto error; + + if (iprim == SIZE_MAX) { + res = sdis_solve_probe(scn, + stardis->N, + pos, + time, + stardis->scale_factor, + stardis->radiative_temp[0], + stardis->radiative_temp[1], + stardis->dump_paths, + &estimator); + } else { + res = sdis_solve_probe_boundary(scn, + stardis->N, + iprim, + uv, + time, + SDIS_FRONT, + stardis->scale_factor, + stardis->radiative_temp[0], + stardis->radiative_temp[1], + stardis->dump_paths, + &estimator); + } + } + else if (mode & MEDIUM_COMPUTE) { + size_t sz, ii; + struct sdis_medium* medium = NULL; + /* Find medium */ + sz = sa_size(stardis->descriptions); + FOR_EACH(ii, 0, sz) { + struct description* desc = stardis->descriptions + ii; + if (desc->type == DESC_MAT_SOLID) { + if (0 == strcmp(stardis->solve_name, desc->d.solid.name)) { + ASSERT(sa_size(media) > ii); + medium = media[ii]; + break; + } + } + else if (desc->type == DESC_MAT_FLUID) { + if (0 == strcmp(stardis->solve_name, desc->d.fluid.name)) { + ASSERT(sa_size(media) > ii); + medium = media[ii]; + break; + } + } + } + if (medium == NULL) { + /* Not found */ + fprintf(stderr, "Cannot solve medium %s (unknown medium)\n", + stardis->solve_name); + res = RES_BAD_ARG; + goto error; + } + time[0] = time[1] = stardis->probe[3]; + res = sdis_solve_medium(scn, + stardis->N, + medium, + time, + stardis->scale_factor, + stardis->radiative_temp[0], + stardis->radiative_temp[1], + stardis->dump_paths, + &estimator); } - printf("#failures: %lu/%lu\n", - (unsigned long)nfailures, - (unsigned long)stardis->N); + else if (mode & BOUNDARY_COMPUTE) { + ASSERT(sa_size(stardis->boundary.primitives) + == sa_size(stardis->boundary.sides)); + if (sa_size(stardis->boundary.sides) == 0) { + fprintf(stderr, "Cannot solve boundary %s (empty geometry)\n", + stardis->solve_name); + } - /* Dump paths according to user settings */ - sdis_estimator_for_each_path(estimator, dump_path, stdout); + time[0] = time[1] = stardis->probe[3]; + res = sdis_solve_boundary(scn, + stardis->N, + stardis->boundary.primitives, + stardis->boundary.sides, + sa_size(stardis->boundary.sides), + time, + stardis->scale_factor, + stardis->radiative_temp[0], + stardis->radiative_temp[1], + stardis->dump_paths, + &estimator); + } else { + CHK(0); + } + if (res != RES_OK) goto error; + if (mode & PROBE_COMPUTE + || mode & MEDIUM_COMPUTE + || mode & BOUNDARY_COMPUTE) { + /* Fetch the estimation data */ + SDIS(estimator_get_temperature(estimator, &temperature)); + SDIS(estimator_get_failure_count(estimator, &nfailures)); + + /* Print the results */ + switch (mode) { + case PROBE_COMPUTE: + printf("Temperature at t=[%g, %g, %g, %g] = %g +/- %g\n", + pos[0], pos[1], pos[2], time[0], + temperature.E, /* Expected value */ + temperature.SE); /* Standard error */ + break; + case MEDIUM_COMPUTE: + printf("Temperature in medium %s at t=%g = %g +/- %g\n", + stardis->solve_name, time[0], + temperature.E, /* Expected value */ + temperature.SE); /* Standard error */ + break; + case BOUNDARY_COMPUTE: + printf("Temperature at boundary %s at t=%g = %g +/- %g\n", + stardis->solve_name, time[0], + temperature.E, /* Expected value */ + temperature.SE); /* Standard error */ + break; + default: FATAL("Invalid mode."); + } + printf("#failures: %lu/%lu\n", + (unsigned long)nfailures, + (unsigned long)stardis->N); + + /* Dump paths according to user settings */ + sdis_estimator_for_each_path(estimator, dump_path, stdout); + } } end: