htmie

Optical properties of water droplets
git clone git://git.meso-star.fr/htmie.git
Log | Files | Refs | README | LICENSE

commit 055c2e753c48994b92ef0f847fbeb2e4635ebe42
parent a0d29fbba1e21a8d36a381d5e67c4e9def08c05e
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 12 Jul 2018 16:57:30 +0200

Implement compute functions on cross sections

Compute the average or the boundaries for a given spectral band.

Diffstat:
Msrc/htmie.c | 193++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/htmie.h | 32++++++++++++++++++++++++++++++++
2 files changed, 209 insertions(+), 16 deletions(-)

diff --git a/src/htmie.c b/src/htmie.c @@ -449,6 +449,43 @@ massic_to_per_particle_xsections } static FINLINE double +interpolate_data + (const struct htmie* htmie, + const double wavelength, /* Input wavelength */ + const enum htmie_filter_type type, /* Interpolation type */ + const size_t idata, /* Id of the upper bound data wrt `wavelength' */ + const double* data) /* Data to interpolate */ +{ + const double* wlens; + double a, b, u; + double val; + ASSERT(data); + + wlens = htmie_get_wavelengths(htmie); + + ASSERT(idata < htmie_get_wavelengths_count(htmie)); + ASSERT(wlens[idata-1] < wavelength && wavelength <= wlens[idata-0]); + + a = data[idata-1]; + b = data[idata-0]; + u = (wavelength - wlens[idata-1]) / (wlens[idata] - wlens[idata-1]); + ASSERT(eq_eps(u, 1, 1.e-6) || u < 1); + ASSERT(eq_eps(u, 0, 1.e-6) || u > 0); + + switch(type) { + case HTMIE_FILTER_NEAREST: + val = u < 0.5 ? a : b; + break; + case HTMIE_FILTER_LINEAR: + CLAMP(u, 0, 1); /* Handle numerical inaccuracy */ + val = u*b + (1-u)*a; + break; + default: FATAL("Unreachable code.\n"); break; + } + return val; +} + +static FINLINE double fetch_data (const struct htmie* htmie, const double wavelength, @@ -474,26 +511,89 @@ fetch_data val = data[0]; } else { const size_t i = (size_t)(wlen_upp - wlens); - const double a = data[i-1]; - const double b = data[i-0]; - const double u = (wavelength - wlens[i-1]) / (wlens[i] - wlens[i-1]); - ASSERT(i < nwlens && (wlens[i] >= wavelength || wlens[i-1] <= wavelength)); - ASSERT(eq_eps(u, 1, 1.e-6) || u < 1); - - switch(type) { - case HTMIE_FILTER_NEAREST: - val = u < 0.5 ? a : b; - break; - case HTMIE_FILTER_LINEAR: - CLAMP(u, 0, 1); /* Handle numerical inaccuracy */ - val = u*b + (1-u)*a; - break; - default: FATAL("Unreachable code.\n"); break; - } + val = interpolate_data(htmie, wavelength, type, i, data); } return val; } +static FINLINE void +min_max(const double wavelength, const double data, void* ctx) +{ + double* bounds = ctx; + ASSERT(ctx); + (void)wavelength; + bounds[0] = MMIN(bounds[0], data); + bounds[1] = MMIN(bounds[1], data); +} + +static FINLINE void +add(const double wavelength, const double data, void* ctx) +{ + double* accum = ctx; + ASSERT(ctx); + (void)wavelength; + *accum += data; +} + +static INLINE void +for_each_wavelength_in_spectral_band + (const struct htmie* htmie, + const double band[2], /* Boundaries of the spectral band in nanometer */ + const enum htmie_filter_type type, + const double* data, /* Input data of the spectral band*/ + void (*op)(const double wavelength, const double data, void* ctx), + void* context) /* Sent as the last argument of the 'op' functor */ +{ + const double* wlens; + const double* wlen_low; + const double* wlen_upp; + double data_low; + double data_upp; + size_t ilow; + size_t iupp; + size_t nwlens; + size_t i; + ASSERT(htmie && band[0] <= band[1]); + + wlens = htmie_get_wavelengths(htmie); + nwlens = htmie_get_wavelengths_count(htmie); + ASSERT(nwlens); + + wlen_low = search_lower_bound + (&band[0], wlens, nwlens, sizeof(double), cmp_dbl); + wlen_upp = search_lower_bound + (&band[1], wlens, nwlens, sizeof(double), cmp_dbl); + + if(!wlen_low) { + ilow = nwlens; + data_low = data[nwlens - 1]; + } else if(wlen_low == wlens) { + ilow = 1; + data_low = data[0]; + } else { + ilow = (size_t)(wlen_low - wlens); + data_low = interpolate_data(htmie, band[0], type, ilow, data); + } + + if(!wlen_upp) { + iupp = nwlens; + data_upp = data[nwlens - 1]; + } else if(wlen_upp == wlens) { + iupp = 1; + data_upp = data[0]; + } else { + iupp = (size_t)(wlen_upp - wlens); + data_upp = interpolate_data(htmie, band[1], type, iupp, data); + } + + op(band[0], data_low, context); + FOR_EACH(i, ilow, iupp) { + op(wlens[i], data[i], context); + } + if(band[0] != band[1]) + op(band[1], data_upp, context); +} + static void release_htmie(ref_T* ref) { @@ -676,6 +776,67 @@ htmie_fetch_xsection_scattering (htmie, wavelength, type, htmie_get_xsections_scattering(htmie)); } + +void +htmie_compute_xsection_absorption_bounds + (const struct htmie* htmie, + const double band[2], /* Boundaries of the spectral band in nanometer */ + const enum htmie_filter_type type, + double bounds[2]) /* Min and Max scattering cross sections in m^2.kg^-1 */ +{ + const double* xsections; + ASSERT(htmie); + bounds[0] = DBL_MAX; + bounds[1] =-DBL_MAX; + xsections = darray_double_cdata_get(&htmie->xsections_absorption); + for_each_wavelength_in_spectral_band + (htmie, band, type, xsections, min_max, bounds); +} + +void +htmie_compute_xsection_scattering_bounds + (const struct htmie* htmie, + const double band[2], /* Boundaries of the spectral band in nanometer */ + const enum htmie_filter_type type, + double bounds[2]) /* Min and Max scattering cross sections in m^2.kg^-1 */ +{ + const double* xsections; + ASSERT(htmie); + bounds[0] = DBL_MAX; + bounds[1] =-DBL_MAX; + xsections = darray_double_cdata_get(&htmie->xsections_scattering); + for_each_wavelength_in_spectral_band + (htmie, band, type, xsections, min_max, bounds); +} + +double +htmie_compute_xsection_absorption_average + (const struct htmie* htmie, + const double band[2], /* Boundaries of of the spectral band in nanometer */ + const enum htmie_filter_type type) +{ + const double* xsections; + double sum = 0; + ASSERT(htmie && band[0] < band[1]); + xsections = darray_double_cdata_get(&htmie->xsections_absorption); + for_each_wavelength_in_spectral_band(htmie, band, type, xsections, add, &sum); + return sum / (band[1] - band[0]); +} + +double +htmie_compute_xsection_scattering_average + (const struct htmie* htmie, + const double band[2], /* Boundaries of of the spectral band in nanometer */ + const enum htmie_filter_type type) +{ + const double* xsections; + double sum = 0; + ASSERT(htmie && band[0] < band[1]); + xsections = darray_double_cdata_get(&htmie->xsections_scattering); + for_each_wavelength_in_spectral_band(htmie, band, type, xsections, add, &sum); + return sum / (band[1] - band[0]); +} + double htmie_fetch_asymmetric_parameter (const struct htmie* htmie, diff --git a/src/htmie.h b/src/htmie.h @@ -111,6 +111,38 @@ htmie_fetch_xsection_scattering const double wavelength, const enum htmie_filter_type type); +/* Compute the maximum and the minimum value of the absorption cross section in + * a given spectral interval */ +HTMIE_API void +htmie_compute_xsection_absorption_bounds + (const struct htmie* htmie, + const double band[2], /* Boundaries of the spectral band in nanometer */ + const enum htmie_filter_type type, + double bounds[2]); /* Min and Max scattering cross sections in m^2.kg^-1 */ + +/* Compute the maximum and the minimum value of the scattering cross section in + * a given spectral interval */ +HTMIE_API void +htmie_compute_xsection_scattering_bounds + (const struct htmie* htmie, + const double band[2], /* Boundaries of the spectral band in nanometer */ + const enum htmie_filter_type type, + double bounds[2]); /* Min and Max scattering cross sections in m^2.kg^-1 */ + +/* Compute the average absorption cross section in a given spectral interval */ +HTMIE_API double +htmie_compute_xsection_absorption_average + (const struct htmie* htmie, + const double band[2], /* Boundaries of of the spectral band in nanometer */ + const enum htmie_filter_type type); + +/* Compute the average scattering cross section in a given spectral interval */ +HTMIE_API double +htmie_compute_xsection_scattering_average + (const struct htmie* htmie, + const double band[2], /* Boundaries of of the spectral band in nanometer */ + const enum htmie_filter_type type); + HTMIE_API double htmie_fetch_asymmetric_parameter (const struct htmie* htmie,