htgop

Optical properties of a gas mixture
git clone git://git.meso-star.fr/htgop.git
Log | Files | Refs | README | LICENSE

commit e875fb97b81112c7279344947a232466e8944d15
parent f187fa13f89458d34d7675d91250c9c04daf6bcf
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 30 Jul 2018 13:58:03 +0200

Implement and test htgop_spectral_interval_sample_quadrature

Diffstat:
Mcmake/CMakeLists.txt | 4++--
Msrc/htgop.c | 47+++++++++++++++++++++++++++++++++++++++++++----
Msrc/htgop.h | 8++++----
Asrc/test_htgop_sample.c | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/test_htgop_sw_sample.c | 120-------------------------------------------------------------------------------
5 files changed, 218 insertions(+), 130 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -98,10 +98,10 @@ if(NOT NO_TEST) new_test(test_htgop) build_test(test_htgop_load) - build_test(test_htgop_sw_sample) + build_test(test_htgop_sample) add_test(test_htgop_load test_htgop_load ${_etc_dst}/ecrad_opt_prop.txt) - add_test(test_htgop_sw_sample test_htgop_sw_sample ${_etc_dst}/ecrad_opt_prop.txt) + add_test(test_htgop_sample test_htgop_sample ${_etc_dst}/ecrad_opt_prop.txt) endif() ################################################################################ diff --git a/src/htgop.c b/src/htgop.c @@ -13,6 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define _POSIX_C_SOURCE 200112L /* nextafter support */ + #include "htgop.h" #include "htgop_c.h" #include "htgop_reader.h" @@ -239,6 +241,7 @@ sample_sw_spectral_interval_CIE const double r, /* Canonical number in [0, 1[ */ size_t* id) { + double r_next = nextafter(r, DBL_MAX); double* find; size_t i; ASSERT(htgop && cdf && cdf_length); @@ -249,17 +252,18 @@ sample_sw_spectral_interval_CIE return RES_BAD_ARG; } - find = search_lower_bound(&r, cdf, cdf_length, sizeof(double), cmp_dbl); - if(!find) { + /* Use r_next rather than r in order to find the first entry that is not less + * that *or equal* to r */ + find = search_lower_bound(&r_next, cdf, cdf_length, sizeof(double), cmp_dbl); + if(!find) { /* <=> CIE XYZ band does not intersect the loaded intervals */ log_err(htgop, "%s: could not sample a spectral interval in the CIE XYZ spectral band.\n", caller); return RES_BAD_OP; } - ASSERT(find); i = (size_t)(find - cdf); - ASSERT(i < cdf_length && cdf[i] > r && (!i || cdf[i-1] < r)); + ASSERT(i < cdf_length && cdf[i] > r && (!i || cdf[i-1] <= r)); *id = i; return RES_OK; } @@ -813,6 +817,7 @@ htgop_get_lw_spectral_interval interval->quadrature_pdf = darray_double_cdata_get(&quad_pdfs[ispecint]); interval->quadrature_cdf = darray_double_cdata_get(&quad_cdfs[ispecint]); interval->quadrature_length = darray_double_size_get(&quad_pdfs[ispecint]); + interval->data__ = htgop; return RES_OK; } @@ -841,6 +846,40 @@ htgop_get_sw_spectral_interval interval->quadrature_pdf = darray_double_cdata_get(&quad_pdfs[ispecint]); interval->quadrature_cdf = darray_double_cdata_get(&quad_cdfs[ispecint]); interval->quadrature_length = darray_double_size_get(&quad_pdfs[ispecint]); + interval->data__ = htgop; + return RES_OK; +} + +res_T +htgop_spectral_interval_sample_quadrature + (const struct htgop_spectral_interval* specint, + const double r, /* Canonical number in [0, 1[ */ + size_t* iquad_point) /* Id of the sample quadrature point */ +{ + const struct htgop* htgop; + double r_next = nextafter(r, DBL_MAX); + double* find; + size_t i; + + if(!specint || !iquad_point) return RES_BAD_ARG; + + htgop = specint->data__; + if(r < 0 || r >= 1) { + log_err(htgop, "%s: invalid canonical random number `%g'.\n", FUNC_NAME, r); + return RES_BAD_ARG; + } + + + /* Use r_next rather than r in order to find the first entry that is not less + * that *or equal* to r */ + find = search_lower_bound(&r_next, specint->quadrature_cdf, + specint->quadrature_length, sizeof(double), cmp_dbl); + ASSERT(find); + i = (size_t)(find - specint->quadrature_cdf); + ASSERT(i < specint->quadrature_length); + ASSERT(specint->quadrature_cdf[i] > r); + ASSERT(!i || specint->quadrature_cdf[i-1] <= r); + *iquad_point = i; return RES_OK; } diff --git a/src/htgop.h b/src/htgop.h @@ -54,6 +54,7 @@ struct htgop_spectral_interval { const double* quadrature_pdf; /* PDF of the quadrature */ const double* quadrature_cdf; /* CDF of the quadrature */ size_t quadrature_length; /* #quadrature points of the interval */ + const void* data__; /* Internal data */ }; struct htgop_level { @@ -203,11 +204,10 @@ htgop_get_sw_spectral_interval struct htgop_spectral_interval* interval); HTGOP_API res_T -htgop_sw_spectral_interval_sample_quadrature - (const struct htgop* htgop, - const size_t ispectral_interval, +htgop_spectral_interval_sample_quadrature + (const struct htgop_spectral_interval* interval, const double r, /* Canonical random number in [0, 1[ */ - size_t* iquad); /* Id of the sampled interval */ + size_t* iquad_point); /* Id of the sample quadrature point */ HTGOP_API res_T htgop_layer_get_lw_spectral_interval diff --git a/src/test_htgop_sample.c b/src/test_htgop_sample.c @@ -0,0 +1,169 @@ +/* Copyright (C) |Meso|Star> 2018 (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "htgop.h" +#include "test_htgop_utils.h" + +#include <rsys/math.h> +#include <string.h> + +#define N 100000 +#define CIE_XYZ_WAVENUMBER_MIN (1.0e7/780.0) +#define CIE_XYZ_WAVENUMBER_MAX (1.0e7/380.0) + +static void +check_sw_sample_specint + (struct htgop* htgop, + res_T (*sample_func)(const struct htgop*, const double, size_t*), + int* hist) +{ + const double* wnums; + size_t nspecints; + size_t ispecint; + size_t i; + + CHK(sample_func && htgop && hist); + CHK(htgop_get_sw_spectral_intervals_count(htgop, &nspecints) == RES_OK); + CHK(htgop_get_sw_spectral_intervals_wave_numbers(htgop, &wnums) == RES_OK); + + CHK(sample_func(NULL, 0, &ispecint) == RES_BAD_ARG); + CHK(sample_func(htgop, 1, &ispecint) == RES_BAD_ARG); + CHK(sample_func(htgop, 0, NULL) == RES_BAD_ARG); + + memset(hist, 0, sizeof(*hist)*nspecints); + FOR_EACH(i, 0, N) { + const double r = rand_canonic(); + CHK(sample_func(htgop, r, &ispecint) == RES_OK); + CHK(ispecint < nspecints); + CHK(wnums[ispecint+0] <= CIE_XYZ_WAVENUMBER_MAX); + CHK(wnums[ispecint+1] >= CIE_XYZ_WAVENUMBER_MIN); + hist[ispecint] += 1; + } +} + +static void +check_sample_quadrature + (struct htgop* htgop, + res_T (*get_nspecints)(const struct htgop*, size_t*), + res_T (*get_specint) + (const struct htgop*, const size_t, struct htgop_spectral_interval*)) +{ + struct htgop_spectral_interval specint; + size_t nspecints; + size_t iquadpt; + size_t i; + + CHK(htgop && get_specint); + + CHK(get_nspecints(htgop, &nspecints) == RES_OK); + CHK(nspecints); + + CHK(get_specint(htgop, 0, &specint) == RES_OK); + CHK(htgop_spectral_interval_sample_quadrature(NULL, 0, &iquadpt) == RES_BAD_ARG); + CHK(htgop_spectral_interval_sample_quadrature(&specint, 1, &iquadpt) == RES_BAD_ARG); + CHK(htgop_spectral_interval_sample_quadrature(&specint, 1, NULL) == RES_BAD_ARG); + CHK(htgop_spectral_interval_sample_quadrature(&specint, 1, NULL) == RES_BAD_ARG); + + FOR_EACH(i, 0, 10) { + int* hist; + size_t ispecint; + size_t j; + + ispecint = (size_t)(rand_canonic() * (double)nspecints); + CHK(get_specint(htgop, ispecint, &specint) == RES_OK); + + CHK(hist = mem_calloc(specint.quadrature_length, sizeof(*hist))); + FOR_EACH(j, 0, N) { + const double r = rand_canonic(); + CHK(htgop_spectral_interval_sample_quadrature(&specint, r, &iquadpt) == RES_OK); + CHK(iquadpt < specint.quadrature_length); + CHK(specint.quadrature_cdf[iquadpt] > r); + CHK(!iquadpt || specint.quadrature_cdf[iquadpt-1] <= r); + + hist[iquadpt] += 1; + } + + FOR_EACH(iquadpt, 0, specint.quadrature_length) { + if(!eq_eps(specint.quadrature_pdf[iquadpt], 0, 1.e-4)) + CHK(hist[iquadpt] > 0); + } + + mem_rm(hist); + } +} + + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct htgop* htgop; + const double* wnums; + int* hist_X; + int* hist_Y; + int* hist_Z; + size_t nspecints; + size_t ispecint; + + if(argc < 2) { + fprintf(stderr, "Usage: %s FILENAME\n", argv[0]); + return 1; + } + + CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); + + CHK(htgop_create(NULL, &allocator, 1, &htgop) == RES_OK); + CHK(htgop_load(htgop, argv[1]) == RES_OK); + CHK(htgop_get_sw_spectral_intervals_count(htgop, &nspecints) == RES_OK); + CHK(nspecints > 0); + + CHK(htgop_get_sw_spectral_intervals_wave_numbers(htgop, &wnums) == RES_OK); + + CHK(hist_X = MEM_CALLOC(&allocator, nspecints, sizeof(*hist_X))); + CHK(hist_Y = MEM_CALLOC(&allocator, nspecints, sizeof(*hist_Y))); + CHK(hist_Z = MEM_CALLOC(&allocator, nspecints, sizeof(*hist_Z))); + + check_sw_sample_specint(htgop, htgop_sample_sw_spectral_interval_CIE_X, hist_X); + check_sw_sample_specint(htgop, htgop_sample_sw_spectral_interval_CIE_Y, hist_Y); + check_sw_sample_specint(htgop, htgop_sample_sw_spectral_interval_CIE_Z, hist_Z); + + FOR_EACH(ispecint, 0, nspecints) { + if(wnums[ispecint+0] > CIE_XYZ_WAVENUMBER_MAX + || wnums[ispecint+1] < CIE_XYZ_WAVENUMBER_MIN) { + CHK(hist_X[ispecint] == 0); + CHK(hist_Y[ispecint] == 0); + CHK(hist_Z[ispecint] == 0); + } else { + CHK(!hist_X[ispecint] || hist_X[ispecint] != hist_Y[ispecint]); + CHK(!hist_X[ispecint] || hist_X[ispecint] != hist_Z[ispecint]); + CHK(!hist_Y[ispecint] || hist_Y[ispecint] != hist_Z[ispecint]); + } + } + + MEM_RM(&allocator, hist_X); + MEM_RM(&allocator, hist_Y); + MEM_RM(&allocator, hist_Z); + + check_sample_quadrature(htgop, htgop_get_sw_spectral_intervals_count, + htgop_get_sw_spectral_interval); + check_sample_quadrature(htgop, htgop_get_lw_spectral_intervals_count, + htgop_get_lw_spectral_interval); + + CHK(htgop_ref_put(htgop) == RES_OK); + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_htgop_sw_sample.c b/src/test_htgop_sw_sample.c @@ -1,120 +0,0 @@ -/* Copyright (C) |Meso|Star> 2018 (contact@meso-star.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include "htgop.h" -#include "test_htgop_utils.h" - -#include <string.h> - -#define N 100000 -#define CIE_XYZ_WAVENUMBER_MIN (1.0e7/780.0) -#define CIE_XYZ_WAVENUMBER_MAX (1.0e7/380.0) - -static void -run_sample_func - (struct htgop* htgop, - res_T (*sample_func)(const struct htgop*, const double, size_t*), - int* hist) -{ - const double* wnums; - size_t nspecints; - size_t ispecint; - size_t i; - - CHK(sample_func && htgop && hist); - CHK(htgop_get_sw_spectral_intervals_count(htgop, &nspecints) == RES_OK); - CHK(htgop_get_sw_spectral_intervals_wave_numbers(htgop, &wnums) == RES_OK); - - memset(hist, 0, sizeof(*hist)*nspecints); - FOR_EACH(i, 0, N) { - const double r = rand_canonic(); - CHK(sample_func(htgop, r, &ispecint) == RES_OK); - CHK(ispecint < nspecints); - CHK(wnums[ispecint+0] <= CIE_XYZ_WAVENUMBER_MAX); - CHK(wnums[ispecint+1] >= CIE_XYZ_WAVENUMBER_MIN); - hist[ispecint] += 1; - } -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct htgop* htgop; - const double* wnums; - int* hist_X; - int* hist_Y; - int* hist_Z; - size_t nspecints; - size_t ispecint; - - if(argc < 2) { - fprintf(stderr, "Usage: %s FILENAME\n", argv[0]); - return 1; - } - - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - - CHK(htgop_create(NULL, &allocator, 1, &htgop) == RES_OK); - CHK(htgop_load(htgop, argv[1]) == RES_OK); - CHK(htgop_get_sw_spectral_intervals_count(htgop, &nspecints) == RES_OK); - CHK(nspecints > 0); - - CHK(htgop_get_sw_spectral_intervals_wave_numbers(htgop, &wnums) == RES_OK); - - hist_X = MEM_CALLOC(&allocator, nspecints, sizeof(*hist_X)); - hist_Y = MEM_CALLOC(&allocator, nspecints, sizeof(*hist_Y)); - hist_Z = MEM_CALLOC(&allocator, nspecints, sizeof(*hist_Z)); - CHK(hist_X && hist_Y && hist_Z); - - CHK(htgop_sample_sw_spectral_interval_CIE_X(NULL, 0, &ispecint) == RES_BAD_ARG); - CHK(htgop_sample_sw_spectral_interval_CIE_X(htgop, 1, &ispecint) == RES_BAD_ARG); - CHK(htgop_sample_sw_spectral_interval_CIE_X(htgop, 0, NULL) == RES_BAD_ARG); - - CHK(htgop_sample_sw_spectral_interval_CIE_Y(NULL, 0, &ispecint) == RES_BAD_ARG); - CHK(htgop_sample_sw_spectral_interval_CIE_Y(htgop, 1, &ispecint) == RES_BAD_ARG); - CHK(htgop_sample_sw_spectral_interval_CIE_Y(htgop, 0, NULL) == RES_BAD_ARG); - - CHK(htgop_sample_sw_spectral_interval_CIE_Z(NULL, 0, &ispecint) == RES_BAD_ARG); - CHK(htgop_sample_sw_spectral_interval_CIE_Z(htgop, 1, &ispecint) == RES_BAD_ARG); - CHK(htgop_sample_sw_spectral_interval_CIE_Z(htgop, 0, NULL) == RES_BAD_ARG); - - run_sample_func(htgop, htgop_sample_sw_spectral_interval_CIE_X, hist_X); - run_sample_func(htgop, htgop_sample_sw_spectral_interval_CIE_Y, hist_Y); - run_sample_func(htgop, htgop_sample_sw_spectral_interval_CIE_Z, hist_Z); - - FOR_EACH(ispecint, 0, nspecints) { - if(wnums[ispecint+0] > CIE_XYZ_WAVENUMBER_MAX - || wnums[ispecint+1] < CIE_XYZ_WAVENUMBER_MIN) { - CHK(hist_X[ispecint] == 0); - CHK(hist_Y[ispecint] == 0); - CHK(hist_Z[ispecint] == 0); - } else { - CHK(!hist_X[ispecint] || hist_X[ispecint] != hist_Y[ispecint]); - CHK(!hist_X[ispecint] || hist_X[ispecint] != hist_Z[ispecint]); - CHK(!hist_Y[ispecint] || hist_Y[ispecint] != hist_Z[ispecint]); - } - } - - MEM_RM(&allocator, hist_X); - MEM_RM(&allocator, hist_Y); - MEM_RM(&allocator, hist_Z); - - CHK(htgop_ref_put(htgop) == RES_OK); - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -}