star-phor-input

File format for describing photoreactor configurations
git clone https://www.edstar.cnrs.fr/git/star-phor-input.git
Log | Files | Refs | README | LICENSE

commit db820201ae9a8f31d402e242938b4fa4aeccd353
parent 3ae3162665bbe7bcec40722f7e5490386a44d6cb
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Tue, 24 Feb 2026 18:17:08 +0100

Update BRDF parsing accordingly to the new config file specification

Take the new BRDF reflectivity options into account when parsing a
configuration file. This commit also simplifies the sphin API for BRDFs
by decoupling the energetic component (i.e., the
directional–hemispherical reflectivity) from the reflection direction
distribution PDF, following a similar approach to that used for surface
sources.

The public sphin API introduces a new enum,
sphin_brdf_reflectivity_type, to represent the different reflectivity
options now supported in the configuration file. Additionally,
sphin_brdf_type has been renamed to the more appropriate
sphin_brdf_direction_distribution.

Reflectivity, previously represented as a real value, is now treated as
a spectral property (although it may be spectral-directional).

Tests have been updated accordingly.

Diffstat:
Msrc/sphin.h | 51+++++++++++++++++++--------------------------------
Msrc/sphin_brdf.c | 84++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/test_sphin_load_surface.c | 60+++++++++++++++++++++++++++++++++++-------------------------
3 files changed, 103 insertions(+), 92 deletions(-)

diff --git a/src/sphin.h b/src/sphin.h @@ -50,10 +50,17 @@ enum sphin_side { SPHIN_SIDE_NONE__ /* 2 */ }; -enum sphin_brdf_type { - SPHIN_BRDF_LAMBERT, /* 0 */ - SPHIN_BRDF_SPECULAR, /* 1 */ - SPHIN_BRDF_NONE__ /* 2 */ +enum sphin_brdf_direction_distribution { + SPHIN_BRDF_DIRECTION_LAMBERT, /* 0 */ + SPHIN_BRDF_DIRECTION_SPECULAR, /* 1 */ + SPHIN_BRDF_DIRECTION_NONE__ /* 2 */ +}; + +enum sphin_brdf_reflectivity_type { + SPHIN_BRDF_REFLECTIVITY_TABULATED, + SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC, + SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC_CONDUCTOR, + SPHIN_BRDF_REFLECTIVITY_NONE__ }; enum sphin_photon_unit { @@ -95,26 +102,6 @@ struct sphin_create_args { static const struct sphin_create_args SPHIN_CREATE_ARGS_DEFAULT = SPHIN_CREATE_ARGS_DEFAULT__; -struct sphin_brdf_lambertian { - double reflectivity; -}; -#define SPHIN_BRDF_LAMBERTIAN_NULL__ {0} -static const struct sphin_brdf_lambertian SPHIN_BRDF_LAMBERTIAN_NULL = - SPHIN_BRDF_LAMBERTIAN_NULL__; - -struct sphin_brdf_specular { - double reflectivity; -}; -#define SPHIN_BRDF_SPECULAR_NULL__ {0} -static const struct sphin_brdf_specular SPHIN_BRDF_SPECULAR_NULL = - SPHIN_BRDF_SPECULAR_NULL__; - -#define SPHIN_BRDF_NULL__ { \ - SPHIN_BRDF_NONE__, \ - SPHIN_BRDF_LAMBERTIAN_NULL__, \ - SPHIN_BRDF_SPECULAR_NULL__ \ -} - struct sphin_source_surface_flux_density { double flux_density; /* either [umol/m^2/s] or [W/m^2] */ struct sphin_spectral_property* emission_spectrum; /* Normalized */ @@ -502,19 +489,19 @@ sphin_brdf_ref_put (struct sphin_brdf* brdf); SPHIN_API res_T -sphin_brdf_get_type - (struct sphin_brdf* brdf, - enum sphin_brdf_type* type); +sphin_brdf_get_direction_distribution +(struct sphin_brdf* brdf, + enum sphin_brdf_direction_distribution* direction_distribution); SPHIN_API res_T -sphin_brdf_lambertian_get_reflectivity +sphin_brdf_get_reflectivity_type (struct sphin_brdf* brdf, - double* reflectivity); + enum sphin_brdf_reflectivity_type* reflectivity_type); SPHIN_API res_T -sphin_brdf_specular_get_reflectivity - (struct sphin_brdf* brdf, - double* reflectivity); +sphin_brdf_get_reflectivity_value + (struct sphin_brdf* brdf, /* Only for SPHIN_BRDF_REFLECTIVITY_CONSTANT */ + struct sphin_spectral_property** reflectivity); /******************************************************************************* * API of the sensor_volume diff --git a/src/sphin_brdf.c b/src/sphin_brdf.c @@ -27,6 +27,8 @@ #include "sphin.h" #include "sphin_c.h" #include "sphin_brdf.h" +#include "sphin_config.h" +#include "sphin_spectral_property.h" #include <rsys/cstr.h> #include <rsys/mem_allocator.h> @@ -35,9 +37,10 @@ #include <rsys/text_reader.h> struct sphin_brdf { - enum sphin_brdf_type type; - struct sphin_brdf_lambertian lambertian; - struct sphin_brdf_specular specular; + enum sphin_brdf_direction_distribution direction_distribution; + enum sphin_brdf_reflectivity_type reflectivity_type; /* Constant, Frensel */ + struct sphin_spectral_property* reflectivity; /* Only used if reflectivity is + * a constant */ struct sphin* sphin; ref_T ref; }; @@ -61,8 +64,9 @@ brdf_create ref_init(&brdf->ref); SPHIN(ref_get(sphin)); brdf->sphin = sphin; - brdf->lambertian = SPHIN_BRDF_LAMBERTIAN_NULL; - brdf->specular = SPHIN_BRDF_SPECULAR_NULL; + brdf->reflectivity_type = SPHIN_BRDF_REFLECTIVITY_NONE__; + brdf->direction_distribution = SPHIN_BRDF_DIRECTION_NONE__; + brdf->reflectivity = NULL; exit: *out_brdf = brdf; @@ -86,6 +90,9 @@ release_brdf brdf = CONTAINER_OF(address, struct sphin_brdf, ref); sphin = brdf->sphin; + if (NULL != brdf->reflectivity) { + SPHIN(spectral_property_ref_put(brdf->reflectivity)); + } MEM_RM(sphin->allocator, brdf); SPHIN(ref_put(sphin)); } @@ -103,7 +110,7 @@ parse_brdf char* brdf_type = NULL; char* str_reflectivity = NULL; char* token_ptr = NULL; - double reflectivity; + char* filename = NULL; struct sphin_brdf* brdf = NULL; res_T res = RES_OK; @@ -119,27 +126,32 @@ parse_brdf brdf_type = strtok_r(value, " \t", &token_ptr); if (NULL == brdf_type){ res = RES_BAD_ARG; goto error; } if (0 == strcmp(brdf_type, "LAMBERT")) { - brdf->type = SPHIN_BRDF_LAMBERT; + brdf->direction_distribution = SPHIN_BRDF_DIRECTION_LAMBERT; } else if (0 == strcmp(brdf_type, "SPECULAR")) { - brdf->type = SPHIN_BRDF_SPECULAR; + brdf->direction_distribution = SPHIN_BRDF_DIRECTION_SPECULAR; } else { res = RES_BAD_ARG; goto error; } /* Parse reflectivity value */ str_reflectivity = strtok_r(NULL, " \t", &token_ptr); - res = cstr_to_double(str_reflectivity, &reflectivity); - if (RES_OK != res) { goto error; } - if (reflectivity < 0 || reflectivity >1 ) { res = RES_BAD_ARG; goto error; } - - switch(brdf->type) { - case SPHIN_BRDF_LAMBERT: - brdf->lambertian.reflectivity = reflectivity; - break; - case SPHIN_BRDF_SPECULAR: - brdf->specular.reflectivity = reflectivity; - break; - default: FATAL("Unreachable code\n"); break; + if (NULL == str_reflectivity){ res = RES_BAD_ARG; goto error; } + + if (0 == strcmp(str_reflectivity, "FRESNEL_DIELECTRIC")) { + brdf->reflectivity_type = SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC; + } + else if (0 == strcmp(str_reflectivity, "FRESNEL_DIELECTRIC_CONDUCTOR")) { + brdf->reflectivity_type + = SPHIN_BRDF_REFLECTIVITY_FRESNEL_DIELECTRIC_CONDUCTOR; + } + else { + filename = trim_keyword(str_reflectivity); + if (NULL == filename) { res = RES_BAD_ARG; goto error; } + + res = parse_spectral_property(sphin, filename, &brdf->reflectivity); + if (RES_OK != res) { goto error; } + + brdf->reflectivity_type = SPHIN_BRDF_REFLECTIVITY_TABULATED; } res = txtrdr_read_line(txtrdr); @@ -182,50 +194,52 @@ sphin_brdf_ref_put } res_T -sphin_brdf_get_type +sphin_brdf_get_direction_distribution (struct sphin_brdf* brdf, - enum sphin_brdf_type* type) + enum sphin_brdf_direction_distribution* direction_distribution) { res_T res = RES_OK; - if (NULL == brdf || NULL == type) { + if (NULL == brdf || NULL == direction_distribution) { return RES_BAD_ARG; } - *type = brdf->type; + *direction_distribution = brdf->direction_distribution; return res; } res_T -sphin_brdf_lambertian_get_reflectivity +sphin_brdf_get_reflectivity_type (struct sphin_brdf* brdf, - double* reflectivity) + enum sphin_brdf_reflectivity_type* reflectivity_type) { res_T res = RES_OK; - if (NULL == brdf || NULL == reflectivity) { - return RES_BAD_ARG; - } - if (SPHIN_BRDF_SPECULAR == brdf->type) { + if (NULL == brdf || NULL == reflectivity_type) { return RES_BAD_ARG; } - *reflectivity = brdf->lambertian.reflectivity; + + *reflectivity_type= brdf->reflectivity_type; return res; } res_T -sphin_brdf_specular_get_reflectivity +sphin_brdf_get_reflectivity_value (struct sphin_brdf* brdf, - double* reflectivity) + struct sphin_spectral_property** reflectivity) { res_T res = RES_OK; if (NULL == brdf || NULL == reflectivity) { return RES_BAD_ARG; } - if (SPHIN_BRDF_LAMBERT == brdf->type) { + + /* Not defined for Fresnel reflectivities types */ + if (SPHIN_BRDF_REFLECTIVITY_TABULATED != brdf->reflectivity_type) { return RES_BAD_ARG; } - *reflectivity = brdf->specular.reflectivity; + + *reflectivity = brdf->reflectivity; + return res; } diff --git a/src/test_sphin_load_surface.c b/src/test_sphin_load_surface.c @@ -92,13 +92,32 @@ write_stl_test_files } static void +write_spec_rad_test_files + (void) +{ + FILE* file; + static const char* test0 = + "100 1\n" + "200 2\n" + "300 3\n" + "400 4\n"; + file = fopen("spectral_property.txt", "w"); + CHK(file != NULL); + fwrite(test0, sizeof(char), strlen(test0), file); + fclose(file); +} + +static void test_surface_api (struct sphin* sphin) { char* name = NULL; const char* path = "file.txt"; - double area, power, reflectivity, response_function; - enum sphin_brdf_type brdf_type = SPHIN_BRDF_NONE__; + double area, power, response_function; + enum sphin_brdf_direction_distribution dir_dist + = SPHIN_BRDF_DIRECTION_NONE__; + enum sphin_brdf_reflectivity_type reflectivity_type + = SPHIN_BRDF_REFLECTIVITY_NONE__; size_t nsurfaces; struct sphin_brdf* brdf = NULL; struct sphin_config* config = NULL; @@ -109,7 +128,7 @@ test_surface_api CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "\t\t surface : \"tube walls\"\n"); - fprintf(fp, "\tbrdf: LAMBERT 0.1935 # my comment\n"); + fprintf(fp, "\tbrdf: LAMBERT spectral_property.txt # my comment\n"); fprintf(fp, "\tgeometry: FRONT test_0.stl\n"); fprintf(fp, "\tgeometry: BACK test_3.stl\n"); fprintf(fp, " \n"); @@ -117,7 +136,7 @@ test_surface_api fprintf(fp, " \n"); fprintf(fp, "surface: \"other_tube walls\"\n"); fprintf(fp, "\tgeometry: FRONT test_0.stl\n"); - fprintf(fp, "\tbrdf\t : SPECULAR 0.1935 \n"); + fprintf(fp, "\tbrdf\t : SPECULAR spectral_property.txt \n"); fprintf(fp, "\tsensor: \n"); fprintf(fp, "\t\tresponse_function: 1\n"); fclose(fp); @@ -144,32 +163,22 @@ test_surface_api CHK(sphin_surface_get_brdf(surface, NULL) == RES_BAD_ARG); CHK(sphin_surface_get_brdf(NULL, &brdf) == RES_BAD_ARG); CHK(sphin_surface_get_brdf(surface, &brdf) == RES_OK); - CHK(sphin_brdf_get_type(brdf, &brdf_type) == RES_OK); - CHK(brdf_type == SPHIN_BRDF_LAMBERT); - CHK(sphin_brdf_lambertian_get_reflectivity(NULL, NULL) == RES_BAD_ARG); - CHK(sphin_brdf_lambertian_get_reflectivity - (NULL, &reflectivity) == RES_BAD_ARG); - CHK(sphin_brdf_specular_get_reflectivity(brdf, &reflectivity) == RES_BAD_ARG); - CHK(sphin_brdf_lambertian_get_reflectivity(NULL, NULL) == RES_BAD_ARG); - CHK(sphin_brdf_lambertian_get_reflectivity - (NULL, &reflectivity) == RES_BAD_ARG); - CHK(sphin_brdf_lambertian_get_reflectivity(brdf, NULL) == RES_BAD_ARG); - CHK(sphin_brdf_lambertian_get_reflectivity(brdf, &reflectivity) == RES_OK); - CHK(eq_eps(reflectivity, 0.1935, 1e-15)); + CHK(sphin_brdf_get_direction_distribution(NULL, NULL) == RES_BAD_ARG); + CHK(sphin_brdf_get_direction_distribution(NULL, &dir_dist) == RES_BAD_ARG); + CHK(sphin_brdf_get_direction_distribution(brdf, NULL) == RES_BAD_ARG); + CHK(sphin_brdf_get_direction_distribution(brdf, &dir_dist) == RES_OK); + CHK(dir_dist == SPHIN_BRDF_DIRECTION_LAMBERT); + CHK(sphin_brdf_get_reflectivity_type(NULL, NULL) == RES_BAD_ARG); + CHK(sphin_brdf_get_reflectivity_type(NULL, &reflectivity_type) == RES_BAD_ARG); + CHK(sphin_brdf_get_reflectivity_type(brdf, NULL) == RES_BAD_ARG); + CHK(sphin_brdf_get_reflectivity_type(brdf, &reflectivity_type) == RES_OK); /* Test surface 1 */ CHK(sphin_config_get_surface(config, 1, &surface) == RES_OK); CHK(sphin_surface_get_brdf(surface, &brdf) == RES_OK); - CHK(sphin_brdf_get_type(brdf, &brdf_type) == RES_OK); - CHK(brdf_type == SPHIN_BRDF_SPECULAR); - CHK(sphin_brdf_lambertian_get_reflectivity - (brdf, &reflectivity) == RES_BAD_ARG); - CHK(sphin_brdf_specular_get_reflectivity(NULL, NULL) == RES_BAD_ARG); - CHK(sphin_brdf_specular_get_reflectivity(brdf, NULL) == RES_BAD_ARG); - CHK(sphin_brdf_specular_get_reflectivity(NULL, &reflectivity) == RES_BAD_ARG); - CHK(sphin_brdf_specular_get_reflectivity(brdf, &reflectivity) == RES_OK); + CHK(sphin_brdf_get_direction_distribution(brdf, &dir_dist) == RES_OK); + CHK(dir_dist == SPHIN_BRDF_DIRECTION_SPECULAR); CHK(sphin_surface_source_get_power(surface, &power) == RES_BAD_ARG); - CHK(eq_eps(reflectivity, 0.1935, 1e-15)); CHK(sphin_surface_compute_total_area(surface, &area) == RES_OK); CHK(eq_eps(area, 0.5, 1e-15)); CHK(sphin_brdf_ref_get(brdf) == RES_OK); @@ -275,6 +284,7 @@ main(int argc, char** argv) sphin_create(&args, &sphin); write_stl_test_files(); + write_spec_rad_test_files(); test_surface_api(sphin); test_surface_api_bad_brdf_key(sphin); test_surface_api_bad_brdf_value(sphin);