rnatm

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

commit c329a88d5ad9d982d50de47a914fea2423e3fe65
parent 4219e2e8b5e6afb11d9d2d7ca91b283218b89b64
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 30 Sep 2022 17:14:42 +0200

Pre-allocate the list of scattering functions

Diffstat:
Msrc/rnatm.c | 66+++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/rnatm_c.h | 54++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/rnatm_properties.c | 287+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
3 files changed, 274 insertions(+), 133 deletions(-)

diff --git a/src/rnatm.c b/src/rnatm.c @@ -28,6 +28,7 @@ #include <star/sars.h> #include <star/sbuf.h> #include <star/sck.h> +#include <star/ssf.h> #include <star/suvm.h> #include <star/svx.h> @@ -384,45 +385,85 @@ rnatm_get_spectral_items_count(const struct rnatm* atm) * Local functions ******************************************************************************/ res_T -phase_fn_init(struct mem_allocator* allocator, struct rnsf** phase_fn) +phase_init(struct mem_allocator* allocator, struct ssf_phase** phase) { + ASSERT(phase); (void)allocator; - *phase_fn = NULL; + *phase = NULL; return RES_OK; } void -phase_fn_release(struct rnsf** phase_fn) +phase_release(struct ssf_phase** phase) { - if(*phase_fn) RNSF(ref_put(*phase_fn)); + ASSERT(phase); + if(*phase) SSF(phase_ref_put(*phase)); } res_T -phase_fn_copy(struct rnsf** dst, struct rnsf* const* src) +phase_copy(struct ssf_phase** dst, struct ssf_phase* const* src) { ASSERT(dst && src); - if(*dst) RNSF(ref_put(*dst)); + if(*dst) SSF(phase_ref_put(*dst)); *dst = *src; - if(*dst) RNSF(ref_get(*dst)); + if(*dst) SSF(phase_ref_get(*dst)); return RES_OK; } res_T -phase_fn_copy_and_release(struct rnsf** dst, struct rnsf** src) +phase_copy_and_release(struct ssf_phase** dst, struct ssf_phase** src) { ASSERT(dst && src); - if(*dst) RNSF(ref_put(*dst)); + if(*dst) SSF(phase_ref_put(*dst)); *dst = *src; *src = NULL; return RES_OK; } res_T +phase_fn_init(struct mem_allocator* allocator, struct phase_fn* phase_fn) +{ + ASSERT(phase_fn); + phase_fn->rnsf = NULL; + darray_phase_init(allocator, &phase_fn->phase_lst); + return RES_OK; +} + +void +phase_fn_release(struct phase_fn* phase_fn) +{ + ASSERT(phase_fn); + if(phase_fn->rnsf) RNSF(ref_put(phase_fn->rnsf)); + darray_phase_release(&phase_fn->phase_lst); +} + +res_T +phase_fn_copy(struct phase_fn* dst, const struct phase_fn* src) +{ + ASSERT(dst && src); + if(dst->rnsf) RNSF(ref_put(dst->rnsf)); + dst->rnsf = src->rnsf; + if(dst->rnsf) RNSF(ref_get(dst->rnsf)); + return darray_phase_copy(&dst->phase_lst, &src->phase_lst); +} + +res_T +phase_fn_copy_and_release(struct phase_fn* dst, struct phase_fn* src) +{ + ASSERT(dst && src); + if(dst->rnsf) RNSF(ref_put(dst->rnsf)); + dst->rnsf = src->rnsf; + src->rnsf = NULL; + return darray_phase_copy_and_release(&dst->phase_lst, &src->phase_lst); +} + +res_T gas_init(struct mem_allocator* allocator, struct gas* gas) { (void)allocator; ASSERT(gas); gas->volume = NULL; + gas->rayleigh = NULL; gas->temperatures = NULL; gas->ck = NULL; gas->ntetrahedra = 0; @@ -435,6 +476,7 @@ gas_release(struct gas* gas) { ASSERT(gas); if(gas->volume) SUVM(volume_ref_put(gas->volume)); + if(gas->rayleigh) SSF(phase_ref_put(gas->rayleigh)); if(gas->temperatures) SBUF(ref_put(gas->temperatures)); if(gas->ck) SCK(ref_put(gas->ck)); } @@ -444,14 +486,17 @@ gas_copy(struct gas* dst, const struct gas* src) { ASSERT(dst && src); if(dst->volume) SUVM(volume_ref_put(dst->volume)); + if(dst->rayleigh) SSF(phase_ref_put(dst->rayleigh)); if(dst->temperatures) SBUF(ref_put(dst->temperatures)); if(dst->ck) SCK(ref_put(dst->ck)); dst->volume = src->volume; + dst->rayleigh = src->rayleigh; dst->temperatures = src->temperatures; dst->ck = src->ck; dst->ntetrahedra = src->ntetrahedra; dst->nvertices = src->nvertices; if(dst->volume) SUVM(volume_ref_get(dst->volume)); + if(dst->rayleigh) SSF(phase_ref_get(dst->rayleigh)); if(dst->temperatures) SBUF(ref_get(dst->temperatures)); if(dst->ck) SCK(ref_get(dst->ck)); return RES_OK; @@ -462,14 +507,17 @@ gas_copy_and_release(struct gas* dst, struct gas* src) { ASSERT(dst && src); if(dst->volume) SUVM(volume_ref_put(dst->volume)); + if(dst->rayleigh) SSF(phase_ref_put(dst->rayleigh)); if(dst->temperatures) SBUF(ref_put(dst->temperatures)); if(dst->ck) SCK(ref_put(dst->ck)); dst->volume = src->volume; + dst->rayleigh = src->rayleigh; dst->temperatures = src->temperatures; dst->ck = src->ck; dst->ntetrahedra = src->ntetrahedra; dst->nvertices = src->nvertices; src->volume = NULL; + src->rayleigh = NULL; src->temperatures = NULL; src->ck = NULL; return RES_OK; diff --git a/src/rnatm_c.h b/src/rnatm_c.h @@ -29,6 +29,7 @@ #include <rsys/str.h> struct rnsf; +struct ssf_phase; /* Generate the dynamic array of dynamic array of size_t */ #define DARRAY_NAME size_t_list @@ -40,30 +41,66 @@ struct rnsf; #include <rsys/dynamic_array.h> /******************************************************************************* + * Phase function (SSF) + ******************************************************************************/ +extern LOCAL_SYM res_T +phase_init + (struct mem_allocator* allocator, + struct ssf_phase** phase); + +extern LOCAL_SYM void +phase_release + (struct ssf_phase** phase); + +extern LOCAL_SYM res_T +phase_copy + (struct ssf_phase** dst, + struct ssf_phase* const* src); + +extern LOCAL_SYM res_T +phase_copy_and_release + (struct ssf_phase** dst, + struct ssf_phase** src); + +/* Generate the dynamic array of SSF phase function */ +#define DARRAY_NAME phase +#define DARRAY_DATA struct ssf_phase* +#define DARRAY_FUNCTOR_INIT phase_init +#define DARRAY_FUNCTOR_RELEASE phase_release +#define DARRAY_FUNCTOR_COPY phase_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE phase_copy_and_release +#include <rsys/dynamic_array.h> + +/******************************************************************************* * Phase function ******************************************************************************/ +struct phase_fn { + struct rnsf* rnsf; + struct darray_phase phase_lst; +}; + extern LOCAL_SYM res_T phase_fn_init (struct mem_allocator* allocator, - struct rnsf** phase_fn); + struct phase_fn* phase_fn); extern LOCAL_SYM void phase_fn_release - (struct rnsf** phase_fn); + (struct phase_fn* phase_fn); extern LOCAL_SYM res_T phase_fn_copy - (struct rnsf** dst, - struct rnsf* const* src); + (struct phase_fn* dst, + const struct phase_fn* src); extern LOCAL_SYM res_T phase_fn_copy_and_release - (struct rnsf** dst, - struct rnsf** src); + (struct phase_fn* dst, + struct phase_fn* src); -/* Generate the dynamic array of phase functions */ +/* Generate the dynamic array of RNSF phase functions */ #define DARRAY_NAME phase_fn -#define DARRAY_DATA struct rnsf* +#define DARRAY_DATA struct phase_fn #define DARRAY_FUNCTOR_INIT phase_fn_init #define DARRAY_FUNCTOR_RELEASE phase_fn_release #define DARRAY_FUNCTOR_COPY phase_fn_copy @@ -75,6 +112,7 @@ phase_fn_copy_and_release ******************************************************************************/ struct gas { struct suvm_volume* volume; + struct ssf_phase* rayleigh; struct sbuf* temperatures; struct sck* ck; size_t ntetrahedra; diff --git a/src/rnatm_properties.c b/src/rnatm_properties.c @@ -290,6 +290,139 @@ check_aerosol_sars_desc return RES_OK; } +static INLINE res_T +create_phase_fn_rayleigh(struct rnatm* atm, struct ssf_phase** phase_fn) +{ + res_T res = RES_OK; + ASSERT(atm && phase_fn); + + res = ssf_phase_create(atm->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) +{ + res_T res = RES_OK; + ASSERT(atm && hg && phase_fn); + + res = ssf_phase_create(atm->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 +create_phase_fn + (struct rnatm* atm, + const struct rnsf_phase_fn* phase_fn, + struct ssf_phase** out_ssf_phase) +{ + struct rnsf_phase_fn_hg hg; + struct rnsf_phase_fn_discrete discrete; + struct ssf_phase* ssf_phase = NULL; + res_T res = RES_OK; + ASSERT(atm && phase_fn && out_ssf_phase); + + /* Create the scattering function */ + switch(rnsf_phase_fn_get_type(phase_fn)) { + case RNSF_PHASE_FN_HG: + RNSF(phase_fn_get_hg(phase_fn, &hg)); + res = create_phase_fn_hg(atm, &hg, &ssf_phase); + if(res != RES_OK) goto error; + break; + case RNSF_PHASE_FN_DISCRETE: + RNSF(phase_fn_get_discrete(phase_fn, &discrete)); + res = create_phase_fn_discrete(atm, &discrete, &ssf_phase); + if(res != RES_OK) goto error; + break; + default: FATAL("Unreachable code\n"); break; + } + +exit: + *out_ssf_phase = ssf_phase; + return res; +error: + if(ssf_phase) { SSF(phase_ref_put(ssf_phase)); ssf_phase = NULL; } + goto exit; +} + +static res_T +phase_fn_create_phase_list + (struct rnatm* atm, + const char* filename, + struct phase_fn* phase_fn) +{ + size_t nphases = 0; + size_t iphase = 0; + res_T res = RES_OK; + ASSERT(atm && filename && phase_fn); + + /* Reserve memory space for the list of phase functions */ + nphases = rnsf_get_phase_fn_count(phase_fn->rnsf); + res = darray_phase_resize(&phase_fn->phase_lst, nphases); + if(res != RES_OK) goto error; + + FOR_EACH(iphase, 0, nphases) { + const struct rnsf_phase_fn* fn = rnsf_get_phase_fn(phase_fn->rnsf, iphase); + struct ssf_phase** phase = darray_phase_data_get(&phase_fn->phase_lst) + iphase; + + res = create_phase_fn(atm, fn, phase); + if(res != RES_OK) goto error; + } + +exit: + return res; + +error: + log_err(atm, "%s: error creating the lisf of phase functions -- %s\n", + filename, res_to_cstr(res)); + darray_phase_clear(&phase_fn->phase_lst); + goto exit; +} + static res_T load_phase_fn (struct rnatm* atm, @@ -334,6 +467,7 @@ load_phase_fn_list size_t iphase_fn, nphase_fn; res_T res = RES_OK; + /* Create loader of scattefing function paths */ rnsl_args.logger = atm->logger; rnsl_args.allocator = atm->allocator; rnsl_args.verbose = atm->verbose; @@ -345,9 +479,11 @@ load_phase_fn_list goto error; } + /* Load the list of phase function paths */ res = rnsl_load(rnsl, args->phase_fn_lst_filename); if(res != RES_OK) goto error; + /* Reserve memory space for the list of phase functions */ nphase_fn = rnsl_get_strings_count(rnsl); res = darray_phase_fn_resize(&aerosol->phase_fn_lst, nphase_fn); if(res != RES_OK) { @@ -358,9 +494,12 @@ load_phase_fn_list FOR_EACH(iphase_fn, 0, nphase_fn) { const char* filename = rnsl_get_string(rnsl, iphase_fn); - struct rnsf** phase_fn = + struct phase_fn* phase_fn = darray_phase_fn_data_get(&aerosol->phase_fn_lst)+iphase_fn; - res = load_phase_fn(atm, filename, phase_fn); + + res = load_phase_fn(atm, filename, &phase_fn->rnsf); + if(res != RES_OK) goto error; + res = phase_fn_create_phase_list(atm, filename, phase_fn); if(res != RES_OK) goto error; } @@ -391,6 +530,10 @@ setup_gas_properties(struct rnatm* atm, const struct rnatm_gas_args* gas_args) log_info(atm, "load gas properties\n"); time_current(&t0); + /* Create the Rayleigh phase function */ + res = ssf_phase_create(atm->allocator, &ssf_phase_rayleigh, &atm->gas.rayleigh); + if(res != RES_OK) goto error; + /* Create the Star-Buffer loader */ sbuf_args.logger = atm->logger; sbuf_args.allocator = atm->allocator; @@ -590,101 +733,27 @@ 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 ssf_phase** out_ssf_phase) { 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; + struct aerosol* aerosol = NULL; + struct phase_fn* phase_fn = NULL; + struct ssf_phase* ssf_phase = 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(atm && args && out_ssf_phase); 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; + aerosol = darray_aerosol_data_get(&atm->aerosols) + args->cell.component; /* Sample the cell node to consider */ bcoords = args->barycentric_coords; @@ -698,7 +767,7 @@ cell_create_phase_fn_aerosol icell_node = 3; } - /* Retrieve the the phase function id of the node */ + /* Retrieve 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); @@ -706,34 +775,23 @@ cell_create_phase_fn_aerosol /* 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]; + phase_fn = darray_phase_fn_data_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); + res = rnsf_fetch_phase_fn + (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; - } + ssf_phase = darray_phase_data_get(&phase_fn->phase_lst)[iphase_fn]; + ASSERT(ssf_phase); + SSF(phase_ref_get(ssf_phase)); exit: + if(out_ssf_phase) *out_ssf_phase = ssf_phase; 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; } + if(ssf_phase) { SSF(phase_ref_put(ssf_phase)); ssf_phase = NULL; } goto exit; } @@ -777,32 +835,29 @@ 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** out_ssf_phase) { - struct ssf_phase* phase_fn = NULL; + struct ssf_phase* ssf_phase = NULL; res_T res = RES_OK; - if(!atm || !phase_fn) { res = RES_BAD_ARG; goto error; } + if(!atm || !out_ssf_phase) { 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; + if(args->cell.component == RNATM_GAS) { + /* Get a reference on the pre-allocated Rayleigh phase function */ + ssf_phase = atm->gas.rayleigh; + SSF(phase_ref_get(ssf_phase)); } 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; - } + res = cell_create_phase_fn_aerosol(atm, args, &ssf_phase); + if(res != RES_OK) goto error; } exit: - if(out_phase_fn) *out_phase_fn = phase_fn; + if(out_ssf_phase) *out_ssf_phase = ssf_phase; return res; error: - if(phase_fn) { SSF(phase_ref_put(phase_fn)); phase_fn = NULL; } + if(ssf_phase) { SSF(phase_ref_put(ssf_phase)); ssf_phase = NULL; } goto exit; }