stardis-solver

Solve coupled heat transfers
git clone git://git.meso-star.fr/stardis-solver.git
Log | Files | Refs | README | LICENSE

commit 9463de1105aeda9fcd0546bf3ea28d1317c6bba0
parent d690a610a8c644778cb2fe13ccaf89d6ce02f70d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 28 May 2019 15:57:36 +0200

Merge branch 'feature_improve_camera_solver' into develop

Diffstat:
Mcmake/CMakeLists.txt | 6+-----
Msrc/sdis.h | 92++++++++++++++++++++++++++++---------------------------------------------------
Dsrc/sdis_accum_buffer.c | 160-------------------------------------------------------------------------------
Msrc/sdis_device.c | 9---------
Msrc/sdis_device_c.h | 13-------------
Msrc/sdis_estimator.c | 19++++++++++++++-----
Asrc/sdis_estimator_buffer.c | 244+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sdis_estimator_buffer_c.h | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/sdis_estimator_c.h | 30++++++++++++++----------------
Msrc/sdis_realisation.c | 6++++++
Msrc/sdis_realisation.h | 17+++++++++--------
Msrc/sdis_realisation_Xd.h | 8++++----
Msrc/sdis_solve.c | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/sdis_solve_probe_Xd.h | 2+-
Msrc/test_sdis_solve_camera.c | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/test_sdis_utils.c | 2+-
Msrc/test_sdis_utils.h | 2+-
17 files changed, 608 insertions(+), 364 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -16,9 +16,6 @@ cmake_minimum_required(VERSION 3.0) project(stardis C) enable_testing() -if(POLICY CMP0054) - cmake_policy(SET CMP0054 OLD) # Disable OpenMP CMake warning -endif() include(CMakeDependentOption) @@ -65,11 +62,11 @@ set(VERSION_PATCH 1) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SDIS_FILES_SRC - sdis_accum_buffer.c sdis_camera.c sdis_data.c sdis_device.c sdis_estimator.c + sdis_estimator_buffer.c sdis_green.c sdis_heat_path.c sdis_interface.c @@ -171,7 +168,6 @@ if(NOT NO_TEST) register_test(${_name} ${_name}) endfunction() - new_test(test_sdis_accum_buffer) new_test(test_sdis_camera) new_test(test_sdis_conducto_radiative) new_test(test_sdis_conducto_radiative_2d) diff --git a/src/sdis.h b/src/sdis.h @@ -56,11 +56,11 @@ struct senc_descriptor; * get or release a reference on the data, i.e. they increment or decrement the * reference counter, respectively. When this counter reaches 0, the object is * silently destroyed and cannot be used anymore. */ -struct sdis_accum_buffer; struct sdis_camera; struct sdis_data; struct sdis_device; struct sdis_estimator; +struct sdis_estimator_buffer; struct sdis_green_function; struct sdis_interface; struct sdis_medium; @@ -137,14 +137,6 @@ struct sdis_interface_fragment { static const struct sdis_interface_fragment SDIS_INTERFACE_FRAGMENT_NULL = SDIS_INTERFACE_FRAGMENT_NULL__; -/* Monte-Carlo accumulator */ -struct sdis_accum { - double sum_weights; /* Sum of Monte-Carlo weights */ - double sum_weights_sqr; /* Sum of Monte-Carlo square weights */ - size_t nweights; /* #accumulated weights */ - size_t nfailures; /* #failures */ -}; - /* Monte-Carlo estimation */ struct sdis_mc { double E; /* Expected value */ @@ -244,22 +236,6 @@ struct sdis_interface_shader { static const struct sdis_interface_shader SDIS_INTERFACE_SHADER_NULL = SDIS_INTERFACE_SHADER_NULL__; -struct sdis_accum_buffer_layout { - size_t width; - size_t height; -}; -#define SDIS_ACCUM_BUFFER_LAYOUT_NULL__ {0, 0} -static const struct sdis_accum_buffer_layout SDIS_ACCUM_BUFFER_LAYOUT_NULL = - SDIS_ACCUM_BUFFER_LAYOUT_NULL__; - -/* Functor use to write accumulations performed by sdis_solve_camera */ -typedef res_T -(*sdis_write_accums_T) - (void* context, /* User data */ - const size_t origin[2], /* Coordinates of the 1st accumulation in image plane */ - const size_t naccums[2], /* #accumulations in X and Y */ - const struct sdis_accum* accums); /* List of row ordered accumulations */ - /* Vertex of heat path v*/ struct sdis_heat_vertex { double P[3]; @@ -418,51 +394,47 @@ sdis_camera_look_at const double up[3]); /******************************************************************************* - * A buffer of accumulations is a 2D array whose each cell stores an - * Monte-Carlo accumulation, i.e. a sum of MC weights, the sum of their square - * and the overall number of summed weights (see struct sdis_accum) - ******************************************************************************/ + * An estimator buffer is 2D array of estimators +******************************************************************************/ SDIS_API res_T -sdis_accum_buffer_create - (struct sdis_device* dev, - const size_t width, /* #cells in X */ - const size_t height, /* #cells in Y */ - struct sdis_accum_buffer** buf); +sdis_estimator_buffer_ref_get + (struct sdis_estimator_buffer* buf); SDIS_API res_T -sdis_accum_buffer_ref_get - (struct sdis_accum_buffer* buf); +sdis_estimator_buffer_ref_put + (struct sdis_estimator_buffer* buf); SDIS_API res_T -sdis_accum_buffer_ref_put - (struct sdis_accum_buffer* buf); +sdis_estimator_buffer_get_definition + (const struct sdis_estimator_buffer* buf, + size_t definition[2]); SDIS_API res_T -sdis_accum_buffer_get_layout - (const struct sdis_accum_buffer* buf, - struct sdis_accum_buffer_layout* layout); +sdis_estimator_buffer_at + (const struct sdis_estimator_buffer* buf, + const size_t x, + const size_t y, + const struct sdis_estimator** estimator); -/* Get a read only pointer toward the memory space of the accum buffer */ SDIS_API res_T -sdis_accum_buffer_map - (const struct sdis_accum_buffer* buf, - const struct sdis_accum** accums); +sdis_estimator_buffer_get_realisation_count + (const struct sdis_estimator_buffer* buf, + size_t* nrealisations); /* Successful ones */ + +SDIS_API res_T +sdis_estimator_buffer_get_failure_count + (const struct sdis_estimator_buffer* buf, + size_t* nfailures); SDIS_API res_T -sdis_accum_buffer_unmap - (const struct sdis_accum_buffer* buf); +sdis_estimator_buffer_get_temperature + (const struct sdis_estimator_buffer* buf, + struct sdis_mc* temperature); -/* Helper function that matches the `sdis_write_accums_T' functor type. One can - * send this function directly to the sdis_solve_camera function, to fill the - * accum buffer with the estimation of the radiative temperature that reaches - * each pixel of an image whose definition matches the definition of the accum - * buffer. */ SDIS_API res_T -sdis_accum_buffer_write - (void* buf, /* User data */ - const size_t origin[2], /* Coordinates of the 1st accum in image plane */ - const size_t naccum[2], /* #accum in X and Y */ - const struct sdis_accum* accums); /* List of row ordered accum */ +sdis_estimator_buffer_get_realisation_time + (const struct sdis_estimator_buffer* buf, + struct sdis_mc* time); /******************************************************************************* * A medium encapsulates the properties of either a fluid or a solid. @@ -931,15 +903,15 @@ SDIS_API res_T sdis_solve_camera (struct sdis_scene* scn, const struct sdis_camera* cam, /* Point of view */ - const double time, /* Observation time */ + const double time_range[2], /* Observation time */ const double fp_to_meter, /* Scale from floating point units to meters */ const double ambient_radiative_temperature, /* In Kelvin */ const double reference_temperature, /* In Kelvin */ const size_t width, /* Image definition in in X */ const size_t height, /* Image definition in Y */ const size_t spp, /* #samples per pixel */ - sdis_write_accums_T writer, - void* writer_data); + const int register_paths, /* Combination of enum sdis_heat_path_flag */ + struct sdis_estimator_buffer** buf); SDIS_API res_T sdis_solve_medium diff --git a/src/sdis_accum_buffer.c b/src/sdis_accum_buffer.c @@ -1,160 +0,0 @@ -/* Copyright (C) 2016-2019 |Meso|Star> (contact@meso-star.com) - * - * 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/>. */ - -#include "sdis.h" -#include "sdis_device_c.h" - -struct sdis_accum_buffer { - struct sdis_accum* accums; - size_t width; - size_t height; - - ref_T ref; - struct sdis_device* dev; -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static void -accum_buffer_release(ref_T* ref) -{ - struct sdis_accum_buffer* buf; - struct sdis_device* dev; - ASSERT(ref); - buf = CONTAINER_OF(ref, struct sdis_accum_buffer, ref); - dev = buf->dev; - if(buf->accums) MEM_RM(dev->allocator, buf->accums); - MEM_RM(dev->allocator, buf); - SDIS(device_ref_put(dev)); -} - -/******************************************************************************* - * Export functions - ******************************************************************************/ -res_T -sdis_accum_buffer_create - (struct sdis_device* dev, - const size_t width, - const size_t height, - struct sdis_accum_buffer** out_buf) -{ - struct sdis_accum_buffer* buf = NULL; - size_t sz; - res_T res = RES_OK; - - if(!dev || !width || !height || !out_buf) { - res = RES_BAD_ARG; - goto error; - } - - buf = MEM_CALLOC(dev->allocator, 1, sizeof(struct sdis_accum_buffer)); - if(!buf) { - res = RES_MEM_ERR; - goto error; - } - ref_init(&buf->ref); - SDIS(device_ref_get(dev)); - buf->dev = dev; - buf->width = width; - buf->height = height; - - sz = buf->width * buf->height * sizeof(struct sdis_accum); - buf->accums = MEM_ALLOC_ALIGNED(dev->allocator, sz, 16); - if(!buf->accums) { - log_err(dev, "%s: could not allocate a buffer accumulations of %lux%lu.\n", - FUNC_NAME, (unsigned long)width, (unsigned long)height); - res = RES_MEM_ERR; - goto error; - } - -exit: - if(out_buf) *out_buf = buf; - return res; -error: - if(buf) { - SDIS(accum_buffer_ref_put(buf)); - buf = NULL; - } - goto exit; -} - -res_T -sdis_accum_buffer_ref_get(struct sdis_accum_buffer* buf) -{ - if(!buf) return RES_BAD_ARG; - ref_get(&buf->ref); - return RES_OK; -} - -res_T -sdis_accum_buffer_ref_put(struct sdis_accum_buffer* buf) -{ - if(!buf) return RES_BAD_ARG; - ref_put(&buf->ref, accum_buffer_release); - return RES_OK; -} - -res_T -sdis_accum_buffer_get_layout - (const struct sdis_accum_buffer* buf, - struct sdis_accum_buffer_layout* layout) -{ - if(!buf || !layout) return RES_BAD_ARG; - layout->width = buf->width; - layout->height = buf->height; - return RES_OK; -} - -res_T -sdis_accum_buffer_map - (const struct sdis_accum_buffer* buf, const struct sdis_accum** accums) -{ - if(!buf || !accums) return RES_BAD_ARG; - *accums = buf->accums; - return RES_OK; -} - -res_T -sdis_accum_buffer_unmap(const struct sdis_accum_buffer* buf) -{ - if(!buf) return RES_BAD_ARG; - /* Do nothing */ - return RES_OK; -} - -res_T -sdis_accum_buffer_write - (void* buffer, - const size_t origin[2], - const size_t size[2], - const struct sdis_accum* accums) -{ - struct sdis_accum_buffer* buf = buffer; - const struct sdis_accum* src_row = accums; - size_t dst_iy; - - if(UNLIKELY(!buffer || !origin || !size || !accums)) return RES_BAD_ARG; - if(UNLIKELY((origin[0] + size[0]) > buf->width)) return RES_BAD_ARG; - if(UNLIKELY((origin[1] + size[1]) > buf->height)) return RES_BAD_ARG; - - FOR_EACH(dst_iy, origin[1], origin[1] + size[1]) { - const size_t dst_irow = dst_iy*buf->width + origin[0]; - memcpy(buf->accums + dst_irow, src_row, size[0] * sizeof(struct sdis_accum)); - src_row += size[0]; - } - return RES_OK; -} - diff --git a/src/sdis_device.c b/src/sdis_device.c @@ -54,7 +54,6 @@ device_release(ref_T* ref) ASSERT(flist_name_is_empty(&dev->media_names)); flist_name_release(&dev->interfaces_names); flist_name_release(&dev->media_names); - darray_tile_release(&dev->tiles); MEM_RM(dev->allocator, dev); } @@ -98,14 +97,6 @@ sdis_device_create ref_init(&dev->ref); flist_name_init(allocator, &dev->interfaces_names); flist_name_init(allocator, &dev->media_names); - darray_tile_init(allocator, &dev->tiles); - - res = darray_tile_resize(&dev->tiles, dev->nthreads); - if(res != RES_OK) { - log_err(dev, - "%s: could not allocate the per thread buffer of estimations.\n", FUNC_NAME); - goto error; - } res = s2d_device_create(log, allocator, 0, &dev->s2d); if(res != RES_OK) { diff --git a/src/sdis_device_c.h b/src/sdis_device_c.h @@ -26,18 +26,6 @@ struct name { FITEM; }; #define FITEM_TYPE name #include <rsys/free_list.h> -#define DARRAY_NAME accum -#define DARRAY_DATA struct sdis_accum -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME tile -#define DARRAY_DATA struct darray_accum -#define DARRAY_FUNCTOR_INIT darray_accum_init -#define DARRAY_FUNCTOR_RELEASE darray_accum_release -#define DARRAY_FUNCTOR_COPY darray_accum_copy -#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_accum_copy_and_release -#include <rsys/dynamic_array.h> - struct sdis_device { struct logger* logger; struct mem_allocator* allocator; @@ -46,7 +34,6 @@ struct sdis_device { struct flist_name interfaces_names; struct flist_name media_names; - struct darray_tile tiles; struct s2d_device* s2d; struct s3d_device* s3d; diff --git a/src/sdis_estimator.c b/src/sdis_estimator.c @@ -82,12 +82,19 @@ sdis_estimator_get_failure_count return RES_OK; } +#define SETUP_MC(Mc, Acc) { \ + (Mc)->E = (Acc)->sum / (double)(Acc)->count; \ + (Mc)->V = (Acc)->sum2 / (double)(Acc)->count - (Mc)->E*(Mc)->E; \ + (Mc)->V = MMAX((Mc)->V, 0); \ + (Mc)->SE = sqrt((Mc)->V / (double)(Acc)->count); \ +} (void)0 + res_T sdis_estimator_get_temperature (const struct sdis_estimator* estimator, struct sdis_mc* mc) { if(!estimator || !mc) return RES_BAD_ARG; - *mc = estimator->temperature; + SETUP_MC(mc, &estimator->temperature); return RES_OK; } @@ -96,7 +103,7 @@ sdis_estimator_get_realisation_time (const struct sdis_estimator* estimator, struct sdis_mc* mc) { if(!estimator || !mc) return RES_BAD_ARG; - *mc = estimator->realisation_time; + SETUP_MC(mc, &estimator->realisation_time); return RES_OK; } @@ -107,7 +114,7 @@ sdis_estimator_get_convective_flux if(!estimator || !flux ||estimator->type != SDIS_ESTIMATOR_FLUX) return RES_BAD_ARG; ASSERT(estimator->fluxes); - *flux = estimator->fluxes[FLUX_CONVECTIVE]; + SETUP_MC(flux, &estimator->fluxes[FLUX_CONVECTIVE]); return RES_OK; } @@ -118,7 +125,7 @@ sdis_estimator_get_radiative_flux if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX) return RES_BAD_ARG; ASSERT(estimator->fluxes); - *flux = estimator->fluxes[FLUX_RADIATIVE]; + SETUP_MC(flux, &estimator->fluxes[FLUX_RADIATIVE]); return RES_OK; } @@ -129,10 +136,12 @@ sdis_estimator_get_total_flux if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX) return RES_BAD_ARG; ASSERT(estimator->fluxes); - *flux = estimator->fluxes[FLUX_TOTAL]; + SETUP_MC(flux, &estimator->fluxes[FLUX_TOTAL]); return RES_OK; } +#undef SETUP_MC + res_T sdis_estimator_get_paths_count (const struct sdis_estimator* estimator, size_t* npaths) diff --git a/src/sdis_estimator_buffer.c b/src/sdis_estimator_buffer.c @@ -0,0 +1,244 @@ +/* Copyright (C) 2016-2019 |Meso|Star> (contact@meso-star.com) + * + * 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/>. */ + +#include "sdis.h" +#include "sdis_device_c.h" +#include "sdis_estimator_c.h" +#include "sdis_estimator_buffer_c.h" + +struct sdis_estimator_buffer { + struct sdis_estimator** estimators; /* Row major per pixe lestimators */ + size_t width; + size_t height; + + struct accum temperature; + struct accum realisation_time; + size_t nrealisations; /* #successes */ + size_t nfailures; + + ref_T ref; + struct sdis_device* dev; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +estimator_buffer_release(ref_T* ref) +{ + struct sdis_estimator_buffer* buf; + struct sdis_device* dev; + size_t i; + ASSERT(ref); + + buf = CONTAINER_OF(ref, struct sdis_estimator_buffer, ref); + dev = buf->dev; + + if(buf->estimators) { + FOR_EACH(i, 0, buf->width*buf->height) { + if(buf->estimators[i]) SDIS(estimator_ref_put(buf->estimators[i])); + } + MEM_RM(dev->allocator, buf->estimators); + } + + MEM_RM(dev->allocator, buf); + SDIS(device_ref_put(dev)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sdis_estimator_buffer_ref_get(struct sdis_estimator_buffer* buf) +{ + if(!buf) return RES_BAD_ARG; + ref_get(&buf->ref); + return RES_OK; +} + +res_T +sdis_estimator_buffer_ref_put(struct sdis_estimator_buffer* buf) +{ + if(!buf) return RES_BAD_ARG; + ref_put(&buf->ref, estimator_buffer_release); + return RES_OK; +} + +res_T +sdis_estimator_buffer_get_definition + (const struct sdis_estimator_buffer* buf, size_t definition[2]) +{ + if(!buf || !definition) return RES_BAD_ARG; + definition[0] = buf->width; + definition[1] = buf->height; + return RES_OK; +} + +res_T +sdis_estimator_buffer_at + (const struct sdis_estimator_buffer* buf, + const size_t x, + const size_t y, + const struct sdis_estimator** estimator) +{ + if(!buf || x >= buf->width || y >= buf->height || !estimator) + return RES_BAD_ARG; + *estimator = estimator_buffer_grab(buf, x, y); + return RES_OK; +} + +res_T +sdis_estimator_buffer_get_realisation_count + (const struct sdis_estimator_buffer* buf, size_t* nrealisations) +{ + if(!buf || !nrealisations) return RES_BAD_ARG; + *nrealisations = buf->nrealisations; + return RES_OK; +} + +res_T +sdis_estimator_buffer_get_failure_count + (const struct sdis_estimator_buffer* buf, size_t* nfailures) +{ + if(!buf || !nfailures) return RES_BAD_ARG; + *nfailures = buf->nfailures; + return RES_OK; +} + +#define SETUP_MC(Mc, Acc) { \ + (Mc)->E = (Acc)->sum / (double)(Acc)->count; \ + (Mc)->V = (Acc)->sum2 / (double)(Acc)->count - (Mc)->E*(Mc)->E; \ + (Mc)->V = MMAX((Mc)->V, 0); \ + (Mc)->SE = sqrt((Mc)->V / (double)(Acc)->count); \ +} (void)0 + +res_T +sdis_estimator_buffer_get_temperature + (const struct sdis_estimator_buffer* buf, struct sdis_mc* mc) +{ + if(!buf || !mc) return RES_BAD_ARG; + SETUP_MC(mc, &buf->temperature); + return RES_OK; +} + +res_T +sdis_estimator_buffer_get_realisation_time +(const struct sdis_estimator_buffer* buf, struct sdis_mc* mc) +{ + if(!buf || !mc) return RES_BAD_ARG; + SETUP_MC(mc, &buf->realisation_time); + return RES_OK; +} + +#undef SETUP_MC + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +estimator_buffer_create + (struct sdis_device* dev, + const size_t width, + const size_t height, + struct sdis_estimator_buffer** out_buf) +{ + struct sdis_estimator_buffer* buf = NULL; + size_t i; + res_T res = RES_OK; + + if(!dev || !width || !height || !out_buf) { + res = RES_BAD_ARG; + goto error; + } + + buf = MEM_CALLOC(dev->allocator, 1, sizeof(*buf)); + if(!buf) { res = RES_MEM_ERR; goto error; } + + ref_init(&buf->ref); + SDIS(device_ref_get(dev)); + buf->dev = dev; + buf->width = width; + buf->height = height; + + buf->estimators = MEM_CALLOC + (dev->allocator, width*height, sizeof(*buf->estimators)); + if(!buf->estimators) { + log_err(dev, "%s: could not allocate a buffer of estimators of %lux%lu.\n", + FUNC_NAME, (unsigned long)width, (unsigned long)height); + res = RES_MEM_ERR; + goto error; + } + + FOR_EACH(i, 0, width*height) { + res = estimator_create(dev, SDIS_ESTIMATOR_TEMPERATURE, buf->estimators+i); + if(res != RES_OK) goto error; + } + +exit: + if(out_buf) *out_buf = buf; + return res; +error: + if(buf) { + SDIS(estimator_buffer_ref_put(buf)); + buf = NULL; + } + goto exit; +} + +struct sdis_estimator* +estimator_buffer_grab + (const struct sdis_estimator_buffer* buf, + const size_t x, + const size_t y) +{ + ASSERT(x < buf->width && y < buf->height); + return buf->estimators[y*buf->width + x]; +} + +void +estimator_buffer_setup_realisations_count + (struct sdis_estimator_buffer* buf, + const size_t nrealisations, + const size_t nsuccesses) +{ + ASSERT(buf && nrealisations && nsuccesses && nsuccesses<=nrealisations); + buf->nrealisations = nsuccesses; + buf->nfailures = nrealisations - nsuccesses; +} + +void +estimator_buffer_setup_temperature + (struct sdis_estimator_buffer* buf, + const double sum, + const double sum2) +{ + ASSERT(buf && buf->nrealisations); + buf->temperature.sum = sum; + buf->temperature.sum2 = sum2; + buf->temperature.count = buf->nrealisations; +} + +void +estimator_buffer_setup_realisation_time + (struct sdis_estimator_buffer* buf, + const double sum, + const double sum2) +{ + ASSERT(buf && buf->nrealisations); + buf->realisation_time.sum = sum; + buf->realisation_time.sum2 = sum2; + buf->realisation_time.count = buf->nrealisations; +} + diff --git a/src/sdis_estimator_buffer_c.h b/src/sdis_estimator_buffer_c.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2016-2019 |Meso|Star> (contact@meso-star.com) + * + * 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/>. */ + +#ifndef SDIS_ESTIMATOR_BUFFER_C_H +#define SDIS_ESTIMATOR_BUFFER_C_H + +#include <rsys/rsys.h> + +/* Forward declaration */ +struct sdis_device; +struct sdis_estimator; +struct sdis_estimator_buffer; + +extern LOCAL_SYM res_T +estimator_buffer_create + (struct sdis_device* dev, + const size_t width, + const size_t height, + struct sdis_estimator_buffer** buf); + +extern LOCAL_SYM struct sdis_estimator* +estimator_buffer_grab + (const struct sdis_estimator_buffer* buf, + const size_t x, + const size_t y); + +extern LOCAL_SYM void +estimator_buffer_setup_realisations_count + (struct sdis_estimator_buffer* buf, + const size_t nrealisations, + const size_t nsuccesses); + +extern LOCAL_SYM void +estimator_buffer_setup_temperature + (struct sdis_estimator_buffer* buf, + const double sum, + const double sum2); + +extern LOCAL_SYM void +estimator_buffer_setup_realisation_time + (struct sdis_estimator_buffer* buf, + const double sum, + const double sum2); + +#endif /* SDIS_ESTIMATOR_BUFFER_C_H */ + diff --git a/src/sdis_estimator_c.h b/src/sdis_estimator_c.h @@ -17,6 +17,7 @@ #define SDIS_ESTIMATOR_C_H #include "sdis_heat_path.h" +#include "sdis_misc.h" #include <rsys/math.h> #include <rsys/ref_count.h> @@ -34,10 +35,10 @@ enum flux_name { }; struct sdis_estimator { - struct sdis_mc temperature; - struct sdis_mc realisation_time; - struct sdis_mc fluxes[FLUX_NAMES_COUNT__]; - size_t nrealisations; + struct accum temperature; + struct accum realisation_time; + struct accum fluxes[FLUX_NAMES_COUNT__]; + size_t nrealisations; /* #successes */ size_t nfailures; struct mutex* mutex; @@ -77,13 +78,6 @@ estimator_setup_realisations_count estimator->nfailures = nrealisations - nsuccesses; } -#define SETUP_MC(McName, Sum, Sum2, Count) { \ - (McName).E = (Sum) / (double)(Count); \ - (McName).V = (Sum2) / (double)(Count) - (McName).E*(McName).E; \ - (McName).V = MMAX((McName).V, 0); \ - (McName).SE = sqrt((McName).V / (double)(Count)); \ -} (void)0 - static INLINE void estimator_setup_temperature (struct sdis_estimator* estim, @@ -91,7 +85,9 @@ estimator_setup_temperature const double sum2) { ASSERT(estim && estim->nrealisations); - SETUP_MC(estim->temperature, sum, sum2, estim->nrealisations); + estim->temperature.sum = sum; + estim->temperature.sum2 = sum2; + estim->temperature.count = estim->nrealisations; } static INLINE void @@ -101,7 +97,9 @@ estimator_setup_realisation_time const double sum2) { ASSERT(estim && estim->nrealisations); - SETUP_MC(estim->realisation_time, sum, sum2, estim->nrealisations); + estim->realisation_time.sum = sum; + estim->realisation_time.sum2 = sum2; + estim->realisation_time.count = estim->nrealisations; } static INLINE void @@ -112,10 +110,10 @@ estimator_setup_flux const double sum2) { ASSERT(estim && (unsigned)name < FLUX_NAMES_COUNT__ && estim->nrealisations); - SETUP_MC(estim->fluxes[name], sum, sum2, estim->nrealisations); + estim->fluxes[name].sum = sum; + estim->fluxes[name].sum2 = sum2; + estim->fluxes[name].count = estim->nrealisations; } -#undef SETUP_MC - #endif /* SDIS_PROBE_ESTIMATOR_C_H */ diff --git a/src/sdis_realisation.c b/src/sdis_realisation.c @@ -32,6 +32,7 @@ ray_realisation_3d const double fp_to_meter, const double Tarad, const double Tref, + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight) { struct rwalk_context ctx = RWALK_CONTEXT_NULL; @@ -50,9 +51,14 @@ ray_realisation_3d ctx.Tarad = Tarad; ctx.Tref3 = Tref*Tref*Tref; + ctx.heat_path = heat_path; f3_set_d3(dir, direction); + /* Register the starting position against the heat path */ + res = register_heat_vertex(heat_path, &rwalk.vtx, 0, SDIS_HEAT_VERTEX_RADIATIVE); + if(res != RES_OK) goto error; + res = trace_radiative_path_3d(scn, dir, fp_to_meter, &ctx, &rwalk, rng, &T); if(res != RES_OK) goto error; diff --git a/src/sdis_realisation.h b/src/sdis_realisation.h @@ -46,8 +46,8 @@ probe_realisation_2d const double fp_to_meter,/* Scale factor from floating point unit to meter */ const double ambient_radiative_temperature, const double reference_temperature, - struct green_path_handle* green_path, - struct sdis_heat_path* heat_path, + struct green_path_handle* green_path, /* May be NULL */ + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight); extern LOCAL_SYM res_T @@ -61,8 +61,8 @@ probe_realisation_3d const double fp_to_meter,/* Scale factor from floating point unit to meter */ const double ambient_radiative_temperature, const double reference_temperature, - struct green_path_handle* green_path, - struct sdis_heat_path* heat_path, + struct green_path_handle* green_path, /* May be NULL */ + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight); /******************************************************************************* @@ -79,8 +79,8 @@ boundary_realisation_2d const double fp_to_meter, const double ambient_radiative_temperature, const double reference_temperature, - struct green_path_handle* green_path, - struct sdis_heat_path* heat_path, + struct green_path_handle* green_path, /* May be NULL */ + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight); extern LOCAL_SYM res_T @@ -94,8 +94,8 @@ boundary_realisation_3d const double fp_to_meter, const double ambient_radiative_temperature, const double reference_temperature, - struct green_path_handle* green_path, - struct sdis_heat_path* heat_path, + struct green_path_handle* green_path, /* May be NULL */ + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight); extern LOCAL_SYM res_T @@ -140,6 +140,7 @@ ray_realisation_3d const double fp_to_meter, const double ambient_radiative_temperature, const double reference_temperature, + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight); #endif /* SDIS_REALISATION_H */ diff --git a/src/sdis_realisation_Xd.h b/src/sdis_realisation_Xd.h @@ -121,8 +121,8 @@ XD(probe_realisation) const double fp_to_meter,/* Scale factor from floating point unit to meter */ const double ambient_radiative_temperature, const double reference_temperature, - struct green_path_handle* green_path, - struct sdis_heat_path* heat_path, + struct green_path_handle* green_path, /* May be NULL */ + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight) { struct rwalk_context ctx = RWALK_CONTEXT_NULL; @@ -213,8 +213,8 @@ XD(boundary_realisation) const double fp_to_meter, const double Tarad, const double Tref, - struct green_path_handle* green_path, - struct sdis_heat_path* heat_path, + struct green_path_handle* green_path, /* May be NULL */ + struct sdis_heat_path* heat_path, /* May be NULL */ double* weight) { struct rwalk_context ctx = RWALK_CONTEXT_NULL; diff --git a/src/sdis_solve.c b/src/sdis_solve.c @@ -17,6 +17,7 @@ #include "sdis_camera.h" #include "sdis_device_c.h" #include "sdis_estimator_c.h" +#include "sdis_estimator_buffer_c.h" #include "sdis_interface_c.h" #include <star/ssp.h> @@ -66,28 +67,43 @@ solve_pixel struct ssp_rng* rng, struct sdis_medium* mdm, const struct sdis_camera* cam, - const double time, /* Observation time */ + const double time_range[2], /* Observation time */ const double fp_to_meter, /* Scale from floating point units to meters */ const double Tarad, /* In Kelvin */ const double Tref, /* In Kelvin */ const size_t ipix[2], /* Pixel coordinate in the image plane */ const size_t nrealisations, + const int register_paths, /* Combination of enum sdis_heat_path_flag */ const double pix_sz[2], /* Pixel size in the normalized image plane */ - struct sdis_accum* accum) + struct sdis_estimator* estimator) { - double sum_weights = 0; - double sum_weights_sqr = 0; - size_t N = 0; /* #realisations that do not fail */ + struct accum acc_temp = ACCUM_NULL; + struct accum acc_time = ACCUM_NULL; size_t irealisation; res_T res = RES_OK; ASSERT(scn && mdm && rng && cam && ipix && nrealisations && Tref >= 0); ASSERT(pix_sz && pix_sz[0] > 0 && pix_sz[1] > 0); + ASSERT(estimator && time_range); FOR_EACH(irealisation, 0, nrealisations) { + struct time t0, t1; double samp[2]; /* Pixel sample */ double ray_pos[3]; double ray_dir[3]; double w = 0; + struct sdis_heat_path* pheat_path = NULL; + struct sdis_heat_path heat_path; + double time; + res_T res_simul = RES_OK; + + /* Begin time registration */ + time_current(&t0); + + time = sample_time(rng, time_range); + if(register_paths) { + heat_path_init(scn->dev->allocator, &heat_path); + pheat_path = &heat_path; + } /* Generate a sample into the pixel to estimate */ samp[0] = ((double)ipix[0] + ssp_rng_canonical(rng)) * pix_sz[0]; @@ -98,23 +114,45 @@ solve_pixel camera_ray(cam, samp, ray_pos, ray_dir); /* Launch the realisation */ - res = ray_realisation_3d(scn, rng, mdm, ray_pos, ray_dir, - time, fp_to_meter, Tarad, Tref, &w); - if(res == RES_OK) { - sum_weights += w; - sum_weights_sqr += w*w; - ++N; - } else if(res == RES_BAD_OP) { - res = RES_OK; - } else { + res_simul = ray_realisation_3d(scn, rng, mdm, ray_pos, ray_dir, + time, fp_to_meter, Tarad, Tref, pheat_path, &w); + + /* Handle fatal error */ + if(res_simul != RES_OK && res_simul != RES_BAD_OP) { + res = res_simul; goto error; } + + if(pheat_path) { + pheat_path->status = res_simul == RES_OK + ? SDIS_HEAT_PATH_SUCCEED + : SDIS_HEAT_PATH_FAILED; + + /* Check if the path must be saved regarding the register_paths mask */ + if(!(register_paths & (int)pheat_path->status)) { + heat_path_release(pheat_path); + } else { /* Register the sampled path */ + res = estimator_add_and_release_heat_path(estimator, pheat_path); + if(res != RES_OK) goto error; + } + } + + /* Stop time registration */ + time_sub(&t0, time_current(&t1), &t0); + + if(res_simul == RES_OK) { + /* Update global accumulators */ + const double usec = (double)time_val(&t0, TIME_NSEC) * 0.001; + acc_temp.sum += w; acc_temp.sum2 += w*w; ++acc_temp.count; + acc_time.sum += usec; acc_time.sum2 += usec*usec; ++acc_time.count; + } } - accum->sum_weights = sum_weights; - accum->sum_weights_sqr = sum_weights_sqr; - accum->nweights = N; - accum->nfailures = nrealisations - N; + /* Setup the pixel estimator */ + ASSERT(acc_temp.count == acc_time.count); + estimator_setup_realisations_count(estimator, nrealisations, acc_temp.count); + estimator_setup_temperature(estimator, acc_temp.sum, acc_temp.sum2); + estimator_setup_realisation_time(estimator, acc_time.sum, acc_time.sum2); exit: return res; @@ -128,22 +166,23 @@ solve_tile struct ssp_rng* rng, struct sdis_medium* mdm, const struct sdis_camera* cam, - const double time, + const double time_range[2], const double fp_to_meter, const double Tarad, const double Tref, const size_t origin[2], /* Tile origin in image plane */ const size_t size[2], /* #pixels in X and Y */ const size_t spp, /* #samples per pixel */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ const double pix_sz[2], /* Pixel size in the normalized image plane */ - struct sdis_accum* accums) + struct sdis_estimator_buffer* buf) { size_t mcode; /* Morton code of the tile pixel */ size_t npixels; res_T res = RES_OK; - ASSERT(scn && rng && mdm && cam && spp && origin && accums && Tref >= 0); - ASSERT(size &&size[0] && size[1]); - ASSERT(pix_sz && pix_sz[0] > 0 && pix_sz[1] > 0); + ASSERT(scn && rng && mdm && cam && spp && origin && Tref >= 0); + ASSERT(size &&size[0] && size[1] && buf); + ASSERT(pix_sz && pix_sz[0] > 0 && pix_sz[1] > 0 && time_range); /* Adjust the #pixels to process them wrt a morton order */ npixels = round_up_pow2(MMAX(size[0], size[1])); @@ -151,19 +190,21 @@ solve_tile FOR_EACH(mcode, 0, npixels) { size_t ipix[2]; - struct sdis_accum* accum; + struct sdis_estimator* estimator; ipix[0] = morton2D_decode((uint32_t)(mcode>>0)); if(ipix[0] >= size[0]) continue; ipix[1] = morton2D_decode((uint32_t)(mcode>>1)); if(ipix[1] >= size[1]) continue; - accum = accums + ipix[1]*size[0] + ipix[0]; ipix[0] = ipix[0] + origin[0]; ipix[1] = ipix[1] + origin[1]; - res = solve_pixel(scn, rng, mdm, cam, time, fp_to_meter, Tarad, Tref, ipix, - spp, pix_sz, accum); + /* Fetch the pixel estimator */ + estimator = estimator_buffer_grab(buf, ipix[0], ipix[1]); + + res = solve_pixel(scn, rng, mdm, cam, time_range, fp_to_meter, Tarad, Tref, + ipix, spp, register_paths, pix_sz, estimator); if(res != RES_OK) goto error; } @@ -360,39 +401,48 @@ res_T sdis_solve_camera (struct sdis_scene* scn, const struct sdis_camera* cam, - const double time, + const double time_range[2], const double fp_to_meter, /* Scale from floating point units to meters */ const double Tarad, /* In Kelvin */ const double Tref, /* In Kelvin */ const size_t width, /* #pixels in X */ const size_t height, /* #pixels in Y */ const size_t spp, /* #samples per pixel */ - sdis_write_accums_T writer, - void* writer_data) + const int register_paths, /* Combination of enum sdis_heat_path_flag */ + struct sdis_estimator_buffer** out_buf) { #define TILE_SIZE 32 /* definition in X & Y of a tile */ STATIC_ASSERT(IS_POW2(TILE_SIZE), TILE_SIZE_must_be_a_power_of_2); + struct sdis_estimator_buffer* buf = NULL; struct sdis_medium* medium = NULL; - struct darray_accum* tiles = NULL; + struct accum acc_temp = ACCUM_NULL; + struct accum acc_time = ACCUM_NULL; struct ssp_rng_proxy* rng_proxy = NULL; struct ssp_rng** rngs = NULL; size_t ntiles_x, ntiles_y, ntiles; double pix_sz[2]; /* Size of a pixel in the normalized image plane */ int64_t mcode; /* Morton code of a tile */ + size_t nrealisations; + size_t nsuccesses; + size_t ix, iy; size_t i; ATOMIC res = RES_OK; - if(!scn || !cam || time < 0 || fp_to_meter <= 0 || Tref < 0 || !width - || !height || !spp || !writer) { + if(!scn || !cam || fp_to_meter <= 0 || Tref < 0 || !width || !height || !spp + || !out_buf) { res = RES_BAD_ARG; goto error; } - if(scene_is_2d(scn)) { log_err(scn->dev, "%s: 2D scene are not supported.\n", FUNC_NAME); goto error; } + if(!time_range || time_range[0] < 0 || time_range[1] < time_range[0] + || (time_range[1] > DBL_MAX && time_range[0] != time_range[1])) { + res = RES_BAD_ARG; + goto error; + } /* Retrieve the medium in which the submitted position lies */ res = scene_get_medium(scn, cam->position, NULL, &medium); @@ -422,15 +472,6 @@ sdis_solve_camera if(res != RES_OK) goto error; } - /* Allocate per thread buffer of accumulations */ - tiles = darray_tile_data_get(&scn->dev->tiles); - ASSERT(darray_tile_size_get(&scn->dev->tiles) == scn->dev->nthreads); - FOR_EACH(i, 0, scn->dev->nthreads) { - const size_t naccums = TILE_SIZE * TILE_SIZE; - res = darray_accum_resize(tiles+i, naccums); - if(res != RES_OK) goto error; - } - ntiles_x = (width + (TILE_SIZE-1)/*ceil*/)/TILE_SIZE; ntiles_y = (height + (TILE_SIZE-1)/*ceil*/)/TILE_SIZE; ntiles = round_up_pow2(MMAX(ntiles_x, ntiles_y)); @@ -439,13 +480,16 @@ sdis_solve_camera pix_sz[0] = 1.0 / (double)width; pix_sz[1] = 1.0 / (double)height; + /* Create the global estimator */ + res = estimator_buffer_create(scn->dev, width, height, &buf); + if(res != RES_OK) goto error; + omp_set_num_threads((int)scn->dev->nthreads); #pragma omp parallel for schedule(static, 1/*chunk size*/) for(mcode = 0; mcode < (int64_t)ntiles; ++mcode) { size_t tile_org[2] = {0, 0}; size_t tile_sz[2] = {0, 0}; const int ithread = omp_get_thread_num(); - struct sdis_accum* accums = NULL; struct ssp_rng* rng = rngs[ithread]; res_T res_local = RES_OK; @@ -462,25 +506,40 @@ sdis_solve_camera tile_sz[0] = MMIN(TILE_SIZE, width - tile_org[0]); tile_sz[1] = MMIN(TILE_SIZE, height - tile_org[1]); - /* Fetch the accumulations buffer */ - accums = darray_accum_data_get(tiles+ithread); - /* Draw the tile */ - res_local = solve_tile(scn, rng, medium, cam, time, fp_to_meter, Tarad, - Tref, tile_org, tile_sz, spp, pix_sz, accums); + res_local = solve_tile(scn, rng, medium, cam, time_range, fp_to_meter, + Tarad, Tref, tile_org, tile_sz, spp, register_paths, pix_sz, buf); if(res_local != RES_OK) { ATOMIC_SET(&res, res_local); continue; } + } - /* Write the accumulations */ - res_local = writer(writer_data, tile_org, tile_sz, accums); - if(res_local != RES_OK) { - ATOMIC_SET(&res, res_local); - continue; + /* Setup the accumulators of the whole estimator buffer */ + acc_temp = ACCUM_NULL; + acc_time = ACCUM_NULL; + nsuccesses = 0; + FOR_EACH(iy, 0, height) { + FOR_EACH(ix, 0, width) { + const struct sdis_estimator* estimator; + SDIS(estimator_buffer_at(buf, ix, iy, &estimator)); + acc_temp.sum += estimator->temperature.sum; + acc_temp.sum2 += estimator->temperature.sum2; + acc_temp.count += estimator->temperature.count; + acc_time.sum += estimator->realisation_time.sum; + acc_time.sum2 += estimator->realisation_time.sum2; + acc_time.count += estimator->realisation_time.count; + nsuccesses += estimator->nrealisations; } } + nrealisations = width*height*spp; + ASSERT(acc_temp.count == acc_time.count); + ASSERT(acc_temp.count == nsuccesses); + estimator_buffer_setup_realisations_count(buf, nrealisations, nsuccesses); + estimator_buffer_setup_temperature(buf, acc_temp.sum, acc_temp.sum2); + estimator_buffer_setup_realisation_time(buf, acc_time.sum, acc_time.sum2); + exit: if(rngs) { FOR_EACH(i, 0, scn->dev->nthreads) { @@ -489,6 +548,7 @@ exit: MEM_RM(scn->dev->allocator, rngs); } if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy)); + if(out_buf) *out_buf = buf; return (res_T)res; error: goto exit; diff --git a/src/sdis_solve_probe_Xd.h b/src/sdis_solve_probe_Xd.h @@ -90,7 +90,7 @@ XD(solve_probe) if(res != RES_OK) goto error; } - /* Create the per thread accumulator */ + /* Create the per thread accumulators */ acc_temps = MEM_CALLOC (scn->dev->allocator, scn->dev->nthreads, sizeof(*acc_temps)); if(!acc_temps) { res = RES_MEM_ERR; goto error; } diff --git a/src/test_sdis_solve_camera.c b/src/test_sdis_solve_camera.c @@ -433,39 +433,59 @@ geometry_add_shape } static void -dump_image(const struct sdis_accum_buffer* buf) +dump_image(const struct sdis_estimator_buffer* buf) { - struct sdis_accum_buffer_layout layout = SDIS_ACCUM_BUFFER_LAYOUT_NULL; struct image img; double* temps = NULL; - const struct sdis_accum* accums = NULL; double Tmax = -DBL_MAX; double Tmin = DBL_MAX; double norm; + size_t definition[2]; size_t i, ix, iy; CHK(buf != NULL); - OK(sdis_accum_buffer_get_layout(buf, &layout)); + OK(sdis_estimator_buffer_get_definition(buf, definition)); - temps = mem_alloc(layout.width*layout.height*sizeof(double)); + temps = mem_alloc(definition[0]*definition[1]*sizeof(double)); CHK(temps != NULL); - OK(sdis_accum_buffer_map(buf, &accums)); - /* Check the results validity */ - FOR_EACH(i, 0, layout.height * layout.width) { - CHK(accums[i].nweights + accums[i].nfailures == SPP); - CHK(accums[i].nfailures <= SPP/100); - CHK(accums[i].sum_weights >= 0); - CHK(accums[i].sum_weights_sqr >= 0); + FOR_EACH(iy, 0, definition[1]) { + FOR_EACH(ix, 0, definition[0]) { + const struct sdis_estimator* estimator; + struct sdis_mc T; + struct sdis_mc time; + size_t nreals; + size_t nfails; + + BA(sdis_estimator_buffer_at(NULL, ix, iy, &estimator)); + BA(sdis_estimator_buffer_at(buf, definition[0]+1, iy, &estimator)); + BA(sdis_estimator_buffer_at(buf, ix, definition[1]+1, &estimator)); + BA(sdis_estimator_buffer_at(buf, ix, iy, NULL)); + OK(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); + + OK(sdis_estimator_get_realisation_count(estimator, &nreals)); + OK(sdis_estimator_get_failure_count(estimator, &nfails)); + OK(sdis_estimator_get_temperature(estimator, &T)); + OK(sdis_estimator_get_realisation_time(estimator, &time)); + + CHK(nreals + nfails == SPP); + CHK(T.E > 0); + CHK(time.E > 0); + } } /* Compute the per pixel temperature */ - FOR_EACH(iy, 0, layout.height) { - const struct sdis_accum* row_accums = accums + iy * layout.width; - double* row = temps + iy * layout.width; - FOR_EACH(ix, 0, layout.width) { - row[ix] = row_accums[ix].sum_weights / (double)row_accums[ix].nweights; + FOR_EACH(iy, 0, definition[1]) { + double* row = temps + iy * definition[0]; + FOR_EACH(ix, 0, definition[0]) { + const struct sdis_estimator* estimator; + struct sdis_mc T; + + OK(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); + OK(sdis_estimator_get_temperature(estimator, &T)); + + row[ix] = T.E; Tmax = MMAX(row[ix], Tmax); Tmin = MMIN(row[ix], Tmin); } @@ -481,10 +501,10 @@ dump_image(const struct sdis_accum_buffer* buf) OK(image_init(NULL, &img)); OK(image_setup(&img, IMG_WIDTH, IMG_HEIGHT, IMG_WIDTH*3, IMAGE_RGB8, NULL)); - FOR_EACH(iy, 0, layout.height) { - const double* src_row = temps + iy*layout.width; + FOR_EACH(iy, 0, definition[1]) { + const double* src_row = temps + iy*definition[0]; char* dst_row = img.pixels + iy*img.pitch; - FOR_EACH(ix, 0, layout.width) { + FOR_EACH(ix, 0, definition[0]) { unsigned char* pixels = (unsigned char*) (dst_row + ix * sizeof_image_format(img.format)); const unsigned char T = (unsigned char) @@ -509,9 +529,11 @@ main(int argc, char** argv) struct geometry geom = GEOMETRY_NULL; struct s3dut_mesh* msh = NULL; struct s3dut_mesh_data msh_data; - struct sdis_accum_buffer* buf = NULL; + struct sdis_mc T = SDIS_MC_NULL; + struct sdis_mc time = SDIS_MC_NULL; struct sdis_camera* cam = NULL; struct sdis_device* dev = NULL; + struct sdis_estimator_buffer* buf = NULL; struct sdis_medium* solid = NULL; struct sdis_medium* fluid0 = NULL; struct sdis_medium* fluid1 = NULL; @@ -522,9 +544,12 @@ main(int argc, char** argv) struct solid solid_param = SOLID_NULL; struct interf interface_param = INTERF_NULL; size_t ntris, npos; + size_t nreals, nfails; + size_t definition[2]; double pos[3]; double tgt[3]; double up[3]; + double trange[2] = {INF, INF}; (void)argc, (void)argv; OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); @@ -590,6 +615,11 @@ main(int argc, char** argv) geometry_get_interface, npos, geometry_get_position, &geom, &scn)); +#if 0 + dump_mesh(stdout, geom.positions, sa_size(geom.positions)/3, geom.indices, + sa_size(geom.indices)/3); +#endif + /* Setup the camera */ d3(pos, 3, 3, 3); d3(tgt, 0, 0, 0); @@ -599,28 +629,80 @@ main(int argc, char** argv) OK(sdis_camera_set_fov(cam, MDEG2RAD(70))); OK(sdis_camera_look_at(cam, pos, tgt, up)); - /* Create the accum buffer */ - OK(sdis_accum_buffer_create(dev, IMG_WIDTH, IMG_HEIGHT, &buf)); - #if 0 dump_mesh(stdout, geom.positions, npos, geom.indices, ntris); exit(0); #endif + BA(sdis_solve_camera(NULL, cam, trange, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, NULL, trange, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, cam, NULL, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, cam, trange, 0, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, cam, trange, 1, 300, -1, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, cam, trange, 1, 300, 300, 0, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, cam, trange, 1, 300, 300, IMG_WIDTH, 0, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, cam, trange, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + 0, SDIS_HEAT_PATH_NONE, &buf)); + BA(sdis_solve_camera(scn, cam, trange, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, NULL)); + + trange[0] = -1; + BA(sdis_solve_camera(scn, cam, trange, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + trange[0] = 10; trange[1] = 1; + BA(sdis_solve_camera(scn, cam, trange, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + trange[0] = trange[1] = INF; /* Launch the simulation */ - OK(sdis_solve_camera(scn, cam, INF, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, SPP, - sdis_accum_buffer_write, buf)); + OK(sdis_solve_camera(scn, cam, trange, 1, 300, 300, IMG_WIDTH, IMG_HEIGHT, + SPP, SDIS_HEAT_PATH_NONE, &buf)); + + BA(sdis_estimator_buffer_get_realisation_count(NULL, &nreals)); + BA(sdis_estimator_buffer_get_realisation_count(buf, NULL)); + OK(sdis_estimator_buffer_get_realisation_count(buf, &nreals)); + + BA(sdis_estimator_buffer_get_failure_count(NULL, &nfails)); + BA(sdis_estimator_buffer_get_failure_count(buf, NULL)); + OK(sdis_estimator_buffer_get_failure_count(buf, &nfails)); + + BA(sdis_estimator_buffer_get_temperature(NULL, &T)); + BA(sdis_estimator_buffer_get_temperature(buf, NULL)); + OK(sdis_estimator_buffer_get_temperature(buf, &T)); + + BA(sdis_estimator_buffer_get_realisation_time(NULL, &time)); + BA(sdis_estimator_buffer_get_realisation_time(buf, NULL)); + OK(sdis_estimator_buffer_get_realisation_time(buf, &time)); + + CHK(nreals + nfails == IMG_WIDTH*IMG_HEIGHT*SPP); + + fprintf(stderr, "Overall temperature ~ %g +/- %g\n", T.E, T.SE); + fprintf(stderr, "Time per realisation (in usec) ~ %g +/- %g\n", time.E, time.SE); + fprintf(stderr, "#failures = %lu/%lu\n", + (unsigned long)nfails, (unsigned long)(IMG_WIDTH*IMG_HEIGHT*SPP)); + + BA(sdis_estimator_buffer_get_definition(NULL, definition)); + BA(sdis_estimator_buffer_get_definition(buf, NULL)); + OK(sdis_estimator_buffer_get_definition(buf, definition)); + CHK(definition[0] == IMG_WIDTH); + CHK(definition[1] == IMG_HEIGHT); /* Write the image */ dump_image(buf); /* Release memory */ + OK(sdis_estimator_buffer_ref_put(buf)); OK(sdis_scene_ref_put(scn)); OK(sdis_camera_ref_put(cam)); OK(sdis_interface_ref_put(interf0)); OK(sdis_interface_ref_put(interf1)); OK(sdis_device_ref_put(dev)); - OK(sdis_accum_buffer_ref_put(buf)); geometry_release(&geom); check_memory_allocator(&allocator); diff --git a/src/test_sdis_utils.c b/src/test_sdis_utils.c @@ -270,7 +270,7 @@ check_green_function(struct sdis_green_function* green) } void -dump_heat_paths(FILE* stream, struct sdis_estimator* estimator) +dump_heat_paths(FILE* stream, const struct sdis_estimator* estimator) { const struct sdis_heat_path* path; size_t ipath; diff --git a/src/test_sdis_utils.h b/src/test_sdis_utils.h @@ -292,7 +292,7 @@ check_green_function extern LOCAL_SYM void dump_heat_paths (FILE* stream, - struct sdis_estimator* estimator); + const struct sdis_estimator* estimator); #endif /* TEST_SDIS_UTILS_H */