commit 4f9640f40316e86e1a3054293e45c9de62526a2a
parent 63bfccee6ba5d16d5314d703f6e9378efbc3f432
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 24 Mar 2016 14:00:50 +0100
Add the super_shape geometry to the YAML file format
Diffstat:
| M | src/schiff_args.c | | | 209 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
1 file changed, 191 insertions(+), 18 deletions(-)
diff --git a/src/schiff_args.c b/src/schiff_args.c
@@ -101,6 +101,7 @@ param_release(struct schiff_param* param)
static void
geometry_release(struct schiff_geometry* geom)
{
+ int i;
ASSERT(geom);
switch(geom->type) {
case SCHIFF_ELLIPSOID:
@@ -119,6 +120,12 @@ geometry_release(struct schiff_geometry* geom)
case SCHIFF_SPHERE:
param_release(&geom->data.sphere.radius);
break;
+ case SCHIFF_SUPER_SHAPE:
+ FOR_EACH(i, 0, 6) {
+ param_release(&geom->data.super_shape.formulas[0][i]);
+ param_release(&geom->data.super_shape.formulas[1][i]);
+ }
+ break;
case SCHIFF_NONE: /* Do nothing */ break;
default: FATAL("Unreachable code\n"); break;
}
@@ -534,6 +541,76 @@ parse_yaml_param_distribution
}
static res_T
+parse_yaml_super_shape_formula
+ (const char* filename,
+ yaml_document_t* doc,
+ const yaml_node_t* node,
+ struct schiff_param formula[6])
+{
+ int mask = 0; /* Register the parsed histogram attributes */
+ size_t nattrs;
+ size_t i;
+ res_T res = RES_OK;
+ ASSERT(filename && doc && node && formula);
+
+ if(node->type != YAML_MAPPING_NODE) {
+ log_err(filename, node,
+ "expecting a mapping of super-formula parameters.\n");
+ return RES_BAD_ARG;
+ }
+
+ nattrs = (size_t)
+ (node->data.mapping.pairs.top - node->data.mapping.pairs.start);
+
+ FOR_EACH(i, 0, nattrs) {
+ yaml_node_t* key, *val;
+
+ key = yaml_document_get_node(doc, node->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, node->data.mapping.pairs.start[i].value);
+ ASSERT(key->type == YAML_SCALAR_NODE);
+
+ #define PARSE_SUPER_SHAPE_PARAM(Param) \
+ if(!strcmp((char*)key->data.scalar.value, STR(Param))) { \
+ if(mask & BIT(Param)) { \
+ log_err(filename, key, \
+ "the "STR(Param)" super-formula parameter is already defined.\n"); \
+ return RES_BAD_ARG; \
+ } \
+ mask |= BIT(Param); \
+ res = parse_yaml_param_distribution \
+ (filename, doc, val, DBL_MIN, DBL_MAX, formula + Param); \
+ if(res != RES_OK) return res; \
+ continue; \
+ } (void)0
+ PARSE_SUPER_SHAPE_PARAM(A);
+ PARSE_SUPER_SHAPE_PARAM(B);
+ PARSE_SUPER_SHAPE_PARAM(M);
+ PARSE_SUPER_SHAPE_PARAM(N0);
+ PARSE_SUPER_SHAPE_PARAM(N1);
+ PARSE_SUPER_SHAPE_PARAM(N2);
+ #undef PARSE_SUPER_SHAPE_PARAM
+
+ log_err(filename, key, "unknown super-formula parameter `%s'.\n",
+ key->data.scalar.value);
+ return RES_BAD_ARG;
+ }
+ #define CHECK_SUPER_SHAPE_PARAM(Param) \
+ if(!(mask & BIT(Param))) { \
+ log_err(filename, node, \
+ "missing the "STR(Param)" super formula parameter.\n"); \
+ return RES_BAD_ARG; \
+ } (void)0
+ CHECK_SUPER_SHAPE_PARAM(A);
+ CHECK_SUPER_SHAPE_PARAM(B);
+ CHECK_SUPER_SHAPE_PARAM(M);
+ CHECK_SUPER_SHAPE_PARAM(N0);
+ CHECK_SUPER_SHAPE_PARAM(N1);
+ CHECK_SUPER_SHAPE_PARAM(N2);
+ #undef CHECK_SUPER_SHAPE_PARAM
+ return RES_OK;
+}
+
+static res_T
parse_yaml_ellipsoid
(const char* filename,
yaml_document_t* doc,
@@ -734,7 +811,7 @@ parse_yaml_cylinder
res = parse_yaml_double
(filename, val, DBL_MIN, DBL_MAX, &geom->data.cylinder.aspect_ratio);
- /* # slices used to discretized the triangular cylinder */
+ /* # slices used to discretized the cylinder */
} else if(!strcmp((char*)key->data.scalar.value, "slices")) {
SETUP_MASK(SLICES, "cylinder number of slices");
res = parse_yaml_uint
@@ -742,7 +819,7 @@ parse_yaml_cylinder
/* Error */
} else {
- log_err(filename, key, "unkown cylinder attribute `%s'.\n",
+ log_err(filename, key, "unknown cylinder attribute `%s'.\n",
key->data.scalar.value);
res = RES_BAD_ARG;
}
@@ -816,33 +893,28 @@ parse_yaml_sphere
val = yaml_document_get_node(doc, node->data.mapping.pairs.start[i].value);
ASSERT(key->type == YAML_SCALAR_NODE);
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & Flag) { \
+ log_err(filename, key, "the "Name" is already defined.\n"); \
+ return RES_BAD_ARG; \
+ } \
+ mask |= Flag; \
+ } (void)0
+
/* Probality to sample this geometry */
if(!strcmp((char*)key->data.scalar.value, "proba")) {
- if(mask & PROBA) {
- log_err(filename, node, "the sphere proba is already defined.\n");
- return RES_BAD_ARG;
- }
- mask |= PROBA;
+ SETUP_MASK(PROBA, "sphere proba");
res = parse_yaml_double(filename, val, DBL_MIN, DBL_MAX, geom_proba);
/* Sphere radius */
} else if(!strcmp((char*)key->data.scalar.value, "radius")) {
- if(mask & RADIUS) {
- log_err(filename, key, "the sphere radius is already defined.\n");
- return RES_BAD_ARG;
- }
- mask |= RADIUS;
+ SETUP_MASK(RADIUS, "sphere radius");
res = parse_yaml_param_distribution
(filename, doc, val, DBL_MIN, DBL_MAX, &geom->data.sphere.radius);
/* # slices used to discretized the triangular sphere */
} else if(!strcmp((char*)key->data.scalar.value, "slices")) {
- if(mask & SLICES) {
- log_err(filename, key,
- "the sphere number of slices is already defined.\n");
- return RES_BAD_ARG;
- }
- mask |= SLICES;
+ SETUP_MASK(SLICES, "sphere number of slices");
res = parse_yaml_uint
(filename, val, 4, 32768, &geom->data.sphere.nslices);
@@ -853,6 +925,8 @@ parse_yaml_sphere
return RES_BAD_ARG;
}
if(res != RES_OK) return res;
+
+ #undef SETUP_MASK
}
/* Ensure the completness of the spherical distribution */
@@ -871,6 +945,103 @@ parse_yaml_sphere
}
static res_T
+parse_yaml_super_shape
+ (const char* filename,
+ yaml_document_t* doc,
+ const yaml_node_t* node,
+ struct schiff_geometry* geom,
+ double* geom_proba)
+{
+ enum {
+ FORMULA0 = BIT(0),
+ FORMULA1 = BIT(1),
+ PROBA = BIT(2),
+ SLICES = BIT(3)
+ };
+ int mask = 0; /* Register the parsed attributes */
+ size_t nattrs;
+ size_t i;
+ res_T res = RES_OK;
+ ASSERT(filename && doc && node && geom && geom_proba);
+
+ if(node->type != YAML_MAPPING_NODE) {
+ log_err(filename, node, "expecting a mapping of super-shape attributes.\n");
+ return RES_BAD_ARG;
+ }
+
+ nattrs = (size_t)
+ (node->data.mapping.pairs.top - node->data.mapping.pairs.start);
+
+ FOR_EACH(i, 0, nattrs) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, node->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, node->data.mapping.pairs.start[i].value);
+ ASSERT(key->type == YAML_SCALAR_NODE);
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & Flag) { \
+ log_err(filename, key, "the "Name" is already defined.\n"); \
+ return RES_BAD_ARG; \
+ } \
+ mask |= Flag; \
+ } (void)0
+
+ /* Geometry probability */
+ if(!strcmp((char*)key->data.scalar.value, "proba")) {
+ SETUP_MASK(PROBA, "super-shape proba");
+ res = parse_yaml_double(filename, val, DBL_MIN, DBL_MAX, geom_proba);
+
+ /* Super shape formula0 */
+ } else if(!strcmp((char*)key->data.scalar.value, "formula0")) {
+ SETUP_MASK(FORMULA0, "super-shape formula0");
+ res = parse_yaml_super_shape_formula
+ (filename, doc, val, geom->data.super_shape.formulas[0]);
+
+ /* Super shape formula1 */
+ } else if(!strcmp((char*)key->data.scalar.value, "formula1")) {
+ SETUP_MASK(FORMULA1, "super-shape formula1");
+ res = parse_yaml_super_shape_formula
+ (filename, doc, val, geom->data.super_shape.formulas[1]);
+
+ /* # slices used to discretized the super shape */
+ } else if(!strcmp((char*)key->data.scalar.value, "slices")) {
+ SETUP_MASK(SLICES, "super-shape number of slices");
+ res = parse_yaml_uint
+ (filename, val, 4, 32768, &geom->data.super_shape.nslices);
+
+ /* Error */
+ } else {
+ log_err(filename, key, "unknown super-shape attribute `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) return res;
+
+ #undef SETUP_MASK
+ }
+
+ /* Ensure the completness of the cylinder distribution */
+ if(!(mask & FORMULA0)) {
+ log_err(filename, node, "missing the formula0 attribute.\n");
+ return RES_BAD_ARG;
+ } else if(!(mask & FORMULA1)) {
+ log_err(filename, node, "missing the formula1 attribute.\n");
+ return RES_BAD_ARG;
+ }
+
+ if(!(mask & PROBA)) { /* Default proba */
+ *geom_proba = 1.0;
+ }
+ if(!(mask & SLICES)) { /* Default number of slices */
+ geom->data.super_shape.nslices = SCHIFF_SUPER_SHAPE_DEFAULT.nslices;
+ }
+ geom->type = SCHIFF_SUPER_SHAPE;
+ return RES_OK;
+}
+
+static res_T
parse_yaml_geom_distrib
(const char* filename,
yaml_document_t* doc,
@@ -899,6 +1070,8 @@ parse_yaml_geom_distrib
res = parse_yaml_cylinder(filename, doc, val, geom, proba);
} else if(!strcmp((char*)key->data.scalar.value, "sphere")) {
res = parse_yaml_sphere(filename, doc, val, geom, proba);
+ } else if(!strcmp((char*)key->data.scalar.value, "super_shape")) {
+ res = parse_yaml_super_shape(filename, doc, val, geom, proba);
} else {
log_err(filename, key, "unknown distribution `%s'.\n",
key->data.scalar.value);