schiff

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

commit 1279c65ed70567198a98237457e91319247a1951
parent d95149b1c8a679f6726611c39c987bc42def30e8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 23 Oct 2015 16:18:09 +0200

Refactor the Schiff mesh generation

Replace the ad-hock mesh data structure by the sbox_schiff_mesh
structure. Store mesh data in dynamic array rather than stretchy arrays
in order to handle memory allocation errors.

Diffstat:
Mcmake/CMakeLists.txt | 10++++++----
Asrc/sbox_schiff_mesh.c | 191+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sbox_schiff_mesh.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/sbox_schiff_sphere.c | 227++++++++++++++++++++++++++++---------------------------------------------------
4 files changed, 333 insertions(+), 151 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -64,12 +64,14 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SBOX_SCHIFF_FILES_SRC sbox_schiff.c - sbox_schiff_sphere.c - sbox_schiff_optical_properties.c) + sbox_schiff_mesh.c + sbox_schiff_optical_properties.c + sbox_schiff_sphere.c) set(SBOX_SCHIFF_FILES_INC sbox_schiff.h - sbox_schiff_sphere.h - sbox_schiff_optical_properties.h) + sbox_schiff_mesh.h + sbox_schiff_optical_properties.h + sbox_schiff_sphere.h) set(SBOX_SCHIFF_FILES_DOC COPYING.fr COPYING.en README.md) # Prepend each file in the `SBOX_SCHIFF_FILES_<SRC|INC>' list by the absolute diff --git a/src/sbox_schiff_mesh.c b/src/sbox_schiff_mesh.c @@ -0,0 +1,191 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#include "sbox_schiff_mesh.h" +#include <rsys/float3.h> + +struct sin_cos { double sinus, cosine; }; + +#define DARRAY_NAME sincos +#define DARRAY_DATA struct sin_cos +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +sbox_schiff_mesh_init_sphere + (struct mem_allocator* allocator, + struct sbox_schiff_mesh* sphere, + const unsigned nthetas) +{ + /* Theta in [0, 2PI[ and phi in [0, PI[ */ + const unsigned nphis = (unsigned)(((double)nthetas + 0.5) / 2.0); + const double step_theta = 2*PI / (double)nthetas; + const double step_phi = PI / (double)nphis; + struct darray_sincos sincos_thetas; + struct darray_sincos sincos_phis; + size_t nverts; + size_t ntris; + size_t i; + unsigned itheta, iphi; + res_T res = RES_OK; + ASSERT(allocator && sphere && nthetas); + + darray_float_init(allocator, &sphere->vertices); + darray_uint_init(allocator, &sphere->indices); + darray_sincos_init(allocator, &sincos_thetas); + darray_sincos_init(allocator, &sincos_phis); + + nverts = nthetas*(nphis-1)/* #contour verts */ + 2/* polar verts */; + ntris = 2*nthetas*(nphis-2)/* #contour tris */ + 2*nthetas/* #polar tris */; + + res = darray_float_resize(&sphere->vertices, nverts * 3/*#coords per vert*/); + if(res != RES_OK) goto error; + res = darray_uint_resize(&sphere->indices, ntris * 3/*#indices per tri*/); + if(res != RES_OK) goto error; + res = darray_sincos_resize(&sincos_thetas, nthetas); + if(res != RES_OK) goto error; + res = darray_sincos_resize(&sincos_phis, nphis); + if(res != RES_OK) goto error; + + /* Precompute the cosine/sinus of the theta/phi angles */ + FOR_EACH(itheta, 0, nthetas) { + const double theta = -PI + (double)itheta * step_theta; + darray_sincos_data_get(&sincos_thetas)[itheta].sinus = sin(theta); + darray_sincos_data_get(&sincos_thetas)[itheta].cosine = cos(theta); + } + FOR_EACH(iphi, 1, nphis) { + const double phi = -PI/2 + (double)iphi * step_phi; + darray_sincos_data_get(&sincos_phis)[iphi].sinus = sin(phi); + darray_sincos_data_get(&sincos_phis)[iphi].cosine = cos(phi); + } + + /* Build the contour vertices */ + i = 0; + FOR_EACH(itheta, 0, nthetas) { + const struct sin_cos* theta = darray_sincos_data_get(&sincos_thetas) + itheta; + FOR_EACH(iphi, 0, nphis-1) { + const struct sin_cos* phi = darray_sincos_data_get(&sincos_phis) + iphi; + darray_float_data_get(&sphere->vertices)[i++] = (float)(theta->cosine * phi->cosine); + darray_float_data_get(&sphere->vertices)[i++] = (float)(theta->sinus * phi->cosine); + darray_float_data_get(&sphere->vertices)[i++] = (float)phi->sinus; + } + } + /* Setup polar vertices */ + f3(darray_float_data_get(&sphere->vertices) + i + 0, 0.f, 0.f,-1.f); + f3(darray_float_data_get(&sphere->vertices) + i + 3, 0.f, 0.f, 1.f); + + /* Define the indices of the contour primitives */ + i = 0; + FOR_EACH(itheta, 0, nthetas) { + const unsigned itheta0 = itheta * (nphis - 1); + const unsigned itheta1 = ((itheta + 1) % nthetas) * (nphis - 1); + FOR_EACH(iphi, 0, nphis-2) { + const unsigned iphi0 = iphi + 0; + const unsigned iphi1 = iphi + 1; + + darray_uint_data_get(&sphere->indices)[i++] = itheta0 + iphi0; + darray_uint_data_get(&sphere->indices)[i++] = itheta0 + iphi1; + darray_uint_data_get(&sphere->indices)[i++] = itheta1 + iphi0; + + darray_uint_data_get(&sphere->indices)[i++] = itheta1 + iphi0; + darray_uint_data_get(&sphere->indices)[i++] = itheta0 + iphi1; + darray_uint_data_get(&sphere->indices)[i++] = itheta1 + iphi1; + } + } + + /* Define the indices of the polar primitives */ + FOR_EACH(itheta, 0, nthetas) { + const unsigned itheta0 = itheta * (nphis - 1); + const unsigned itheta1 = ((itheta + 1) % nthetas) * (nphis - 1); + + darray_uint_data_get(&sphere->indices)[i++] = nthetas * (nphis - 1); + darray_uint_data_get(&sphere->indices)[i++] = itheta0; + darray_uint_data_get(&sphere->indices)[i++] = itheta1; + + darray_uint_data_get(&sphere->indices)[i++] = nthetas * (nphis - 1) + 1; + darray_uint_data_get(&sphere->indices)[i++] = itheta1 + (nphis - 2); + darray_uint_data_get(&sphere->indices)[i++] = itheta0 + (nphis - 2); + } + +exit: + darray_sincos_release(&sincos_thetas); + darray_sincos_release(&sincos_phis); + return res; +error: + sbox_schiff_mesh_release(sphere); + goto exit; +} + +void +sbox_schiff_mesh_release(struct sbox_schiff_mesh* mesh) +{ + ASSERT(mesh); + darray_float_release(&mesh->vertices); + darray_uint_release(&mesh->indices); +} + +res_T +sbox_schiff_mesh_dump(struct sbox_schiff_mesh* mesh, const char* filename) +{ + FILE* fp = NULL; + size_t nverts, ntris; + size_t i; + res_T res = RES_OK; + ASSERT(mesh && filename); + ASSERT(darray_float_size_get(&mesh->vertices) % 3 == 0); /* 3D */ + ASSERT(darray_uint_size_get(&mesh->indices) % 3 == 0); /* Triangles */ + + fp = fopen(filename, "r"); + if(!fp) { + res = RES_IO_ERR; + goto error; + } + + nverts = darray_float_size_get(&mesh->vertices) / 3; + FOR_EACH(i, 0, nverts) { + fprintf(fp, "v %f %f %f\n", + SPLIT3(darray_float_data_get(&mesh->vertices) + i*3)); + } + + ntris = darray_uint_size_get(&mesh->indices) / 3; + FOR_EACH(i, 0, ntris) { + fprintf(fp, "f %u %u %u\n", + darray_uint_data_get(&mesh->indices)[i*3 + 0], + darray_uint_data_get(&mesh->indices)[i*3 + 1], + darray_uint_data_get(&mesh->indices)[i*3 + 2]); + } + +exit: + if(fp) fclose(fp); + return res; +error: + goto exit; +} + diff --git a/src/sbox_schiff_mesh.h b/src/sbox_schiff_mesh.h @@ -0,0 +1,56 @@ +/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#ifndef SBOX_SCHIFF_MESH_H +#define SBOX_SCHIFF_MESH_H + +#include <rsys/dynamic_array_float.h> +#include <rsys/dynamic_array_uint.h> + +struct sbox_schiff_mesh { + struct darray_float vertices; + struct darray_uint indices; +}; + +extern LOCAL_SYM res_T +sbox_schiff_mesh_init_sphere + (struct mem_allocator* alocator, + struct sbox_schiff_mesh* mesh, + const unsigned nthetas); /* # discret points along 2PI */ + +extern LOCAL_SYM void +sbox_schiff_mesh_release + (struct sbox_schiff_mesh* mesh); + +extern LOCAL_SYM res_T +sbox_schiff_mesh_dump + (struct sbox_schiff_mesh* mesh, + const char* filename); + +#endif /* SBOX_SCHIFF_MESH_H */ + diff --git a/src/sbox_schiff_sphere.c b/src/sbox_schiff_sphere.c @@ -29,6 +29,7 @@ #define _POSIX_C_SOURCE 2 /* getopt support */ #include "sbox_schiff.h" +#include "sbox_schiff_mesh.h" #include "sbox_schiff_optical_properties.h" #include "sbox_schiff_sphere.h" @@ -47,7 +48,6 @@ #include <unistd.h> #endif - /* Default values */ #define NDIRS 100 #define NGEOMS 1000 @@ -55,6 +55,7 @@ #define SIGMA 1.0 #define NTHETAS 64 +/* Argument of the schiff sphere command */ struct schiff_sphere_args { const char* material; const char* output; @@ -71,23 +72,18 @@ static const struct schiff_sphere_args SCHIFF_SPHERE_ARGS_NULL = { NULL, NULL, NULL, NULL, RADIUS, SIGMA, NDIRS, NGEOMS, NTHETAS }; -struct mesh { - unsigned* indices; - float* vertices; -}; - -static const struct mesh MESH_NULL = { NULL, NULL }; - +/* Sphere geometry */ struct sphere { - struct mesh* mesh; - float radius; + struct sbox_schiff_mesh* mesh; /* Triangular mesh of an unit sphere */ + float radius; /* Sphere radius */ }; +/* Geometry distribution of a sphere */ struct schiff_sphere_geometry_distribution_context { - struct mesh* mesh; - struct sbox_schiff_optical_properties* properties; - double mean_radius; - double sigma; + struct sbox_schiff_mesh* mesh; /* Triangular mesh of an unit sphere */ + struct sbox_schiff_optical_properties* properties; /* Per wavelength properties */ + double mean_radius; /* Mean radius of the log normal sphere distribution */ + double sigma; /* Sigma argument of the log normal sphere distribution */ }; /******************************************************************************* @@ -105,9 +101,7 @@ cmp_properties(const void* op0, const void* op1) { const struct sbox_schiff_optical_properties* prop0 = op0; const struct sbox_schiff_optical_properties* prop1 = op1; - if (prop0->W < prop1->W) return -1; - else if(prop0->W > prop1->W) return 1; - else return 0; + return prop0->W < prop1->W ? -1 : (prop0->W > prop1->W ? 1 : 0); } static void @@ -115,23 +109,22 @@ get_indices(const unsigned itri, unsigned ids[3], void* ctx) { struct sphere* sphere = ctx; const size_t i = itri * 3; - ASSERT(sa_size(sphere->mesh->indices) % 3 == 0); - ASSERT(itri < sa_size(sphere->mesh->indices) / 3); - ids[0] = sphere->mesh->indices[i + 0]; - ids[1] = sphere->mesh->indices[i + 1]; - ids[2] = sphere->mesh->indices[i + 2]; + ASSERT(darray_uint_size_get(&sphere->mesh->indices) % 3 == 0); + ASSERT(itri < darray_uint_size_get(&sphere->mesh->indices) / 3); + ids[0] = darray_uint_data_get(&sphere->mesh->indices)[i + 0]; + ids[1] = darray_uint_data_get(&sphere->mesh->indices)[i + 1]; + ids[2] = darray_uint_data_get(&sphere->mesh->indices)[i + 2]; } -static INLINE void +static void get_position(const unsigned ivert, float vertex[3], void* ctx) { struct sphere* sphere = ctx; const size_t i = ivert * 3; - ASSERT(sa_size(sphere->mesh->vertices) % 3 == 0); - ASSERT(ivert < sa_size(sphere->mesh->vertices) / 3); - vertex[0] = sphere->mesh->vertices[i + 0] * sphere->radius; - vertex[1] = sphere->mesh->vertices[i + 1] * sphere->radius; - vertex[2] = sphere->mesh->vertices[i + 2] * sphere->radius; + ASSERT(darray_float_size_get(&sphere->mesh->vertices) % 3 == 0); + ASSERT(ivert < darray_float_size_get(&sphere->mesh->vertices) / 3); + f3_set(vertex, darray_float_data_get(&sphere->mesh->vertices) + i); + f3_mulf(vertex, vertex, sphere->radius); } static void @@ -146,7 +139,7 @@ get_material_property size_t i; /* Assume that properties are sorted in ascending order with respect to the - * wavelength. TODO use a binary search */ + * wavelength. TODO use a binary search of the upper bound */ FOR_EACH(i, 0, nproperties) { if(properties[i].W >= wavelength) break; @@ -161,9 +154,10 @@ get_material_property const size_t i_prev = i - 1; const double d = properties[i].W - properties[i_prev].W; const double u = (wavelength - properties[i_prev].W) / d; - Ne = u * properties[i].Ne + (1-u) * properties[i_prev].Ne; - Kr = u * properties[i].Kr + (1-u) * properties[i_prev].Kr; - Nr = u * properties[i].Nr + (1-u) * properties[i_prev].Nr; + const double v = 1.0 - u; + Ne = u * properties[i].Ne + v * properties[i_prev].Ne; + Kr = u * properties[i].Kr + v * properties[i_prev].Kr; + Nr = u * properties[i].Nr + v * properties[i_prev].Nr; } NCHECK(props, NULL); @@ -172,93 +166,6 @@ get_material_property props->relative_real_refractive_index = Nr; } -static void -mesh_init_sphere(struct mesh* sphere, const unsigned ntheta) -{ - const unsigned nphi = (unsigned)(((double)ntheta + 0.5) / 2.0); - const double step_theta = 2*PI / (double)ntheta; - const double step_phi = PI / (double)nphi; - double* cos_theta = NULL; - double* sin_theta = NULL; - double* cos_phi = NULL; - double* sin_phi = NULL; - unsigned itheta, iphi; - ASSERT(sphere && ntheta); - - sphere->vertices = NULL; - sphere->indices = NULL; - - /* Precompute the cosine/sinus of the theta/phi angles */ - FOR_EACH(itheta, 0, ntheta) { - const double theta = -PI + (double)itheta * step_theta; - sa_push(cos_theta, cos(theta)); - sa_push(sin_theta, sin(theta)); - } - FOR_EACH(iphi, 1, nphi) { - const double phi = -PI/2 + (double)iphi * step_phi; - sa_push(cos_phi, cos(phi)); - sa_push(sin_phi, sin(phi)); - } - /* Compute the contour vertices */ - FOR_EACH(itheta, 0, ntheta) { - FOR_EACH(iphi, 0, nphi-1) { - sa_push(sphere->vertices, (float)(cos_theta[itheta]*cos_phi[iphi])); - sa_push(sphere->vertices, (float)(sin_theta[itheta]*cos_phi[iphi])); - sa_push(sphere->vertices, (float)sin_phi[iphi]); - } - } - /* Compute the polar vertices */ - f3(sa_add(sphere->vertices, 3), 0.f, 0.f,-1.f); - f3(sa_add(sphere->vertices, 3), 0.f, 0.f, 1.f); - - /* Define the indices of the contour primitives */ - FOR_EACH(itheta, 0, ntheta) { - const unsigned itheta0 = itheta * (nphi - 1); - const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); - FOR_EACH(iphi, 0, nphi-2) { - const unsigned iphi0 = iphi + 0; - const unsigned iphi1 = iphi + 1; - - sa_push(sphere->indices, itheta0 + iphi0); - sa_push(sphere->indices, itheta0 + iphi1); - sa_push(sphere->indices, itheta1 + iphi0); - - sa_push(sphere->indices, itheta1 + iphi0); - sa_push(sphere->indices, itheta0 + iphi1); - sa_push(sphere->indices, itheta1 + iphi1); - } - } - - /* Define the indices of the polar primitives */ - FOR_EACH(itheta, 0, ntheta) { - const unsigned itheta0 = itheta * (nphi - 1); - const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); - - sa_push(sphere->indices, ntheta * (nphi - 1)); - sa_push(sphere->indices, itheta0); - sa_push(sphere->indices, itheta1); - - sa_push(sphere->indices, ntheta * (nphi - 1) + 1); - sa_push(sphere->indices, itheta1 + (nphi - 2)); - sa_push(sphere->indices, itheta0 + (nphi - 2)); - } - - /* Release the intermediary data structure */ - sa_release(cos_theta); - sa_release(sin_theta); - sa_release(cos_phi); - sa_release(sin_phi); -} - -static void -mesh_release(struct mesh* sphere) -{ - sa_release(sphere->vertices); - sa_release(sphere->indices); - sphere->vertices = NULL; - sphere->indices = NULL; -} - /* Assume that props0 and props1 are sorted. If two entries have the same * wavelength the entry of props1 is skipped. */ static void @@ -413,8 +320,8 @@ schiff_sphere_sample_geometry mtl->get_property = get_material_property; mtl->material = ctx->properties; - nverts = sa_size(ctx->mesh->vertices) / 3/*#coords*/; - nprims = sa_size(ctx->mesh->indices) / 3/*#indices per prim*/; + nverts = darray_float_size_get(&ctx->mesh->vertices) / 3/*#coords*/; + nprims = darray_uint_size_get(&ctx->mesh->indices) / 3/*#indices per prim*/; return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, get_indices, (unsigned)nverts, &attrib, 1, &sphere); @@ -426,16 +333,26 @@ schiff_sphere_run struct sbox_schiff* schiff, struct schiff_sphere_args* args) { + char buf[64]; struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION; struct schiff_sphere_geometry_distribution_context ctx; - struct mesh mesh = MESH_NULL; + struct sschiff_estimator* estimator = NULL; + struct sschiff_estimator_state* states = NULL; struct sschiff_device* sschiff = NULL; struct ssp_rng* rng = NULL; - size_t iwave, nwaves; + struct sbox_schiff_mesh mesh; + struct time t0, t1; + size_t iwlen, nwlens; res_T res = RES_OK; ASSERT(sbox); - mesh_init_sphere(&mesh, args->nthetas); + /* Generate the spherical mesh */ + res = sbox_schiff_mesh_init_sphere(&schiff->allocator, &mesh, args->nthetas); + if(res != RES_OK) { + logger_print(&sbox->logger, LOG_ERROR, + "Couldn't create the Schiff sphere mesh discretised in %u steps along 2PI\n", + args->nthetas); + } /* FIXME use the rng type defined in sbox */ res = ssp_rng_create(&schiff->allocator, &ssp_rng_threefry, &rng); @@ -453,47 +370,63 @@ schiff_sphere_run goto error; } + /* Setup the geometry distribution context */ ctx.mesh = &mesh; ctx.properties = args->props; ctx.mean_radius = args->radius; ctx.sigma = args->sigma; + /* Setup the geometry distribution */ distrib.sample = schiff_sphere_sample_geometry; distrib.context = &ctx; - nwaves = sa_size(args->wavelengths); - FOR_EACH(iwave, 0, nwaves) { - struct sschiff_estimator* estimator; - struct sschiff_estimator_status status; - struct time t0, t1; - char buf[64]; - - time_current(&t0); - res = sschiff_integrate(sschiff, rng, &distrib, args->wavelengths[iwave], 1, + /* Invoke the Schiff integration */ + nwlens = sa_size(args->wavelengths); + time_current(&t0); + res = sschiff_integrate(sschiff, rng, &distrib, args->wavelengths, nwlens, 1, args->ngeoms, args->ndirs, &estimator); - time_current(&t1); - if(res != RES_OK) { - logger_print(&sbox->logger, LOG_ERROR, - "Error in Schiff integration of the wavelength `%g'.\n", - args->wavelengths[iwave]); - continue; - } + time_current(&t1); + if(res != RES_OK) { + logger_print(&sbox->logger, LOG_ERROR, "Schiff integration error.\n"); + goto error; + } + time_sub(&t0, &t1, &t0); + time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf)); + + /* Retrieve estimation results */ + states = sa_add(states, nwlens); + SSCHIFF(estimator_get_states(estimator, states)); + + /* Print the estimation results */ + FOR_EACH(iwlen, 0, nwlens) { + const struct sschiff_estimator_value* val; + + logger_print(&sbox->logger, LOG_OUTPUT, + "Wavelength %7.2g:\n", states[iwlen].wavelength); - time_sub(&t0, &t1, &t0); - time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf)); + val = states[iwlen].values + SSCHIFF_EXTINCTION_CROSS_SECTION; + logger_print(&sbox->logger, LOG_OUTPUT, + " Extinction cross section ~ %12.7g +/- %12.7g\n", val->E, val->SE); - SSCHIFF(estimator_get_extinction_cross_section(estimator, &status)); + val = states[iwlen].values + SSCHIFF_ABSORPTION_CROSS_SECTION; logger_print(&sbox->logger, LOG_OUTPUT, -"Wavelength: %7.2g - Extinction cross section ~ %12.7g +/- %12.7g - %s\n", - args->wavelengths[iwave], status.E, status.SE, buf); + " Absorption cross section ~ %12.7g +/- %12.7g\n", val->E, val->SE); - SSCHIFF(estimator_ref_put(estimator)); + val = states[iwlen].values + SSCHIFF_SCATTERING_CROSS_SECTION; + logger_print(&sbox->logger, LOG_OUTPUT, + " Scattering cross section ~ %12.7g +/- %12.7g\n", val->E, val->SE); + + val = states[iwlen].values + SSCHIFF_AVERAGE_PROJECTED_AREA; + logger_print(&sbox->logger, LOG_OUTPUT, + " Average projected area ~ %12.7g +/- %12.7g\n", val->E, val->SE); } exit: + if(estimator) SSCHIFF(estimator_ref_put(estimator)); if(sschiff) SSCHIFF(device_ref_put(sschiff)); if(rng) SSP(rng_ref_put(rng)); - mesh_release(&mesh); + sa_release(states); + sbox_schiff_mesh_release(&mesh); return res; error: goto exit;