atrri

Refractive indices varying with wavelength
git clone git://git.meso-star.fr/atrri.git
Log | Files | Refs | README | LICENSE

commit ec9b7c46cfb3f4004566d89aad562e01b230d305
parent f5e69aabf7a56e38e5f7a19fd89efc24ff10d845
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 13 Jan 2021 13:55:38 +0100

Test the load process

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Asrc/test_atrri_load.c | 330+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 331 insertions(+), 1 deletion(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -82,7 +82,7 @@ if(NOT NO_TEST) endfunction() new_test(test_atrri) - #new_test(test_atrri_load) + new_test(test_atrri_load m) endif() ################################################################################ diff --git a/src/test_atrri_load.c b/src/test_atrri_load.c @@ -0,0 +1,330 @@ +/* Copyright (C) 2021 CNRS + * + * 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/>. */ + +#define _POSIX_C_SOURCE 200112L /* nextafter support */ + +#include "atrri.h" + +#include <rsys/math.h> +#include <rsys/mem_allocator.h> + +#include <float.h> +#include <math.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static INLINE double +rand_canonic() +{ + return (double)rand() / (double)((size_t)RAND_MAX + 1); +} + +static void +check_desc + (const struct atrri_desc* desc, + const double refract_ids[], + const size_t nrefract_ids) +{ + size_t i; + + CHK(desc && refract_ids && nrefract_ids); + CHK(desc->nindices == nrefract_ids); + FOR_EACH(i, 0, nrefract_ids) { + if(i != 0) { + CHK(desc->indices[i].wavelength > desc->indices[i-1].wavelength); + } + CHK(desc->indices[i].wavelength == refract_ids[i*3+0]); + CHK(desc->indices[i].n == refract_ids[i*3+1]); + CHK(desc->indices[i].kappa == refract_ids[i*3+2]); + } +} + +static void +fetch_refractive_index + (const struct atrri_desc* desc, + const double wavelength, + struct atrri_refractive_index* index) +{ + size_t i; + CHK(desc && wavelength >= 0 && index); + + /* Naive linear search the first refractive index whose associated wavelength + * is greater than or equal to the submitted wavelength */ + FOR_EACH(i, 0, desc->nindices) { + if(desc->indices[i].wavelength >= wavelength) break; + } + + if(i >= desc->nindices) { + *index = desc->indices[desc->nindices-1]; + } else if(i == 0) { + *index = desc->indices[0]; + } else { + const struct atrri_refractive_index* next = desc->indices + i; + const struct atrri_refractive_index* prev = desc->indices + i - 1; + const double len = next->wavelength - prev->wavelength; + const double u = CLAMP((wavelength - prev->wavelength) / len, 0, 1); + + CHK(wavelength > prev->wavelength); + CHK(wavelength <= next->wavelength); + + index->wavelength = wavelength; + index->n = u * prev->n + (1.0-u) * next->n; + index->kappa = u * prev->kappa + (1.0-u) * next->kappa; + } +} + +static void +test_load(struct atrri* atrri) +{ + const double refract_ids[] = { /* Wavelength n kappa */ + 300.000011921, 1.740000010, 0.469999999, + 310.000002384, 1.741990328, 0.469004273, + 319.999992847, 1.743917465, 0.468010038, + 329.999983311, 1.745785475, 0.467014253, + 339.999973774, 1.748130083, 0.465993971, + 349.999964237, 1.750000000, 0.464985400, + 359.999954700, 1.750000000, 0.463959038, + 369.999945164, 1.750000000, 0.462961257, + 379.999935627, 1.750000000, 0.461990029, + 389.999926090, 1.750000000, 0.460981935, + 399.999916553, 1.750000000, 0.459957659, + 409.999907017, 1.750000000, 0.458958119, + 419.999897480, 1.750000000, 0.457983255, + 429.999887943, 1.750000000, 0.456973791, + 439.999878407, 1.750000000, 0.455950528, + 449.999868870, 1.750000000, 0.454950303, + 459.999859333, 1.750000000, 0.453971595, + 469.999849796, 1.750000000, 0.452998221, + 479.999840260, 1.750000000, 0.451974779, + 489.999830723, 1.750000000, 0.450974643, + 499.999821186, 1.750000000, 0.449385107, + 509.999811649, 1.750000000, 0.447702825, + 519.999802113, 1.750000000, 0.445923656, + 529.999792576, 1.750000000, 0.443915308, + 539.999783039, 1.750000000, 0.441953331, + 549.999773502, 1.750000000, 0.440498799, + 559.999763966, 1.750000000, 0.439258754, + 569.999754429, 1.750000000, 0.438044012, + 579.999744892, 1.750000000, 0.437014997, + 589.999735355, 1.750000000, 0.436012030, + 599.999725819, 1.750000000, 0.435097486, + 609.999716282, 1.750000000, 0.435064077, + 619.999706745, 1.750000000, 0.435031146, + 629.999697208, 1.750000000, 0.434985548, + 639.999687672, 1.750000000, 0.434602797, + 649.999678135, 1.750000000, 0.434226334, + 659.999668598, 1.750000000, 0.433855951, + 669.999659061, 1.750000000, 0.432947546, + 679.999649525, 1.750000000, 0.431957632, + 689.999639988, 1.750000000, 0.430984408, + 699.999630451, 1.750000000, 0.430428028, + 709.999620914, 1.750000000, 0.430284500, + 719.999611378, 1.750000000, 0.430143028, + 729.999601841, 1.750000000, 0.430003524, + 739.999592304, 1.750000000, 0.430000007, + 749.999582767, 1.750000000, 0.430000007, + 759.999573231, 1.750000000, 0.430000007, + 769.999563694, 1.750000000, 0.430021703, + 779.999554157, 1.750000000, 0.430100024, + 789.999544621, 1.750000000, 0.430177301, + 799.999535084, 1.750000000, 0.430253685 + }; + const size_t nrefract_ids = sizeof(refract_ids) / sizeof(double[3]); + struct atrri_desc desc = ATRRI_DESC_NULL; + struct atrri_refractive_index index = ATRRI_REFRACTIVE_INDEX_NULL; + size_t irefract_id = 0; + const char* filename = "test_file.atrri"; + FILE* fp = NULL; + double wlen; + size_t i; + + fp = fopen(filename, "w+"); + CHK(fp); + + /* Write the input file */ + fprintf(fp, "# Wavelength (in nm) n kappa\n"); + FOR_EACH(irefract_id, 0, nrefract_ids) { + fprintf(fp, "%.9f %.9f %.9f\n", + refract_ids[irefract_id*3+0], + refract_ids[irefract_id*3+1], + refract_ids[irefract_id*3+2]); + } + + rewind(fp); + CHK(atrri_load_stream(NULL, fp, filename) == RES_BAD_ARG); + CHK(atrri_load_stream(atrri, NULL, filename) == RES_BAD_ARG); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_OK); + CHK(atrri_get_desc(NULL, &desc) == RES_BAD_ARG); + CHK(atrri_get_desc(atrri, NULL) == RES_BAD_ARG); + CHK(atrri_get_desc(atrri, &desc) == RES_OK); + check_desc(&desc, refract_ids, nrefract_ids); + + rewind(fp); + CHK(atrri_load_stream(atrri, fp, filename) == RES_OK); + check_desc(&desc, refract_ids, nrefract_ids); + + wlen = desc.indices[0].wavelength; + CHK(atrri_fetch_refractive_index(NULL, wlen, &index) == RES_BAD_ARG); + CHK(atrri_fetch_refractive_index(atrri, -1, &index) == RES_BAD_ARG); + CHK(atrri_fetch_refractive_index(atrri, wlen, NULL) == RES_BAD_ARG); + CHK(atrri_fetch_refractive_index(atrri, wlen, &index) == RES_OK); + CHK(index.wavelength == desc.indices[0].wavelength); + CHK(index.n == desc.indices[0].n); + CHK(index.kappa == desc.indices[0].kappa); + + /* Test clamp to lower bound */ + i = 0; + wlen = nextafter(wlen, 0); + CHK(atrri_fetch_refractive_index(atrri, wlen, &index) == RES_OK); + CHK(index.wavelength == desc.indices[i].wavelength); + CHK(index.n == desc.indices[i].n); + CHK(index.kappa == desc.indices[i].kappa); + + /* Test clamp to upper bound */ + i = desc.nindices-1; + wlen = nextafter(desc.indices[i].wavelength, DBL_MAX); + CHK(atrri_fetch_refractive_index(atrri, wlen, &index) == RES_OK); + CHK(index.wavelength == desc.indices[i].wavelength); + CHK(index.n == desc.indices[i].n); + CHK(index.kappa == desc.indices[i].kappa); + + /* Test random fetches */ + FOR_EACH(i, 0, 10000) { + struct atrri_refractive_index index_ref = ATRRI_REFRACTIVE_INDEX_NULL; + const double r = rand_canonic(); + wlen = + r * (desc.indices[desc.nindices-1].wavelength - desc.indices[0].wavelength) + + desc.indices[0].wavelength; + + CHK(atrri_fetch_refractive_index(atrri, wlen, &index) == RES_OK); + + fetch_refractive_index(&desc, wlen, &index_ref); + CHK(index_ref.wavelength == index.wavelength); + CHK(eq_eps(index_ref.n, index.n, 1.e-6)); + CHK(eq_eps(index_ref.kappa, index.kappa, 1.e-6)); + } + + fclose(fp); +} + +static void +test_load_failure(struct atrri* atrri) +{ + FILE* fp = NULL; + + fp = tmpfile(); + CHK(fp); + fprintf(fp, "# Empty file\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "-1 10 10\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "1 -1 1\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "1 1 -1\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "1 1 1\n"); + fprintf(fp, "3 3 3\n"); + fprintf(fp, "2 2 2\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "1, 1 1\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "1 1; 1\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "1 1 1.0.1\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_BAD_ARG); + fclose(fp); + + fp = tmpfile(); + fprintf(fp, "1 1 1 hello world !\n"); + rewind(fp); + CHK(atrri_load_stream(atrri, fp, NULL) == RES_OK); /* Warning */ + fclose(fp); +} + +static void +test_load_files(struct atrri* atrri, int argc, char** argv) +{ + int iarg; + CHK(atrri); + FOR_EACH(iarg, 1, argc) { + struct atrri_desc desc = ATRRI_DESC_NULL; + size_t i; + + printf("Load %s\n", argv[iarg]); + CHK(atrri_load(atrri, argv[iarg]) == RES_OK); + CHK(atrri_get_desc(atrri, &desc) == RES_OK); + CHK(desc.nindices != 0); + + FOR_EACH(i, 0, desc.nindices) { + CHK(desc.indices[i].wavelength == desc.indices[i].wavelength); /* !NaN */ + CHK(desc.indices[i].n == desc.indices[i].n); /* !NaN */ + CHK(desc.indices[i].kappa == desc.indices[i].kappa); /* !NaN */ + CHK(desc.indices[i].wavelength >= 0); + CHK(desc.indices[i].n >= 0); + CHK(desc.indices[i].kappa >= 0); + } + } +} + + +/******************************************************************************* + * Main function + ******************************************************************************/ +int +main(int argc, char** argv) +{ + struct atrri* atrri = NULL; + (void)argc, (void)argv; + + CHK(atrri_create(NULL, &mem_default_allocator, 1, &atrri) == RES_OK); + + test_load(atrri); + test_load_failure(atrri); + test_load_files(atrri, argc, argv); + + CHK(atrri_ref_put(atrri) == RES_OK); + CHK(mem_allocated_size() == 0); + return 0; +}