commit c41c0ba905d0247f8d621eae291403721d8a9d37
parent e72deb14e89f35cf26ae04dbf1f31cae3ebead98
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 24 Aug 2022 18:24:30 +0200
Build the octrees for the user-defined spectral range
The spectral range is an input parameter of the rnatm_create function
Diffstat:
4 files changed, 91 insertions(+), 8 deletions(-)
diff --git a/src/rnatm.c b/src/rnatm.c
@@ -87,6 +87,10 @@ check_rnatm_create_args(const struct rnatm_create_args* args)
if(res != RES_OK) return res;
}
+ /* Invalid spectral range */
+ if(args->spectral_range[0] > args->spectral_range[1])
+ return RES_BAD_ARG;
+
/* Check miscalleneous arguments */
if(!args->name
|| args->optical_thickness < 0
diff --git a/src/rnatm.h b/src/rnatm.h
@@ -85,6 +85,8 @@ struct rnatm_create_args {
size_t naerosols;
char* name; /* Name of the atmosphere */
+ /* Spectral range to consider (in wavenumbers). Limits are inclusive */
+ double spectral_range[2];
double optical_thickness; /* Threshold used during octree building */
unsigned grid_definition_hint; /* Hint on the grid definition */
@@ -102,6 +104,7 @@ struct rnatm_create_args {
0, /* Number of aerosols */ \
"atmosphere", /* Name */ \
\
+ {12820.513, 26315.789}, /* Spectral range */ \
1, /* Optical thickness */ \
\
512, /* Hint on the grid definition */ \
@@ -122,7 +125,7 @@ struct rnatm;
BEGIN_DECLS
/*******************************************************************************
- * API of the Rad-Net GRounD library
+ * API of the Rad-Net ATMosphere library
******************************************************************************/
RNATM_API res_T
rnatm_create
diff --git a/src/rnatm_octree.c b/src/rnatm_octree.c
@@ -245,6 +245,60 @@ error:
goto exit;
}
+static res_T
+find_band_range
+ (const struct rnatm* atm,
+ const double range[2], /* In nanometers */
+ size_t bands[2])
+{
+ struct sck_band band_low;
+ struct sck_band band_upp;
+ size_t nbands;
+ size_t nbands_overlaped;
+ size_t ilow, iupp;
+ res_T res = RES_OK;
+ ASSERT(atm && range && bands && range[0] <= range[1]);
+
+ nbands = sck_get_bands_count(atm->gas.ck);
+
+ /* Find the lower bound */
+ FOR_EACH(ilow, 0, nbands) {
+ SCK(get_band(atm->gas.ck, ilow, &band_low));
+ if(band_low.upper >= range[0]) break;
+ }
+
+ /* Find the upper bound */
+ FOR_EACH(iupp, ilow, nbands) {
+ SCK(get_band(atm->gas.ck, iupp, &band_upp));
+ if(band_upp.lower > range[1]) break;
+ }
+
+ bands[0] = ilow;
+ bands[1] = iupp - 1; /* Make the boundary inclusive */
+
+ if(bands[0] > bands[1]) {
+ log_err(atm,
+ "the spectral range [%g, %g] cm^-1 does not overlap any bands\n",
+ SPLIT2(range));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ nbands_overlaped = bands[1] - bands[0] + 1;
+ log_info(atm,
+ "the spectral range [%g, %g] cm^-1 overlaps %lu band%sin [%g, %g] cm^-1\n",
+ SPLIT2(range),
+ (unsigned long)nbands_overlaped,
+ nbands_overlaped > 1 ? "s ": " ",
+ band_low.lower,
+ band_upp.upper);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
static FINLINE unsigned
round_pow2(const unsigned val)
{
@@ -998,8 +1052,8 @@ build_octrees
* the voxel, we therefore build `voxel_width' octrees in parallel from a
* single voxelization of the atmospheric meshes */
for(istruct = 0; istruct < naccel_structs; istruct += voxel_width) {
- const size_t nthreads = MMIN(voxel_width, naccel_structs - istruct);
- omp_set_num_threads((int)nthreads);
+ const size_t batch_size = MMIN(voxel_width, naccel_structs - istruct);
+ omp_set_num_threads((int)batch_size);
/* Note that we are using a parallel block rather than a parallel loop in
* order to add an implicit barrier after a batch has been fully consumed.
@@ -1104,16 +1158,21 @@ error:
}
static res_T
-create_octrees(struct rnatm* atm, const struct rnatm_create_args* args)
+create_octrees
+ (struct rnatm* atm,
+ const struct rnatm_create_args* args,
+ const size_t bands[2]) /* Limits are inclusive */
{
struct build_sync sync = BUILD_SYNC_NULL;
struct pool* pool = NULL;
- const size_t bands[2] = {0,0}; /* TODO handle multiple bands */
+ size_t nbands = 0;
ATOMIC res = RES_OK;
- ASSERT(atm);
+ ASSERT(atm && bands && bands[0] <= bands[1]);
- res = create_pool(atm, &pool, bands[1] - bands[0] + 1);
+ nbands = bands[1] - bands[0] + 1;
+
+ res = create_pool(atm, &pool, nbands);
if(res != RES_OK) goto error;
res = setup_accel_structs(atm, bands);
if(res != RES_OK) goto error;
@@ -1170,6 +1229,7 @@ res_T
setup_octrees(struct rnatm* atm, const struct rnatm_create_args* args)
{
char buf[128];
+ size_t bands[2];
struct time t0, t1;
size_t sz;
res_T res = RES_OK;
@@ -1180,7 +1240,9 @@ setup_octrees(struct rnatm* atm, const struct rnatm_create_args* args)
res = compute_grid_definition(atm, args);
if(res != RES_OK) goto error;
- res = create_octrees(atm, args);
+ res = find_band_range(atm, args->spectral_range, bands);
+ if(res != RES_OK) goto error;
+ res = create_octrees(atm, args, bands);
if(res != RES_OK) goto error;
/* Log elapsed time */
diff --git a/src/rnatm_properties.c b/src/rnatm_properties.c
@@ -302,9 +302,12 @@ setup_gas_properties(struct rnatm* atm, const struct rnatm_gas_args* gas_args)
{
char buf[128];
struct time t0, t1;
+ struct sck_band band_low = SCK_BAND_NULL;
+ struct sck_band band_upp = SCK_BAND_NULL;
struct sck_create_args sck_args = SCK_CREATE_ARGS_DEFAULT;
struct sbuf_create_args sbuf_args = SBUF_CREATE_ARGS_DEFAULT;
struct sbuf_desc sbuf_desc = SBUF_DESC_NULL;
+ size_t nbands;
res_T res = RES_OK;
ASSERT(atm && gas_args);
@@ -346,6 +349,17 @@ setup_gas_properties(struct rnatm* atm, const struct rnatm_gas_args* gas_args)
time_dump(&t0, TIME_ALL, NULL, buf, sizeof(buf));
log_info(atm, "gas properties loaded in %s\n", buf);
+ /* Print gas informations */
+ nbands = sck_get_bands_count(atm->gas.ck);
+ res = sck_get_band(atm->gas.ck, 0, &band_low);
+ if(res != RES_OK) goto error;
+ res = sck_get_band(atm->gas.ck, nbands-1, &band_upp);
+ if(res != RES_OK) goto error;
+ log_info(atm, "the gas is composed of %lu band%sin [%g, %g] cm^-1\n",
+ nbands, nbands > 1 ? "s " : " ",
+ band_low.lower,
+ band_upp.upper);
+
exit:
return res;
error: