htgop

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

commit ac5a4071d4ab1e6bbf07ef5144d7ca4875708980
parent 8c91240f90f27048e16f570cc0b44991ee2d8c95
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 30 Jul 2018 15:46:15 +0200

Implement and test htgop_position_to_layer_id

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Msrc/htgop.c | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/htgop.h | 6++++++
Msrc/test_htgop_load.c | 46++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -24,7 +24,7 @@ option(NO_TEST "Do not build tests" OFF) # Check dependencies ################################################################################ find_package(RCMake 0.3 REQUIRED) -find_package(RSys 0.6 REQUIRED) +find_package(RSys 0.7 REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) diff --git a/src/htgop.c b/src/htgop.c @@ -60,6 +60,14 @@ cmp_dbl(const void* a, const void* b) return d0 < d1 ? -1 : (d0 > d1 ? 1 : 0); } +static INLINE int +cmp_lvl(const void* key, const void* data) +{ + const double height = *((const double*)key); + const struct htgop_level* lvl = (const struct htgop_level*)data; + return height < lvl->height ? -1 : (height > lvl->height ? 1 : 0); +} + static FINLINE double trapezoidal_integration (const double lambda_lo, /* Integral lower bound. In nanometer */ @@ -411,6 +419,7 @@ load_stream(struct htgop* htgop, FILE* stream, const char* stream_name) struct layer* layers = NULL; unsigned long nlvls, nlays, tab_len, nspecints_lw, nspecints_sw; unsigned long ilvl, ilay, itab; + unsigned long iline_saved; res_T res = RES_OK; ASSERT(htgop && stream && stream_name); reader_init(&rdr, stream, stream_name); @@ -424,8 +433,21 @@ load_stream(struct htgop* htgop, FILE* stream, const char* stream_name) /* Parse the number of levels/layers */ CALL(cstr_to_ulong(read_line(&rdr), &nlvls)); + iline_saved = rdr.iline; CALL(cstr_to_ulong(read_line(&rdr), &nlays)); - if(nlvls != nlays + 1) { res = RES_BAD_ARG; goto error; } + if(!nlays) { + log_err(htgop, "%s:%lu: The number of layers cannot be null.\n", + rdr.name, rdr.iline); + res = RES_BAD_ARG; + goto error; + } + if(nlvls != nlays + 1) { + log_err(htgop, + "%s:%lu: Invalid number of levels `%lu' (#layers = `%lu').\n", + rdr.name, iline_saved, nlvls, nlays); + res = RES_BAD_ARG; + goto error; + } /* Parse the ground temperature */ CALL(cstr_to_double(read_line(&rdr), &htgop->ground.temperature)); @@ -935,6 +957,42 @@ htgop_sample_sw_spectral_interval_CIE_Z r, ispecint); } +res_T +htgop_position_to_layer_id + (const struct htgop* htgop, const double pos, size_t* ilayer) +{ + const struct htgop_level* lvls; + size_t nlvls; + + if(!htgop || !ilayer) return RES_BAD_ARG; + + lvls = darray_level_cdata_get(&htgop->levels); + nlvls = darray_level_size_get(&htgop->levels); + ASSERT(nlvls); + + if(pos == lvls[0].height) { + *ilayer = 0; + } else if(pos == lvls[nlvls-1].height) { + *ilayer = nlvls - 2; + } else { + const struct htgop_level* find; + size_t i; + + find = search_lower_bound(&pos, lvls, nlvls, sizeof(*lvls), cmp_lvl); + if(!find || find == lvls) { + log_err(htgop, "%s: the position `%g' is outside the atmospheric slices.\n", + FUNC_NAME, pos); + return RES_BAD_ARG; + } + + i = (size_t)(find - lvls); + ASSERT(i < nlvls && i > 0); + ASSERT(lvls[i].height > pos && (!i || lvls[i-1].height <= pos)); + *ilayer = i - 1; + } + return RES_OK; +} + /******************************************************************************* * Local functions ******************************************************************************/ diff --git a/src/htgop.h b/src/htgop.h @@ -233,6 +233,12 @@ htgop_layer_sw_spectral_interval_get_tab const size_t iquadrature_point, struct htgop_layer_sw_spectral_interval_tab* tab); +HTGOP_API res_T +htgop_position_to_layer_id + (const struct htgop* htgop, + const double pos, + size_t* ilayer); + END_DECLS #endif /* HTGOP */ diff --git a/src/test_htgop_load.c b/src/test_htgop_load.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_reader.h" @@ -20,6 +22,48 @@ #include <rsys/cstr.h> +static void +check_position_to_layer_id(const struct htgop* htgop) +{ + struct htgop_level lvl0, lvl1; + const size_t N = 10000; + double org, sz; + size_t ilay; + size_t i, n; + + CHK(htgop_get_levels_count(htgop, &n) == RES_OK); + CHK(n > 1); + + /* Test the htgop_position_to_layer_id function */ + CHK(htgop_get_level(htgop, 0, &lvl0) == RES_OK); + CHK(htgop_get_level(htgop, n-1, &lvl1) == RES_OK); + org = lvl0.height; + sz = lvl1.height - lvl0.height; + + CHK(htgop_position_to_layer_id(NULL, lvl0.height, &ilay) == RES_BAD_ARG); + CHK(htgop_position_to_layer_id + (htgop, nextafter(lvl0.height,-DBL_MAX), &ilay) == RES_BAD_ARG); + CHK(htgop_position_to_layer_id + (htgop, nextafter(lvl1.height, DBL_MAX), &ilay) == RES_BAD_ARG); + CHK(htgop_position_to_layer_id(htgop, lvl0.height, NULL) == RES_BAD_ARG); + + CHK(htgop_position_to_layer_id(htgop, lvl0.height, &ilay) == RES_OK); + CHK(ilay == 0); + CHK(htgop_position_to_layer_id(htgop, lvl1.height, &ilay) == RES_OK); + CHK(ilay == n - 2); + + FOR_EACH(i, 0, N) { + const double r = rand_canonic(); + const double pos = org + r * sz; + + CHK(htgop_position_to_layer_id(htgop, pos, &ilay) == RES_OK); + CHK(htgop_get_level(htgop, ilay+0, &lvl0) == RES_OK); + CHK(htgop_get_level(htgop, ilay+1, &lvl1) == RES_OK); + CHK(pos >= lvl0.height); + CHK(pos <= lvl1.height); + } +} + int main(int argc, char** argv) { @@ -310,6 +354,8 @@ main(int argc, char** argv) } } + check_position_to_layer_id(htgop); + CHK(fclose(fp) == 0); reader_release(&rdr); CHK(htgop_ref_put(htgop) == RES_OK);