commit a2d8927486f97b3a6c9cba491701776c18b7e47a
parent 4c97784d48b341ca409e1c12892b4b8b742daa5f
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 14 Mar 2016 14:31:27 +0100
Improve the geometry distribution YAML file format
A single YAML mapping node can be used to declare a single geometry
distribution.
Diffstat:
| M | src/schiff_args.c | | | 114 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
1 file changed, 72 insertions(+), 42 deletions(-)
diff --git a/src/schiff_args.c b/src/schiff_args.c
@@ -721,6 +721,42 @@ parse_yaml_sphere
}
static res_T
+parse_yaml_geom_distrib
+ (const char* filename,
+ yaml_document_t* doc,
+ yaml_node_t* node,
+ struct schiff_geometry* geom,
+ double* proba)
+{
+ res_T res;
+ yaml_node_t *key, *val;
+ ASSERT(filename && doc && node && geom && proba);
+
+ if(node->type != YAML_MAPPING_NODE
+ || node->data.mapping.pairs.top - node->data.mapping.pairs.start > 1) {
+ log_err(filename, node,
+ "expecting a mapping of the geometry distribution to its parameters\n");
+ return RES_BAD_ARG;
+ }
+
+ key = yaml_document_get_node(doc, node->data.mapping.pairs.start[0].key);
+ val = yaml_document_get_node(doc, node->data.mapping.pairs.start[0].value);
+ ASSERT(key->type == YAML_SCALAR_NODE);
+
+ if(!strcmp((char*)key->data.scalar.value, "cylinder")) {
+ 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 {
+ log_err(filename, key, "unknown distribution `%s'.\n",
+ key->data.scalar.value);
+ return RES_BAD_ARG;
+ }
+ if(res != RES_OK) return res;
+ return RES_OK;
+}
+
+static res_T
parse_yaml
(const char* filename,
struct schiff_geometry** out_geoms,
@@ -733,9 +769,9 @@ parse_yaml
size_t idistrib;
struct schiff_geometry* geoms = NULL;
double* probas = NULL;
- double accum_proba = 0;
struct ssp_ran_discrete* ran = NULL;
FILE* file = NULL;
+ int doc_is_init = 0;
res_T res = RES_OK;
ASSERT(filename && out_geoms && out_ran);
@@ -763,18 +799,26 @@ parse_yaml
res = RES_IO_ERR;
goto error;
}
+ doc_is_init = 1;
root = yaml_document_get_root_node(&doc);
- if(root->type != YAML_SEQUENCE_NODE) {
- fprintf(stderr, "Expecting YAML sequence.\n");
+ if(root->type == YAML_MAPPING_NODE) {
+ ndistribs = (size_t)
+ (root->data.mapping.pairs.top - root->data.mapping.pairs.start);
+ } else if(root->type == YAML_SEQUENCE_NODE) {
+ /* Define the number of submitted distributions */
+ ndistribs = (size_t)
+ (root->data.sequence.items.top - root->data.sequence.items.start);
+ }
+
+ if((root->type == YAML_MAPPING_NODE && ndistribs > 1)
+ || (root->type != YAML_MAPPING_NODE && root->type != YAML_SEQUENCE_NODE)) {
+ fprintf(stderr,
+ "Expecting either one or a list of geometry distributions.\n");
res = RES_BAD_ARG;
goto error;
}
- /* Define the number of submitted distributions */
- ndistribs = (size_t)
- (root->data.sequence.items.top - root->data.sequence.items.start);
-
/* Allocate the list geometry distributions */
if(!sa_add(geoms, ndistribs)) {
log_err(filename, root,
@@ -802,46 +846,32 @@ parse_yaml
goto error;
}
- /* Parse the geometry distributions */
- accum_proba = 0;
- FOR_EACH(idistrib, 0, ndistribs) {
- yaml_node_t* distrib, *key, *val;
+ /* Only one distribution */
+ if(root->type == YAML_MAPPING_NODE) {
+ res = parse_yaml_geom_distrib(filename, &doc, root, &geoms[0], &probas[0]);
+ if(res != RES_OK) goto error;
- distrib = yaml_document_get_node
- (&doc, root->data.sequence.items.start[idistrib]);
- if(distrib->type != YAML_MAPPING_NODE
- || distrib->data.mapping.pairs.top - distrib->data.mapping.pairs.start > 1) {
- log_err(filename, distrib,
- "expecting a mapping of the geometry distribution to its parameters\n");
- res = RES_BAD_ARG;
- goto error;
- }
+ /* List of geometry distributions */
+ } else {
+ double accum_proba = 0;
+ ASSERT(root->type == YAML_SEQUENCE_NODE);
- key = yaml_document_get_node(&doc, distrib->data.mapping.pairs.start[0].key);
- val = yaml_document_get_node(&doc, distrib->data.mapping.pairs.start[0].value);
- ASSERT(key->type == YAML_SCALAR_NODE);
+ FOR_EACH(idistrib, 0, ndistribs) {
+ yaml_node_t* distrib;
- if(!strcmp((char*)key->data.scalar.value, "cylinder")) {
- res = parse_yaml_cylinder
- (filename, &doc, val, &geoms[idistrib], &probas[idistrib]);
- } else if(!strcmp((char*)key->data.scalar.value, "sphere")) {
- res = parse_yaml_sphere
- (filename, &doc, val, &geoms[idistrib], &probas[idistrib]);
- } else {
- log_err(filename, key, "unknown distribution `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
+ distrib = yaml_document_get_node
+ (&doc, root->data.sequence.items.start[idistrib]);
+ res = parse_yaml_geom_distrib
+ (filename, &doc, distrib, &geoms[idistrib], &probas[idistrib]);
+ if(res != RES_OK) goto error;
+
+ accum_proba += probas[idistrib];
}
- if(res != RES_OK) goto error;
- accum_proba += probas[idistrib];
+ /* Normalized the geometry distribution probabilities */
+ FOR_EACH(idistrib, 0, ndistribs-1) probas[idistrib] /= accum_proba;
+ probas[ndistribs-1] = 1.f; /* Handle precision issues */
}
- /* Normalized the geometry distribution probabilities */
- FOR_EACH(idistrib, 0, ndistribs-1)
- probas[idistrib] /= accum_proba;
- probas[ndistribs-1] = 1.f; /* Handle precision issues */
-
/* Setup the geometry distributions random variate */
res = ssp_ran_discrete_setup(ran, probas, ndistribs);
if(res != RES_OK) {
@@ -852,7 +882,7 @@ parse_yaml
exit:
yaml_parser_delete(&parser);
- yaml_document_delete(&doc);
+ if(doc_is_init) yaml_document_delete(&doc);
if(file) fclose(file);
if(probas) sa_release(probas);
*out_geoms = geoms;