stardis-solver

Solve coupled heat transfers
git clone git://git.meso-star.fr/stardis-solver.git
Log | Files | Refs | README | LICENSE

commit 6389937a6eaa279d45175b0d9ee5ba9852247218
parent b7e3fba6d3d04c3eb4813876ced3822ef070a409
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 25 Oct 2021 08:52:24 +0200

Rewrite some bondary helper functions

Rewrite of the functions that define a valid reinjection ray, i.e. a
a valid direction and a valid reinjection distance along it.

Diffstat:
Msrc/sdis_heat_path_boundary_Xd_c.h | 414++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 222 insertions(+), 192 deletions(-)

diff --git a/src/sdis_heat_path_boundary_Xd_c.h b/src/sdis_heat_path_boundary_Xd_c.h @@ -25,10 +25,49 @@ #include "sdis_Xd_begin.h" +struct XD(find_reinjection_ray_args) { + const struct sdis_medium* solid; /* Medium into which the reinjection occurs */ + const struct XD(rwalk)* rwalk; /* Current random walk state */ + float dir0[DIM]; /* Challenged ray direction */ + float dir1[DIM]; /* Challenged ray direction */ + double distance; /* Maximum reinjection distance */ + + /* Define if the random walk position can be moved or not to find a valid + * reinjection direction */ + int can_move; +}; +static const struct XD(find_reinjection_ray_args) +XD(FIND_REINJECTION_RAY_ARGS_NULL) = { NULL, NULL, {0}, {0}, 0, 0 }; + +struct XD(reinjection_ray) { + double org[DIM]; /* Origin of the reinjection */ + float dir[DIM]; /* Direction of the reinjection */ + float dst; /* Reinjection distance along dir */ + struct sXd(hit) hit; /* Hit along the reinjection dir */ + + /* Define whether or not the random walk was moved to find this reinjection + * ray */ + int position_was_moved; +}; +static const struct XD(reinjection_ray) +XD(REINJECTION_RAY_NULL) = { {0}, {0}, 0, SXD_HIT_NULL__, 0 }; + /******************************************************************************* * Helper functions ******************************************************************************/ static INLINE int +XD(check_find_reinjection_ray_args) + (const struct XD(find_reinjection_ray_args)* args) +{ + return args + && args->solid + && args->rwalk + && args->distance > 0 + && fX(is_normalized)(args->dir0) + && fX(is_normalized)(args->dir1); +} + +static INLINE int XD(check_sample_reinjection_step_args) (const struct XD(sample_reinjection_step_args)* args) { @@ -141,8 +180,9 @@ XD(sample_reinjection_dir) #if DIM == 2 static void XD(move_away_primitive_boundaries) - (struct XD(rwalk)* rwalk, - const double delta) + (const struct XD(rwalk)* rwalk, + const double delta, + double position[DIM]) /* Position to move */ { struct sXd(attrib) attr; float pos[DIM]; @@ -153,20 +193,21 @@ XD(move_away_primitive_boundaries) SXD(primitive_get_attrib(&rwalk->hit.prim, SXD_POSITION, st, &attr)); - fX_set_dX(pos, rwalk->vtx.P); + fX_set_dX(pos, position); fX(sub)(dir, attr.value, pos); len = fX(normalize)(dir, dir); len = MMIN(len, (float)(delta*0.1)); - XD(move_pos)(rwalk->vtx.P, dir, len); + XD(move_pos)(position, dir, len); } #else -/* Move the random walk away from the primitive boundaries to avoid numerical - * issues leading to inconsistent random walks. */ +/* Move the submitted position away from the primitive boundaries to avoid + * numerical issues leading to inconsistent random walks. */ static void XD(move_away_primitive_boundaries) - (struct XD(rwalk)* rwalk, - const double delta) + (const struct XD(rwalk)* rwalk, + const double delta, + double position[DIM]) { struct s3d_attrib v0, v1, v2; /* Triangle vertices */ float E[3][4]; /* 3D edge equations */ @@ -183,7 +224,7 @@ XD(move_away_primitive_boundaries) int i; ASSERT(rwalk && delta > 0 && !S3D_HIT_NONE(&rwalk->hit)); - fX_set_dX(P, rwalk->vtx.P); + fX_set_dX(P, position); /* Fetch triangle vertices */ S3D(triangle_get_vertex_attrib(&rwalk->hit.prim, 0, S3D_POSITION, &v0)); @@ -255,23 +296,15 @@ XD(move_away_primitive_boundaries) /* Define the displacement distance as the minimum between 10 percent of * delta and len / 2. */ len = MMIN(len*0.5f, (float)(delta*0.1)); - XD(move_pos)(rwalk->vtx.P, E[imin], len); + XD(move_pos)(position, E[imin], len); } #endif static res_T -XD(select_reinjection_dir) +XD(find_reinjection_ray) (const struct sdis_scene* scn, - const struct sdis_medium* mdm, /* Medium into which the reinjection occurs */ - struct XD(rwalk)* rwalk, /* Current random walk state */ - const float dir0[DIM], /* Challenged direction */ - const float dir1[DIM], /* Challanged direction */ - const double delta, /* Max reinjection distance */ - float reinject_dir[DIM], /* Selected direction */ - float* reinject_dst, /* Effective reinjection distance */ - int can_move, /* Define of the random wal pos can be moved or not */ - int* move_pos, /* Define if the current random walk was moved. May be NULL */ - struct sXd(hit)* reinject_hit) /* Hit along the reinjection dir */ + const struct XD(find_reinjection_ray_args)* args, + struct XD(reinjection_ray)* ray) { /* Emperical scale factor applied to the challenged reinjection distance. If * the distance to reinject is less than this adjusted value, the solver will @@ -279,81 +312,89 @@ XD(select_reinjection_dir) * numerical issues. */ const float REINJECT_DST_MIN_SCALE = 0.125f; + /* # attempts to find a ray direction */ + int MAX_ATTEMPTS = 1; + + /* Physical properties */ struct sdis_interface* interf; struct sdis_medium* mdm0; struct sdis_medium* mdm1; + struct hit_filter_data filter_data; struct sXd(hit) hit; struct sXd(hit) hit0; struct sXd(hit) hit1; - double rwalk_pos_backup[DIM]; double tmp[DIM]; double dst; double dst0; double dst1; - const double delta_adjusted = delta * RAY_RANGE_MAX_SCALE; const float* dir; - const float reinject_threshold = (float)delta * REINJECT_DST_MIN_SCALE; + float reinject_threshold; + double dst_adjusted; float org[DIM]; - float range[2]; + const float range[2] = {0, FLT_MAX}; enum sdis_side side; int iattempt = 0; - const int MAX_ATTEMPTS = can_move ? 2 : 1; res_T res = RES_OK; - ASSERT(scn && mdm && rwalk && dir0 && dir1 && delta > 0); - ASSERT(reinject_dir && reinject_dst && reinject_hit); - /* Save the submitted position to restore it if an error occurs */ - dX(set)(rwalk_pos_backup, rwalk->vtx.P); + ASSERT(scn && args && ray); + ASSERT(XD(check_find_reinjection_ray_args)(args)); + + *ray = XD(REINJECTION_RAY_NULL); + MAX_ATTEMPTS = args->can_move ? 2 : 1; - if(move_pos) *move_pos = 0; + dst_adjusted = args->distance * RAY_RANGE_MAX_SCALE; + reinject_threshold = (float)args->distance * REINJECT_DST_MIN_SCALE; + + dX(set)(ray->org, args->rwalk->vtx.P); do { - f2(range, 0, FLT_MAX); - fX_set_dX(org, rwalk->vtx.P); - filter_data.XD(hit) = rwalk->hit; - filter_data.epsilon = delta * 0.01; - SXD(scene_view_trace_ray(scn->sXd(view), org, dir0, range, &filter_data, &hit0)); - SXD(scene_view_trace_ray(scn->sXd(view), org, dir1, range, &filter_data, &hit1)); + fX_set_dX(org, ray->org); + filter_data.XD(hit) = args->rwalk->hit; + filter_data.epsilon = args->distance * 0.01; + SXD(scene_view_trace_ray + (scn->sXd(view), org, args->dir0, range, &filter_data, &hit0)); + SXD(scene_view_trace_ray + (scn->sXd(view), org, args->dir1, range, &filter_data, &hit1)); /* Retrieve the medium at the reinjection pos along dir0 */ if(SXD_HIT_NONE(&hit0)) { - XD(move_pos)(dX(set)(tmp, rwalk->vtx.P), dir0, (float)delta); + XD(move_pos)(dX(set)(tmp, ray->org), args->dir0, (float)args->distance); res = scene_get_medium_in_closed_boundaries(scn, tmp, &mdm0); if(res == RES_BAD_OP) { mdm0 = NULL; res = RES_OK; } if(res != RES_OK) goto error; } else { interf = scene_get_interface(scn, hit0.prim.prim_id); - side = fX(dot)(dir0, hit0.normal) < 0 ? SDIS_FRONT : SDIS_BACK; + side = fX(dot)(args->dir0, hit0.normal) < 0 ? SDIS_FRONT : SDIS_BACK; mdm0 = interface_get_medium(interf, side); } /* Retrieve the medium at the reinjection pos along dir1 */ if(SXD_HIT_NONE(&hit1)) { - XD(move_pos)(dX(set)(tmp, rwalk->vtx.P), dir1, (float)delta); + XD(move_pos)(dX(set)(tmp, ray->org), args->dir1, (float)args->distance); res = scene_get_medium_in_closed_boundaries(scn, tmp, &mdm1); if(res == RES_BAD_OP) { mdm1 = NULL; res = RES_OK; } if(res != RES_OK) goto error; } else { interf = scene_get_interface(scn, hit1.prim.prim_id); - side = fX(dot)(dir1, hit1.normal) < 0 ? SDIS_FRONT : SDIS_BACK; + side = fX(dot)(args->dir1, hit1.normal) < 0 ? SDIS_FRONT : SDIS_BACK; mdm1 = interface_get_medium(interf, side); } dst0 = dst1 = -1; - if(mdm0 == mdm) { /* Check reinjection consistency */ - if(hit0.distance <= delta_adjusted) { + if(mdm0 == args->solid) { /* Check reinjection consistency */ + if(hit0.distance <= dst_adjusted) { dst0 = hit0.distance; } else { - dst0 = delta; + dst0 = args->distance; hit0 = SXD_HIT_NULL; } } - if(mdm1 == mdm) {/* Check reinjection consistency */ - if(hit1.distance <= delta_adjusted) { + if(mdm1 == args->solid) { /* Check reinjection consistency */ + if(hit1.distance <= dst_adjusted) { dst1 = hit1.distance; } else { - dst1 = delta; + dst1 = args->distance; hit1 = SXD_HIT_NULL; } } @@ -367,26 +408,26 @@ XD(select_reinjection_dir) * both situations, try to slightly move away from the primitive boundaries * and retry to find a valid reinjection. */ if(dst0 == -1 && dst1 == -1) { - XD(move_away_primitive_boundaries)(rwalk, delta); - if(move_pos) *move_pos = 1; + XD(move_away_primitive_boundaries)(args->rwalk, args->distance, ray->org); + ray->position_was_moved = 1; } } while(dst0 == -1 && dst1 == -1 && ++iattempt < MAX_ATTEMPTS); if(dst0 == -1 && dst1 == -1) { /* No valid reinjection */ log_warn(scn->dev, "%s: no valid reinjection direction at {%g, %g, %g}.\n", - FUNC_NAME, SPLIT3(rwalk->vtx.P)); + FUNC_NAME, SPLIT3(ray->org)); res = RES_BAD_OP_IRRECOVERABLE; goto error; } if(dst0 == -1) { /* Invalid dir0 -> move along dir1 */ - dir = dir1; + dir = args->dir1; dst = dst1; hit = hit1; } else if(dst1 == -1) { /* Invalid dir1 -> move along dir0 */ - dir = dir0; + dir = args->dir0; dst = dst0; hit = hit0; } else if(dst0 < reinject_threshold && dst1 < reinject_threshold) { @@ -395,29 +436,29 @@ XD(select_reinjection_dir) * are ignored. Move along the direction that allows the maximum * displacement. */ if(dst0 > dst1) { - dir = dir0; + dir = args->dir0; dst = dst0; hit = hit0; } else { - dir = dir1; + dir = args->dir1; dst = dst1; hit = hit1; } } else if(dst0 < reinject_threshold) { /* Ingore dir0 that is bellow the reinject threshold */ - dir = dir1; + dir = args->dir1; dst = dst1; hit = hit1; } else if(dst1 < reinject_threshold) { /* Ingore dir1 that is bellow the reinject threshold */ - dir = dir0; + dir = args->dir0; dst = dst0; hit = hit0; } else { /* All reinjection directions are valid. Choose the first 1 that was * randomly selected by the sample_reinjection_dir procedure and adjust * the displacement distance. */ - dir = dir0; + dir = args->dir0; /* Define the reinjection distance along dir0 and its corresponding hit */ if(dst0 <= dst1) { @@ -438,63 +479,44 @@ XD(select_reinjection_dir) } } - /* Setup output variable */ - fX(set)(reinject_dir, dir); - *reinject_dst = (float)dst; - *reinject_hit = hit; + /* Setup the ray */ + fX(set)(ray->dir, dir); + ray->dst = (float)dst; + ray->hit = hit; exit: return res; error: - dX(set)(rwalk->vtx.P, rwalk_pos_backup); /* Restore the rwalk position */ goto exit; } static res_T -XD(select_reinjection_dir_and_check_validity) +XD(find_reinjection_ray_and_check_validity) (const struct sdis_scene* scn, - const struct sdis_medium* mdm, /* Medium into which the reinjection occurs */ - struct XD(rwalk)* rwalk, /* Current random walk state */ - const float dir0[DIM], /* Challenged direction */ - const float dir1[DIM], /* Challanged direction */ - const double delta, /* Max reinjection distance */ - float out_reinject_dir[DIM], /* Selected direction */ - float* out_reinject_dst, /* Effective reinjection distance */ - int can_move, /* Define of the random wal pos can be moved or not */ - int* move_pos, /* Define if the current random walk was moved. May be NULL */ - int* is_valid, /* Define if the reinjection defines a valid pos */ - struct sXd(hit)* out_reinject_hit) /* Hit along the reinjection dir */ + const struct XD(find_reinjection_ray_args)* args, + struct XD(reinjection_ray)* ray) { double pos[DIM]; struct sdis_medium* reinject_mdm; - struct sXd(hit) reinject_hit; - float reinject_dir[DIM]; - float reinject_dst; res_T res = RES_OK; - ASSERT(is_valid && out_reinject_dir && out_reinject_dst && out_reinject_hit); + + ASSERT(scn && args && ray); + ASSERT(XD(check_find_reinjection_ray_args)(args)); /* Select a reinjection direction */ - res = XD(select_reinjection_dir)(scn, mdm, rwalk, dir0, dir1, delta, - reinject_dir, &reinject_dst, can_move, move_pos, &reinject_hit); + res = XD(find_reinjection_ray)(scn, args, ray); if(res != RES_OK) goto error; - if(!SXD_HIT_NONE(&reinject_hit)) { - *is_valid = 1; - } else { + if(SXD_HIT_NONE(&ray->hit)) { /* Check medium consistency at the reinjection position */ - XD(move_pos)(dX(set)(pos, rwalk->vtx.P), reinject_dir, reinject_dst); - res = scene_get_medium_in_closed_boundaries - (scn, pos, &reinject_mdm); - if(res == RES_BAD_OP) { reinject_mdm = NULL; res = RES_OK; } + XD(move_pos)(dX(set)(pos, ray->org), ray->dir, (float)ray->dst); + res = scene_get_medium_in_closed_boundaries(scn, pos, &reinject_mdm); if(res != RES_OK) goto error; - *is_valid = reinject_mdm == mdm; - } - - if(*is_valid) { - fX(set)(out_reinject_dir, reinject_dir); - *out_reinject_dst = reinject_dst; - *out_reinject_hit = reinject_hit; + if(reinject_mdm != args->solid) { + res = RES_BAD_OP; + goto error; + } } exit: @@ -512,18 +534,18 @@ XD(sample_reinjection_step_solid_fluid) const struct XD(sample_reinjection_step_args)* args, struct XD(reinjection_step)* step) { + /* Input/output data of the function finding a valid reinjection ray */ + struct XD(find_reinjection_ray_args) find_reinject_ray_args = + XD(FIND_REINJECTION_RAY_ARGS_NULL); + struct XD(reinjection_ray) ray = XD(REINJECTION_RAY_NULL); + /* In 2D it is useless to try to resample a reinjection direction since there * is only one possible direction */ const int MAX_ATTEMPTS = DIM == 2 ? 1 : 10; - /* Control if the position of the random walk can be slightly move to handle - * numerical uncertainty */ - const int RWALK_POS_CAN_BE_UPDATED = 1; - /* Miscellaneous variables */ float dir0[DIM]; /* Sampled direction */ float dir1[DIM]; /* Sampled direction reflected */ - int reinjection_is_valid = 0; /* Can reinjection be performed */ int iattempt = 0; /* #attempts to find a reinjection dir */ res_T res = RES_OK; @@ -531,7 +553,6 @@ XD(sample_reinjection_step_solid_fluid) ASSERT(scn && args && step); ASSERT(XD(check_sample_reinjection_step_args)(args)); - reinjection_is_valid = 0; iattempt = 0; do { /* Sample a reinjection direction */ @@ -547,22 +568,18 @@ XD(sample_reinjection_step_solid_fluid) } /* Find the reinjection step */ - res = XD(select_reinjection_dir_and_check_validity) - (scn, - args->solid, - args->rwalk, - dir0, - dir1, - args->distance, - step->direction, - &step->distance, - RWALK_POS_CAN_BE_UPDATED, - NULL, - &reinjection_is_valid, - &step->hit); + find_reinject_ray_args.solid = args->solid; + find_reinject_ray_args.rwalk = args->rwalk; + find_reinject_ray_args.distance = args->distance; + find_reinject_ray_args.can_move = 1; + fX(set)(find_reinject_ray_args.dir0, dir0); + fX(set)(find_reinject_ray_args.dir1, dir1); + res = XD(find_reinjection_ray_and_check_validity) + (scn, &find_reinject_ray_args, &ray); + if(res == RES_BAD_OP) continue; /* Cannot find a valid reinjection ray. Retry */ if(res != RES_OK) goto error; - } while(!reinjection_is_valid && ++iattempt < MAX_ATTEMPTS); + } while(res != RES_OK && ++iattempt < MAX_ATTEMPTS); /* Could not find a valid reinjecton step */ if(iattempt >= MAX_ATTEMPTS) { @@ -573,7 +590,18 @@ XD(sample_reinjection_step_solid_fluid) goto error; } + /* Setup the reinjection step */ + step->hit = ray.hit; + step->distance = ray.dst; + fX(set)(step->direction, ray.dir); + + /* Update the random walk position if necessary */ + if(ray.position_was_moved) { + dX(set)(args->rwalk->vtx.P, ray.org); + } + /* Post-conditions */ + ASSERT(dX(eq)(args->rwalk->vtx.P, ray.org)); ASSERT(XD(check_reinjection_step)(step)); exit: @@ -585,15 +613,23 @@ error: res_T XD(sample_reinjection_step_solid_solid) (const struct sdis_scene* scn, - const struct XD(sample_reinjection_step_args)* args_front, - const struct XD(sample_reinjection_step_args)* args_back, - struct XD(reinjection_step)* step_front, - struct XD(reinjection_step)* step_back) + const struct XD(sample_reinjection_step_args)* args_frt, + const struct XD(sample_reinjection_step_args)* args_bck, + struct XD(reinjection_step)* step_frt, + struct XD(reinjection_step)* step_bck) { + /* Input/output data of the function finding a valid reinjection ray */ + struct XD(find_reinjection_ray_args) find_reinject_ray_frt_args = + XD(FIND_REINJECTION_RAY_ARGS_NULL); + struct XD(find_reinjection_ray_args) find_reinject_ray_bck_args = + XD(FIND_REINJECTION_RAY_ARGS_NULL); + struct XD(reinjection_ray) ray_frt = XD(REINJECTION_RAY_NULL); + struct XD(reinjection_ray) ray_bck = XD(REINJECTION_RAY_NULL); + /* Initial random walk position used as a backup */ double rwalk_pos_backup[DIM]; - /* Input arguments shared by the 2 sides of the boundary */ + /* Variables shared by the two side */ struct XD(rwalk)* rwalk = NULL; struct ssp_rng* rng = NULL; @@ -601,99 +637,85 @@ XD(sample_reinjection_step_solid_solid) * is only one possible direction */ const int MAX_ATTEMPTS = DIM == 2 ? 1 : 10; - float dir_front_samp[DIM]; /* Sampled direction */ - float dir_front_refl[DIM]; /* Sampled direction reflected */ - float dir_back_samp[DIM]; /* Negated sampled direction */ - float dir_back_refl[DIM]; /* Negated sampled direction reflected */ - int reinjection_is_valid = 0; /* Can reinjection be performed */ + float dir_frt_samp[DIM]; /* Sampled direction */ + float dir_frt_refl[DIM]; /* Sampled direction reflected */ + float dir_bck_samp[DIM]; /* Negated sampled direction */ + float dir_bck_refl[DIM]; /* Negated sampled direction reflected */ int iattempt = 0; /* #attempts to find a reinjection dir */ res_T res = RES_OK; /* Pre-conditions */ - ASSERT(scn && args_front && args_back && step_front && step_back); - ASSERT(XD(check_sample_reinjection_step_args)(args_front)); - ASSERT(XD(check_sample_reinjection_step_args)(args_back)); - ASSERT(args_front->side == SDIS_FRONT); - ASSERT(args_back->side == SDIS_BACK); + ASSERT(scn && args_frt && args_bck && step_frt && step_bck); + ASSERT(XD(check_sample_reinjection_step_args)(args_frt)); + ASSERT(XD(check_sample_reinjection_step_args)(args_bck)); + ASSERT(args_frt->side == SDIS_FRONT); + ASSERT(args_bck->side == SDIS_BACK); - rwalk = args_front->rwalk; - rng = args_front->rng; - ASSERT(args_back->rng == rng); - ASSERT(args_back->rwalk == rwalk); + rng = args_frt->rng; + rwalk = args_frt->rwalk; + ASSERT(args_bck->rng == rng); + ASSERT(args_bck->rwalk == rwalk); dX(set)(rwalk_pos_backup, rwalk->vtx.P); - reinjection_is_valid = 0; iattempt = 0; do { - int rwalk_pos_moved = 0; - + /* Restore random walk pos */ if(iattempt != 0) dX(set)(rwalk->vtx.P, rwalk_pos_backup); /* Sample a reinjection direction and reflect it around the normal. Then * reflect them on the back side of the interface. */ - XD(sample_reinjection_dir)(rwalk, rng, dir_front_samp); - XD(reflect)(dir_front_refl, dir_front_samp, rwalk->hit.normal); - fX(minus)(dir_back_samp, dir_front_samp); - fX(minus)(dir_back_refl, dir_front_refl); - - /* Select the reinjection direction and distance for the front side */ - res = XD(select_reinjection_dir_and_check_validity) - (scn, - args_front->solid, - rwalk, - dir_front_samp, - dir_front_refl, - args_front->distance, - step_front->direction, - &step_front->distance, - 1, /* Can move */ - NULL, - &reinjection_is_valid, - &step_front->hit); + XD(sample_reinjection_dir)(rwalk, rng, dir_frt_samp); + XD(reflect)(dir_frt_refl, dir_frt_samp, rwalk->hit.normal); + fX(minus)(dir_bck_samp, dir_frt_samp); + fX(minus)(dir_bck_refl, dir_frt_refl); + + /* Find the reinjection ray for the front side */ + find_reinject_ray_frt_args.solid = args_frt->solid; + find_reinject_ray_frt_args.rwalk = args_frt->rwalk; + find_reinject_ray_frt_args.distance = args_frt->distance; + find_reinject_ray_frt_args.can_move = 1; + fX(set)(find_reinject_ray_frt_args.dir0, dir_frt_samp); + fX(set)(find_reinject_ray_frt_args.dir1, dir_frt_refl); + res = XD(find_reinjection_ray_and_check_validity) + (scn, &find_reinject_ray_frt_args, &ray_frt); + if(res == RES_BAD_OP) continue; if(res != RES_OK) goto error; - if(!reinjection_is_valid) continue; + + /* Update the random walk position if necessary */ + if(ray_frt.position_was_moved) dX(set)(rwalk->vtx.P, ray_frt.org); /* Select the reinjection direction and distance for the back side */ - res = XD(select_reinjection_dir_and_check_validity) - (scn, - args_back->solid, - rwalk, - dir_back_samp, - dir_back_refl, - args_back->distance, - step_back->direction, - &step_back->distance, - 1, /* Can move */ - &rwalk_pos_moved, - &reinjection_is_valid, - &step_back->hit); + find_reinject_ray_bck_args.solid = args_bck->solid; + find_reinject_ray_bck_args.rwalk = args_bck->rwalk; + find_reinject_ray_bck_args.distance = args_bck->distance; + find_reinject_ray_bck_args.can_move = 1; + fX(set)(find_reinject_ray_bck_args.dir0, dir_bck_samp); + fX(set)(find_reinject_ray_bck_args.dir1, dir_bck_refl); + res = XD(find_reinjection_ray_and_check_validity) + (scn, &find_reinject_ray_bck_args, &ray_bck); + if(res == RES_BAD_OP) continue; if(res != RES_OK) goto error; - if(!reinjection_is_valid) continue; - - /* If random walk was moved by the select_reinjection_dir on back side, one - * has to rerun the select_reinjection_dir on front side at the new pos */ - if(rwalk_pos_moved) { - res = XD(select_reinjection_dir_and_check_validity) - (scn, - args_front->solid, - rwalk, - dir_front_samp, - dir_front_refl, - args_front->distance, - step_front->direction, - &step_front->distance, - 0, /* Can't move */ - NULL, - &reinjection_is_valid, - &step_front->hit); + + /* Update the random walk position if necessary */ + if(ray_bck.position_was_moved) dX(set)(rwalk->vtx.P, ray_bck.org); + + /* If random walk was moved to find a valid rinjection ray on back side, + * one has to find a valid reinjection ob front side from the new pos */ + if(ray_bck.position_was_moved) { + find_reinject_ray_frt_args.can_move = 0; + res = XD(find_reinjection_ray_and_check_validity) + (scn, &find_reinject_ray_frt_args, &ray_frt); + if(res == RES_BAD_OP) continue; if(res != RES_OK) goto error; - if(!reinjection_is_valid) continue; + + /* Update the random walk position if necessary */ + if(ray_frt.position_was_moved) dX(set)(rwalk->vtx.P, ray_frt.org); } - } while(!reinjection_is_valid && ++iattempt < MAX_ATTEMPTS); + } while(res != RES_OK && ++iattempt < MAX_ATTEMPTS); /* Could not find a valid reinjection */ if(iattempt >= MAX_ATTEMPTS) { - dX(set)(rwalk->vtx.P, rwalk_pos_backup); + dX(set)(rwalk->vtx.P, rwalk_pos_backup); /* Restore random walk pos */ log_warn(scn->dev, "%s: could not find a valid solid/solid reinjection at {%g, %g, %g}.\n", FUNC_NAME, SPLIT3(rwalk->vtx.P)); @@ -701,9 +723,17 @@ XD(sample_reinjection_step_solid_solid) goto error; } + /* Setup the front and back reinjection steps */ + step_frt->hit = ray_frt.hit; + step_bck->hit = ray_bck.hit; + step_frt->distance = ray_frt.dst; + step_bck->distance = ray_bck.dst; + fX(set)(step_frt->direction, ray_frt.dir); + fX(set)(step_bck->direction, ray_bck.dir); + /* Post-conditions */ - ASSERT(XD(check_reinjection_step)(step_front)); - ASSERT(XD(check_reinjection_step)(step_back)); + ASSERT(XD(check_reinjection_step)(step_frt)); + ASSERT(XD(check_reinjection_step)(step_bck)); exit: return res;