commit 5441ee76ecbdd9721bcc10685f04b94f54087345
parent bfd9f35c045995007128c3ac8fcc627978f05ff7
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 27 Jan 2021 12:16:15 +0100
Add auto computation of the grid definition
Diffstat:
3 files changed, 129 insertions(+), 32 deletions(-)
diff --git a/src/atrstm.c b/src/atrstm.c
@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#define _POSIX_C_SOURCE 200112L /* snprintf support */
+#define _POSIX_C_SOURCE 200112L /* snprintf & lround support */
#include "atrstm.h"
#include "atrstm_c.h"
@@ -36,21 +36,88 @@
static int
check_args(const struct atrstm_args* args)
{
- return args
- && args->sth_filename
- && (args->spectral_type != ATRSTM_SPECTRAL_LW || args->atrck_filename)
- && args->atrtp_filename
- && args->atrri_filename
- && args->name
- && (unsigned)args->spectral_type < ATRSTM_SPECTRAL_TYPES_COUNT__
- && args->wlen_range[0] <= args->wlen_range[1]
- && args->gyration_radius_prefactor > 0
- && args->fractal_dimension > 0
- && args->grid_max_definition[0]
- && args->grid_max_definition[1]
- && args->grid_max_definition[2]
- && args->optical_thickness >= 0
- && args->nthreads;
+ if(!args
+ || !args->sth_filename
+ || (args->spectral_type == ATRSTM_SPECTRAL_LW && !args->atrck_filename)
+ || !args->atrtp_filename
+ || !args->atrri_filename
+ || !args->name
+ || (unsigned)args->spectral_type >= ATRSTM_SPECTRAL_TYPES_COUNT__
+ || args->wlen_range[0] > args->wlen_range[1]
+ || args->gyration_radius_prefactor <= 0
+ || args->fractal_dimension <= 0
+ || args->optical_thickness < 0
+ || !args->nthreads) {
+ return 0;
+ }
+
+ if(args->auto_grid_definition) {
+ if(!args->auto_grid_definition_hint)
+ return 0;
+ } else {
+ if(!args->grid_max_definition[0]
+ || !args->grid_max_definition[1]
+ || !args->grid_max_definition[2])
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+compute_default_grid_definition
+ (const struct atrstm* atrstm,
+ const unsigned definition_hint,
+ unsigned def[3])
+{
+ double low[3];
+ double upp[3];
+ double sz[3];
+ double sz_max;
+ double vxsz;
+ int iaxis_max;
+ int iaxis_remain[2];
+ size_t next_pow2[2];
+ int i;
+ ASSERT(atrstm && def);
+
+ SUVM(volume_get_aabb(atrstm->volume, low, upp));
+ sz[0] = upp[0] - low[0];
+ sz[1] = upp[1] - low[1];
+ sz[2] = upp[2] - low[2];
+
+ /* Define the dimension along which the volume AABB is the greatest */
+ sz_max = -DBL_MAX;
+ FOR_EACH(i, 0, 3) {
+ if(sz[i] > sz_max) { iaxis_max = i; sz_max = sz[i]; }
+ }
+
+ /* Define the other axes */
+ iaxis_remain[0] = (iaxis_max + 1) % 3;
+ iaxis_remain[1] = (iaxis_max + 2) % 3;
+
+ /* Fix the definition to along the maximum axis and compute the voxel size
+ * along this axis */
+ def[iaxis_max] = (unsigned)round_up_pow2(definition_hint);
+ vxsz = sz[iaxis_max] / def[iaxis_max];
+
+ /* Compute the definition along the 2 remaining axes. First, copute these
+ * definitions by assuming that the voxels ar cubics [...] */
+ def[iaxis_remain[0]] = (unsigned)lround(sz[iaxis_remain[0]]/vxsz);
+ def[iaxis_remain[1]] = (unsigned)lround(sz[iaxis_remain[1]]/vxsz);
+
+ /* [...] Next compute the power of two directly greatest that the computed
+ * definition [...] */
+ next_pow2[0] = round_up_pow2(def[iaxis_remain[0]]);
+ next_pow2[1] = round_up_pow2(def[iaxis_remain[1]]);
+
+ /* [...] Finally round the definition to its nearest power of two. */
+ def[iaxis_remain[0]] =
+ next_pow2[0] - def[iaxis_remain[0]] < next_pow2[0]/4
+ ? (unsigned)next_pow2[0] : (unsigned)next_pow2[0]/2;
+ def[iaxis_remain[1]] =
+ next_pow2[1] - def[iaxis_remain[1]] < next_pow2[1]/4
+ ? (unsigned)next_pow2[1] : (unsigned)next_pow2[1]/2;
}
static void
@@ -118,9 +185,6 @@ atrstm_create
atrstm->spectral_type = args->spectral_type;
atrstm->wlen_range[0] = args->wlen_range[0];
atrstm->wlen_range[1] = args->wlen_range[1];
- atrstm->grid_max_definition[0] = args->grid_max_definition[0];
- atrstm->grid_max_definition[1] = args->grid_max_definition[1];
- atrstm->grid_max_definition[2] = args->grid_max_definition[2];
atrstm->optical_thickness = args->optical_thickness;
str_init(allocator, &atrstm->name);
@@ -190,6 +254,16 @@ atrstm_create
(atrstm, args->precompute_normals, args->sth_filename, &atrstm->volume);
if(res != RES_OK) goto error;
+ /* Define the grid definition */
+ if(args->auto_grid_definition) {
+ compute_default_grid_definition
+ (atrstm, args->auto_grid_definition_hint, atrstm->grid_max_definition);
+ } else {
+ atrstm->grid_max_definition[0] = args->grid_max_definition[0];
+ atrstm->grid_max_definition[1] = args->grid_max_definition[1];
+ atrstm->grid_max_definition[2] = args->grid_max_definition[2];
+ }
+
/* Load the thermodynamic properties of the volumetric mesh */
res = atrtp_create
(atrstm->logger, atrstm->allocator, atrstm->verbose, &atrstm->atrtp);
diff --git a/src/atrstm.h b/src/atrstm.h
@@ -104,7 +104,10 @@ struct atrstm_args {
double gyration_radius_prefactor;
double fractal_dimension;
- unsigned grid_max_definition[3]; /* Maximum definition of the grid */
+ unsigned grid_max_definition[3]; /* Fixed grid definition along the 3 axes */
+ unsigned auto_grid_definition_hint; /* Hint on the grid definition to eval */
+ int auto_grid_definition; /* Switch between auto and fixed grid definition */
+
double optical_thickness; /* Threshold used during octree building */
int precompute_normals; /* Pre-compute the tetrahedra normals */
@@ -120,13 +123,21 @@ struct atrstm_args {
NULL, /* AtrRI filename */ \
NULL, /* Cache filename */ \
"semi transparent medium", /* Name */ \
+ \
ATRSTM_SPECTRAL_SW, /* Spectral type */ \
{500,500}, /* Spectral integration range */ \
- 1.70, /* Prefactor */ \
+ \
+ 1.70, /* Gyration radius prefactor */ \
1.75, /* Fractal dimension */ \
+ \
{256, 256, 256}, /* Acceleration grid max definition */ \
+ 256, /* Hint on grid Definition in 'auto grid definition' mode */ \
+ 1, /* Enable/disable 'auto grid definition' mode */ \
+ \
1, /* Optical thickness */ \
+ \
0, /* Precompute tetrahedra normals */ \
+ \
(unsigned)~0, /* #threads */ \
0 /* Verbosity level */ \
}
diff --git a/src/test_atrstm.c b/src/test_atrstm.c
@@ -77,7 +77,8 @@ print_help(const char* cmd)
" -t NTHREADS hint on the number of threads to use. By default use\n"
" as many threads as CPU cores.\n");
printf(
-" -V X,Y,Z maximum definition of the acceleration grids\n"
+" -V <DEFINITION|X,Y,Z>\n"
+" maximum definition of the acceleration grids\n"
" along the 3 axis. Its default value is [%u, %u, %u].\n",
SPLIT3(ATRSTM_ARGS_DEFAULT.grid_max_definition));
printf(
@@ -103,22 +104,33 @@ parse_grid_definition(struct atrstm_args* args, const char* str)
ASSERT(args && str);
res = cstr_to_list_uint(str, ',', def, &len, 3);
- if(res == RES_OK && len != 3) res = RES_BAD_ARG;
+ if(res == RES_OK && len == 2) res = RES_OK;
if(res != RES_OK) {
fprintf(stderr, "Invalid grid definition `%s'.\n", str);
goto error;
}
- if(!def[0] || !def[1] || !def[2]) {
- fprintf(stderr,
- "Invalid null grid definition [%u, %u, %u].\n", SPLIT3(def));
- res = RES_BAD_ARG;
- goto error;
- }
+ if(len == 1) {
+ if(!def[0]) {
+ fprintf(stderr, "Invalid null grid definition %u.\n", def[0]);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ args->auto_grid_definition = 1;
+ args->auto_grid_definition_hint = def[0];
- args->grid_max_definition[0] = def[0];
- args->grid_max_definition[1] = def[1];
- args->grid_max_definition[2] = def[2];
+ } else {
+ if(!def[0] || !def[1] || !def[2]) {
+ fprintf(stderr,
+ "Invalid null grid definition [%u, %u, %u].\n", SPLIT3(def));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ args->auto_grid_definition = 0;
+ args->grid_max_definition[0] = def[0];
+ args->grid_max_definition[1] = def[1];
+ args->grid_max_definition[2] = def[2];
+ }
exit:
return res;