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 de49cd3e8a2cf59641477c0ad75784e68a791c6a
parent f2625a85c5a32ea1d00b6d7a9fa933aa4bf3a3dd
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Tue, 25 Feb 2025 18:16:41 +0100

Refactor and extend BRDF and flux density handling

- Rename sphin_side, sphin_brdf_type, and sphin_flux_density_unit enums constants for better consistency;

- Introduce reference counting for the sphin_brdf struct;

- Refactor source flux density handling to reflect changes in the model input file.

Diffstat:
MMakefile | 7++++---
Msrc/sphin.h | 71++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/sphin_brdf.c | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/sphin_brdf.h | 26++++++--------------------
Msrc/sphin_geometry.c | 4++--
Msrc/sphin_source.c | 39++++++++++++++++++++++++++++-----------
Msrc/sphin_source.h | 2+-
Msrc/sphin_surface.c | 68+++++++++++++++-----------------------------------------------------
8 files changed, 251 insertions(+), 132 deletions(-)

diff --git a/Makefile b/Makefile @@ -36,11 +36,12 @@ default: build_library ################################################################################ SRC = \ src/sphin.c \ + src/sphin_brdf.c \ src/sphin_config.c \ - src/sphin_volume.c \ - src/sphin_surface.c \ src/sphin_geometry.c \ - src/sphin_source.c + src/sphin_source.c \ + src/sphin_surface.c \ + src/sphin_volume.c OBJ = $(SRC:.c=.o) DEP = $(SRC:.c=.d) diff --git a/src/sphin.h b/src/sphin.h @@ -45,21 +45,21 @@ #endif enum sphin_side { - SPHIN_BACK, /* 0 */ - SPHIN_FRONT, /* 1 */ + SPHIN_SIDE_BACK, /* 0 */ + SPHIN_SIDE_FRONT, /* 1 */ SPHIN_SIDE_NONE__ /* 2 */ }; enum sphin_brdf_type { - SPHIN_LAMBERT, /* 0 */ - SPHIN_SPECULAR, /* 1 */ + SPHIN_BRDF_LAMBERT, /* 0 */ + SPHIN_BRDF_SPECULAR, /* 1 */ SPHIN_BRDF_NONE__ /* 2 */ }; -enum sphin_flux_density_unit { - SPHIN_FLUX_DENSITY_MOL, /* [mol hv/m^2/s] */ - SPHIN_FLUX_DENSITY_POW, /* [W/m^2] */ - SPHIN_FLUX_DENSITY_NONE__ +enum sphin_photon_unit { + SPHIN_PHOTON_UNIT_MOL, /* [mol hv] */ + SPHIN_PHOTON_UNIT_JOULE, /* [J] */ + SPHIN_PHOTON_UNIT_NONE__ }; enum sphin_source_direction_distribution_type { @@ -92,25 +92,19 @@ struct sphin_brdf_specular { static const struct sphin_brdf_specular SPHIN_BRDF_SPECULAR_NULL = SPHIN_BRDF_SPECULAR_NULL__; -struct sphin_brdf { - enum sphin_brdf_type type; - struct sphin_brdf_lambertian lambertian; - struct sphin_brdf_specular specular; -}; #define SPHIN_BRDF_NULL__ { \ SPHIN_BRDF_NONE__, \ SPHIN_BRDF_LAMBERTIAN_NULL__, \ SPHIN_BRDF_SPECULAR_NULL__ \ } -static const struct sphin_brdf SPHIN_BRDF_NULL = SPHIN_BRDF_NULL__; -struct sphin_flux_density { - double flux_density; /* either [mol hv/m^2/s] or [W/m^2] */ - enum sphin_flux_density_unit unit; +struct sphin_source_flux_density { + double flux_density; /* either [umol/m^2/s] or [W/m^2] */ + enum sphin_photon_unit unit; }; -#define SPHIN_FLUX_DENSITY_NULL__ {0, SPHIN_FLUX_DENSITY_NONE__} -static const struct sphin_flux_density SPHIN_FLUX_DENSITY_NULL = - SPHIN_FLUX_DENSITY_NULL__; +#define SPHIN_SOURCE_FLUX_DENSITY_NULL__ {0, SPHIN_PHOTON_UNIT_NONE__} +static const struct sphin_source_flux_density SPHIN_SOURCE_FLUX_DENSITY_NULL = + SPHIN_SOURCE_FLUX_DENSITY_NULL__; struct sphin_source_direction_distribution_cos_pow_n { double collimation_degree; @@ -147,10 +141,11 @@ static const struct sphin_source_direction_distribution * users of the programming interface exposed by star-phor-input. Thus, the user * must use the functions exposed by the library to manipulate this structure. */ struct sphin; /* Library handler */ +struct sphin_brdf; struct sphin_config; /* Physical configuration */ -struct sphin_volume; struct sphin_source; struct sphin_surface; +struct sphin_volume; BEGIN_DECLS @@ -260,14 +255,40 @@ sphin_source_ref_put (struct sphin_source* source); SPHIN_API res_T -sphin_source_get_flux_density +sphin_source_get_direction_distribution + (const struct sphin_source* source, + struct sphin_source_direction_distribution* distrib); + +/* SPHIN_API res_T +sphin_source_get_power (const struct sphin_source* source, - struct sphin_flux_density* density); + struct sphin_source_power* power);*/ SPHIN_API res_T -sphin_source_get_direction_distribution +sphin_source_surface_get_flux_density (const struct sphin_source* source, - struct sphin_source_direction_distribution* distrib); + struct sphin_source_flux_density* density); + +/******************************************************************************* + * API of the source + ******************************************************************************/ +SPHIN_API res_T +sphin_brdf_ref_get + (struct sphin_brdf* brdf); + +SPHIN_API res_T +sphin_brdf_ref_put + (struct sphin_brdf* brdf); + +SPHIN_API res_T +sphin_brdf_lambertian_get_reflectivity + (struct sphin_brdf* brdf, + double* reflectivity); + +SPHIN_API res_T +sphin_brdf_specular_get_reflectivity + (struct sphin_brdf* brdf, + double* reflectivity); END_DECLS diff --git a/src/sphin_brdf.c b/src/sphin_brdf.c @@ -21,35 +21,167 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define _POSIX_C_SOURCE 200112L /* for strtok_r support */ +#include "sphin.h" +#include "sphin_c.h" #include "sphin_brdf.h" -/****************************************************************************** +#include <rsys/cstr.h> +#include <rsys/ref_count.h> +#include <rsys/text_reader.h> + + +struct sphin_brdf { + enum sphin_brdf_type type; + struct sphin_brdf_lambertian lambertian; + struct sphin_brdf_specular specular; + struct sphin* sphin; + ref_T ref; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +brdf_create + (struct sphin* sphin, + struct sphin_brdf** out_brdf) +{ + struct sphin_brdf* brdf = NULL; + res_T res = RES_OK; + + ASSERT(NULL != sphin); + ASSERT(NULL != out_brdf); + + brdf = MEM_CALLOC(sphin->allocator, 1, sizeof(struct sphin_brdf)); + if (NULL == brdf) { res = RES_MEM_ERR; goto error; } + ref_init(&brdf->ref); + SPHIN(ref_get(sphin)); + brdf->sphin = sphin; + brdf->lambertian = SPHIN_BRDF_LAMBERTIAN_NULL; + brdf->specular = SPHIN_BRDF_SPECULAR_NULL; + +exit: + *out_brdf = brdf; + return res; +error: + if (NULL != brdf) { + SPHIN(brdf_ref_put(brdf)); + brdf = NULL; + } + goto exit; +} + +static void +release_brdf(ref_T* address) +{ + struct sphin_brdf* brdf = NULL; + struct sphin* sphin = NULL; + + ASSERT(NULL != address); + + brdf = CONTAINER_OF(address, struct sphin_brdf, ref); + sphin = brdf->sphin; + MEM_RM(sphin->allocator, brdf); + SPHIN(ref_put(sphin)); +} + +/******************************************************************************* * Local functions ******************************************************************************/ -void -brdf_init - (struct mem_allocator* allocator, - struct brdf* brdf) +res_T +parse_brdf + (struct sphin* sphin, + struct txtrdr* txtrdr, + char* value, + struct sphin_brdf** out_brdf) +{ + char* brdf_type; + char* str_reflectivity; + char* token_ptr; + double reflectivity; + struct sphin_brdf* brdf; + res_T res = RES_OK; + + ASSERT(NULL != sphin); + (void) txtrdr; /* Disable unused variable warning */ + res = brdf_create(sphin, &brdf); + if (RES_OK != res) { res = RES_BAD_ARG; goto error; } + /* Parse brdf type */ + 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; + } + else if (0 == strcmp(brdf_type, "SPECULAR")) { + brdf->type = SPHIN_BRDF_SPECULAR; + } + else { res = RES_BAD_ARG; goto error; } + + /* Parse reflectivity value */ + str_reflectivity = strtok_r(value, " \t", &token_ptr); + res = cstr_to_double(str_reflectivity, &reflectivity); + if (RES_OK != res) { res = RES_BAD_ARG; 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; + } + +exit: + *out_brdf = brdf; + return res; +error: + if (brdf != NULL){ + SPHIN(brdf_ref_put(brdf)); + brdf = NULL; + } + goto exit; +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sphin_brdf_ref_get(struct sphin_brdf* brdf) { - ASSERT(NULL != brdf); - brdf->type= SPHIN_BRDF_NONE__; + if(NULL == brdf) { + return RES_BAD_ARG; + } + ref_get(&brdf->ref); + return RES_OK; } -void -brdf_release - (struct brdf* brdf) +res_T +sphin_brdf_ref_put(struct sphin_brdf* brdf) { + if(NULL == brdf) { + return RES_BAD_ARG; + } + ref_put(&brdf->ref, release_brdf); + return RES_OK; } res_T -brdf_copy - (struct brdf* dst, - const struct brdf* src) +sphin_brdf_lambertian_get_reflectivity + (struct sphin_brdf* brdf, + double* reflectivity) { res_T res = RES_OK; - ASSERT(NULL != dst); - ASSERT(NULL != src); - dst->type = src->type; - return res; + + if (NULL == brdf) { + return RES_BAD_ARG; + } + if (SPHIN_BRDF_SPECULAR == brdf->type) { + return RES_BAD_ARG; + } + reflectivity = &brdf->specular.reflectivity; + return res; } diff --git a/src/sphin_brdf.h b/src/sphin_brdf.h @@ -22,33 +22,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - #ifndef SPHIN_BRDF_H #define SPHIN_BRDF_H -#include "sphin.h" - #include <rsys/rsys.h> struct mem_allocator; - -struct brdf { - enum sphin_brdf_type type; - double reflectivity; -}; - -extern LOCAL_SYM void -brdf_init - (struct mem_allocator* allocator, - struct brdf* brdf); - -extern LOCAL_SYM void -brdf_release - (struct brdf* brdf); +struct txtrdr; extern LOCAL_SYM res_T -brdf_copy - (struct brdf* dst, - const struct brdf* src); +parse_brdf +(struct sphin* sphin, + struct txtrdr* txtrdr, + char* value, + struct sphin_brdf** out_brdf); #endif /* SPHIN_BRDF_H*/ diff --git a/src/sphin_geometry.c b/src/sphin_geometry.c @@ -70,8 +70,8 @@ geometry_parse /* Parse side */ side = strtok_r(value, " \t", &token_ptr); if (NULL == side){ res = RES_BAD_ARG; goto error; } - if (0 == strcmp(side, "FRONT")){ geom->side = SPHIN_FRONT; } - else if (0 == strcmp(side, "BACK")){ geom->side = SPHIN_BACK; } + if (0 == strcmp(side, "FRONT")){ geom->side = SPHIN_SIDE_FRONT; } + else if (0 == strcmp(side, "BACK")){ geom->side = SPHIN_SIDE_BACK; } else { res = RES_BAD_ARG; goto error; } /* Parse filename */ diff --git a/src/sphin_source.c b/src/sphin_source.c @@ -36,12 +36,14 @@ struct sphin_source { struct str name; - struct sphin* sphin; struct sphin_source_direction_distribution direction_distribution; - struct sphin_flux_density flux_density; + struct sphin_source_flux_density flux_density; + + struct sphin* sphin; ref_T ref; }; + /******************************************************************************* * Helper functions ******************************************************************************/ @@ -65,7 +67,7 @@ source_create SPHIN(ref_get(sphin)); source->sphin = sphin; source->direction_distribution = SPHIN_SOURCE_DIRECTION_DISTRIBUTION_NULL; - source->flux_density = SPHIN_FLUX_DENSITY_NULL; + source->flux_density = SPHIN_SOURCE_FLUX_DENSITY_NULL; str_init(sphin->allocator, &source->name); res = str_set(&source->name, name); @@ -159,7 +161,7 @@ parse_flux_density struct txtrdr* txtrdr, char* value) { - char* flux_density_type; + char* flux_density_unit; char* str_flux_density; char* token_ptr; double flux_density; @@ -168,13 +170,6 @@ parse_flux_density ASSERT(NULL != source); (void) txtrdr; /* Disable unused variable warning */ - /* Parse unit */ - flux_density_type = strtok_r(value, " \t", &token_ptr); - if (NULL == flux_density_type){ res = RES_BAD_ARG; goto error; } - if (0 == strcmp(flux_density_type, "MOL")){ source->flux_density.unit= SPHIN_FLUX_DENSITY_MOL; } - else if (0 == strcmp(flux_density_type, "POW")){ source->flux_density.unit = SPHIN_FLUX_DENSITY_POW; } - else { res = RES_BAD_ARG; goto error; } - /* Parse flux density value */ str_flux_density = strtok_r(value, " \t", &token_ptr); res = cstr_to_double(str_flux_density, &flux_density); @@ -183,6 +178,28 @@ parse_flux_density source->flux_density.flux_density = flux_density; + /* Parse unit */ + flux_density_unit = strtok_r(value, " \t", &token_ptr); + if (NULL == flux_density_unit){ res = RES_BAD_ARG; goto error; } + /* Kinetic flux density unit */ + if (0 == strcmp(flux_density_unit, "mol/m^2/s") + || 0 == strcmp(flux_density_unit, "mol.m^-2.s^-1")) { + source->flux_density.unit= SPHIN_PHOTON_UNIT_MOL; + source->flux_density.flux_density *= 1e-6; /* From mol to umol */ + } + else if (0 == strcmp(flux_density_unit, "umol/m^2/s") + || 0 == strcmp(flux_density_unit, "umol.m^-2.s^-1")) { + source->flux_density.unit= SPHIN_PHOTON_UNIT_MOL; + source->flux_density.flux_density *= 1; /* No conversion */ + } + /* Energy flux density energy */ + else if (0 == strcmp(flux_density_unit, "W/m^2") + || 0 == strcmp(flux_density_unit, "W.s^-1")) { + source->flux_density.unit= SPHIN_PHOTON_UNIT_JOULE; + source->flux_density.flux_density *= 1; /* No conversion */ + } + else { res = RES_BAD_ARG; goto error; } + exit: return res; error: diff --git a/src/sphin_source.h b/src/sphin_source.h @@ -25,7 +25,7 @@ #ifndef SPHIN_SOURCE_H #define SPHIN_SOURCE_H -#include "rsys/rsys.h" +#include <rsys/rsys.h> struct sphin_source; struct txtrdr; diff --git a/src/sphin_surface.c b/src/sphin_surface.c @@ -28,6 +28,7 @@ #include "sphin_c.h" #include "sphin_config.h" #include "sphin_geometry.h" +#include "sphin_source.h" #include "sphin_surface.h" #include <rsys/cstr.h> @@ -38,9 +39,10 @@ struct sphin_surface { struct str name; struct sphin* sphin; + struct sphin_brdf* brdf; struct darray_geometry geometries; /* dynamic array of struct geometry. see rsys/dynamic_array.h */ - struct sphin_brdf brdf; + struct sphin_source* source; ref_T ref; }; @@ -66,7 +68,7 @@ surface_create ref_init(&surface->ref); SPHIN(ref_get(sphin)); surface->sphin = sphin; - surface->brdf = SPHIN_BRDF_NULL; + surface->brdf = NULL; str_init(sphin->allocator, &surface->name); res = str_set(&surface->name, name); @@ -86,14 +88,17 @@ error: static void release_surface(ref_T* address) { - struct sphin_surface* surface = NULL; struct sphin* sphin = NULL; - + struct sphin_brdf* brdf = NULL; + struct sphin_surface* surface = NULL; ASSERT(NULL != address); surface = CONTAINER_OF(address, struct sphin_surface, ref); str_release(&surface->name); sphin = surface->sphin; + brdf = surface->brdf; + SPHIN(ref_put(sphin)); + SPHIN(brdf_ref_put(brdf)); MEM_RM(sphin->allocator, surface); SPHIN(ref_put(sphin)); } @@ -125,49 +130,6 @@ error: goto exit; } -static res_T -parse_brdf - (struct sphin_surface* surface, - struct txtrdr* txtrdr, - char* value) -{ - char* brdf_type; - char* str_reflectivity; - char* token_ptr; - double reflectivity; - res_T res = RES_OK; - - ASSERT(NULL != surface); - (void) txtrdr; /* Disable unused variable warning */ - - /* Parse brdf type */ - brdf_type = strtok_r(value, " \t", &token_ptr); - if (NULL == brdf_type){ res = RES_BAD_ARG; goto error; } - if (0 == strcmp(brdf_type, "LAMBERT")){ surface->brdf.type = SPHIN_LAMBERT; } - else if (0 == strcmp(brdf_type, "SPECULAR")){ surface->brdf.type = SPHIN_SPECULAR; } - else { res = RES_BAD_ARG; goto error; } - - /* Parse reflectivity value */ - str_reflectivity = strtok_r(value, " \t", &token_ptr); - res = cstr_to_double(str_reflectivity, &reflectivity); - if (RES_OK != res) { res = RES_BAD_ARG; goto error; } - if (reflectivity < 0 || reflectivity >1 ) { res = RES_BAD_ARG; goto error; } - - switch(surface->brdf.type) { - case SPHIN_LAMBERT: - surface->brdf.lambertian.reflectivity = reflectivity; - break; - case SPHIN_SPECULAR: - surface->brdf.specular.reflectivity = reflectivity; - break; - default: FATAL("Unreachable code\n"); break; - } - -exit: - return res; -error: - goto exit; -} /******************************************************************************* * Local functions ******************************************************************************/ @@ -216,11 +178,11 @@ parse_surface res = parse_geometry(surface, txtrdr, value); } else if (0 == strcmp(keyword, "brdf")){ - res = parse_brdf(surface, txtrdr, value); + res = parse_brdf(surface->sphin, txtrdr, value, &surface->brdf); + } + else if (0 == strcmp(keyword, "source")) { + res = parse_source(surface->sphin, txtrdr, value, &surface->source); } - /*else if (0 == strcmp(keyword, "source")) { - res = parse_source(surface->sphin, txtrdr, &surface->source); - }*/ else { break; } @@ -260,7 +222,7 @@ sphin_surface_ref_put(struct sphin_surface* surface) return RES_OK; } -res_T +/* res_T sphin_surface_get_brdf (const struct sphin_surface* surface, struct sphin_brdf* brdf) @@ -270,4 +232,4 @@ sphin_surface_get_brdf } *brdf = surface->brdf; return RES_OK; -} +} */