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:
| M | src/rnatm.c | | | 66 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
| M | src/rnatm_c.h | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++-------- |
| M | src/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;
}