commit de5e84bde83cd7f27183410d8ddc75a0a2e62850
parent 8905ab82a5f0b9ab5e05973f9354569e411125ed
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 22 Mar 2017 16:38:21 +0100
Specify, load and test the dielectric material descriptor
Diffstat:
7 files changed, 276 insertions(+), 9 deletions(-)
diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt
@@ -91,6 +91,7 @@ if(NOT NO_TEST)
new_test(test_solparser5)
new_test(test_solparser6)
new_test(test_solparser7)
+ new_test(test_solparser8)
rcmake_copy_runtime_libraries(test_solparser)
endif()
diff --git a/doc/input b/doc/input
@@ -219,17 +219,22 @@
back: <material-descriptor>
<material-descriptor> ::=
- <mirror> | <matte> | <thin-dielectric> | <virtual>
+ <dielectric> | <matte> | <mirror> | thin-dielectric> | <virtual>
-<mirror> ::=
- mirror:
- reflectivity: REAL # in [0, 1]
- roughness: REAL # in [0, 1]
+<dielectric> ::=
+ dielectric:
+ eta_i: REAL # in ]0, INF)
+ eta_t: REAL # in ]0, INF)
<matte> ::=
matte:
reflectivity: REAL # in [0, 1]
+<mirror> ::=
+ mirror:
+ reflectivity: REAL # in [0, 1]
+ roughness: REAL # in [0, 1]
+
<virtual> ::=
virtual: EMPTY-STRING
diff --git a/src/parser/solparser.c b/src/parser/solparser.c
@@ -44,6 +44,11 @@ struct target_alias {
#define DARRAY_DATA struct target_alias
#include <rsys/dynamic_array.h>
+/* Declare the array of dielectric materials */
+#define DARRAY_NAME dielectric
+#define DARRAY_DATA struct solparser_material_dielectric
+#include <rsys/dynamic_array.h>
+
/* Declare the array of matte materials */
#define DARRAY_NAME matte
#define DARRAY_DATA struct solparser_material_matte
@@ -188,6 +193,7 @@ struct solparser {
struct htable_yaml2sols yaml2mtls; /* Cache of materials */
struct darray_material mtls;
struct darray_material2 mtls2; /* Double sided materials */
+ struct darray_dielectric dielectrics;
struct darray_matte mattes;
struct darray_mirror mirrors;
struct darray_thin_dielectric thin_dielectrics;
@@ -386,6 +392,7 @@ parser_clear(struct solparser* parser)
htable_yaml2sols_clear(&parser->yaml2mtls);
darray_material_clear(&parser->mtls);
darray_material2_clear(&parser->mtls2);
+ darray_dielectric_clear(&parser->dielectrics);
darray_matte_clear(&parser->mattes);
darray_mirror_clear(&parser->mirrors);
darray_thin_dielectric_clear(&parser->thin_dielectrics);
@@ -438,6 +445,7 @@ parser_release(ref_T* ref)
htable_yaml2sols_release(&parser->yaml2mtls);
darray_material_release(&parser->mtls);
darray_material2_release(&parser->mtls2);
+ darray_dielectric_release(&parser->dielectrics);
darray_matte_release(&parser->mattes);
darray_mirror_release(&parser->mirrors);
darray_thin_dielectric_release(&parser->thin_dielectrics);
@@ -859,6 +867,99 @@ error:
* Material
******************************************************************************/
static res_T
+parse_material_dielectric
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* dielec,
+ struct solparser_material_dielectric_id* out_imtl)
+{
+ enum { ETA_I, ETA_T };
+ struct solparser_material_dielectric* mtl = NULL;
+ size_t imtl = SIZE_MAX;
+ int mask = 0; /* Register the parsed attributes */
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && dielec && out_imtl);
+
+ if(dielec->type != YAML_MAPPING_NODE) {
+ log_err(parser, dielec,
+ "expect a mapping of dielec material attributes.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the dielec material */
+ imtl = darray_dielectric_size_get(&parser->dielectrics);
+ res = darray_dielectric_resize(&parser->dielectrics, imtl + 1);
+ if(res != RES_OK) {
+ log_err(parser, dielec,
+ "could not allocate the dielec material.\n");
+ goto error;
+ }
+ mtl = darray_dielectric_data_get(&parser->dielectrics) + imtl;
+
+ n = dielec->data.mapping.pairs.top - dielec->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, dielec->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, dielec->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a dielec material parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the "Name" of the dielectric material is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "eta_i")) {
+ SETUP_MASK(ETA_I, "eta_i");
+ res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &mtl->eta_i);
+ } else if(!strcmp((char*)key->data.scalar.value, "eta_t")) {
+ SETUP_MASK(ETA_T, "eta_t");
+ res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &mtl->eta_t);
+ } else {
+ log_err(parser, key, "unknown dielectric parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(res != RES_OK) {
+ log_node(parser, key);
+ goto error;
+ }
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, dielec, \
+ "the "Name" of the dielectric material is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(ETA_I, "eta_i");
+ CHECK_PARAM(ETA_T, "eta_t");
+ #undef CHECK_PARAM
+exit:
+ out_imtl->i = imtl;
+ return res;
+error:
+ if(imtl) {
+ darray_dielectric_pop_back(&parser->dielectrics);
+ imtl = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
parse_material_matte
(struct solparser* parser,
yaml_document_t* doc,
@@ -1048,7 +1149,7 @@ parse_material_thin_dielectric
if(thin->type != YAML_MAPPING_NODE) {
log_err(parser, thin,
- "expect a mapping of thin material attributes.\n");
+ "expect a mapping of thin dielectric material attributes.\n");
res = RES_BAD_ARG;
goto error;
}
@@ -1211,7 +1312,11 @@ parse_material_descriptor
} \
mask |= BIT(Flag); \
} (void)0
- if(!strcmp((char*)key->data.scalar.value, "matte")) {
+ if(!strcmp((char*)key->data.scalar.value, "dielectric")) {
+ SETUP_MASK(DESCRIPTOR, "descriptor");
+ mtl->type = SOLPARSER_MATERIAL_DIELECTRIC;
+ res = parse_material_dielectric(parser, doc, val, &mtl->data.dielectric);
+ } else if(!strcmp((char*)key->data.scalar.value, "matte")) {
SETUP_MASK(DESCRIPTOR, "descriptor");
mtl->type = SOLPARSER_MATERIAL_MATTE;
res = parse_material_matte(parser, doc, val, &mtl->data.matte);
@@ -3627,6 +3732,7 @@ solparser_create
htable_yaml2sols_init(mem_allocator, &parser->yaml2mtls);
darray_material_init(mem_allocator, &parser->mtls);
darray_material2_init(mem_allocator, &parser->mtls2);
+ darray_dielectric_init(mem_allocator, &parser->dielectrics);
darray_matte_init(mem_allocator, &parser->mattes);
darray_mirror_init(mem_allocator, &parser->mirrors);
darray_thin_dielectric_init(mem_allocator, &parser->thin_dielectrics);
@@ -3964,6 +4070,16 @@ solparser_get_material_double_sided
return darray_material2_cdata_get(&parser->mtls2) + mtl2.i;
}
+const struct solparser_material_dielectric*
+solparser_get_material_dielectric
+ (const struct solparser* parser,
+ const struct solparser_material_dielectric_id dielectric)
+{
+ ASSERT(parser);
+ ASSERT(dielectric.i < darray_dielectric_size_get(&parser->dielectrics));
+ return darray_dielectric_cdata_get(&parser->dielectrics) + dielectric.i;
+}
+
const struct solparser_material_matte*
solparser_get_material_matte
(const struct solparser* parser,
diff --git a/src/parser/solparser.h b/src/parser/solparser.h
@@ -102,6 +102,11 @@ solparser_get_material_double_sided
(const struct solparser* parser,
const struct solparser_material_double_sided_id mtl2);
+extern LOCAL_SYM const struct solparser_material_dielectric*
+solparser_get_material_dielectric
+ (const struct solparser* parser,
+ const struct solparser_material_dielectric_id dielectric);
+
extern LOCAL_SYM const struct solparser_material_matte*
solparser_get_material_matte
(const struct solparser* parser,
diff --git a/src/parser/solparser_material.h b/src/parser/solparser_material.h
@@ -19,12 +19,20 @@
#include <stddef.h>
enum solparser_material_type {
+ SOLPARSER_MATERIAL_DIELECTRIC,
SOLPARSER_MATERIAL_MATTE,
SOLPARSER_MATERIAL_MIRROR,
SOLPARSER_MATERIAL_THIN_DIELECTRIC,
SOLPARSER_MATERIAL_VIRTUAL
};
+struct solparser_material_dielectric {
+ double eta_i; /* Refractive index of the medium the material "looks at" */
+ double eta_t; /* Refractive index of the opposite medium */
+};
+
+struct solparser_material_dielectric_id { size_t i; };
+
struct solparser_material_matte {
double reflectivity; /* In [0, 1] */
};
@@ -49,6 +57,7 @@ struct solparser_material_thin_dielectric_id { size_t i; };
struct solparser_material {
enum solparser_material_type type;
union {
+ struct solparser_material_dielectric_id dielectric;
struct solparser_material_matte_id matte;
struct solparser_material_mirror_id mirror;
struct solparser_material_thin_dielectric_id thin_dielectric;
diff --git a/src/parser/test_solparser8.c b/src/parser/test_solparser8.c
@@ -0,0 +1,99 @@
+/* Copyright (C) CNRS 2016-2017
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "solparser.h"
+#include "solparser_sun.h"
+#include "test_solstice_utils.h"
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct solparser* parser;
+ struct solparser_entity_iterator it, end;
+ struct solparser_entity_id entity_id;
+ struct solparser_object_id obj_id;
+ const struct solparser_entity* entity;
+ const struct solparser_geometry* geom;
+ const struct solparser_material_double_sided* mtl2;
+ const struct solparser_material* mtl;
+ const struct solparser_material_dielectric* dielec;
+ const struct solparser_object* obj;
+ const struct solparser_shape* shape;
+ FILE* stream;
+ (void)argc, (void)argv;
+
+ CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
+ solparser_create(&allocator, &parser);
+
+ stream = tmpfile();
+ NCHECK(stream, NULL);
+
+ fprintf(stream, "- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1 }] }\n");
+ fprintf(stream, "- entity:\n");
+ fprintf(stream, " name: test\n");
+ fprintf(stream, " primary: 0\n");
+ fprintf(stream, " geometry:\n");
+ fprintf(stream, " - sphere: { radius: 1 }\n");
+ fprintf(stream, " material:\n");
+ fprintf(stream, " front: { dielectric: { eta_i: 1.0, eta_t: 1.5 } }\n");
+ fprintf(stream, " back: { dielectric: { eta_i: 1.5, eta_t: 1.0 } }\n");
+ rewind(stream);
+
+ CHECK(solparser_setup(parser, NULL, stream), RES_OK);
+ CHECK(solparser_load(parser), RES_OK);
+
+ solparser_entity_iterator_begin(parser, &it);
+ solparser_entity_iterator_end(parser, &end);
+ CHECK(solparser_entity_iterator_eq(&it, &end), 0);
+
+ entity_id = solparser_entity_iterator_get(&it);
+ entity = solparser_get_entity(parser, entity_id);
+
+ CHECK(strcmp("test", str_cget(&entity->name)), 0);
+ CHECK(solparser_entity_get_children_count(entity), 0);
+ CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY);
+ geom = solparser_get_geometry(parser, entity->data.geometry);
+ CHECK(solparser_geometry_get_objects_count(geom), 1);
+ obj_id = solparser_geometry_get_object(geom, 0);
+ obj = solparser_get_object(parser, obj_id);
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_SPHERE);
+ mtl2 = solparser_get_material_double_sided(parser, obj->mtl2);
+ NCHECK(mtl2->front.i, mtl2->back.i);
+
+ mtl = solparser_get_material(parser, mtl2->front);
+ CHECK(mtl->type, SOLPARSER_MATERIAL_DIELECTRIC);
+ dielec = solparser_get_material_dielectric(parser, mtl->data.dielectric);
+ CHECK(dielec->eta_i, 1.0);
+ CHECK(dielec->eta_t, 1.5);
+
+ mtl = solparser_get_material(parser, mtl2->back);
+ CHECK(mtl->type, SOLPARSER_MATERIAL_DIELECTRIC);
+ dielec = solparser_get_material_dielectric(parser, mtl->data.dielectric);
+ CHECK(dielec->eta_i, 1.5);
+ CHECK(dielec->eta_t, 1.0);
+
+ CHECK(solparser_load(parser), RES_BAD_OP);
+ solparser_ref_put(parser);
+
+ fclose(stream);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
+
diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml
@@ -245,6 +245,38 @@
# invalid refractive index
- material:
thin_dielectric: { absorption: 0, thickness: 0, refractive_index: -0.0001 }
+
+---
+
+#
+# <dielectric> ::=
+# dielectric:
+# eta_i: REAL # in ]0, INF)
+# eta_t: REAL # in ]0, INF)
+#
+
+# invalid eta_i
+- material:
+ dielectric: { eta_i: -1, eta_t: 1 }
+---
+- material:
+ dielectric: { eta_i: 0, eta_t: 1 }
+---
+# invalid eta_t
+- material:
+ dielectric: { eta_i: 1, eta_t: -1 }
+---
+# invalid eta_t
+- material:
+ dielectric: { eta_i: 1, eta_t: 0 }
+---
+# missing eta_t
+- material:
+ dielectric: { eta_i: 1 }
+---
+# missing eta_i
+- material:
+ dielectric: { eta_t: 1 }
---
#
@@ -772,7 +804,7 @@
- [-0.50, -0.50]
- [-0.50, 0.50]
- [0.50, 0.50]
- - [0.50, -0.50]
+ - [0.50, -0.50]
---
# invalid slices
- geometry: &target
@@ -784,7 +816,7 @@
- [-0.50, -0.50]
- [-0.50, 0.50]
- [0.50, 0.50]
- - [0.50, -0.50]
+ - [0.50, -0.50]
---
#