star-schiff

Library for estimating radiative properties
git clone git://git.meso-star.com/star-schiff.git
Log | Files | Refs | README | LICENSE

test_sschiff_estimator_sphere.c (17869B)


      1 /* Copyright (C) 2015, 2016, 2026 Centre National de la Recherche Scientifique
      2  * Copyright (C) 2026 Clermont Auvergne INP
      3  * Copyright (C) 2026 Institut Mines Télécom Albi-Carmaux
      4  * Copyright (C) 2020, 2021, 2023, 2026 |Méso|Star> (contact@meso-star.com)
      5  * Copyright (C) 2026 Université de Lorraine
      6  * Copyright (C) 2026 Université de Toulouse
      7  *
      8  * This program is free software: you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation, either version 3 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     20 
     21 #include "sschiff.h"
     22 #include "test_sschiff_utils.h"
     23 
     24 #include <rsys/clock_time.h>
     25 #include <rsys/float3.h>
     26 #include <rsys/stretchy_array.h>
     27 
     28 #include <star/s3d.h>
     29 #include <star/ssp.h>
     30 
     31 struct result {
     32   double mean_radius; /* In micron */
     33   double absorption_cross_section;
     34   double scattering_cross_section;
     35   double extinction_cross_section;
     36 };
     37 
     38 struct sampler_context {
     39   struct geometry geometry;
     40   double wavelength; /* In micron */
     41   double medium_refractive_index;
     42   double relative_real_refractive_index;
     43   double relative_imaginary_refractive_index;
     44   double mean_radius; /* In micron */
     45   double sigma;
     46 };
     47 
     48 static void
     49 get_material_property
     50   (void* mtl,
     51    const double wavelength,
     52    struct sschiff_material_properties* properties)
     53 {
     54   struct sampler_context* ctx = mtl;
     55 
     56   CHK(mtl != NULL);
     57   CHK(properties != NULL);
     58   CHK(eq_eps(ctx->wavelength, wavelength, 1.e-8) == 1);
     59 
     60   properties->medium_refractive_index = ctx->medium_refractive_index;
     61   properties->relative_real_refractive_index =
     62     ctx->relative_real_refractive_index;
     63   properties->relative_imaginary_refractive_index =
     64     ctx->relative_imaginary_refractive_index;
     65 }
     66 
     67 static res_T
     68 sample_sphere
     69   (struct ssp_rng* rng,
     70    void** shape_data,
     71    struct s3d_shape* shape,
     72    void* sampler_context)
     73 {
     74   struct sampler_context* sampler_ctx = sampler_context;
     75   struct sphere sphere;
     76   CHK(rng && shape_data);
     77 
     78   sphere.geometry = &sampler_ctx->geometry;
     79   sphere.radius = (float)ssp_ran_lognormal
     80     (rng, log(sampler_ctx->mean_radius), log(sampler_ctx->sigma));
     81 
     82   *shape_data = NULL;
     83 
     84   return sphere_setup_s3d_shape(&sphere, shape);
     85 }
     86 
     87 static void
     88 check_schiff_estimation
     89   (struct sschiff_device* dev,
     90    struct ssp_rng* rng,
     91    struct sampler_context* sampler_ctx,
     92    const struct result* results,
     93    const size_t nresults)
     94 {
     95   char buf[64];
     96   struct sschiff_estimator* estimator;
     97   struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION;
     98   struct sschiff_cross_section cross_section;
     99   struct time t0, t1;
    100   size_t i;
    101 
    102   const size_t nscatt_angles = 1000;
    103   const size_t ngeoms = 100;
    104   const size_t ndirs = 100;
    105   const double wavelength = sampler_ctx->wavelength;
    106 
    107   CHK(sampler_ctx != NULL);
    108   CHK(results != NULL);
    109   CHK(results != 0);
    110 
    111   distrib.material.get_property = get_material_property;
    112   distrib.material.material = sampler_ctx;
    113   distrib.sample = sample_sphere;
    114   distrib.context = sampler_ctx;
    115 
    116   printf("Schiff sphere estimation - m: %g; n_r: %g; kappa_r: %g; n_e: %g\n",
    117     sampler_ctx->wavelength,
    118     sampler_ctx->relative_real_refractive_index,
    119     sampler_ctx->relative_imaginary_refractive_index,
    120     sampler_ctx->medium_refractive_index);
    121 
    122   FOR_EACH(i, 0, nresults) {
    123     const struct sschiff_state* val;
    124     double dst;
    125 
    126     sampler_ctx->mean_radius = results[i].mean_radius;
    127     distrib.characteristic_length = sampler_ctx->mean_radius * 2.0;
    128 
    129     time_current(&t0);
    130     CHK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1,
    131       sschiff_uniform_scattering_angles, nscatt_angles, ngeoms, ndirs, 0, &estimator)
    132     == RES_OK);
    133     time_current(&t1);
    134     time_sub(&t0, &t1, &t0);
    135     time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf));
    136     printf("%d - mean radius: %5.2f micron - %s: \n", (int)i, results[i].mean_radius, buf);
    137 
    138     CHK(sschiff_estimator_get_cross_sections(estimator, &cross_section) == RES_OK);
    139 
    140     val = &cross_section.extinction;
    141     dst = val->E - results[i].extinction_cross_section;
    142     printf("  Extinction cross section = %7.2f ~ %12.7f +/- %12.7f (%6.2f)\n",
    143       results[i].extinction_cross_section, val->E, val->SE, dst / val->SE);
    144     CHK(eq_eps(val->E, results[i].extinction_cross_section, 4*val->SE) == 1);
    145 
    146     val = &cross_section.absorption;
    147     dst = val->E - results[i].absorption_cross_section;
    148     printf("  Absorption cross section = %7.2f ~ %12.7f +/- %12.7f (%6.2f)\n",
    149       results[i].absorption_cross_section, val->E, val->SE, dst / val->SE);
    150     CHK(eq_eps(val->E, results[i].absorption_cross_section, 4*val->SE) == 1);
    151 
    152     val = &cross_section.scattering;
    153     dst = val->E - results[i].scattering_cross_section;
    154     printf("  Scattering cross section = %7.2f ~ %12.7f +/- %12.7f (%6.2f)\n",
    155       results[i].scattering_cross_section, val->E, val->SE, dst / val->SE);
    156     CHK(eq_eps(val->E, results[i].scattering_cross_section, 4*val->SE) == 1);
    157 
    158     val = &cross_section.average_projected_area;
    159     printf("  Averavege projected area = %12.7g +/- %12.7g\n", val->E, val->SE);
    160 
    161     CHK(sschiff_estimator_ref_put(estimator) == RES_OK);
    162   }
    163 }
    164 
    165 int
    166 main(int argc, char** argv)
    167 {
    168   struct mem_allocator allocator;
    169   struct sampler_context sampler_ctx;
    170   struct sschiff_device* dev;
    171   struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION;
    172   struct sschiff_estimator* estimator;
    173   struct sschiff_cross_section cross_section;
    174   struct ssp_rng* rng;
    175   const struct result results_n_r_1_01[] = {
    176     { 1.00, 0.484, 0.159, 0.643 },
    177     { 3.22, 13.4,  13.2,  26.6 },
    178     { 5.44, 54.6,  79.6,  134 },
    179     { 7.67, 131,   225,   356 },
    180     { 9.89, 243,   440,   683 },
    181     { 12.1, 393,   691,   1080 },
    182     { 14.3, 578,   951,   1530 },
    183     { 16.6, 799,   1200,  2000 },
    184     { 18.8, 1060,  1460,  2510 },
    185     { 21.0, 1350,  1730,  3070 }
    186   };
    187   const struct result results_n_r_1_1[] = {
    188     { 1.00, 0.484, 7.90, 8.39 },
    189     { 3.22, 13.4,  55.9, 69.3 },
    190     { 5.44, 54.6,  143,  197 },
    191     { 7.67, 131,   261,  392 },
    192     { 9.89, 243,   408,  651 },
    193     { 12.1, 393,   582,  975 },
    194     { 14.3, 578,   787,  1370 },
    195     { 16.6, 799,   1020, 1820 },
    196     { 19.0, 1080,  1310, 2390 },
    197     { 21.0, 1350,  1580, 2930 }
    198   };
    199   const double wlen = 0.6; /* Micron */
    200   double wlens[3] = { 0, 0, 0 };
    201   const double* dbls = NULL;
    202   size_t i, count;
    203   (void)argc, (void)argv;
    204 
    205   mem_init_proxy_allocator(&allocator, &mem_default_allocator);
    206 
    207   CHK(ssp_rng_create(&allocator, SSP_RNG_THREEFRY, &rng) == RES_OK);
    208   CHK(sschiff_device_create
    209     (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 1, NULL, &dev) == RES_OK);
    210 
    211   geometry_init_sphere(&sampler_ctx.geometry, 64);
    212 
    213   sampler_ctx.wavelength = wlen;
    214   sampler_ctx.relative_real_refractive_index = 1.1;
    215   sampler_ctx.relative_imaginary_refractive_index = 0.004;
    216   sampler_ctx.medium_refractive_index = 4.0/3.0;
    217   sampler_ctx.mean_radius = 1.0;
    218   sampler_ctx.sigma = 1.18;
    219 
    220   distrib.material.get_property = get_material_property;
    221   distrib.material.material = &sampler_ctx;
    222   distrib.characteristic_length = 1;
    223   distrib.sample = sample_sphere;
    224   distrib.context = &sampler_ctx;
    225 
    226   CHK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    227   CHK(sschiff_integrate(dev, NULL, NULL, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    228   CHK(sschiff_integrate(NULL, rng, NULL, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    229   CHK(sschiff_integrate(dev, rng, NULL, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    230   CHK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    231   CHK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    232   CHK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    233   CHK(sschiff_integrate(dev, rng, &distrib, NULL, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    234   CHK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    235   CHK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    236   CHK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    237   CHK(sschiff_integrate(dev, rng, NULL, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    238   CHK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    239   CHK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    240   CHK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    241   CHK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    242   CHK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    243   CHK(sschiff_integrate(dev, NULL, NULL, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    244   CHK(sschiff_integrate(NULL, rng, NULL, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    245   CHK(sschiff_integrate(dev, rng, NULL, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    246   CHK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    247   CHK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    248   CHK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    249   CHK(sschiff_integrate(dev, rng, &distrib, NULL, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    250   CHK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    251   CHK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    252   CHK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    253   CHK(sschiff_integrate(dev, rng, NULL, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    254   CHK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    255   CHK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    256   CHK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    257   CHK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, NULL) == RES_BAD_ARG);
    258   CHK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    259   CHK(sschiff_integrate(dev, NULL, NULL, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    260   CHK(sschiff_integrate(NULL, rng, NULL, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    261   CHK(sschiff_integrate(dev, rng, NULL, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    262   CHK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    263   CHK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    264   CHK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    265   CHK(sschiff_integrate(dev, rng, &distrib, NULL, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    266   CHK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    267   CHK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    268   CHK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    269   CHK(sschiff_integrate(dev, rng, NULL, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    270   CHK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    271   CHK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    272   CHK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    273   CHK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    274   CHK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    275   CHK(sschiff_integrate(dev, NULL, NULL, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    276   CHK(sschiff_integrate(NULL, rng, NULL, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    277   CHK(sschiff_integrate(dev, rng, NULL, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    278   CHK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    279   CHK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    280   CHK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    281   CHK(sschiff_integrate(dev, rng, &distrib, NULL, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    282   CHK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    283   CHK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    284   CHK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    285   CHK(sschiff_integrate(dev, rng, NULL, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    286   CHK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    287   CHK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    288   CHK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    289   CHK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    290 
    291   CHK(sschiff_integrate(dev, rng, &distrib, &wlen, 1,
    292     sschiff_uniform_scattering_angles, 1, 1, 1, 0, &estimator) == RES_BAD_ARG);
    293   CHK(sschiff_integrate(dev, rng, &distrib, &wlen, 1,
    294     sschiff_uniform_scattering_angles, 10, 1000, 1, 0, &estimator) == RES_OK);
    295 
    296   CHK(sschiff_estimator_get_wavelengths(NULL, NULL, NULL) == RES_BAD_ARG);
    297   CHK(sschiff_estimator_get_wavelengths(estimator, NULL, NULL) == RES_OK);/*Useless*/
    298   CHK(sschiff_estimator_get_wavelengths(NULL, NULL, &count) == RES_BAD_ARG);
    299   CHK(sschiff_estimator_get_wavelengths(estimator, NULL, &count) == RES_OK);
    300   CHK(count == 1);
    301   CHK(sschiff_estimator_get_wavelengths(NULL, &dbls, NULL) == RES_BAD_ARG);
    302   CHK(sschiff_estimator_get_wavelengths(estimator, &dbls, NULL) == RES_OK);
    303   CHK(dbls[0] == wlen);
    304   CHK(sschiff_estimator_get_wavelengths(NULL, &dbls, &count) == RES_BAD_ARG);
    305   CHK(sschiff_estimator_get_wavelengths(estimator, &dbls, &count) == RES_OK);
    306   CHK(dbls[0] == wlen);
    307   CHK(count == 1);
    308 
    309   CHK(sschiff_estimator_get_scattering_angles(NULL, NULL, NULL) == RES_BAD_ARG);
    310   CHK(sschiff_estimator_get_scattering_angles(estimator, NULL, NULL) == RES_OK); /* Useless */
    311   CHK(sschiff_estimator_get_scattering_angles(NULL, NULL, &count) == RES_BAD_ARG);
    312   CHK(sschiff_estimator_get_scattering_angles(estimator, NULL, &count) == RES_OK);
    313   CHK(count == 10);
    314   CHK(sschiff_estimator_get_scattering_angles(NULL, &dbls, NULL) == RES_BAD_ARG);
    315   CHK(sschiff_estimator_get_scattering_angles(estimator, &dbls, NULL) == RES_OK); /* Useless */
    316   FOR_EACH(i, 0, count)
    317     CHK(eq_eps(dbls[i], (double)i*PI/((double)count-1), 1.e-6) == 1);
    318   CHK(sschiff_estimator_get_scattering_angles(NULL, &dbls, &count) == RES_BAD_ARG);
    319   CHK(sschiff_estimator_get_scattering_angles(estimator, &dbls, &count) == RES_OK);
    320   FOR_EACH(i, 0, count)
    321     CHK(eq_eps(dbls[i], (double)i*PI/((double)count-1), 1.e-6) == 1);
    322   CHK(count == 10);
    323 
    324   CHK(sschiff_estimator_get_realisations_count(NULL, NULL) == RES_BAD_ARG);
    325   CHK(sschiff_estimator_get_realisations_count(estimator, NULL) == RES_BAD_ARG);
    326   CHK(sschiff_estimator_get_realisations_count(NULL, &count) == RES_BAD_ARG);
    327   CHK(sschiff_estimator_get_realisations_count(estimator, &count) == RES_OK);
    328   CHK(count == 1000);
    329 
    330   CHK(sschiff_estimator_get_cross_section(NULL, 1, NULL) == RES_BAD_ARG);
    331   CHK(sschiff_estimator_get_cross_section(estimator, 1, NULL) == RES_BAD_ARG);
    332   CHK(sschiff_estimator_get_cross_section(NULL, 1, &cross_section) == RES_BAD_ARG);
    333   CHK(sschiff_estimator_get_cross_section(estimator, 1, &cross_section) == RES_BAD_ARG);
    334   CHK(sschiff_estimator_get_cross_section(NULL, 0, NULL) == RES_BAD_ARG);
    335   CHK(sschiff_estimator_get_cross_section(estimator, 0, NULL) == RES_BAD_ARG);
    336   CHK(sschiff_estimator_get_cross_section(NULL, 0, &cross_section) == RES_BAD_ARG);
    337   CHK(sschiff_estimator_get_cross_section(estimator, 0, &cross_section) == RES_OK);
    338 
    339   CHK(sschiff_estimator_ref_get(NULL) == RES_BAD_ARG);
    340   CHK(sschiff_estimator_ref_get(estimator) == RES_OK);
    341   CHK(sschiff_estimator_ref_put(NULL) == RES_BAD_ARG);
    342   CHK(sschiff_estimator_ref_put(estimator) == RES_OK);
    343   CHK(sschiff_estimator_ref_put(estimator) == RES_OK);
    344 
    345   wlens[0] = 0.2, wlens[1] = 0.6, wlens[2] = 0.4;
    346   CHK(sschiff_integrate(dev, rng, &distrib, wlens, 3,
    347     sschiff_uniform_scattering_angles, 10, 1000, 1, 0, &estimator) == RES_BAD_ARG);
    348 
    349   CHK(sschiff_integrate(dev, rng, &distrib, &wlen, 1,
    350     sschiff_uniform_scattering_angles, 2, 1, 1, 1, &estimator) == RES_OK);
    351   CHK(sschiff_estimator_ref_put(estimator) == RES_OK);
    352 
    353   sampler_ctx.relative_real_refractive_index = 1.1;
    354   check_schiff_estimation(dev, rng, &sampler_ctx, results_n_r_1_1,
    355     sizeof(results_n_r_1_1)/sizeof(struct result));
    356 
    357   printf("\n");
    358   sampler_ctx.relative_real_refractive_index = 1.01;
    359   check_schiff_estimation(dev, rng, &sampler_ctx, results_n_r_1_01,
    360     sizeof(results_n_r_1_01)/sizeof(struct result));
    361 
    362   CHK(sschiff_device_ref_put(dev) == RES_OK);
    363   CHK(ssp_rng_ref_put(rng) == RES_OK);
    364 
    365   geometry_release(&sampler_ctx.geometry);
    366   check_memory_allocator(&allocator);
    367   mem_shutdown_proxy_allocator(&allocator);
    368   CHK(mem_allocated_size() == 0);
    369   return 0;
    370 }
    371