commit 47a11f3369b05172f06044db812cefaaa7df1239
parent ff3dd07b51cb4dece229359a0864ec9ef09adcad
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 7 Dec 2022 08:40:55 +0100
htrdr-planeto: source radiance by wavelength
Source radiance can now be described by wavelength by providing a new
file following a file format described in this commit. When set,
this new argument overrides the source temperature.
In any case, these data are loaded, but are not used internally either
to sample a wavelength during rendering, nor to return spectrally
varying radiance when querying the source. Those are the next steps.
Diffstat:
7 files changed, 158 insertions(+), 10 deletions(-)
diff --git a/cmake/planeto/CMakeLists.txt b/cmake/planeto/CMakeLists.txt
@@ -26,6 +26,7 @@ find_package(RNATM 0.0 REQUIRED)
find_package(RNGRD 0.0 REQUIRED)
find_package(RSys 0.11 REQUIRED)
find_package(Star3D 0.8 REQUIRED)
+find_package(StarBuffer 0.0 REQUIRED)
find_package(StarCamera 0.0 REQUIRED)
find_package(StarSF 0.6 REQUIRED)
find_package(StarSP 0.12 REQUIRED)
@@ -40,6 +41,7 @@ include_directories(
${RNGRD}
${RSys_INCLUDE_DIR}
${Star3D_INCLUDE_DIR}
+ ${StarBuffer_INCLUDE_DIR}
${StarCamera_INCLUDE_DIR}
${StarSF_INCLUDE_DIR}
${StarSP_INCLUDE_DIR}
@@ -81,7 +83,7 @@ add_library(htrdr-planeto SHARED
${HTRDR_PLANETO_FILES_SRC}
${HTRDR_PLANETO_FILES_INC})
target_link_libraries(htrdr-planeto
- htrdr-core RNATM RNGRD RSys Star3D StarCamera StarSF StarSP)
+ htrdr-core RNATM RNGRD RSys Star3D StarBuffer StarCamera StarSF StarSP)
set_target_properties(htrdr-planeto PROPERTIES
DEFINE_SYMBOL HTRDR_SHARED_BUILD
diff --git a/doc/htrdr-planeto.1.scd.in b/doc/htrdr-planeto.1.scd.in
@@ -18,7 +18,7 @@ htrdr-planeto(1)
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
-# Name
+# NAME
htrdr-planeto - simulate radiative transfer in 3D planetary atmosphere
diff --git a/doc/rnrl.scd b/doc/rnrl.scd
@@ -0,0 +1,85 @@
+rnrl(5)
+
+; 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
+; (contact-edstar@laplace.univ-tlse.fr)
+; 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/>.
+
+# NAME
+
+rnsr - Rad-Net Radiance List file format
+
+# DESCRIPTION
+
+*rnrl* is a binary file format for storing a list of spectrally varying
+radiances. The radiances (in W/m²/sr/m) are listed by wavelength (in nm)
+sorted in ascending order.
+
+A *rnrl* file is actually a Star-Buffer file (see *sbuf*(5)). It starts with a
+header of 4 64-bit integers describing the layout of the data. The first integer
+is a power of two (usually 4096) that defines the size of the memory page in
+bytes to which the list of per wavelength radiances aligns (_pagesize_). The
+second integer is the _size_ of the array, i.e. the number of wavelength for
+which a radiance is defined. Finally, the 2 remaining integers store the memory
+size (16 bytes, i.e. 2 double precision values) and the memory alignment (16
+bytes) of a per wavelength radiance.
+
+An *rnrl* file is actually a Star-Buffer file (see *sbuf*(5)). It starts with a
+header of 4 64-bit integers describing the layout of the data. The first integer
+is a power of two (usually 4096) which defines the size of the memory page in
+bytes on which the list of radiances by wavelength aligns (_pagesize_). The
+second integer is the _size_ of the array, that is, the number of wavelengths
+for which a radiance is defined. Finally, the remaining 2 integers store the
+memory size (16 bytes) and memory alignment (16 bytes) of a radiance per
+wavelength.
+
+The fill bytes follow the file header to align the radiances by wavelength to
+_pagesize_.
+
+Each item in the list is composed of 2 double-precision floating-point values:
+the wavelength in nanometers and its corresponding radiance in W/m²/sr/m.
+
+The end of the file is eventually padded with dummy bytes to ensure that the
+overall file size is a multiple of _pagesize_.
+
+# BINARY FILE FORMAT
+
+Data are encoded with respect to the little endian bytes ordering, i.e. least
+significant bytes are stored first.
+
+```
+<rnsr> ::= <pagesize> <size> 16 16
+ <padding>
+ <radiances>
+ <padding>
+
+<pagesize> ::= UINT64
+<size> ::= UINT64 # Number of items stored
+
+---
+
+<radiances> ::= <property> ... ...
+<property> ::= <wavelength> <radiance>
+<wavelength> ::= DOUBLE # in nanometer
+<radiance> ::= DOUBLE # in W/m²/sr/m
+
+---
+
+<padding> ::= [ BYTE ... ] # Ensure alignement
+```
+
+# SEE ALSO
+
+*sbuf*(5)
diff --git a/src/core/htrdr_ran_wlen_planck.c b/src/core/htrdr_ran_wlen_planck.c
@@ -298,7 +298,7 @@ htrdr_ran_wlen_planck_create
if(!planck) {
res = RES_MEM_ERR;
htrdr_log_err(htrdr,
- "%s: could not allocate longwave random variate data structure -- %s.\n",
+ "%s: could not allocate Planck distribution -- %s.\n",
FUNC_NAME, res_to_cstr(res));
goto error;
}
diff --git a/src/planeto/htrdr_planeto_args.c b/src/planeto/htrdr_planeto_args.c
@@ -386,7 +386,7 @@ error:
static res_T
parse_source_parameters(const char* str, void* ptr)
{
- enum {LAT, LON, DST, RADIUS, TEMP} iparam;
+ enum {LAT, LON, DST, RADIUS, TEMP, RAD} iparam;
char buf[BUFSIZ];
struct htrdr_planeto_args* args = ptr;
struct htrdr_planeto_source_args* src = NULL;
@@ -411,6 +411,7 @@ parse_source_parameters(const char* str, void* ptr)
if(!strcmp(key, "lat")) iparam = LAT;
else if(!strcmp(key, "lon")) iparam = LON;
else if(!strcmp(key, "dst")) iparam = DST;
+ else if(!strcmp(key, "rad")) iparam = RAD;
else if(!strcmp(key, "radius")) iparam = RADIUS;
else if(!strcmp(key, "temp")) iparam = TEMP;
else {
@@ -442,11 +443,23 @@ parse_source_parameters(const char* str, void* ptr)
res = cstr_to_double(val, &src->distance);
if(res == RES_OK && src->distance < 0) res = RES_BAD_ARG;
break;
+ case RAD:
+ /* Use a per wavelength radiance rather than a constant temperature */
+ src->temperature = -1;
+ if(src->rnrl_filename) mem_rm(src->rnrl_filename);
+ src->rnrl_filename = str_dup(val);
+ if(!src->rnrl_filename) res = RES_MEM_ERR;
+ break;
case RADIUS:
res = cstr_to_double(val, &src->radius);
if(res == RES_OK && src->radius < 0) res = RES_BAD_ARG;
break;
case TEMP:
+ /* Use a constant temperature rather than a per wavelength radiance */
+ if(src->rnrl_filename) {
+ mem_rm(src->rnrl_filename);
+ src->rnrl_filename = NULL;
+ }
res = cstr_to_double(val, &src->temperature);
if(res == RES_OK && src->temperature < 0) res = RES_BAD_ARG;
break;
@@ -692,6 +705,7 @@ htrdr_planeto_args_release(struct htrdr_planeto_args* args)
if(args->ground.props_filename) mem_rm(args->ground.props_filename);
if(args->ground.mtllst_filename) mem_rm(args->ground.mtllst_filename);
if(args->ground.name) mem_rm(args->ground.name);
+ if(args->source.rnrl_filename) mem_rm(args->source.rnrl_filename);
FOR_EACH(i, 0, args->naerosols) {
struct rnatm_aerosol_args* aerosol = args->aerosols + i;
@@ -775,9 +789,13 @@ htrdr_planeto_source_args_check(const struct htrdr_planeto_source_args* args)
|| args->distance < 0)
return RES_BAD_ARG;
- /* Miscellaneous parameters */
- if(args->radius < 0
- || args->temperature < 0)
+ /* Invalid radius */
+ if(args->radius < 0)
+ return RES_BAD_ARG;
+
+ /* Invalid radiance */
+ if((args->temperature < 0 && !args->rnrl_filename) /* Both are invalids */
+ || (args->temperature >=0 && args->rnrl_filename)) /* Both are valids */
return RES_BAD_ARG;
return RES_OK;
diff --git a/src/planeto/htrdr_planeto_args.h.in b/src/planeto/htrdr_planeto_args.h.in
@@ -43,13 +43,16 @@ static const struct htrdr_planeto_spectral_args
HTRDR_PLANETO_SPECTRAL_ARGS_DEFAULT = HTRDR_PLANETO_SPECTRAL_ARGS_DEFAULT__;
struct htrdr_planeto_source_args {
+ /* Radiance of the source per wavelength. May be NULL */
+ char* rnrl_filename;
+
double longitude; /* In [-180, 180] degrees */
double latitude; /* In [-90, 90] degrees */
double distance; /* In km */
double radius; /* In km */
double temperature; /* In Kelvin */
};
-#define HTRDR_PLANETO_SOURCE_ARGS_NULL__ {0,0,0,-1,-1}
+#define HTRDR_PLANETO_SOURCE_ARGS_NULL__ {NULL,0,0,0,-1,-1}
static const struct htrdr_planeto_source_args HTRDR_PLANETO_SOURCE_ARGS_NULL =
HTRDR_PLANETO_SOURCE_ARGS_NULL__;
diff --git a/src/planeto/htrdr_planeto_source.c b/src/planeto/htrdr_planeto_source.c
@@ -21,8 +21,10 @@
#include "core/htrdr.h"
#include "core/htrdr_log.h"
+#include <star/sbuf.h>
#include <star/ssp.h>
+#include <rsys/cstr.h>
#include <rsys/double3.h>
#include <rsys/ref_count.h>
@@ -30,7 +32,11 @@ struct htrdr_planeto_source {
double position[3]; /* In m */
double radius; /* In m */
- double temperature; /* In Kelvin */
+
+ /* In Kelvin. Defined if the radiances by wavelength is no set */
+ double temperature;
+
+ struct sbuf* per_wlen_radiances; /* List of radiances by wavelength */
ref_T ref;
struct htrdr* htrdr;
@@ -39,6 +45,32 @@ struct htrdr_planeto_source {
/*******************************************************************************
* Helper functions
******************************************************************************/
+static res_T
+setup_per_wavelength_radiances
+ (struct htrdr_planeto_source* src,
+ const struct htrdr_planeto_source_args* args)
+{
+ struct sbuf_create_args sbuf_args;
+ res_T res = RES_OK;
+ ASSERT(src && args && args->rnrl_filename && args->temperature < 0);
+
+ sbuf_args.logger = htrdr_get_logger(src->htrdr);
+ sbuf_args.allocator = htrdr_get_allocator(src->htrdr);
+ sbuf_args.verbose = htrdr_get_verbosity_level(src->htrdr);
+ res = sbuf_create(&sbuf_args, &src->per_wlen_radiances);
+ if(res != RES_OK) goto error;
+
+ res = sbuf_load(src->per_wlen_radiances, args->rnrl_filename);
+ if(res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ htrdr_log_err(src->htrdr, "error loading %s -- %s\n",
+ args->rnrl_filename, res_to_cstr(res));
+ goto exit;
+}
+
static void
release_source(ref_T* ref)
{
@@ -48,6 +80,7 @@ release_source(ref_T* ref)
source = CONTAINER_OF(ref, struct htrdr_planeto_source, ref);
htrdr = source->htrdr;
+ if(source->per_wlen_radiances) SBUF(ref_put(source->per_wlen_radiances));
MEM_RM(htrdr_get_allocator(htrdr), source);
htrdr_ref_put(htrdr);
}
@@ -79,7 +112,14 @@ htrdr_planeto_source_create
htrdr_ref_get(cmd->htrdr);
src->htrdr = cmd->htrdr;
src->radius = args->radius * 1e3/*From km to m*/;
- src->temperature = args->temperature;
+
+ if(!args->rnrl_filename) {
+ src->temperature = args->temperature;
+ } else {
+ res = setup_per_wavelength_radiances(src, args);
+ if(res != RES_OK) goto error;
+ src->temperature = -1; /* Not used */
+ }
/* Convert latitude and longitude to radians and distance in m */
lat = MDEG2RAD(args->latitude);