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 85c79ef8fa7af34d24066933566921453cc5ca42
parent f445cd6944a67b66b86098cb5f303f2a368af0fc
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Tue, 10 Feb 2026 18:30:26 +0100

Change format specification for prop_rad type in star-phor-input

The prop_rad type was previously specified inconsistently when compared
to other named elements in the configuration file, such as volumes and
surfaces. This commit introduces a new format for the prop_rad type
(currently only applied to scatterers) to standardize element
declarations and improve overall coherence of the configuration file.

As a compromise, an additional indentation level is added (although
the underlying abstraction layer was already present).

Docs, parsing, and tests have been updated accordingly.

Diffstat:
Mdoc/star-phor-input.5.scd | 8++++++--
Msrc/sphin_prop_rad.c | 47++++++++++++++++++++++++-----------------------
Msrc/sphin_prop_rad.h | 3++-
Msrc/sphin_volume.c | 2+-
Msrc/test_sphin_load_prop_rad.c | 22++++++++++++++--------
Msrc/test_sphin_load_volume.c | 3++-
6 files changed, 49 insertions(+), 36 deletions(-)

diff --git a/doc/star-phor-input.5.scd b/doc/star-phor-input.5.scd @@ -120,10 +120,14 @@ The syntax rules enabling the description of a photoreactor are as follows: <sensor> ::= 'sensor:' 'response_function:' real -<prop-rad> ::= 'prop_rad:' <name> <prop-rad-type> +<prop-rad> ::= 'prop_rad:' <name> + <prop-rad-spec> + +<prop-rad-spec> ::= <scatterer> + +<scatterer> ::= 'scatterer:' <concentration> <cross-sections> -<prop-rad-type> ::= 'SCATTERER' <concentration> ::= 'concentration:' real \\ <concentration-unit> diff --git a/src/sphin_prop_rad.c b/src/sphin_prop_rad.c @@ -33,6 +33,7 @@ #include <rsys/ref_count.h> #include <rsys/rsys.h> #include <rsys/str.h> +#include <rsys/text_reader.h> /******************************************************************************* * Helper functions @@ -97,47 +98,45 @@ release_prop_rad ******************************************************************************/ res_T parse_prop_rad - (struct sphin_volume* volume, + (struct sphin_config* config, + struct sphin_volume* volume, struct txtrdr* txtrdr, char* value) { - char* name = NULL; - char* name_start = NULL; char* prop_rad_type_str = NULL; + char* name = NULL; char* token = NULL; char* token_ptr = NULL; enum sphin_prop_rad_type prop_rad_type = SPHIN_PROP_RAD_NONE__; + struct str line; struct sphin_prop_rad* prop_rad = NULL; - size_t len = 0; res_T res = RES_OK; ASSERT(NULL != volume); ASSERT(NULL != txtrdr); + ASSERT(NULL != value); + ASSERT('\0' != value[0]); /* Name can't be empty */ - if (NULL == value) { res = RES_BAD_ARG; goto error; } + str_init(config->sphin->allocator, &line); - /* Find first occurence of " in the value string */ - name_start = strchr(value, '"'); - if (NULL == name_start) { res = RES_BAD_ARG; goto error; } + /* Parse name of the prop_rad */ + name = trim_string(value); + if (NULL == name){ res = RES_BAD_ARG; goto error; } - /* Get the number of tabs and spaces (allowed characters) at the beginning - * of the string */ - len = strspn(value, " \t"); - if (value + len != name_start) { - /* There are characters before the first " other than spaces and tabs */ - res = RES_BAD_ARG; goto error; - } - name = strtok_r(name_start, "\"", &token_ptr); - if (NULL == name) { res = RES_BAD_ARG; goto error; } + /* Next line: corresponds to the prop_rad type */ + res = txtrdr_read_line(txtrdr); + if (RES_OK != res) { goto error; } - token = strtok_r(NULL, " \t", &token_ptr); + if (NULL == txtrdr_get_line(txtrdr)) { res = RES_BAD_ARG; goto error; } + + res = str_set(&line, txtrdr_get_cline(txtrdr)); + if (RES_OK != res) { goto error; } + + token = strtok_r(str_get(&line), ":", &token_ptr); if (NULL == token) { res = RES_BAD_ARG; goto error; } - prop_rad_type_str = trim_keyword(token); - if (NULL == prop_rad_type_str) { res = RES_BAD_ARG; goto error; } - if (NULL == prop_rad_type_str) { - prop_rad_type = SPHIN_PROP_RAD_BOLTZMANN; - } else if ( 0 == strcmp(prop_rad_type_str, "SCATTERER")) { + prop_rad_type_str = trim_keyword(token); + if (0 == strcmp(prop_rad_type_str, "scatterer")) { prop_rad_type = SPHIN_PROP_RAD_SCATTERER; } else { res = RES_BAD_ARG; goto error; @@ -146,6 +145,7 @@ parse_prop_rad res = prop_rad_create(volume->sphin, name, &prop_rad); if (RES_OK != res) { goto error; } + /* Parse prop rad parameters in function of its type */ switch(prop_rad_type) { case SPHIN_PROP_RAD_BOLTZMANN: /* TODO Parse prop rad coefficients */ @@ -168,6 +168,7 @@ parse_prop_rad if (RES_OK != res) { goto error; } exit: + str_release(&line); return res; error: if (NULL != prop_rad) { diff --git a/src/sphin_prop_rad.h b/src/sphin_prop_rad.h @@ -44,7 +44,8 @@ struct sphin_prop_rad{ extern LOCAL_SYM res_T parse_prop_rad - (struct sphin_volume* volume, + (struct sphin_config* config, + struct sphin_volume* volume, struct txtrdr* txtrdr, char* value); diff --git a/src/sphin_volume.c b/src/sphin_volume.c @@ -209,7 +209,7 @@ parse_volume res = parse_geometry(volume, txtrdr, token); } else if (0 == strcmp(keyword, "prop_rad")){ - res = parse_prop_rad(volume, txtrdr, token); + res = parse_prop_rad(config, volume, txtrdr, token); } else if (0 == strcmp(keyword, "sensor")) { /* for the sensor_volume, diff --git a/src/test_sphin_load_prop_rad.c b/src/test_sphin_load_prop_rad.c @@ -110,7 +110,8 @@ test_prop_rad_api CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad:\"my prop_rad\" SCATTERER\n"); + fprintf(fp, "\tprop_rad:\"my prop_rad\"\n"); + fprintf(fp, "\t\tscatterer:\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: abs_cross_sec_0.txt nm m^2/part\n"); @@ -197,7 +198,8 @@ test_prop_rad_api_units CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad: \"name\" SCATTERER\n"); + fprintf(fp, "\tprop_rad: \"name\"\n"); + fprintf(fp, "\t\tscatterer:\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: abs_cross_sec_0.txt cm m^2/part\n"); @@ -233,7 +235,8 @@ test_prop_rad_api_bad_comment CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad: SCATTERER \"name\"\n"); + fprintf(fp, "\tprop_rad: \"name\"\n"); + fprintf(fp, "\t\tscatterer:\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: abs_cross_sec_1.txt nm m^2/part\n"); @@ -253,7 +256,8 @@ test_prop_rad_api_unsorted_wavelengths CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad: SCATTERER \"name\"\n"); + fprintf(fp, "\tprop_rad: \"name\"\n"); + fprintf(fp, "\t\tscatterer:\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: abs_cross_sec_2.txt nm m^2/part\n"); @@ -273,7 +277,8 @@ test_prop_rad_api_missing_data CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad: SCATTERER \"name\"\n"); + fprintf(fp, "\tprop_rad: \"name\"\n"); + fprintf(fp, "\t\tscatterer:\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: abs_cross_sec_3.txt nm m^2/part\n"); @@ -293,7 +298,7 @@ test_prop_rad_api_bad_formatting CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad: SCATTERER \"name\"\n"); + fprintf(fp, "\tprop_rad: \"name\"\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: abs_cross_sec_4.txt nm m^2/part\n"); @@ -313,13 +318,14 @@ test_prop_rad_api_non_existing_file CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad: SCATTERER \"name\"\n"); + fprintf(fp, "\tprop_rad: \"name\"\n"); + fprintf(fp, "\t\tscatterer:\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: non_existing_file.txt nm m^2/part\n"); fclose(fp); - CHK(sphin_load(sphin, path, &config) == RES_BAD_ARG); + CHK(sphin_load(sphin, path, &config) == RES_IO_ERR); } int diff --git a/src/test_sphin_load_volume.c b/src/test_sphin_load_volume.c @@ -126,7 +126,8 @@ test_volume_api CHK(fp = fopen(path, "w+")); fprintf(fp, "#Mot Clé Nom\n"); fprintf(fp, "volume: \"reaction volume\"\n"); - fprintf(fp, "\tprop_rad: \"name\" SCATTERER\n"); + fprintf(fp, "\tprop_rad: \"name\" \n"); + fprintf(fp, "\tscatterer:\n"); fprintf(fp, "\t\tconcentration: 1.935 mol/m^3\n"); fprintf(fp, "\t\tcross_sections:\n"); fprintf(fp, "\t\t\tabs_cross_sec: spectral_property.txt nm m^2/part\n");