schiff

Estimate the radiative properties of soft particless
git clone git://git.meso-star.com/schiff.git
Log | Files | Refs | README | LICENSE

commit 747d6686186a368619dbf1313e0e9bf047b6b6a0
parent 900372082fa4dc19fd75d7d76078cf57df796dc6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 29 Mar 2016 12:11:12 +0200

Major update of the schiff output

Write the cross sections, the phase function descriptors, the phase
functions, the cumulative phase functions and the inverse cumulative
phase functions. The [[inverse] cumulative] phase functions are
preceded by their associated value (an angle or a probability for the
inverse cumulative).

Diffstat:
Msrc/schiff.c | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/schiff_args.c | 11+++++++++++
2 files changed, 208 insertions(+), 56 deletions(-)

diff --git a/src/schiff.c b/src/schiff.c @@ -100,53 +100,22 @@ error: goto exit; } -static res_T -run_integration - (const struct schiff_args* args, - struct sschiff_geometry_distribution* distrib, - struct ssp_rng* rng, - FILE* stream) +static void +write_cross_sections + (FILE* stream, + struct sschiff_estimator* estimator, + const double* wlens, /* List of wavelengths in microns */ + const size_t nwlens) /* #wavelengths */ { - struct sschiff_device* sschiff = NULL; - struct sschiff_estimator* estimator = NULL; - const double* angles = NULL; - double* thetas = NULL; - size_t iwlen, nwlens; - size_t nangles; - res_T res = RES_OK; - ASSERT(args && sa_size(args->wavelengths) && rng && stream); - - res = sschiff_device_create(NULL, NULL, args->nthreads, 1, NULL, &sschiff); - if(res != RES_OK) { - fprintf(stderr, "Couldn't create the Star Schiff device.\n"); - goto error; - } - - if(!sa_add(thetas, args->nangles_inv)) { - fprintf(stderr, -"Couldn't allocate the list of inverse cumulative phase function angles.\n"); - res = RES_MEM_ERR; - goto error; - } + size_t iwlen; + ASSERT(stream && estimator && wlens && nwlens); - /* Invoke the Schiff integration */ - nwlens = sa_size(args->wavelengths); - res = sschiff_integrate(sschiff, rng, distrib, args->wavelengths, nwlens, - sschiff_uniform_scattering_angles, args->nangles, args->nrealisations, - args->ndirs, &estimator); - if(res != RES_OK) { - fprintf(stderr, "Schiff integration error.\n"); - goto error; - } - - /* Print the estimated cross sections */ FOR_EACH(iwlen, 0, nwlens) { const struct sschiff_state* val; struct sschiff_cross_section cross_section; SSCHIFF(estimator_get_cross_section(estimator, iwlen, &cross_section)); - - fprintf(stream, "%g ", args->wavelengths[iwlen]); + fprintf(stream, "%g ", wlens[iwlen]); val = &cross_section.extinction; fprintf(stream, "%g %g ", val->E, val->SE); @@ -158,9 +127,24 @@ run_integration fprintf(stream, "%g %g\n", val->E, val->SE); } fprintf(stream, "\n"); +} + +static void +write_phase_function_descriptors + (FILE* stream, + struct sschiff_estimator* estimator, + const double* wlens, /* List of wavelengths in microns */ + const size_t nwlens, /* #wavelenghts */ + const size_t nangles_inv) /* Number of inversed cumulative entries */ +{ + size_t iwlen; + const double* angles; + size_t nangles; + res_T res = RES_OK; + ASSERT(stream && estimator && wlens && nwlens && nangles_inv > 1); - /* Print the phase functions estimations */ SSCHIFF(estimator_get_scattering_angles(estimator, &angles, &nangles)); + FOR_EACH(iwlen, 0, nwlens) { size_t iangle; struct sschiff_state cdf, pf; @@ -168,13 +152,16 @@ run_integration res = sschiff_estimator_get_limit_scattering_angle_index (estimator, iwlen, &iangle); - if(res == RES_BAD_OP) { /* No valid limit angle => no phase function */ + + if(res == RES_BAD_OP) { + /* No valid limit angle => no phase function. Print -1 for all the data */ fprintf(stderr, "The phase function couldn't be computed.\n" - "wavelength = %g microns\n", args->wavelengths[iwlen]); - fprintf(stream, "-1 -1 -1 -1 -1 -1 -1\n"); - FOR_EACH(iangle, 0, args->nangles_inv) fprintf(stream, "-1\n"); + "wavelength = %g microns\n", wlens[iwlen]); + fprintf(stream, "-1 -1 -1 -1 -1 -1 -1 -1 -1\n"); + } else { + /* Retrieve the phase function descriptor data */ ASSERT(res == RES_OK); SSCHIFF(estimator_get_wide_scattering_angle_model_parameter (estimator, iwlen, &n)); @@ -183,30 +170,184 @@ run_integration SSCHIFF(estimator_get_differential_cross_section_cumulative (estimator, iwlen, iangle, &cdf)); - fprintf(stream, "%g %g %g %g %g %g %g\n", - args->wavelengths[iwlen], angles[iangle], pf.E, pf.SE, cdf.E, cdf.SE, n); + /* Write the phase function descriptor */ + fprintf(stream, "%g %g %g %g %g %g %g %lu %lu\n", + wlens[iwlen], angles[iangle], pf.E, pf.SE, cdf.E, cdf.SE, n, + (unsigned long)nangles, + (unsigned long)nangles_inv); + } + } + fprintf(stream, "\n"); /* Empty line */ +} + +static void +write_phase_functions + (FILE* stream, + const struct sschiff_estimator* estimator, + const double* wlens, + const size_t nwlens) +{ + size_t iwlen; + const double* angles; + const struct sschiff_state* phase_funcs; + size_t iangle, nangles; + ASSERT(stream && estimator && wlens && nwlens); + (void)wlens; + + SSCHIFF(estimator_get_scattering_angles(estimator, &angles, &nangles)); + FOR_EACH(iwlen, 0, nwlens) { + const res_T res = sschiff_estimator_get_phase_function + (estimator, iwlen, &phase_funcs); + if(res == RES_BAD_OP) { + /* The phase function couldn't be computed. Write default data. */ + FOR_EACH(iangle, 0, nangles) { + fprintf(stream, "-1 -1 -1\n"); + } + } else { + ASSERT(res == RES_OK); + FOR_EACH(iangle, 0, nangles) { + fprintf(stream, "%g %g %g\n", + angles[iangle], + phase_funcs[iangle].E, + phase_funcs[iangle].SE); + } + } + fprintf(stream, "\n"); + } +} + +static void +write_phase_functions_cum + (FILE* stream, + struct sschiff_estimator* estimator, + const double* wlens, + const size_t nwlens) +{ + size_t iwlen; + const double* angles; + const struct sschiff_state* phase_funcs_cum; + size_t iangle, nangles; + ASSERT(stream && estimator && wlens && nwlens); + (void)wlens; + + SSCHIFF(estimator_get_scattering_angles(estimator, &angles, &nangles)); + FOR_EACH(iwlen, 0, nwlens) { + const res_T res = sschiff_estimator_get_phase_function_cumulative + (estimator, iwlen, &phase_funcs_cum); + if(res == RES_BAD_OP) { + /* The cumulative phase func couldn't be computed. Write default data */ + FOR_EACH(iangle, 0, nangles) { + fprintf(stream, "-1 -1 -1\n"); + } + } else { + ASSERT(res == RES_OK); + FOR_EACH(iangle, 0, nangles) { + fprintf(stream, "%g %g %g\n", + angles[iangle], + phase_funcs_cum[iangle].E, + phase_funcs_cum[iangle].SE); + } + } + fprintf(stream, "\n"); + } +} + +static void +write_phase_functions_invcum + (FILE* stream, + struct sschiff_estimator* estimator, + const double* wlens, + const size_t nwlens, + const size_t nangles_inv) +{ + double* invcum = NULL; + size_t iangle; + size_t iwlen; + double step; + ASSERT(stream && estimator && wlens && nwlens && nangles_inv > 1); + + step = 1.0 / (double)(nangles_inv - 1); - res = sschiff_estimator_inverse_cumulative_phase_function - (estimator, iwlen, thetas, args->nangles_inv); + if(!sa_add(invcum, nangles_inv)) { + fprintf(stderr, + "Couldn't allocate the list of inverse cumulative phase function angles.\n"); + + /* Print the default -1 value */ + FOR_EACH(iwlen, 0, nwlens) { + FOR_EACH(iangle, 0, nangles_inv) { + fprintf(stream, "-1 -1\n"); + } + fprintf(stream, "\n"); + } + } else { + FOR_EACH(iwlen, 0, nwlens) { + const res_T res = sschiff_estimator_inverse_cumulative_phase_function + (estimator, iwlen, invcum, nangles_inv); if(res != RES_OK) { + /* The inverse cumulative cannot be computed. Write -1 */ fprintf(stderr, "Couldn't inverse the cumulative phase function.\n" - "wavelength = %g microns, n = %g\n", - args->wavelengths[iwlen], n); - FOR_EACH(iangle, 0, args->nangles_inv) fprintf(stream, "-1\n"); + "wavelength = %g microns\n", wlens[iwlen]); + FOR_EACH(iangle, 0, nangles_inv) { + fprintf(stream, "-1 -1\n"); + } } else { - FOR_EACH(iangle, 0, args->nangles_inv) { - fprintf(stream, "%g\n", thetas[iangle]); + /* Write the inverse cumulative values */ + FOR_EACH(iangle, 0, nangles_inv-1) { + fprintf(stream, "%g %g\n", (double)iangle*step, invcum[iangle]); } + /* Handle precision issues */ + fprintf(stream, "1 %g\n", invcum[nangles_inv-1]); } + fprintf(stream, "\n"); /* Empty line */ } - fprintf(stream, "\n"); } + if(invcum) + sa_release(invcum); +} + +static res_T +run_integration + (const struct schiff_args* args, + struct sschiff_geometry_distribution* distrib, + struct ssp_rng* rng, + FILE* stream) +{ + struct sschiff_device* sschiff = NULL; + struct sschiff_estimator* estimator = NULL; + size_t nwlens; + res_T res = RES_OK; + ASSERT(args && sa_size(args->wavelengths) && rng && stream); + + res = sschiff_device_create(NULL, NULL, args->nthreads, 1, NULL, &sschiff); + if(res != RES_OK) { + fprintf(stderr, "Couldn't create the Star Schiff device.\n"); + goto error; + } + + /* Invoke the Schiff integration */ + nwlens = sa_size(args->wavelengths); + res = sschiff_integrate(sschiff, rng, distrib, args->wavelengths, nwlens, + sschiff_uniform_scattering_angles, args->nangles, args->nrealisations, + args->ndirs, &estimator); + if(res != RES_OK) { + fprintf(stderr, "Schiff integration error.\n"); + goto error; + } + + /* Write results */ + write_cross_sections(stream, estimator, args->wavelengths, nwlens); + write_phase_function_descriptors + (stream, estimator, args->wavelengths, nwlens, args->nangles_inv); + write_phase_functions(stream, estimator, args->wavelengths, nwlens); + write_phase_functions_cum(stream, estimator, args->wavelengths, nwlens); + write_phase_functions_invcum + (stream, estimator, args->wavelengths, nwlens, args->nangles_inv); + exit: if(estimator) SSCHIFF(estimator_ref_put(estimator)); if(sschiff) SSCHIFF(device_ref_put(sschiff)); - if(thetas) sa_release(thetas); return res; error: goto exit; diff --git a/src/schiff_args.c b/src/schiff_args.c @@ -86,6 +86,14 @@ print_help(const char* binary) " integrate.\n\n"); } +static int +cmp_double(const void* op0, const void* op1) +{ + const double* a = op0; + const double* b = op1; + return *a < *b ? -1 : (*a > *b ? 1 : 0); +} + static INLINE void param_release(struct schiff_param* param) { @@ -1466,6 +1474,9 @@ schiff_args_init res = RES_BAD_ARG; goto error; } + /* Sort the submitted wavelengths in ascending order */ + qsort(args->wavelengths, sa_size(args->wavelengths), + sizeof(args->wavelengths[0]), cmp_double); if(args->characteristic_length < 0.0) { fprintf(stderr,