htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit 5e0bb9b16e0f6a7e171691578234083cdc80fb89
parent c2cb907802e65c023d683e735398dd7f998b8870
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 28 Oct 2022 16:43:18 +0200

htrdr-planeto: start implementing planeto_draw_map

Write function draw_pixel_image until sampling a path which is still not
implemented

Diffstat:
Mcmake/planeto/CMakeLists.txt | 1+
Asrc/planeto/htrdr_planeto_draw_map.c | 295+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 296 insertions(+), 0 deletions(-)

diff --git a/cmake/planeto/CMakeLists.txt b/cmake/planeto/CMakeLists.txt @@ -53,6 +53,7 @@ include_directories( set(HTRDR_PLANETO_FILES_SRC htrdr_planeto.c htrdr_planeto_args.c + htrdr_planeto_draw_map.c htrdr_planeto_main.c htrdr_planeto_source.c) diff --git a/src/planeto/htrdr_planeto_draw_map.c b/src/planeto/htrdr_planeto_draw_map.c @@ -0,0 +1,295 @@ +/* Copyright (C) 2018, 2019, 2020, 2021 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2018, 2019, 2021 CNRS + * Copyright (C) 2018, 2019, Université Paul Sabatier + * + * 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 "planeto/htrdr_planeto_c.h" + +#include "core/htrdr.h" +#include "core/htrdr_accum.h" +#include "core/htrdr_buffer.h" +#include "core/htrdr_draw_map.h" +#include "core/htrdr_log.h" +#include "core/htrdr_ran_wlen_cie_xyz.h" + +#include <rad-net/rnatm.h> +#include <star/scam.h> +#include <star/ssp.h> + +#include <rsys/clock_time.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +draw_pixel_xwave + (struct htrdr* htrdr, + const struct htrdr_draw_pixel_args* args, + void* data) +{ + /* TODO */ + (void)htrdr, (void)args, (void)data; +} + +static void +draw_pixel_image + (struct htrdr* htrdr, + const struct htrdr_draw_pixel_args* args, + void* data) +{ + struct htrdr_accum XYZ[3]; /* X, Y, and Z */ + struct htrdr_accum time; + struct htrdr_planeto* cmd; + struct planeto_pixel_image* pixel = data; + size_t ichannel; + ASSERT(htrdr && htrdr_draw_pixel_args_check(args) && data); + (void)htrdr; + + cmd = args->context; + ASSERT(cmd); + ASSERT(cmd->spectral_domain.spectral_type == HTRDR_SPECTRAL_SW_CIE_XYZ); + ASSERT(cmd->output_type == HTRDR_PLANETO_ARGS_OUTPUT_IMAGE); + + /* Reset accumulators */ + XYZ[0] = HTRDR_ACCUM_NULL; + XYZ[1] = HTRDR_ACCUM_NULL; + XYZ[2] = HTRDR_ACCUM_NULL; + time = HTRDR_ACCUM_NULL; + + FOR_EACH(ichannel, 0, 3) { + size_t isamp; + + FOR_EACH(isamp, 0, args->spp) { + struct time t0, t1; + struct scam_sample sample = SCAM_SAMPLE_NULL; + struct scam_ray ray = SCAM_RAY_NULL; + double weight; + double r0, r1, r2; + double wlen[2]; /* Sampled wavelength into the spectral band */ + double pdf; + size_t iband[2]; /* Sampled spectral band */ + size_t iquad; /* Sampled quadrature point into the spectral band */ + double usec; + + /* Begin the registration of the time spent to in the realisation */ + time_current(&t0); + + /* Sample a position into the pixel, in the normalized image plane */ + sample.film[0] = (double)args->pixel_coord[0]+ssp_rng_canonical(args->rng); + sample.film[1] = (double)args->pixel_coord[1]+ssp_rng_canonical(args->rng); + sample.film[0] *= args->pixel_normalized_size[0]; + sample.film[1] *= args->pixel_normalized_size[1]; + sample.lens[0] = ssp_rng_canonical(args->rng); + sample.lens[1] = ssp_rng_canonical(args->rng); + + /* Generate a camera ray */ + scam_generate_ray(cmd->camera, &sample, &ray); + + r0 = ssp_rng_canonical(args->rng); + r1 = ssp_rng_canonical(args->rng); + r2 = ssp_rng_canonical(args->rng); + + /* Sample a wavelength according to the CIE XYZ color space */ + switch(ichannel) { + case 0: + wlen[0] = htrdr_ran_wlen_cie_xyz_sample_X(cmd->cie, r0, r1, &pdf); + break; + case 1: + wlen[0] = htrdr_ran_wlen_cie_xyz_sample_Y(cmd->cie, r0, r1, &pdf); + break; + case 2: + wlen[0] = htrdr_ran_wlen_cie_xyz_sample_Z(cmd->cie, r0, r1, &pdf); + break; + default: FATAL("Unreachable code.\n"); break; + } + pdf *= 1.e9; /* Transform the pdf from nm⁻¹ to m⁻¹ */ + + /* Find the band the wavelength belongs to and sample a quadrature point */ + wlen[1] = wlen[0]; + RNATM(find_bands(cmd->atmosphere, wlen, iband)); + RNATM(band_sample_quad_pt(cmd->atmosphere, r2, iband[0], &iquad)); + ASSERT(iband[0] == iband[1]); + + /* TODO Compute the radiance in W/m²/sr/m */ + /*weight = planeto_compute_radiance(cmd, args->ithread, args->rng, + ray.org, ray.dir, wlen, iband, iquad); */ + ASSERT(weight >= 0); + + weight /= pdf; /* In W/m²/sr */ + + /* End of time recording per realisation */ + time_sub(&t0, time_current(&t1), &t0); + usec = (double)time_val(&t0, TIME_NSEC) * 0.001; + + /* Update pixel channel accumulators */ + XYZ[ichannel].sum_weights += weight; + XYZ[ichannel].sum_weights_sqr += weight*weight; + XYZ[ichannel].nweights += 1; + + /* Update the per realisation time accumulator */ + time.sum_weights += usec; + time.sum_weights_sqr += usec*usec; + time.nweights += 1; + } + } + + /* Flush pixel data */ + htrdr_accum_get_estimation(XYZ+0, &pixel->X); + htrdr_accum_get_estimation(XYZ+1, &pixel->Y); + htrdr_accum_get_estimation(XYZ+2, &pixel->Z); + pixel->time = time; +} + + +static INLINE void +write_accum + (const struct htrdr_accum* acc, /* Accum to dump */ + struct htrdr_accum* out_acc, /* May be NULL */ + FILE* stream) +{ + ASSERT(acc && stream); + + if(acc->nweights == 0) { + fprintf(stream, "0 0 "); + } else { + struct htrdr_estimate estimate = HTRDR_ESTIMATE_NULL; + + htrdr_accum_get_estimation(acc, &estimate); + fprintf(stream, "%g %g ", estimate.E, estimate.SE); + + if(out_acc) { + out_acc->sum_weights += acc->sum_weights; + out_acc->sum_weights_sqr += acc->sum_weights_sqr; + out_acc->nweights += acc->nweights; + } + } +} + +static INLINE void +write_pixel_image + (const struct planeto_pixel_image* pix, + struct htrdr_accum* time_acc, /* May be NULL */ + FILE* stream) +{ + ASSERT(pix && stream); + fprintf(stream, "%g %g ", pix->X.E, pix->X.SE); + fprintf(stream, "%g %g ", pix->Y.E, pix->Y.SE); + fprintf(stream, "%g %g ", pix->Z.E, pix->Z.SE); + write_accum(&pix->time, time_acc, stream); + fprintf(stream, "\n"); +} + +static INLINE void +write_pixel_xwave + (const struct planeto_pixel_xwave* pix, + struct htrdr_accum* time_acc, /* May be NULL */ + FILE* stream) +{ + ASSERT(pix && stream); + fprintf(stream, "%g %g %f %f 0 0 ", + pix->radiance_temperature.E, + pix->radiance_temperature.SE, + pix->radiance.E, + pix->radiance.SE); + write_accum(&pix->time, time_acc, stream); + fprintf(stream, "\n"); +} + +static res_T +write_buffer + (struct htrdr_planeto* cmd, + struct htrdr_buffer* buf, + struct htrdr_accum* time_acc, + FILE* stream) +{ + struct htrdr_pixel_format pixfmt; + struct htrdr_buffer_layout layout; + size_t x, y; + ASSERT(cmd && buf && time_acc && stream); + ASSERT(cmd->output_type == HTRDR_PLANETO_ARGS_OUTPUT_IMAGE); + + planeto_get_pixel_format(cmd, &pixfmt); + htrdr_buffer_get_layout(buf, &layout); + CHK(pixfmt.size == layout.elmt_size); + + fprintf(stream, "%lu %lu\n", layout.width, layout.height); + *time_acc = HTRDR_ACCUM_NULL; + + FOR_EACH(y, 0, layout.height) { + FOR_EACH(x, 0, layout.width) { + void* pix_raw = htrdr_buffer_at(buf, x, y); + ASSERT(IS_ALIGNED(pix_raw, pixfmt.alignment)); + + switch(cmd->spectral_domain.spectral_type) { + case HTRDR_SPECTRAL_LW: + case HTRDR_SPECTRAL_SW: + write_pixel_xwave(pix_raw, time_acc, stream); + break; + case HTRDR_SPECTRAL_SW_CIE_XYZ: + write_pixel_image(pix_raw, time_acc, stream); + break; + default: FATAL("Unreachable code\n"); break; + } + } + } + return RES_OK; +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +planeto_draw_map(struct htrdr_planeto* cmd) +{ + struct htrdr_draw_map_args args = HTRDR_DRAW_MAP_ARGS_NULL; + struct htrdr_estimate path_time = HTRDR_ESTIMATE_NULL; + struct htrdr_accum path_time_acc = HTRDR_ACCUM_NULL; + res_T res = RES_OK; + ASSERT(cmd && cmd->output_type == HTRDR_PLANETO_ARGS_OUTPUT_IMAGE); + + args.buffer_layout = cmd->buf_layout; + args.spp = cmd->spp; + args.context = cmd; + switch(cmd->spectral_domain.spectral_type) { + case HTRDR_SPECTRAL_LW: + case HTRDR_SPECTRAL_SW: + args.draw_pixel = draw_pixel_xwave; + break; + case HTRDR_SPECTRAL_SW_CIE_XYZ: + args.draw_pixel = draw_pixel_image; + break; + default: FATAL("Unreachable code\n"); break; + } + + res = htrdr_draw_map(cmd->htrdr, &args, cmd->buf); + if(res != RES_OK) goto error; + + /* Nothing more to do on non master processes */ + if(htrdr_get_mpi_rank(cmd->htrdr) != 0) goto exit; + + /* Write output image */ + res = write_buffer(cmd, cmd->buf, &path_time_acc, cmd->output); + if(res != RES_OK) goto error; + + /* Log time per realisation */ + htrdr_accum_get_estimation(&path_time_acc, &path_time); + htrdr_log(cmd->htrdr, "Time per radiative path (in µs): %g +/- %g\n", + path_time.E, path_time.SE); + +exit: + return res; +error: + goto exit; +}