rnatm

Load and structure data describing an atmosphere
git clone git://git.meso-star.fr/rnatm.git
Log | Files | Refs | README | LICENSE

commit 4219e2e8b5e6afb11d9d2d7ca91b283218b89b64
parent 5d2d3a7d65a5b0c697c9fa622a52fb2e74e13538
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 28 Sep 2022 10:42:43 +0200

Start implementating the rngrd_cell_create_phase_fn function

Discrete phase functions are not yet supported

Diffstat:
MREADME.md | 1+
Mcmake/CMakeLists.txt | 4+++-
Msrc/rnatm.h | 14++++++++++++++
Msrc/rnatm_properties.c | 226++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 243 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md @@ -23,6 +23,7 @@ on the [Rad-Net Scattering Function](https://gitlab.com/meso-star/rnsf), [Star-Buffer](https://gitlab.com/meso-star/star-buffer), [Star-CorrelatedK](https://gitlab.com/meso-star/star-ck), [Star-Mesh](https://gitlab.com/meso-star/star-mesh), +[Star-ScatteringFunctions](https://gitlab.com/meso-star/star-sf), [Star-UnstructuredVolumetricMesh](https://gitlab.com/meso-star/star-uvm), [Star-VoXel](https://gitlab.com/meso-star/star-vx) libraries, and on [OpenMP](https://www.openmp.org) 1.2 to parallelize its diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -37,6 +37,7 @@ find_package(StarAerosol REQUIRED) find_package(StarBuffer REQUIRED) find_package(StarCK REQUIRED) find_package(StarMesh REQUIRED) +find_package(StarSF 0.7 REQUIRED) find_package(StarUVM 0.0 REQUIRED) find_package(StarVX 0.2 REQUIRED) @@ -52,6 +53,7 @@ include_directories( ${StarBuffer_INCLUDE_DIR} ${StarCK_INCLUDE_DIR} ${StarMesh_INCLUDE_DIR} + ${StarSF_INCLUDE_DIR} ${StarUVM_INCLUDE_DIR} ${StarVX_INCLUDE_DIR}) @@ -90,7 +92,7 @@ rcmake_prepend_path(RNATM_FILES_DOC ${PROJECT_SOURCE_DIR}/../) add_library(rnatm SHARED ${RNATM_FILES_SRC} ${RNATM_FILES_INC} ${RNATM_FILES_INC_API}) target_link_libraries(rnatm RNSL RNSF RSys StarAerosol StarBuffer StarCK StarMesh - StarUVM StarVX m) + StarSF StarUVM StarVX m) set_target_properties(rnatm PROPERTIES COMPILE_FLAGS "${OpenMP_C_FLAGS}" diff --git a/src/rnatm.h b/src/rnatm.h @@ -51,6 +51,7 @@ /* Forward declaration of external data types */ struct logger; struct mem_allocator; +struct ssf_phase; enum rnatm_radcoef { RNATM_RADCOEF_Ka, /* Absorption coefficient */ @@ -115,6 +116,13 @@ struct rnatm_cell_get_radcoef_args { static const struct rnatm_cell_get_radcoef_args RNATM_CELL_GET_RADCOEF_ARGS_NULL = RNATM_CELL_GET_RADCOEF_ARGS_NULL__; +struct rnatm_cell_create_phase_fn_args { + struct rnatm_cell cell; /* Cell to query */ + double barycentric_coords[4]; /* Position into and relative to the cell */ + double wavelength; /* In nm */ + double r[2]; /* Random numbers uniformaly distributed in [0, 1[ */ +}; + struct rnatm_trace_ray_args { double ray_org[3]; /* Origin of the ray */ double ray_dir[3]; /* Direction of the ray */ @@ -246,6 +254,12 @@ rnatm_cell_get_radcoef double* k); RNATM_API res_T +rnatm_cell_create_phase_fn + (struct rnatm* atm, + const struct rnatm_cell_create_phase_fn_args* args, + struct ssf_phase** phase_fn); + +RNATM_API res_T rnatm_trace_ray (struct rnatm* rnatm, const struct rnatm_trace_ray_args* args, diff --git a/src/rnatm_properties.c b/src/rnatm_properties.c @@ -28,6 +28,7 @@ #include <star/sars.h> #include <star/sbuf.h> #include <star/sck.h> +#include <star/ssf.h> #include <rsys/clock_time.h> #include <rsys/cstr.h> @@ -42,7 +43,7 @@ check_rnatm_cell_get_radcoef_args { double sum_bcoords; size_t i, n; - ASSERT(darray_band_size_get(&atm->bands)); + ASSERT(atm && darray_band_size_get(&atm->bands)); if(!args) return RES_BAD_ARG; @@ -84,6 +85,49 @@ check_rnatm_cell_get_radcoef_args return RES_OK; } +static res_T +check_rnatm_cell_create_phase_fn_args + (struct rnatm* atm, + const struct rnatm_cell_create_phase_fn_args* args) +{ + double sum_bcoords; + ASSERT(atm); + + if(!args) return RES_BAD_ARG; + + /* Invalid geometric primitive */ + if(!SUVM_PRIMITIVE_NONE(&args->cell.prim) + || args->cell.prim.nvertices != 4) /* Expect a tetraheron */ + return RES_BAD_ARG; + + /* Invalid component */ + + /* Invalid component */ + if(args->cell.component != RNATM_GAS + && args->cell.component >= darray_aerosol_size_get(&atm->aerosols)) + return RES_BAD_ARG; + + /* Invalid barycentric coordinates */ + sum_bcoords = + args->barycentric_coords[0] + + args->barycentric_coords[1] + + args->barycentric_coords[2] + + args->barycentric_coords[3]; + if(!eq_eps(sum_bcoords, 1, 1.e-6)) + return RES_BAD_ARG; + + /* Invalid wavelength */ + if(args->wavelength < 0) + return RES_BAD_ARG; + + /* Invalid random numbers */ + if(args->r[0] < 0 || args->r[0] >= 1 + || args->r[1] < 0 || args->r[1] >= 1) + return RES_BAD_ARG; + + return RES_OK; +} + static INLINE void reset_gas_properties(struct gas* gas) { @@ -546,6 +590,153 @@ error: goto exit; } +static INLINE res_T +create_phase_fn_rayleigh(struct rnatm* atm, struct ssf_phase** phase_fn) +{ + struct mem_allocator* allocator = NULL; + res_T res = RES_OK; + ASSERT(atm && phase_fn); + + /* TODO speed up allocation by using a [per thread] fifo allocator */ + allocator = atm->allocator; + + res = ssf_phase_create(allocator, &ssf_phase_rayleigh, phase_fn); + if(res != RES_OK) goto error; + +exit: + return res; +error: + if(*phase_fn) { SSF(phase_ref_put(*phase_fn)); *phase_fn = NULL; } + goto exit; +} + +static INLINE res_T +create_phase_fn_hg + (struct rnatm* atm, + const struct rnsf_phase_fn_hg* hg, + struct ssf_phase** phase_fn) +{ + struct mem_allocator* allocator = NULL; + res_T res = RES_OK; + ASSERT(atm && hg && phase_fn); + + /* TODO speed up allocation by using a [per thread] fifo allocator */ + allocator = atm->allocator; + + res = ssf_phase_create(allocator, &ssf_phase_hg, phase_fn); + if(res != RES_OK) goto error; + res = ssf_phase_hg_setup(*phase_fn, hg->g); + if(res != RES_OK) goto error; + +exit: + return res; +error: + if(*phase_fn) { SSF(phase_ref_put(*phase_fn)); *phase_fn = NULL; } + goto exit; +} + +static INLINE res_T +create_phase_fn_discrete + (struct rnatm* atm, + const struct rnsf_phase_fn_discrete* discrete, + struct ssf_phase** phase_fn) +{ + struct mem_allocator* allocator = NULL; + res_T res = RES_OK; + ASSERT(atm && discrete && phase_fn); + + /* TODO speed up allocation by using a [per thread] fifo allocator */ + allocator = atm->allocator; + + VFATAL("%s: function not implemented\n", ARG1(FUNC_NAME)); + (void)allocator; + (void)atm; + (void)discrete; + (void)phase_fn; + goto error; + +exit: + return res; +error: + if(*phase_fn) { SSF(phase_ref_put(*phase_fn)); *phase_fn = NULL; } + goto exit; +} + +static res_T +cell_create_phase_fn_aerosol + (struct rnatm* atm, + const struct rnatm_cell_create_phase_fn_args* args, + struct ssf_phase** phase_fn) +{ + struct sbuf_desc sbuf_desc; + struct rnsf_phase_fn_hg hg; + struct rnsf_phase_fn_discrete discrete; + const double* bcoords = NULL; + const struct aerosol* aerosol = NULL; + const struct rnsf* rnsf = NULL; + const struct rnsf_phase_fn* rnsf_phase_fn = NULL; + uint32_t phase_fn_id = 0; + size_t inode = 0; + size_t iphase_fn = 0; + int icell_node = 0; + res_T res = RES_OK; + ASSERT(atm && args && phase_fn); + ASSERT(args->cell.component < darray_aerosol_size_get(&atm->aerosols)); + + /* Get the aerosol the cell belongs to */ + aerosol = darray_aerosol_cdata_get(&atm->aerosols) + args->cell.component; + + /* Sample the cell node to consider */ + bcoords = args->barycentric_coords; + if(args->r[0] < bcoords[0]) { + icell_node = 0; + } else if(args->r[0] < bcoords[0] + bcoords[1]) { + icell_node = 1; + } else if(args->r[0] < bcoords[0] + bcoords[1] + bcoords[2]) { + icell_node = 2; + } else { + icell_node = 3; + } + + /* Retrieve the the phase function id of the node */ + SBUF(get_desc(aerosol->phase_fn_ids, &sbuf_desc)); + inode = args->cell.prim.indices[icell_node]; + ASSERT(inode < sbuf_desc.size); + phase_fn_id = *((const uint32_t*)sbuf_desc_at(&sbuf_desc, inode)); + + /* Retrieve the spectrally varying phase function of the node */ + ASSERT(phase_fn_id < darray_phase_fn_size_get(&aerosol->phase_fn_lst)); + rnsf = darray_phase_fn_cdata_get(&aerosol->phase_fn_lst)[phase_fn_id]; + + /* Get the phase function based on the input wavelength */ + res = rnsf_fetch_phase_fn(rnsf, args->wavelength, args->r[1], &iphase_fn); + if(res != RES_OK) goto error; + rnsf_phase_fn = rnsf_get_phase_fn(rnsf, iphase_fn); + + /* Create the scattering function */ + switch(rnsf_phase_fn_get_type(rnsf_phase_fn)) { + case RNSF_PHASE_FN_HG: + RNSF(phase_fn_get_hg(rnsf_phase_fn, &hg)); + res = create_phase_fn_hg(atm, &hg, phase_fn); + if(res != RES_OK) goto error; + break; + case RNSF_PHASE_FN_DISCRETE: + RNSF(phase_fn_get_discrete(rnsf_phase_fn, &discrete)); + res = create_phase_fn_discrete(atm, &discrete, phase_fn); + if(res != RES_OK) goto error; + break; + default: FATAL("Unreachable code\n"); break; + } + +exit: + return res; +error: + log_err(atm, "error creating the %s phase function -- %s\n", + str_cget(&aerosol->name), res_to_cstr(res)); + if(*phase_fn) { SSF(phase_ref_put(*phase_fn)); *phase_fn = NULL; } + goto exit; +} + /******************************************************************************* * Exported functions ******************************************************************************/ @@ -582,6 +773,39 @@ error: goto exit; } +res_T +rnatm_cell_create_phase_fn + (struct rnatm* atm, + const struct rnatm_cell_create_phase_fn_args* args, + struct ssf_phase** out_phase_fn) +{ + struct ssf_phase* phase_fn = NULL; + res_T res = RES_OK; + + if(!atm || !phase_fn) { res = RES_BAD_ARG; goto error; } + res = check_rnatm_cell_create_phase_fn_args(atm, args); + if(res != RES_OK) goto error; + + if(args->cell.component != RNATM_GAS) { + res = cell_create_phase_fn_aerosol(atm, args, &phase_fn); + if(res != RES_OK) goto error; + } else { + res = create_phase_fn_rayleigh(atm, &phase_fn); + if(res != RES_OK) { + log_err(atm, "error creating the gas phase function -- %s\n", + res_to_cstr(res)); + goto error; + } + } + +exit: + if(out_phase_fn) *out_phase_fn = phase_fn; + return res; +error: + if(phase_fn) { SSF(phase_ref_put(phase_fn)); phase_fn = NULL; } + goto exit; +} + /******************************************************************************* * Local functions ******************************************************************************/