commit cf24c2bb68478e17b329006d514692e3022a571e
parent 86e4bffd6bcc4fd7f5c441485f6da04ebc52fbf9
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 23 Jul 2024 15:42:50 +0200
Correction of flux calculation at boundaries
The flux calculation failed on the surfaces defining the boundaries of a
multi-fluid enclosure. Until now, we calculated the fluid temperature by
sampling a convective path on the ‘fluid’ enclosure. But it is not
possible to sample such a path because it is impossible to determine the
fluid in the enclosure since there are several of them. In other words,
this enclosure is beyond the limit of the space of convective paths. In
fact, defining several media amounts to defining a set of boundary
conditions, where each fluid stores the temperature of one of Robin's
boundary conditions. It is therefore normal to prohibit the sampling of
convective paths in these enclosures since such path does not exist.
But it is still legitimate to want to calculate the convective flux on
such boundaries. Therefore, this commit updates the way in which the
fluid temperature is calculated for a convective flux calculation.
Before sampling a convective path, we first check whether the
temperature of the fluid around the current boundary is known, i.e.
whether it is a boundary condition beyond which a convective path cannot
be sampled.
Note that the flux calculation test has been updated to highlight this
problem and ensure that it is now corrected.
Diffstat:
5 files changed, 105 insertions(+), 65 deletions(-)
diff --git a/src/sdis_heat_path_boundary_Xd.h b/src/sdis_heat_path_boundary_Xd.h
@@ -25,58 +25,6 @@
#include "sdis_Xd_begin.h"
/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-/* This function checks whether the random walk is on a boundary and, if so,
- * verifies that the temperature of the medium attached to the interface is
- * known. This medium can be different from the medium of the enclosure. Indeed,
- * the enclosure can contain several media used to set the temperatures of
- * several boundary conditions. Hence this function, which queries the medium on
- * the trajectory coming from a boundary */
-static res_T
-XD(handle_known_medium_temperature)
- (struct sdis_scene* scn,
- struct rwalk_context* ctx,
- struct rwalk* rwalk,
- struct temperature* T)
-{
- struct sdis_interface* interf = NULL;
- struct sdis_medium* mdm = NULL;
- double temperature = SDIS_TEMPERATURE_NONE;
- res_T res = RES_OK;
- ASSERT(scn && ctx && rwalk && T);
-
- /* Not at an interface */
- if(SXD_HIT_NONE(&rwalk->XD(hit))) return RES_OK; /* Nothing to do */
-
- interf = scene_get_interface(scn, rwalk->XD(hit).prim.prim_id);
- mdm = rwalk->hit_side==SDIS_FRONT ? interf->medium_front: interf->medium_back;
-
- temperature = medium_get_temperature(mdm, &rwalk->vtx);
-
- /* Check if the temperature is known */
- if(SDIS_TEMPERATURE_IS_UNKNOWN(temperature)) goto exit;
-
- T->value += temperature;
- T->done = 1;
-
- if(ctx->green_path) {
- res = green_path_set_limit_vertex
- (ctx->green_path, mdm, &rwalk->vtx, rwalk->elapsed_time);
- if(res != RES_OK) goto error;
- }
-
- if(ctx->heat_path) {
- heat_path_get_last_vertex(ctx->heat_path)->weight = T->value;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-/*******************************************************************************
* Local functions
******************************************************************************/
res_T
@@ -135,7 +83,6 @@ XD(boundary_path)
}
if(res != RES_OK) goto error;
-#if 1
if(T->done) goto exit;
/* Handling limit boundary condition, i.e. the trajectory originates from a
@@ -155,11 +102,10 @@ XD(boundary_path)
* computationally, and in fact it's also a handy way of testing
* border cases */
if(T->func == XD(convective_path) || T->func == XD(conductive_path)) {
- res = XD(handle_known_medium_temperature)(scn, ctx, rwalk, T);
+ res = XD(query_medium_temperature_from_boundary)(scn, ctx, rwalk, T);
if(res != RES_OK) goto error;
if(T->done) goto exit; /* That's all folks */
}
-#endif
exit:
return res;
diff --git a/src/sdis_heat_path_boundary_Xd_c.h b/src/sdis_heat_path_boundary_Xd_c.h
@@ -1138,4 +1138,53 @@ XD(check_Tref)
return RES_OK;
}
+/* This function checks whether the random walk is on a boundary and, if so,
+ * verifies that the temperature of the medium attached to the interface is
+ * known. This medium can be different from the medium of the enclosure. Indeed,
+ * the enclosure can contain several media used to set the temperatures of
+ * several boundary conditions. Hence this function, which queries the medium on
+ * the path coming from a boundary */
+res_T
+XD(query_medium_temperature_from_boundary)
+ (struct sdis_scene* scn,
+ struct rwalk_context* ctx,
+ struct rwalk* rwalk,
+ struct temperature* T)
+{
+ struct sdis_interface* interf = NULL;
+ struct sdis_medium* mdm = NULL;
+ double temperature = SDIS_TEMPERATURE_NONE;
+ res_T res = RES_OK;
+ ASSERT(scn && ctx && rwalk && T);
+
+ /* Not at an interface */
+ if(SXD_HIT_NONE(&rwalk->XD(hit))) return RES_OK; /* Nothing to do */
+
+ interf = scene_get_interface(scn, rwalk->XD(hit).prim.prim_id);
+ mdm = rwalk->hit_side==SDIS_FRONT ? interf->medium_front: interf->medium_back;
+
+ temperature = medium_get_temperature(mdm, &rwalk->vtx);
+
+ /* Check if the temperature is known */
+ if(SDIS_TEMPERATURE_IS_UNKNOWN(temperature)) goto exit;
+
+ T->value += temperature;
+ T->done = 1;
+
+ if(ctx->green_path) {
+ res = green_path_set_limit_vertex
+ (ctx->green_path, mdm, &rwalk->vtx, rwalk->elapsed_time);
+ if(res != RES_OK) goto error;
+ }
+
+ if(ctx->heat_path) {
+ heat_path_get_last_vertex(ctx->heat_path)->weight = T->value;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
#include "sdis_Xd_end.h"
diff --git a/src/sdis_heat_path_boundary_c.h b/src/sdis_heat_path_boundary_c.h
@@ -204,6 +204,24 @@ check_Tref_3d
const double Tref,
const char* call_func_name);
+/* Query medium temperature from the boundary. This medium can be different
+ * from the medium of the enclosure. Hence this function, which queries the
+ * medium on the path coming from a boundary. If the temperature is known, T is
+ * set to done. */
+extern LOCAL_SYM res_T
+query_medium_temperature_from_boundary_2d
+ (struct sdis_scene* scn,
+ struct rwalk_context* ctx,
+ struct rwalk* rwalk,
+ struct temperature* T);
+
+extern LOCAL_SYM res_T
+query_medium_temperature_from_boundary_3d
+ (struct sdis_scene* scn,
+ struct rwalk_context* ctx,
+ struct rwalk* rwalk,
+ struct temperature* T);
+
/*******************************************************************************
* Boundary sub-paths
******************************************************************************/
diff --git a/src/sdis_realisation_Xd.h b/src/sdis_realisation_Xd.h
@@ -15,6 +15,7 @@
#include "sdis_device_c.h"
#include "sdis_heat_path.h"
+#include "sdis_heat_path_boundary_c.h"
#include "sdis_interface_c.h"
#include "sdis_log.h"
#include "sdis_medium_c.h"
@@ -449,10 +450,28 @@ XD(boundary_flux_realisation)
/* Compute fluid temperature */
if(compute_convective) {
RESET_WALK(fluid_side, enc_ids[fluid_side]);
- T.func = XD(convective_path);
- res = XD(sample_coupled_path)(scn, &ctx, &rwalk, args->rng, &T);
+
+ /* Check whether the temperature of the fluid is known by querying it from
+ * its boundary. This makes it possible to handle situations where fluids
+ * are used as Robin's boundary condition. In this case, a geometric
+ * enclosure may have several fluids, each defining the temperature of a
+ * boundary condition. Sampling of convective paths in such an enclosure is
+ * forbidden since this enclosure does not exist for this path space: it is
+ * beyond its boundary */
+ res = XD(query_medium_temperature_from_boundary)(scn, &ctx, &rwalk, &T);
if(res != RES_OK) return res;
- result->Tfluid = T.value;
+
+ /* Robin's boundary condition */
+ if(T.done) {
+ result->Tfluid = T.value;
+
+ /* Sample a convective path */
+ } else {
+ T.func = XD(convective_path);
+ res = XD(sample_coupled_path)(scn, &ctx, &rwalk, args->rng, &T);
+ if(res != RES_OK) return res;
+ result->Tfluid = T.value;
+ }
}
#undef SET_PARAM
diff --git a/src/test_sdis_solve_boundary_flux.c b/src/test_sdis_solve_boundary_flux.c
@@ -266,7 +266,8 @@ main(int argc, char** argv)
{
struct sdis_data* data = NULL;
struct sdis_device* dev = NULL;
- struct sdis_medium* fluid = NULL;
+ struct sdis_medium* fluid1 = NULL;
+ struct sdis_medium* fluid2 = NULL;
struct sdis_medium* solid = NULL;
struct sdis_interface* interf_adiabatic = NULL;
struct sdis_interface* interf_Tb = NULL;
@@ -299,13 +300,19 @@ main(int argc, char** argv)
create_default_device(&argc, &argv, &is_master_process, &dev);
radenv = create_radenv(dev);
- /* Create the fluid medium */
+ /* Create the fluid medium. In fact, create two fluid media, even if they are
+ * identical, to check that Robin's boundary conditions can be defined with
+ * several media, without compromising path sampling. Convective paths cannot
+ * be sampled in enclosures with several media, but radiative paths can be,
+ * and it should be possible to calculate the boundary flux without any
+ * problem */
OK(sdis_data_create
(dev, sizeof(struct fluid), ALIGNOF(struct fluid), NULL, &data));
fluid_args = sdis_data_get(data);
fluid_args->temperature = Tf;
fluid_shader.temperature = fluid_get_temperature;
- OK(sdis_fluid_create(dev, &fluid_shader, data, &fluid));
+ OK(sdis_fluid_create(dev, &fluid_shader, data, &fluid1));
+ OK(sdis_fluid_create(dev, &fluid_shader, data, &fluid2));
OK(sdis_data_ref_put(data));
/* Create the solid_medium */
@@ -329,7 +336,7 @@ main(int argc, char** argv)
interf_props->temperature = SDIS_TEMPERATURE_NONE;
interf_props->emissivity = 0;
OK(sdis_interface_create
- (dev, solid, fluid, &interf_shader, data, &interf_adiabatic));
+ (dev, solid, fluid1, &interf_shader, data, &interf_adiabatic));
OK(sdis_data_ref_put(data));
/* Create the Tb interface */
@@ -342,7 +349,7 @@ main(int argc, char** argv)
interf_shader.back.emissivity = interface_get_emissivity;
interf_shader.back.reference_temperature = interface_get_reference_temperature;
OK(sdis_interface_create
- (dev, solid, fluid, &interf_shader, data, &interf_Tb));
+ (dev, solid, fluid1, &interf_shader, data, &interf_Tb));
interf_shader.back.emissivity = NULL;
OK(sdis_data_ref_put(data));
@@ -356,13 +363,14 @@ main(int argc, char** argv)
interf_shader.back.emissivity = interface_get_emissivity;
interf_shader.back.reference_temperature = interface_get_reference_temperature;
OK(sdis_interface_create
- (dev, solid, fluid, &interf_shader, data, &interf_H));
+ (dev, solid, fluid2, &interf_shader, data, &interf_H));
interf_shader.back.emissivity = NULL;
OK(sdis_data_ref_put(data));
/* Release the media */
OK(sdis_medium_ref_put(solid));
- OK(sdis_medium_ref_put(fluid));
+ OK(sdis_medium_ref_put(fluid1));
+ OK(sdis_medium_ref_put(fluid2));
/* Map the interfaces to their box triangles */
box_interfaces[0] = box_interfaces[1] = interf_adiabatic; /* Front */