commit d455bd9660c60a24525c3d4450841465be11a4f3
parent 86bd7c698a0127dfc4b851c0ff4ba4a6d1080844
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date: Wed, 21 May 2025 15:03:17 +0200
Add Surface API function to get total emitted power
In the star-phor-input file, the user specifies the flux of a surface
source as a power density (i.e., power per unit area). However, during a
computation, it may be useful to obtain the total power emitted by the
surface, not just the specific power density.
This commit introduces a function in the surface API to compute and
retrieve the total emitted power from a surface, provided it is a
source.
Note that this function is added to the Surface API rather than the
Source API. This design decision is due to the fact that computing total
power requires knowledge of the surface's geometry, which resides within
the surface struct. In the current architecture, sources are agnostic of
the surfaces they are associated with. Hence, the function logically
belongs to the surface API.
Diffstat:
8 files changed, 97 insertions(+), 8 deletions(-)
diff --git a/config.mk b/config.mk
@@ -31,7 +31,8 @@ SSTL_INCS = $$($(PKG_CONFIG) --cflags sstl)
SSTL_LIBS = $$($(PKG_CONFIG) --libs sstl)
INCS = $(RSYS_INCS) $(SSTL_INCS)
-LIBS = $(RSYS_LIBS) $(SSTL_LIBS)
+LIBS = $(RSYS_LIBS) $(SSTL_LIBS) -lm
+
################################################################################
# Compilation options
################################################################################
diff --git a/src/sphin.h b/src/sphin.h
@@ -329,6 +329,11 @@ sphin_surface_get_geometry
size_t igeometry,
struct sphin_geometry** geometry);
+SPHIN_API res_T
+sphin_surface_source_get_power
+ (struct sphin_surface* surface,
+ double* power);
+
/*******************************************************************************
* API of the source
******************************************************************************/
@@ -350,12 +355,6 @@ sphin_source_surface_get_flux_density
(const struct sphin_source* source,
struct sphin_source_flux_density* density);
-/* TODO */
-SPHIN_API res_T
-sphin_source_get_power
- (const struct sphin_source* source,
- struct sphin_source_power* power);
-
/*******************************************************************************
* API of the BRDF
******************************************************************************/
diff --git a/src/sphin_geometry.c b/src/sphin_geometry.c
@@ -93,6 +93,44 @@ error:
/*******************************************************************************
* Local functions
******************************************************************************/
+double
+geometry_compute_area
+ (struct sphin_geometry* geom)
+{
+ const double* pos = NULL;
+ const double* v0 = NULL;
+ const double* v1 = NULL;
+ const double* v2 = NULL;
+ const size_t* ids = NULL;
+ double area = 0.0;
+ double E0[3], E1[3], N[3];
+ size_t id, itri, tri_count;
+
+ ASSERT(geom);
+
+ pos = darray_double_data_get(&geom->coords);
+ ids = darray_size_t_data_get(&geom->indices);
+ tri_count = darray_size_t_size_get(&geom->indices)/3;
+ if(0 == tri_count) return 0.f;
+
+ for (itri = 0; itri < tri_count; itri++) {
+ id = itri * 3; /*#ids per vertex*/
+
+ /* Retrieve vertex coordinates */
+ v0 = pos + ids[id+0]*3;
+ v1 = pos + ids[id+1]*3;
+ v2 = pos + ids[id+2]*3;
+
+ /* Construct vectors defining the triangle */
+ d3_sub(E0, v1, v0);
+ d3_sub(E1, v2, v0);
+
+ /* Increment total area */
+ area += d3_len(d3_cross(N, E0, E1));
+ }
+ return area * 0.5f;
+}
+
res_T
geometry_parse
diff --git a/src/sphin_geometry.h b/src/sphin_geometry.h
@@ -53,6 +53,10 @@ geometry_parse
char* value,
struct sphin_geometry** out_geom);
+extern LOCAL_SYM double
+geometry_compute_area
+ (struct sphin_geometry* geom);
+
/* Generate a dynamic array for storing sphin_geometry* elements and its API
* using the API provided by rsys/dynamic_array.h
*
diff --git a/src/sphin_source.c b/src/sphin_source.c
@@ -27,6 +27,7 @@
#include "sphin_c.h"
#include "sphin_config.h"
#include "sphin_source.h"
+#include "sphin_surface.h"
#include <rsys/cstr.h>
#include <rsys/double3.h>
diff --git a/src/sphin_surface.c b/src/sphin_surface.c
@@ -336,3 +336,43 @@ sphin_surface_get_geometry
return RES_OK;
}
+
+res_T
+sphin_surface_source_get_power
+ (struct sphin_surface* surface,
+ double* power)
+{
+ double sum_powers = 0;
+ double total_geometry_area = 0;
+ size_t geometry_count = 0;
+ size_t i = 0;
+ struct sphin_geometry* geometry = NULL;
+ struct sphin_source* source = NULL;
+ struct sphin_source_flux_density density = SPHIN_SOURCE_FLUX_DENSITY_NULL;
+ res_T res = RES_OK;
+
+ source = surface->source;
+
+ if (NULL == source) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = sphin_source_surface_get_flux_density(source, &density);
+ if (RES_OK != res) { goto error; }
+
+ geometry_count = darray_sphin_geometry_ptr_size_get(&surface->geometries);
+
+ FOR_EACH(i, 0, geometry_count) {
+ geometry = darray_sphin_geometry_ptr_data_get(&surface->geometries)[i];
+ total_geometry_area += geometry_compute_area(geometry);
+ }
+
+ sum_powers = total_geometry_area * density.flux_density;
+
+exit:
+ *power = sum_powers;
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/test_sphin_load_source.c b/src/test_sphin_load_source.c
@@ -54,6 +54,7 @@ test_source_api
(struct sphin* sphin)
{
const char* path = "file.txt";
+ double power;
size_t nsurfaces, ngeometries;
struct sphin_config* config = NULL;
struct sphin_surface* surface = NULL;
@@ -127,8 +128,12 @@ test_source_api
CHK(dir_dist.collim.direction[0] == SPHIN_SOURCE_DIRECTION_DISTRIBUTION_COLLIM_NULL.direction[0]);
CHK(dir_dist.collim.direction[1] == SPHIN_SOURCE_DIRECTION_DISTRIBUTION_COLLIM_NULL.direction[1]);
CHK(dir_dist.collim.direction[2] == SPHIN_SOURCE_DIRECTION_DISTRIBUTION_COLLIM_NULL.direction[2]);
+ CHK(sphin_source_surface_get_flux_density(source, NULL) == RES_BAD_ARG);
+ CHK(sphin_source_surface_get_flux_density(NULL, &flux_density) == RES_BAD_ARG);
CHK(sphin_source_surface_get_flux_density(source, &flux_density) == RES_OK);
CHK(eq_eps(flux_density.flux_density, 200, 1e-15));
+ CHK(sphin_surface_source_get_power(surface, &power) == RES_OK);
+ CHK(eq_eps(power, 100, 1e-15));
CHK(flux_density.unit == SPHIN_PHOTON_UNIT_JOULE);
CHK(sphin_config_ref_put(config) == RES_OK);
diff --git a/src/test_sphin_load_surface.c b/src/test_sphin_load_surface.c
@@ -91,7 +91,7 @@ test_surface_api
{
struct sphin_config* config = NULL;
const char* path = "file.txt";
- double reflectivity;
+ double power, reflectivity;
struct sphin_surface* surface = NULL;
struct sphin_brdf* brdf = NULL;
size_t nsurfaces;
@@ -144,6 +144,7 @@ test_surface_api
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_surface_source_get_power(surface, &power) == RES_BAD_ARG);
CHK(eq_eps(reflectivity, 0.5, 1e-15));
CHK(sphin_brdf_ref_get(brdf) == RES_OK);
CHK(sphin_brdf_ref_put(brdf) == RES_OK);