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:
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;
-}
+} */