commit efcfe09e6e9255dfd6e9222170639eec104f51d9
parent c9622ff2e17c935a0b63ff5434d5fa83221422ed
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date: Tue, 16 Dec 2025 14:46:28 +0100
Update all accums during realization
In star-phor the same algorithm can compute different quantities in a
single run. This is done using the struct accum abstraction (and more
precisely a list of such structs) that can be used to update the sum of
weights and the sum of the squared weights for the different quantities
that are estimated as expectations of random variables.
This implementation enables the possibility of calculating quantities
that are combinations of these other quantities. In the MVREA algorithm,
for instance, we can compute the volume-averaged rate of photon
absorption per unit volume in a given region and combine these to
compute the total volume-averaged rate of photon absorption in the
volume (and then combine the per-volume rates of photon absorption to
get the scene mean volumetric rate of photon absorption).
The strategy previously used to achieve these computations was to,
during the algorithm, store only the accum corresponding to the finest
level of granularity and to construct the accums corresponding to the
quantities that are combinations of these a posteriori, after the MC
algorithm was executed.
This works fine for the expectation of the accums and to compute the
variance in some cases. However, when we need to combine dependent
random variables that are updated with non-zero weights within the same
realization, the variance of the combined variable requires covariance
terms that depend on the cross-products of weights from the finer-level
random variables. These cross-products cannot be reconstructed a
posteriori from the individual weight sums alone.
This imposes a new strategy to handle these accums. We choose to update
the weights of all accums at the end of each realization, regardless of
the level of granularity of the corresponding random variable.
As a consequence, all accumulators must be initialized prior to the
start of the realizations. The writing to stream is simplified, since
now no accums sum is required and a simple loop over all accums
suffices.
Diffstat:
4 files changed, 194 insertions(+), 329 deletions(-)
diff --git a/src/sphor_accum.c b/src/sphor_accum.c
@@ -141,7 +141,7 @@ accum_compute_estim
sum2 = accum->sum2;
mean = sum/samples;
- var = (sum2/samples - mean * mean) / (samples - 1);
+ var = (sum2 - sum * sum / samples) / (samples - 1);
std = sqrt(var);
estim->mean = mean;
@@ -174,12 +174,12 @@ write_accum_estim
str_cget(&accum->observable),
str_cget(&accum->sensor),
estim.mean, estim.std);
- } else {
+ } else {
fprintf
(stream, "%s:%lf:%lf\n",
str_cget(&accum->observable),
estim.mean, estim.std);
- }
+ }
}
extern LOCAL_SYM void
@@ -194,7 +194,6 @@ accum_add
result->sum = op0->sum + op1->sum;
result->sum2 = op0->sum2 + op1->sum2;
- result->n_realizations = op0->n_realizations + op1->n_realizations;
}
extern LOCAL_SYM void
diff --git a/src/sphor_accum.h b/src/sphor_accum.h
@@ -25,6 +25,8 @@
#ifndef SPHOR_ACCUM_H
#define SPHOR_ACCUM_H
+#include "sphor_interface.h"
+
#include <rsys/dynamic_array.h>
#include <rsys/hash_table.h>
#include <rsys/str.h>
@@ -60,7 +62,7 @@ struct accum_key {
size_t sensor_id;
size_t component_id;
};
-#define ACCUM_KEY_NULL__ {SPHOR_SENSOR_NONE, SIZE_MAX, SIZE_MAX}
+#define ACCUM_KEY_NULL__ {SPHOR_SENSOR_NONE, INVALID_ID, INVALID_ID}
static const struct accum_key ACCUM_KEY_NULL = ACCUM_KEY_NULL__;
extern LOCAL_SYM void
diff --git a/src/sphor_compute_mvrea.c b/src/sphor_compute_mvrea.c
@@ -38,6 +38,10 @@
#include <rsys/hash_table.h>
#include <omp.h>
+/* Syntactic sugar */
+#define ALL_COMPONENTS INVALID_ID
+#define ALL_SENSORS INVALID_ID
+
enum ray_interface_interaction_type {
RAY_INTERFACE_INTERACTION_REFLECTION, /* 0 */
RAY_INTERFACE_INTERACTION_TRANSMISSION, /* 1 */
@@ -49,9 +53,41 @@ enum ray_interface_interaction_type {
* Helper functions
******************************************************************************/
static res_T
-setup_MVREA_accums_surfaces
+setup_MVREA_surfaces_accum
(struct sphor* sphor,
- struct htable_accum2id *accum2id,
+ struct htable_accum2id* accum2id,
+ struct darray_accum* accums)
+{
+ size_t accum_id = 0;
+ res_T res = RES_OK;
+
+ ASSERT(NULL != sphor);
+ ASSERT(NULL != accum2id);
+ ASSERT(NULL != accums);
+
+ res = register_accum
+ (sphor->allocator, "LOSSES", "\0", "\0", accums);
+ if (RES_OK != res){ goto error; }
+ accum_id = darray_accum_size_get(accums) - 1;
+
+ /* Set corresponding entry in the accum2id hash table */
+ struct accum_key accum_key = ACCUM_KEY_NULL;
+ accum_key.sensor_type = SPHOR_SENSOR_SURFACE;
+ accum_key.sensor_id = INVALID_ID;
+ accum_key.component_id = INVALID_ID;
+ res = htable_accum2id_set(accum2id, &accum_key, &accum_id);
+ if (RES_OK != res){ goto error; }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+setup_MVREA_per_surface_accums
+ (struct sphor* sphor,
+ struct htable_accum2id* accum2id,
struct darray_accum* accums)
{
char* surface_name = NULL;
@@ -81,7 +117,7 @@ setup_MVREA_accums_surfaces
if (RES_OK != res){ goto error; }
res = register_accum
- (sphor->allocator, "LOSSES", surface_name, NULL, accums);
+ (sphor->allocator, "LOSSES", surface_name, "\0", accums);
if (RES_OK != res){ goto error; }
accum_id = darray_accum_size_get(accums) - 1;
@@ -101,7 +137,92 @@ error:
}
static res_T
-setup_MVREA_accums_volumes
+setup_MVREA_volumes_accum
+ (struct sphor* sphor,
+ struct htable_accum2id* accum2id,
+ struct darray_accum* accums)
+{
+ size_t accum_id = 0;
+ res_T res = RES_OK;
+
+ ASSERT(NULL != sphor);
+ ASSERT(NULL != accum2id);
+ ASSERT(NULL != accums);
+
+ res = register_accum
+ (sphor->allocator, "MVREA", "\0", "\0", accums);
+ if (RES_OK != res){ goto error; }
+ accum_id = darray_accum_size_get(accums) - 1;
+
+ /* Set corresponding entry in the accum2id hash table */
+ struct accum_key accum_key = ACCUM_KEY_NULL;
+ accum_key.sensor_type = SPHOR_SENSOR_VOLUME;
+ accum_key.sensor_id = INVALID_ID;
+ accum_key.component_id = INVALID_ID;
+ res = htable_accum2id_set(accum2id, &accum_key, &accum_id);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+setup_MVREA_per_volume_accums
+(struct sphor* sphor,
+ struct htable_accum2id* accum2id,
+ struct darray_accum* accums)
+{
+ char* volume_name = NULL;
+ size_t accum_id = 0;
+ size_t volume_count = 0;
+ size_t i_volume = 0;
+ struct sphin_config* config = sphor->config;
+ struct sphin_volume* volume = NULL;
+ struct sphin_sensor_volume* sensor = NULL;
+ res_T res = RES_OK;
+
+ ASSERT(NULL != sphor);
+ ASSERT(NULL != accum2id);
+ ASSERT(NULL != accums);
+
+ res = sphin_config_get_volume_count(config, &volume_count);
+ if (RES_OK != res){ goto error; }
+
+ FOR_EACH(i_volume, 0, volume_count){
+ res = sphin_config_get_volume(config, i_volume, &volume);
+ if (RES_OK != res){ goto error; }
+
+ res = sphin_volume_get_sensor(volume, &sensor);
+ if (RES_OK != res){ goto error; }
+ if (NULL != sensor) {
+ res = sphin_volume_get_name(volume, &volume_name);
+ if (RES_OK != res){ goto error; }
+
+ res = register_accum
+ (sphor->allocator, "MVREA", volume_name, "\0", accums);
+ if (RES_OK != res){ goto error; }
+ accum_id = darray_accum_size_get(accums) - 1;
+
+ /* Set corresponding entry in the accum2id hash table */
+ struct accum_key accum_key = ACCUM_KEY_NULL;
+ accum_key.sensor_type = SPHOR_SENSOR_VOLUME;
+ accum_key.sensor_id = i_volume;
+ accum_key.component_id = INVALID_ID;
+ res = htable_accum2id_set(accum2id, &accum_key, &accum_id);
+ if (RES_OK != res){ goto error; }
+
+ }
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+setup_MVREA_per_volume_component_accums
(struct sphor* sphor,
struct htable_accum2id *accum2id,
struct darray_accum* accums)
@@ -179,12 +300,25 @@ setup_MVREA_accums
ASSERT(NULL != sphor);
ASSERT(NULL != accums);
- res = setup_MVREA_accums_volumes(sphor, accum2id, accums);
+ /* Total MVREA in the scene */
+ res = setup_MVREA_volumes_accum(sphor, accum2id, accums);
+ if (RES_OK != res){ goto error; }
+
+ /* One accum per sensor volume; all components of the volume contribute to the accum */
+ res = setup_MVREA_per_volume_accums(sphor, accum2id, accums);
+ if (RES_OK != res){ goto error; }
+
+ /* One accum per component per sensor volume */
+ res = setup_MVREA_per_volume_component_accums(sphor, accum2id, accums);
if (RES_OK != res){ goto error; }
- res = setup_MVREA_accums_surfaces(sphor, accum2id, accums);
+ /* Total losses in the scene */
+ res = setup_MVREA_surfaces_accum(sphor, accum2id, accums);
if (RES_OK != res){ goto error; }
+ /* One accum per sensor surface */
+ res = setup_MVREA_per_surface_accums(sphor, accum2id, accums);
+ if (RES_OK != res){ goto error; }
exit:
return res;
error:
@@ -681,302 +815,9 @@ error:
goto exit;
}
-/*******************************************************************************
- * Write volumes
- ******************************************************************************/
-static res_T
-MVREA_aggregate_vol_accums
- (struct sphor* sphor,
- const struct htable_accum2id* accum2id,
- const struct darray_accum* accums,
- size_t i_volume,
- struct darray_accum* vol_accums)
-{
- char* volume_name;
- size_t j_proprad = 0;
- size_t prop_rad_count = 0;
- size_t* paccum_id = NULL;
- struct accum* accum = NULL;
- struct accum vol_accum = ACCUM_NULL;
- struct accum_key accum_key = ACCUM_KEY_NULL;
- struct sphin_volume* volume = NULL;
- res_T res = RES_OK;
-
- ASSERT(NULL != sphor);
- ASSERT(NULL != accum2id);
- ASSERT(NULL != accums);
- ASSERT(NULL != vol_accums);
-
- accum_init(sphor->allocator, &vol_accum);
-
- res = sphin_config_get_volume(sphor->config, i_volume, &volume);
- if (RES_OK != res){ goto error; }
-
- res = sphin_volume_get_name(volume, &volume_name);
- if (RES_OK != res){ goto error; }
-
- res = sphin_volume_get_prop_rad_count(volume, &prop_rad_count);
- if (RES_OK != res){ goto error; }
-
- str_set(&vol_accum.observable, "MVREA");
- str_set(&vol_accum.sensor, volume_name);
-
- FOR_EACH(j_proprad, 0, prop_rad_count){
- accum_key.sensor_type = SPHOR_SENSOR_VOLUME;
- accum_key.sensor_id = i_volume;
- accum_key.component_id = j_proprad;
- paccum_id = htable_accum2id_find
- ((struct htable_accum2id *)accum2id, &accum_key);
- ASSERT(NULL != paccum_id);
-
- accum = (struct accum*)&darray_accum_cdata_get(accums)[*paccum_id];
- accum_add(&vol_accum, accum, &vol_accum);
- }
- res = darray_accum_push_back(vol_accums, &vol_accum);
- if (RES_OK != res){ goto error; }
-
-exit:
- accum_release(&vol_accum);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-MVREA_aggregate_vols_accums
- (struct sphor* sphor,
- const struct htable_accum2id* accum2id,
- const struct darray_accum* accums,
- struct darray_accum* vol_accums)
-{
- size_t volume_count = 0;
- size_t i_volume = 0;
- struct sphin_config* config = sphor->config;
- struct sphin_volume* volume = NULL;
- struct sphin_sensor_volume* sensor = NULL;
- res_T res = RES_OK;
-
- ASSERT(NULL != sphor);
- ASSERT(NULL != accum2id);
- ASSERT(NULL != accums);
- ASSERT(NULL != vol_accums);
-
- res = sphin_config_get_volume_count(config, &volume_count);
- if (RES_OK != res){ goto error; }
-
- FOR_EACH(i_volume, 0, volume_count){
- res = sphin_config_get_volume(config, i_volume, &volume);
- if (RES_OK != res){ goto error; }
-
- res = sphin_volume_get_sensor(volume, &sensor);
- if (RES_OK != res){ goto error; }
- if (NULL != sensor) {
- res = MVREA_aggregate_vol_accums
- (sphor, accum2id, accums, i_volume, vol_accums);
- if (RES_OK != res){ goto error; }
- }
- }
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-MVREA_write_volumes_outputs
- (struct sphor* sphor,
- const struct htable_accum2id* accum2id,
- const struct darray_accum* accums,
- size_t samples,
- FILE* stream)
-{
- size_t i = 0;
- struct accum* accum = NULL;
- struct accum tot_accum = ACCUM_NULL;
- struct darray_accum vols_accums;
- res_T res = RES_OK;
-
- ASSERT(NULL != sphor);
- ASSERT(NULL != accum2id);
- ASSERT(NULL != accums);
- ASSERT(NULL != stream);
-
- accum_init(sphor->allocator, &tot_accum);
- darray_accum_init(sphor->allocator, &vols_accums);
- res = MVREA_aggregate_vols_accums(sphor, accum2id, accums, &vols_accums);
- if (RES_OK != res){ goto error; }
-
- sum_accums(&vols_accums, &tot_accum);
-
- res = str_set(&tot_accum.observable, "MVREA");
- if (RES_OK != res){ goto error; }
- tot_accum.n_realizations = samples;
-
- write_accum_estim(&tot_accum, stream);
-
- accum = darray_accum_data_get(&vols_accums);
- FOR_EACH(i, 0, darray_accum_size_get(&vols_accums)){
- accum += i;
- accum->n_realizations = samples;
- write_accum_estim(accum, stream);
- }
-
-exit:
- accum_release(&tot_accum);
- darray_accum_release(&vols_accums);
- return res;
-error:
- goto exit;
-}
-
-/*******************************************************************************
- * Write surfaces
- ******************************************************************************/
-static res_T
-MVREA_aggregate_surf_accums
- (struct sphor* sphor,
- const struct htable_accum2id* accum2id,
- const struct darray_accum* accums,
- size_t i_surface,
- struct darray_accum* surf_accums)
-{
- char* surface_name;
- size_t j_proprad = 0;
- size_t* paccum_id = NULL;
- struct accum* accum = NULL;
- struct accum surf_accum = ACCUM_NULL;
- struct accum_key accum_key = ACCUM_KEY_NULL;
- struct sphin_surface* surface = NULL;
- res_T res = RES_OK;
-
- ASSERT(NULL != sphor);
- ASSERT(NULL != accum2id);
- ASSERT(NULL != accums);
- ASSERT(NULL != surf_accums);
-
- accum_init(sphor->allocator, &surf_accum);
-
- res = sphin_config_get_surface(sphor->config, i_surface, &surface);
- if (RES_OK != res){ goto error; }
-
- res = sphin_surface_get_name(surface, &surface_name);
- if (RES_OK != res){ goto error; }
-
- str_set(&surf_accum.observable, "LOSSES");
- str_set(&surf_accum.sensor, surface_name);
-
- accum_key.sensor_type = SPHOR_SENSOR_VOLUME;
- accum_key.sensor_id = i_surface;
- accum_key.component_id = j_proprad;
- paccum_id = htable_accum2id_find
- ((struct htable_accum2id *)accum2id, &accum_key);
- ASSERT(NULL != paccum_id);
-
- accum = (struct accum*)&darray_accum_cdata_get(accums)[*paccum_id];
- accum_add(&surf_accum, accum, &surf_accum);
-
- res = darray_accum_push_back(surf_accums, &surf_accum);
- if (RES_OK != res){ goto error; }
-
-exit:
- accum_release(&surf_accum);
- return res;
-error:
- goto exit;
-}
-
-static res_T
-MVREA_aggregate_surfs_accums
- (struct sphor* sphor,
- const struct htable_accum2id* accum2id,
- const struct darray_accum* accums,
- struct darray_accum* surfs_accums)
-{
- size_t surface_count = 0;
- size_t i_surface = 0;
- struct sphin_config* config = sphor->config;
- struct sphin_surface* surface = NULL;
- struct sphin_sensor_surface* sensor = NULL;
- res_T res = RES_OK;
-
- ASSERT(NULL != sphor);
- ASSERT(NULL != accum2id);
- ASSERT(NULL != accums);
- ASSERT(NULL != surfs_accums);
-
- res = sphin_config_get_surface_count(config, &surface_count);
- if (RES_OK != res){ goto error; }
-
- FOR_EACH(i_surface, 0, surface_count){
- res = sphin_config_get_surface(config, i_surface, &surface);
- if (RES_OK != res){ goto error; }
-
- res = sphin_surface_get_sensor(surface, &sensor);
- if (RES_OK != res){ goto error; }
- if (NULL != sensor) {
- res = MVREA_aggregate_surf_accums
- (sphor, accum2id, accums, i_surface, surfs_accums);
- if (RES_OK != res){ goto error; }
- }
- }
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-MVREA_write_surfaces_outputs
- (struct sphor* sphor,
- const struct htable_accum2id* accum2id,
- const struct darray_accum* accums,
- size_t samples,
- FILE* stream)
-{
- size_t i = 0;
- struct accum* accum = NULL;
- struct accum tot_accum = ACCUM_NULL;
- struct darray_accum surf_accums;
- res_T res = RES_OK;
-
- ASSERT(NULL != sphor);
- ASSERT(NULL != accum2id);
- ASSERT(NULL != accums);
- ASSERT(NULL != stream);
-
- accum_init(sphor->allocator, &tot_accum);
- darray_accum_init(sphor->allocator, &surf_accums);
- res = MVREA_aggregate_surfs_accums(sphor, accum2id, accums, &surf_accums);
- if (RES_OK != res){ goto error; }
-
- sum_accums(&surf_accums, &tot_accum);
-
- res = str_set(&tot_accum.observable, "LOSSES");
- if (RES_OK != res){ goto error; }
-
- tot_accum.n_realizations = samples;
-
- write_accum_estim(&tot_accum, stream);
-
- accum = darray_accum_data_get(&surf_accums);
- FOR_EACH(i, 0, darray_accum_size_get(&surf_accums)){
- accum += i;
- accum->n_realizations = samples;
- write_accum_estim(accum, stream);
- }
-
-exit:
- accum_release(&tot_accum);
- darray_accum_release(&surf_accums);
- return res;
-error:
- goto exit;
-}
-
static res_T
MVREA_write_outputs
(struct sphor* sphor,
- const struct htable_accum2id* accum2id,
const struct darray_accum* accums,
size_t nfailures)
{
@@ -986,28 +827,17 @@ MVREA_write_outputs
res_T res = RES_OK;
ASSERT(NULL != sphor);
- ASSERT(NULL != accum2id);
ASSERT(NULL != accums);
samples = sphor->samples - nfailures;
- res = MVREA_write_volumes_outputs(sphor, accum2id, accums, samples, sphor->stream);
- if (RES_OK != res){ goto error; }
-
- res = MVREA_write_surfaces_outputs(sphor, accum2id, accums, samples, sphor->stream);
- if (RES_OK != res){ goto error; }
-
- accum = (struct accum*)darray_accum_cdata_get(accums);
FOR_EACH(i, 0, darray_accum_size_get(accums)){
- accum += i;
+ accum = (struct accum*)darray_accum_cdata_get(accums) + i;
accum->n_realizations = samples;
write_accum_estim(accum, sphor->stream);
}
-exit:
return res;
-error:
- goto exit;
}
static res_T
@@ -1026,7 +856,6 @@ compute_MVREA_realization
enum ray_interface_interaction_type ray_interface_interaction_type =
RAY_INTERFACE_INTERACTION_NONE__;
enum sphin_side side_id = SPHIN_SIDE_NONE__;
- struct accum_key accum_key = ACCUM_KEY_NULL;
struct interface interface = INTERFACE_NULL;
struct s3d_hit hit = S3D_HIT_NULL;
struct s3d_primitive prim = S3D_PRIMITIVE_NULL;
@@ -1084,21 +913,55 @@ compute_MVREA_realization
/* Check if the volume is a sensor */
res = sphin_volume_get_sensor(volume, &sensor_volume);
if (RES_OK != res){ goto error; }
- /* TODO Increment the weight of each chemical species in the volume by
- * ( ka_i / ka_tot ) response_function */
-
/* If the volume is a sensor, compute the weight using the response
* function */
if (NULL != sensor_volume) {
+
+ struct accum_key accum_key = ACCUM_KEY_NULL;
+ size_t prop_rad_count = 0;
+ size_t i_proprad = 0;
+ double vol = 0;
+ double tot_pow = 0;
+ double mc_weight = 0;
+
res = sphin_sensor_volume_get_response_function
(sensor_volume, &response_function);
if (RES_OK != res){ goto error; }
+ res = sphin_volume_compute_total_volume(volume, &vol);
+ if (RES_OK != res){ goto error; }
+ res = sphin_config_get_total_surface_power(sphor->config, &tot_pow);
+ if (RES_OK != res){ goto error; }
+ res = sphin_volume_get_prop_rad_count(volume, &prop_rad_count);
+ if (RES_OK != res){ goto error; }
+
+ mc_weight = tot_pow / vol;
+
+ /* Update total accumulator for all volumes in the scene*/
+ accum_key.sensor_type = SPHOR_SENSOR_VOLUME;
+ accum_key.sensor_id = ALL_SENSORS;
+ accum_key.component_id = ALL_COMPONENTS;
+ update_accum(accum2id, &accum_key, mc_weight, accums);
- /* Update accumulator corresponding to the photon absortion */
+ /* Update total accumulator in the volume */
accum_key.sensor_type = SPHOR_SENSOR_VOLUME;
accum_key.sensor_id = interface.volumes[side_id];
- accum_key.component_id = 0; /* TODO HARD CODED TO TEST: CHANGE IT */
- update_accum(accum2id, &accum_key, response_function, accums);
+ accum_key.component_id = ALL_COMPONENTS;
+ update_accum(accum2id, &accum_key, mc_weight, accums);
+
+ /* Increment the weight of each chemical species in the volume by
+ * ( ka_i / ka_tot ) response_function */
+ FOR_EACH(i_proprad, 0, prop_rad_count) {
+ double ka_i = 0;
+ struct sphin_prop_rad* prop_rad = NULL;
+ res = sphin_volume_get_prop_rad(volume, i_proprad, &prop_rad);
+ if (RES_OK != res){ goto error; }
+ res = prop_rad_compute_ka(prop_rad, wavelength, &ka_i);
+ if (RES_OK != res){ goto error; }
+ accum_key.component_id = i_proprad;
+
+ mc_weight = ka_i / ka * tot_pow / vol;
+ update_accum(accum2id, &accum_key, mc_weight, accums);
+ }
}
/* If the volume is not a sensor, the absorbed photon does not count in
* the weight. The weight is implictly 0 */
@@ -1257,7 +1120,7 @@ sphor_compute_MVREA
/* Aggregate accums from the different threads in the main accumulator */
sum_accum_lists(&accums_threads, &accums);
- res = MVREA_write_outputs(sphor, &accum2id, &accums, nfailures);
+ res = MVREA_write_outputs(sphor, &accums, nfailures);
if (res != RES_OK) { goto error; }
exit:
diff --git a/src/sphor_config.c b/src/sphor_config.c
@@ -303,11 +303,12 @@ setup_interface_surface_geometry_triangle
surf_count = interface->surface_count[side];
if(MAX_SURFACE_COUNT <= surf_count) {
- ERROR(sphor,
- "Too many surfaces on the same side of interface defined by triangle from file '%s'. "
- "Maximum allowed: %d\n",
- geom_desc->filename, MAX_SURFACE_COUNT);
- goto error;
+ ERROR(sphor,
+ "Too many surfaces on the same side of interface defined by triangle from file '%s'. "
+ "Maximum allowed: %d\n",
+ geom_desc->filename, MAX_SURFACE_COUNT);
+ res = RES_MEM_ERR;
+ goto error;
}
interface->surfaces[side][surf_count] = isurface;
interface->surface_count[side] += 1;