htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit ae1775a93de88ca1cea2c9ba60c926cbe00a2013
parent 0a4c1facc1a8dd69f1c66892f1706fca85920f09
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 18 May 2020 15:42:56 +0200

Refactor the longwave sampling

Diffstat:
Msrc/htrdr_compute_radiance_lw.c | 22++++++++++++----------
Msrc/htrdr_draw_radiance.c | 16++++++----------
Msrc/htrdr_ran_lw.c | 188++++++++++++++++++++-----------------------------------------------------------
Msrc/htrdr_ran_lw.h | 30+++---------------------------
Msrc/htrdr_solve.h | 1+
5 files changed, 69 insertions(+), 188 deletions(-)

diff --git a/src/htrdr_compute_radiance_lw.c b/src/htrdr_compute_radiance_lw.c @@ -139,6 +139,7 @@ htrdr_compute_radiance_lw const double pos_in[3], const double dir_in[3], const double wlen, /* In nanometer */ + const double samp_band_bounds[2], /* In nanometer */ const size_t iband, const size_t iquad) { @@ -153,23 +154,22 @@ htrdr_compute_radiance_lw double range[2]; double pos_next[3]; double dir_next[3]; - double wlen_bounds[2]; /* sub-interval bounds in nano meters */ - double wlen_bounds_m[2]; /* sub-interval bounds in meters */ - double delta_wlen ; /* sub-interval size in meters */ + double samp_band_bounds_m[2]; /* sub-interval bounds in meters */ + double delta_wlen_m; /* sub-interval size in meters */ double temperature; double g; double w = 0; /* Weight */ ASSERT(htrdr && rng && pos_in && dir_in && ithread < htrdr->nthreads); + ASSERT(samp_band_bounds); - /* Retrieve the band boundaries in nano meters*/ - htrdr_ran_lw_get_wlen_band_bounds(htrdr->ran_lw, wlen, wlen_bounds); /* Convert to meters */ - wlen_bounds_m[0] = wlen_bounds[0] * 1e-9; - wlen_bounds_m[1] = wlen_bounds[1] * 1e-9; + samp_band_bounds_m[0] = samp_band_bounds[0] * 1e-9; + samp_band_bounds_m[1] = samp_band_bounds[1] * 1e-9; /* If monochromatic, set delta_wlen to 1 m, otherwise lmax - lmin in meters */ - delta_wlen = eq_eps(wlen_bounds[0],wlen_bounds[1],1e-6) ? 1 : wlen_bounds_m[1]-wlen_bounds_m[0] ; + delta_wlen_m = samp_band_bounds_m[1] - samp_band_bounds_m[0]; + if(delta_wlen_m == 0) delta_wlen_m = 1.0; /* Setup the phase function for this spectral band & quadrature point */ CHK(RES_OK == ssf_phase_create @@ -224,7 +224,8 @@ htrdr_compute_radiance_lw ASSERT(!SVX_HIT_NONE(&svx_hit)); temperature = htsky_fetch_temperature(htrdr->sky, pos_next); /* weight is planck integrated over the spectral sub-interval */ - w = planck(wlen_bounds_m[0],wlen_bounds_m[1],temperature)*delta_wlen ; + w = planck(samp_band_bounds_m[0], samp_band_bounds_m[1], temperature); + w = w * delta_wlen_m; break; } @@ -273,7 +274,8 @@ htrdr_compute_radiance_lw w = 0; } else { /* weight is planck integrated over the spectral sub-interval */ - w = planck(wlen_bounds_m[0],wlen_bounds_m[1],temperature) * delta_wlen ; + w = planck(samp_band_bounds_m[0], samp_band_bounds_m[1], temperature); + w = w * delta_wlen_m; } break; } diff --git a/src/htrdr_draw_radiance.c b/src/htrdr_draw_radiance.c @@ -601,11 +601,11 @@ draw_pixel_lw double ray_dir[3]; double weight; double r0, r1; - double wlen_range_nm[2] ; double wlen; size_t iband; size_t iquad; double usec; + double samp_band_bounds[2]; double band_pdf; /* Begin the registration of the time spent in the realisation */ @@ -623,26 +623,22 @@ draw_pixel_lw r1 = ssp_rng_canonical(rng); /* Sample a wavelength */ - wlen = htrdr_ran_lw_sample(htrdr->ran_lw, r0); + wlen = htrdr_ran_lw_sample(htrdr->ran_lw, r0, samp_band_bounds, &band_pdf); /* Select the associated band and sample a quadrature point */ iband = htsky_find_spectral_band(htrdr->sky, wlen); iquad = htsky_spectral_band_sample_quadrature(htrdr->sky, r1, iband); - /* Retrieve the PDF to sample this sky band */ - /* band_pdf is the pdf in the band of ran_lw->band_len nm */ - band_pdf = htrdr_ran_lw_get_wlen_band_pdf(htrdr->ran_lw,wlen) ; - /* Compute the integrated luminance in W/m^2/sr */ - weight = htrdr_compute_radiance_lw - (htrdr, ithread, rng, ray_org, ray_dir, wlen, iband, iquad); + weight = htrdr_compute_radiance_lw(htrdr, ithread, rng, ray_org, ray_dir, + wlen, samp_band_bounds, iband, iquad); /* Importance sampling: correct weight with pdf */ weight /= band_pdf; - htrdr_ran_lw_get_wlen_range(htrdr->ran_lw, wlen_range_nm) ; /* From integrated radiance to average radiance in W/m^2/sr/m */ - if (!eq_eps(wlen_range_nm[0], wlen_range_nm[1], 1e-6)) { + if(htrdr->wlen_range_m[0] != htrdr->wlen_range_m[1]) { + /* Is not monochromatic */ weight /= (htrdr->wlen_range_m[1] - htrdr->wlen_range_m[0]) ; } ASSERT(weight >= 0); diff --git a/src/htrdr_ran_lw.c b/src/htrdr_ran_lw.c @@ -32,8 +32,6 @@ struct htrdr_ran_lw { struct darray_double pdf; struct darray_double cdf; - /* Probas to sample a sky band overlapped by the range */ - struct darray_double sky_bands_pdf; double range[2]; /* Boundaries of the handled CIE XYZ color space */ double band_len; /* Length in nanometers of a band */ double ref_temperature; /* In Kelvin */ @@ -123,37 +121,19 @@ error: goto exit; } -static res_T -compute_sky_bands_pdf - (struct htrdr_ran_lw* ran_lw, - const char* func_name, - double* out_min_band_len) +static double +compute_sky_min_band_len(struct htrdr_ran_lw* ran_lw, const char* func_name) { - double* pdf = NULL; double min_band_len = DBL_MAX; size_t nbands; - res_T res = RES_OK; ASSERT(ran_lw && htsky_is_long_wave(ran_lw->htrdr->sky) && func_name); nbands = htsky_get_spectral_bands_count(ran_lw->htrdr->sky); - res = darray_double_resize(&ran_lw->sky_bands_pdf, nbands); - if(res != RES_OK) { - htrdr_log_err(ran_lw->htrdr, - "%s: error allocating the PDF of the long wave spectral bands " - "of the sky -- %s.\n", - func_name, res_to_cstr(res)); - goto error; - } - - pdf = darray_double_data_get(&ran_lw->sky_bands_pdf); - if(eq_eps(ran_lw->range[0], ran_lw->range[1], 1.e-6)) { ASSERT(nbands == 1); - pdf[0] = 1; min_band_len = 0; } else { - double sum = 0; size_t i = 0; /* Compute the *unormalized* probability to sample a long wave band */ @@ -167,35 +147,18 @@ compute_sky_bands_pdf wlens[1] = MMIN(wlens[1], ran_lw->range[1]); min_band_len = MMIN(wlens[1] - wlens[0], min_band_len); - - /* Convert from nanometer to meter */ - wlens[0] *= 1.e-9; - wlens[1] *= 1.e-9; - - /* Compute the probability of the current band */ - pdf[i] = blackbody_fraction(wlens[0], wlens[1], ran_lw->ref_temperature); - - /* Update the norm */ - sum += pdf[i]; } - - /* Normalize the probabilities */ - FOR_EACH(i, 0, nbands) pdf[i] /= sum; } - -exit: - *out_min_band_len = min_band_len; - return res; -error: - darray_double_clear(&ran_lw->sky_bands_pdf); - goto exit; + return min_band_len; } static double -ran_lw_sample_discreet +ran_lw_sample_discrete (const struct htrdr_ran_lw* ran_lw, const double r, - const char* func_name) + const char* func_name, + double sampled_band_bounds[2], + double* pdf) { const double* cdf = NULL; const double* find = NULL; @@ -223,6 +186,15 @@ ran_lw_sample_discreet wlen = ran_lw->range[0] + ran_lw->band_len * ((double)i + 0.5); ASSERT(ran_lw->range[0] < wlen && wlen < ran_lw->range[1]); + if(sampled_band_bounds) { + sampled_band_bounds[0] = ran_lw->range[0] + (double)i*ran_lw->band_len; + sampled_band_bounds[1] = sampled_band_bounds[0] + ran_lw->band_len; + } + + if(pdf) { + *pdf = darray_double_cdata_get(&ran_lw->pdf)[i]; + } + return wlen; } @@ -230,7 +202,9 @@ static double ran_lw_sample_continue (const struct htrdr_ran_lw* ran_lw, const double r, - const char* func_name) + const char* func_name, + double sampled_band_bounds[2], + double* pdf) { /* Numerical parameters of the dichotomy search */ const size_t MAX_ITER = 100; @@ -290,6 +264,19 @@ ran_lw_sample_continue func_name, SPLIT2(ran_lw->range), ran_lw->ref_temperature); } + if(sampled_band_bounds) { + const double lambda = lambda_m * 1.e+9; + sampled_band_bounds[0] = lambda; + sampled_band_bounds[1] = lambda; + } + + if(pdf) { + const double Tref = ran_lw->ref_temperature; + const double B_lambda = planck(lambda_m, lambda_m, Tref); + const double B_mean = planck(range_m[0], range_m[1], Tref); + *pdf = B_lambda / (B_mean * (range_m[1]-range_m[0])); + } + return lambda_m * 1.0e9; /* Convert in nanometers */ } @@ -301,7 +288,6 @@ release_ran_lw(ref_T* ref) ran_lw = CONTAINER_OF(ref, struct htrdr_ran_lw, ref); darray_double_release(&ran_lw->cdf); darray_double_release(&ran_lw->pdf); - darray_double_release(&ran_lw->sky_bands_pdf); MEM_RM(ran_lw->htrdr->allocator, ran_lw); } @@ -337,15 +323,13 @@ htrdr_ran_lw_create ran_lw->htrdr = htrdr; darray_double_init(htrdr->allocator, &ran_lw->cdf); darray_double_init(htrdr->allocator, &ran_lw->pdf); - darray_double_init(htrdr->allocator, &ran_lw->sky_bands_pdf); ran_lw->range[0] = range[0]; ran_lw->range[1] = range[1]; ran_lw->ref_temperature = ref_temperature; ran_lw->nbands = nbands; - res = compute_sky_bands_pdf(ran_lw, FUNC_NAME, &min_band_len); - if(res != RES_OK) goto error; + min_band_len = compute_sky_min_band_len(ran_lw, FUNC_NAME); if(nbands == HTRDR_RAN_LW_CONTINUE) { ran_lw->band_len = 0; @@ -391,102 +375,24 @@ htrdr_ran_lw_ref_put(struct htrdr_ran_lw* ran_lw) double htrdr_ran_lw_sample (const struct htrdr_ran_lw* ran_lw, - const double r) + const double r, + double sampled_band_bounds[2], + double* pdf) { ASSERT(ran_lw); - if(ran_lw->nbands != HTRDR_RAN_LW_CONTINUE) { - return ran_lw_sample_discreet(ran_lw, r, FUNC_NAME); + if(ran_lw->nbands != HTRDR_RAN_LW_CONTINUE) { /* Discrete */ + return ran_lw_sample_discrete + (ran_lw, r, FUNC_NAME, sampled_band_bounds, pdf); } else if(eq_eps(ran_lw->range[0], ran_lw->range[1], 1.e-6)) { + if(sampled_band_bounds) { /* Monochromatic */ + sampled_band_bounds[0] = ran_lw->range[0]; + sampled_band_bounds[1] = ran_lw->range[0]; + } + if(pdf) *pdf = 1; return ran_lw->range[0]; - } else { - return ran_lw_sample_continue(ran_lw, r, FUNC_NAME); - } -} - -res_T -htrdr_ran_lw_get_wlen_range - (const struct htrdr_ran_lw* ran_lw, - double * wlens) -{ - wlens[0] = ran_lw->range[0] ; - wlens[1] = ran_lw->range[1] ; - return RES_OK ; -} - -res_T -htrdr_ran_lw_get_wlen_band_bounds - (const struct htrdr_ran_lw* ran_lw, - const double wlen, - double * wlens) -{ - size_t i = htrdr_ran_lw_get_index_wlen(ran_lw,wlen) ; - wlens[0] = ran_lw->range[0] + (double) i*ran_lw->band_len ; - wlens[1] = ran_lw->range[0] + (double)(i+1)*ran_lw->band_len ; - return RES_OK ; -} - -size_t -htrdr_ran_lw_get_index_wlen - (const struct htrdr_ran_lw* ran_lw, - const double wlen) -{ - /* i==0 corresponds to pdf for band - * [range[0], range[0] + band_len] - * i==j corresponds to pdf for band - * [range[0] + j*band_len , range[0] +(j+1)* band_len] - * to find i, floor((wlen - range[0]) / band_len) */ - if (eq_eps(ran_lw->range[0], ran_lw->range[1], 1.e-6)) { - return 0 ; - } - else { - return (size_t) ((wlen - ran_lw->range[0]) / ran_lw->band_len ); + } else { /* Continue */ + return ran_lw_sample_continue + (ran_lw, r, FUNC_NAME, sampled_band_bounds, pdf); } } -double -htrdr_ran_lw_get_wlen_band_pdf - (const struct htrdr_ran_lw* ran_lw, - const double wlen) -{ - /* need to retrieve ran_lw->pdf[i] - * where i corresponds to the wlen */ - size_t i ; - ASSERT(ran_lw); - ASSERT(wlen >= ran_lw->range[0]); - ASSERT(wlen <= ran_lw->range[1]); - - i = htrdr_ran_lw_get_index_wlen(ran_lw,wlen) ; - - if (darray_double_size_get(&ran_lw->pdf)==0) { - return 1 ; - } - else { - /* Fetch its PDF */ - ASSERT(i < darray_double_size_get(&ran_lw->pdf)); - return darray_double_cdata_get(&ran_lw->pdf)[i]; - } -} - -double -htrdr_ran_lw_get_sky_band_pdf - (const struct htrdr_ran_lw* ran_lw, - const size_t iband) -{ - size_t i; - size_t nbands; - (void)nbands; - ASSERT(ran_lw); - - nbands = htsky_get_spectral_bands_count(ran_lw->htrdr->sky); - ASSERT(nbands); - ASSERT(iband >= htsky_get_spectral_band_id(ran_lw->htrdr->sky, 0)); - ASSERT(iband <= htsky_get_spectral_band_id(ran_lw->htrdr->sky, nbands-1)); - - /* Compute the index of the spectral band */ - i = iband - htsky_get_spectral_band_id(ran_lw->htrdr->sky, 0); - - /* Fetch its PDF */ - ASSERT(i < darray_double_size_get(&ran_lw->sky_bands_pdf)); - return darray_double_cdata_get(&ran_lw->sky_bands_pdf)[i]; -} - diff --git a/src/htrdr_ran_lw.h b/src/htrdr_ran_lw.h @@ -45,33 +45,9 @@ htrdr_ran_lw_ref_put extern LOCAL_SYM double htrdr_ran_lw_sample (const struct htrdr_ran_lw* ran_lw, - const double r); /* Canonical number in [0, 1[ */ - -size_t -htrdr_ran_lw_get_index_wlen - (const struct htrdr_ran_lw* ran_lw, - const double wlen); - -res_T -htrdr_ran_lw_get_wlen_range - (const struct htrdr_ran_lw* ran_lw, - double * wlens) ; - -res_T -htrdr_ran_lw_get_wlen_band_bounds - (const struct htrdr_ran_lw* ran_lw, - const double wlen, - double * wlens) ; - -double -htrdr_ran_lw_get_wlen_band_pdf - (const struct htrdr_ran_lw* ran_lw, - const double wlen); - -extern LOCAL_SYM double -htrdr_ran_lw_get_sky_band_pdf - (const struct htrdr_ran_lw* ran_lw, - const size_t iband); + const double r, /* Canonical number in [0, 1[ */ + double sampled_band_bounds[2], /* May be NULL */ + double* pdf); /* May be NULL */ #endif /* HTRDR_RAN_LW_H */ diff --git a/src/htrdr_solve.h b/src/htrdr_solve.h @@ -75,6 +75,7 @@ htrdr_compute_radiance_lw const double pos[3], const double dir[3], const double wlen, /* In nanometer */ + const double samp_band_bounds[2], /* In nanometer */ const size_t iband, /* Index of the spectral band */ const size_t iquad); /* Index of the quadrature point into the band */