solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

commit 82ac79788359da79eeef64cb26da3a80ae817787
parent 8905ab82a5f0b9ab5e05973f9354569e411125ed
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 27 Mar 2017 15:03:13 +0200

Merge branch 'feature_material_dielectric' into develop

Diffstat:
Mcmake/parser/CMakeLists.txt | 3+++
Mdoc/input | 21+++++++++++++++------
Msrc/parser/solparser.c | 250+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/parser/solparser.h | 10++++++++++
Msrc/parser/solparser_material.h | 20++++++++++++++++++--
Msrc/parser/test_solparser7.c | 18++++++++++++++----
Asrc/parser/test_solparser8.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser/yaml/test_ko_0.yaml | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/parser/yaml/test_ok_5.yaml | 14+++++++-------
Asrc/parser/yaml/test_ok_7.yaml | 40++++++++++++++++++++++++++++++++++++++++
Msrc/solstice_material.c | 152+++++++++++++++++++++++++++++++++----------------------------------------------
11 files changed, 589 insertions(+), 130 deletions(-)

diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt @@ -82,6 +82,8 @@ if(NOT NO_TEST) ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_5.yaml) add_test(test_solparser_ok_6 test_solparser ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_6.yaml) + add_test(test_solparser_ok_7 test_solparser + ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_7.yaml) add_test(test_solparser_ko test_solparser -e ${SOLPARSER_SOURCE_DIR}/yaml/test_ko_0.yaml) @@ -91,6 +93,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,25 +219,34 @@ 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: + medium_i: <dielectric-medium> + medium_t: <dielectric-medium> <matte> ::= matte: reflectivity: REAL # in [0, 1] +<mirror> ::= + mirror: + reflectivity: REAL # in [0, 1] + roughness: REAL # in [0, 1] + <virtual> ::= virtual: EMPTY-STRING <thin-dielectric> ::= thin_dielectric: - absorption: REAL # in [0, INF) thickness: REAL # in [0, INF) + medium_i: <dielectric-medium> + medium_t: <dielectric-medium> + +<dielectric-medium> ::= refractive_index: REAL # in ]0, INF) + absorptivity: REAL # in [0, INF) #---------------------------------------- <entity> ::= diff --git a/src/parser/solparser.c b/src/parser/solparser.c @@ -44,6 +44,16 @@ struct target_alias { #define DARRAY_DATA struct target_alias #include <rsys/dynamic_array.h> +/* Declare the array of mediums */ +#define DARRAY_NAME medium +#define DARRAY_DATA struct solparser_medium +#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 +198,8 @@ struct solparser { struct htable_yaml2sols yaml2mtls; /* Cache of materials */ struct darray_material mtls; struct darray_material2 mtls2; /* Double sided materials */ + struct darray_medium mediums; + struct darray_dielectric dielectrics; struct darray_matte mattes; struct darray_mirror mirrors; struct darray_thin_dielectric thin_dielectrics; @@ -386,6 +398,8 @@ parser_clear(struct solparser* parser) htable_yaml2sols_clear(&parser->yaml2mtls); darray_material_clear(&parser->mtls); darray_material2_clear(&parser->mtls2); + darray_medium_clear(&parser->mediums); + darray_dielectric_clear(&parser->dielectrics); darray_matte_clear(&parser->mattes); darray_mirror_clear(&parser->mirrors); darray_thin_dielectric_clear(&parser->thin_dielectrics); @@ -438,6 +452,8 @@ parser_release(ref_T* ref) htable_yaml2sols_release(&parser->yaml2mtls); darray_material_release(&parser->mtls); darray_material2_release(&parser->mtls2); + darray_medium_release(&parser->mediums); + darray_dielectric_release(&parser->dielectrics); darray_matte_release(&parser->mattes); darray_mirror_release(&parser->mirrors); darray_thin_dielectric_release(&parser->thin_dielectrics); @@ -859,6 +875,192 @@ error: * Material ******************************************************************************/ static res_T +parse_medium + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* medium, + struct solparser_medium_id* out_imedium) +{ + enum { ABSORPTIVITY, REFRACTIVE_INDEX }; + struct solparser_medium* mdm = NULL; + size_t imedium = SIZE_MAX; + int mask = 0; /* Register the parsed attributes */ + intptr_t i, n; + res_T res = RES_OK; + ASSERT(doc && medium && out_imedium); + + if(medium->type != YAML_MAPPING_NODE) { + log_err(parser, medium, "expect a mapping of medium attributes.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* Allocate the medium */ + imedium = darray_medium_size_get(&parser->mediums); + res = darray_medium_resize(&parser->mediums, imedium + 1); + if(res != RES_OK) { + log_err(parser, medium, "could not allocate the medium.\n"); + res = RES_BAD_ARG; + goto error; + } + mdm = darray_medium_data_get(&parser->mediums) + imedium; + + n = medium->data.mapping.pairs.top - medium->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, medium->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, medium->data.mapping.pairs.start[i].value); + if(key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect a medium 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 medium is already defined.\n");\ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "absorptivity")) { + SETUP_MASK(ABSORPTIVITY, "absorptivity"); + res = parse_real(parser, val, 0, DBL_MAX, &mdm->absorptivity); + } else if(!strcmp((char*)key->data.scalar.value, "refractive_index")) { + SETUP_MASK(REFRACTIVE_INDEX, "refractive_index"); + res = parse_real + (parser, val, nextafter(0, 1), DBL_MAX, &mdm->refractive_index); + } else { + log_err(parser, key, "unknown medium 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, medium, "the "Name" of the medium is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(ABSORPTIVITY, "absorptivity"); + CHECK_PARAM(REFRACTIVE_INDEX, "refractive_index"); + #undef CHECK_PARAM + +exit: + out_imedium->i = imedium; + return res; +error: + if(imedium) { + darray_medium_pop_back(&parser->mediums); + imedium = SIZE_MAX; + } + goto exit; +} + +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 { MEDIUM_I, MEDIUM_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, "medium_i")) { + SETUP_MASK(MEDIUM_I, "medium_i"); + res = parse_medium(parser, doc, val, &mtl->medium_i); + } else if(!strcmp((char*)key->data.scalar.value, "medium_t")) { + SETUP_MASK(MEDIUM_T, "medium_t"); + res = parse_medium(parser, doc, val, &mtl->medium_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(MEDIUM_I, "medium_i"); + CHECK_PARAM(MEDIUM_T, "medium_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, @@ -1038,7 +1240,7 @@ parse_material_thin_dielectric yaml_node_t* thin, struct solparser_material_thin_dielectric_id* out_imtl) { - enum { ABSORPTION, REFRACTIVE_INDEX, THICKNESS }; + enum { MEDIUM_I, MEDIUM_T, THICKNESS }; struct solparser_material_thin_dielectric* mtl = NULL; size_t imtl = SIZE_MAX; int mask = 0; /* Register the parsed attributes */ @@ -1048,7 +1250,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; } @@ -1085,13 +1287,12 @@ parse_material_thin_dielectric } \ mask |= BIT(Flag); \ } (void)0 - if(!strcmp((char*)key->data.scalar.value, "absorption")) { - SETUP_MASK(ABSORPTION, "absorption"); - res = parse_real(parser, val, 0, DBL_MAX, &mtl->absorption); - } else if(!strcmp((char*)key->data.scalar.value, "refractive_index")) { - SETUP_MASK(REFRACTIVE_INDEX, "refractive_index"); - res = parse_real - (parser, val, nextafter(0, 1), DBL_MAX, &mtl->refractive_index); + if(!strcmp((char*)key->data.scalar.value, "medium_i")) { + SETUP_MASK(MEDIUM_I, "medium_i"); + res = parse_medium(parser, doc, val, &mtl->medium_i); + } else if(!strcmp((char*)key->data.scalar.value, "medium_t")) { + SETUP_MASK(MEDIUM_T, "medium_t"); + res = parse_medium(parser, doc, val, &mtl->medium_t); } else if(!strcmp((char*)key->data.scalar.value, "thickness")) { SETUP_MASK(THICKNESS, "thickness"); res = parse_real(parser, val, 0, DBL_MAX, &mtl->thickness); @@ -1115,8 +1316,8 @@ parse_material_thin_dielectric res = RES_BAD_ARG; \ goto error; \ } (void)0 - CHECK_PARAM(ABSORPTION, "absorption"); - CHECK_PARAM(REFRACTIVE_INDEX, "refractive_index"); + CHECK_PARAM(MEDIUM_I, "medium_i"); + CHECK_PARAM(MEDIUM_T, "medium_t"); CHECK_PARAM(THICKNESS, "thickness"); #undef CHECK_PARAM @@ -1211,7 +1412,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 +3832,8 @@ solparser_create htable_yaml2sols_init(mem_allocator, &parser->yaml2mtls); darray_material_init(mem_allocator, &parser->mtls); darray_material2_init(mem_allocator, &parser->mtls2); + darray_medium_init(mem_allocator, &parser->mediums); + 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); @@ -3946,6 +4153,15 @@ solparser_get_geometry return darray_geometry_cdata_get(&parser->geometries) + geom.i; } +const struct solparser_medium* +solparser_get_medium + (const struct solparser* parser, + const struct solparser_medium_id medium) +{ + ASSERT(parser && medium.i < darray_medium_size_get(&parser->mediums)); + return darray_medium_cdata_get(&parser->mediums) + medium.i; +} + const struct solparser_material* solparser_get_material (const struct solparser* parser, @@ -3964,6 +4180,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 @@ -92,6 +92,11 @@ solparser_get_geometry (const struct solparser* parser, const struct solparser_geometry_id geom); +extern LOCAL_SYM const struct solparser_medium* +solparser_get_medium + (const struct solparser* parser, + const struct solparser_medium_id medium); + extern LOCAL_SYM const struct solparser_material* solparser_get_material (const struct solparser* parser, @@ -102,6 +107,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,27 @@ #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_medium { + double refractive_index; + double absorptivity; +}; + +struct solparser_medium_id { size_t i; }; + +struct solparser_material_dielectric { + struct solparser_medium_id medium_i; /* Medium the material "looks at" */ + struct solparser_medium_id medium_t; /* Opposite medium */ +}; + +struct solparser_material_dielectric_id { size_t i; }; + struct solparser_material_matte { double reflectivity; /* In [0, 1] */ }; @@ -39,8 +54,8 @@ struct solparser_material_mirror { struct solparser_material_mirror_id { size_t i; }; struct solparser_material_thin_dielectric { - double absorption; - double refractive_index; + struct solparser_medium_id medium_i; /* Outside medium */ + struct solparser_medium_id medium_t; /* Medium of the slab */ double thickness; }; @@ -49,6 +64,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_solparser7.c b/src/parser/test_solparser7.c @@ -30,6 +30,7 @@ main(int argc, char** argv) const struct solparser_material_double_sided* mtl2; const struct solparser_material* mtl; const struct solparser_material_thin_dielectric* thin; + const struct solparser_medium* medium; const struct solparser_object* obj; const struct solparser_shape* shape; FILE* stream; @@ -49,9 +50,13 @@ main(int argc, char** argv) fprintf(stream, " - sphere: { radius: 1 }\n"); fprintf(stream, " material:\n"); fprintf(stream, " thin_dielectric:\n"); - fprintf(stream, " absorption: 0.5\n"); fprintf(stream, " thickness: 0.123\n"); - fprintf(stream, " refractive_index: 1.5\n"); + fprintf(stream, " medium_i: &outside\n"); + fprintf(stream, " refractive_index: 1\n"); + fprintf(stream, " absorptivity: 0\n"); + fprintf(stream, " medium_t: &inside\n"); + fprintf(stream, " refractive_index: 1.5\n"); + fprintf(stream, " absorptivity: 20\n"); rewind(stream); CHECK(solparser_setup(parser, NULL, stream), RES_OK); @@ -79,9 +84,14 @@ main(int argc, char** argv) CHECK(mtl->type, SOLPARSER_MATERIAL_THIN_DIELECTRIC); thin = solparser_get_material_thin_dielectric (parser, mtl->data.thin_dielectric); - CHECK(thin->absorption, 0.5); CHECK(thin->thickness, 0.123); - CHECK(thin->refractive_index, 1.5); + + medium = solparser_get_medium(parser, thin->medium_i); + CHECK(medium->refractive_index, 1); + CHECK(medium->absorptivity, 0); + medium = solparser_get_medium(parser, thin->medium_t); + CHECK(medium->refractive_index, 1.5); + CHECK(medium->absorptivity, 20); CHECK(solparser_load(parser), RES_BAD_OP); solparser_ref_put(parser); diff --git a/src/parser/test_solparser8.c b/src/parser/test_solparser8.c @@ -0,0 +1,118 @@ +/* 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_medium* medium; + 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:\n"); + fprintf(stream, " dielectric:\n"); + fprintf(stream, " medium_i: &outside\n"); + fprintf(stream, " refractive_index: 1\n"); + fprintf(stream, " absorptivity: 0\n"); + fprintf(stream, " medium_t: &inside\n"); + fprintf(stream, " refractive_index: 1.5\n"); + fprintf(stream, " absorptivity: 20\n"); + fprintf(stream, " back:\n"); + fprintf(stream, " dielectric:\n"); + fprintf(stream, " medium_i: *inside\n"); + fprintf(stream, " medium_t: *outside\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); + medium = solparser_get_medium(parser, dielec->medium_i); + CHECK(medium->refractive_index, 1); + CHECK(medium->absorptivity, 0); + medium = solparser_get_medium(parser, dielec->medium_t); + CHECK(medium->refractive_index, 1.5); + CHECK(medium->absorptivity, 20); + + mtl = solparser_get_material(parser, mtl2->back); + CHECK(mtl->type, SOLPARSER_MATERIAL_DIELECTRIC); + dielec = solparser_get_material_dielectric(parser, mtl->data.dielectric); + medium = solparser_get_medium(parser, dielec->medium_i); + CHECK(medium->refractive_index, 1.5); + CHECK(medium->absorptivity, 20); + medium = solparser_get_medium(parser, dielec->medium_t); + CHECK(medium->refractive_index, 1); + CHECK(medium->absorptivity, 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 @@ -225,26 +225,79 @@ # # <thin-dielectric> ::= # thin_dielectric: -# absorption: REAL # in [0, 1] # thickness: REAL # in [0, INF) -# refractive_index: REAL # in ]0, INF) +# medium_i: <dielectric-medium> +# medium_t: <dielectric-medium> # -# invalid absorption +# invalid absorptivity - material: - thin_dielectric: { absorption: -1, thickness: 0, refractive_index: 1 } + thin_dielectric: + thickness: 0 + medium_i: &m { refractive_index: 1, absorptivity: -1 } + medium_t: *m --- # invalid thickness - material: - thin_dielectric: { absorption: 0, thickness: -0.01, refractive_index: 1 } + thin_dielectric: + thickness: -0.01 + medium_i: &m { refractive_index: 1, absorptivity: 0 } + medium_t: *m --- # invalid refractive index - material: - thin_dielectric: { absorption: 0, thickness: 0, refractive_index: 0 } + thin_dielectric: + thickness: 0 + medium_i: &m { refractive_index: 0, absorptivity: 0 } + medium_t: *m --- -# invalid refractive index +# missing thickness +- material: + thin_dielectric: + medium_i: &m { refractive_index: 1, absorptivity: 0 } + medium_t: *m +--- + +# +# <dielectric> ::= +# dielectric: +# medium_i: <dielectric-medium> +# medium_t: <dielectric-medium> +# + +# invalid refractive_index +- material: + dielectric: + medium_i: &m { refractive_index: 0, absorptivity: 0 } + medium_t: *m +--- +# invalid absorptivity +- material: + dielectric: + medium_i: &m { refractive_index: 1, absorptivity: -1 } + medium_t: *m +--- +# missing refractive_index +- material: + dielectric: + medium_i: &m { absorptivity: 0 } + medium_t: *m +--- +# missing absorptivity +- material: + dielectric: + medium_i: &m { refractive_index: 1 } + medium_t: *m +--- +# missing medium_i +- material: + dielectric: + medium_t: { refractive_index: 1, absorptivity: 0 } +--- +# missing medium_t - material: - thin_dielectric: { absorption: 0, thickness: 0, refractive_index: -0.0001 } + dielectric: + medium_i: { refractive_index: 1, absorptivity: 0 } --- # @@ -772,7 +825,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 +837,7 @@ - [-0.50, -0.50] - [-0.50, 0.50] - [0.50, 0.50] - - [0.50, -0.50] + - [0.50, -0.50] --- # diff --git a/src/parser/yaml/test_ok_5.yaml b/src/parser/yaml/test_ok_5.yaml @@ -2,9 +2,9 @@ - material: &thin_dielectric thin_dielectric: - absorption: 0.1 - thickness: 0.2 - refractive_index: 1.00027 + thickness: 1 + medium_i: { absorptivity: 0, refractive_index: 1.00027 } + medium_t: { absorptivity: 0.1, refractive_index: 1.5 } - entity: name: "entity" @@ -17,9 +17,9 @@ - material: &thin_dielectric thin_dielectric: - absorption: 0 thickness: 0 - refractive_index: 0.0001 + medium_i: { absorptivity: 0, refractive_index: 0.00027 } + medium_t: { absorptivity: 0.1, refractive_index: 1.5 } - entity: name: "entity" @@ -37,7 +37,7 @@ - cylinder: { height: 1, radius: 1 } material: thin_dielectric: - absorption: 40 thickness: 10 - refractive_index: 0.0001 + medium_i: { absorptivity: 0, refractive_index: 1 } + medium_t: { absorptivity: 20, refractive_index: 1.5 } diff --git a/src/parser/yaml/test_ok_7.yaml b/src/parser/yaml/test_ok_7.yaml @@ -0,0 +1,40 @@ +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } + +- material: &dielectric + dielectric: + medium_i: { absorptivity: 0, refractive_index: 1.00027 } + medium_t: { absorptivity: 0.1, refractive_index: 1.5 } + +- entity: + name: "entity" + primary: 0 + geometry: + - material: *dielectric + cylinder: { height: 1, radius: 1 } +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } + +- material: &dielectric + dielectric: + medium_i: { absorptivity: 0, refractive_index: 0.00027 } + medium_t: { absorptivity: 0.1, refractive_index: 1.5 } + +- entity: + name: "entity" + primary: 0 + geometry: + - material: *dielectric + cylinder: { height: 1, radius: 1 } + +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + name: "entity" + primary: 0 + geometry: + - cylinder: { height: 1, radius: 1 } + material: + dielectric: + medium_i: { absorptivity: 0, refractive_index: 1 } + medium_t: { absorptivity: 20, refractive_index: 1.5 } + diff --git a/src/solstice_material.c b/src/solstice_material.c @@ -18,19 +18,13 @@ #include <solstice/ssol.h> -struct mirror_param { - double reflectivity; - double roughness; -}; - struct matte_param { double reflectivity; }; -struct thin_dielectric_param { - double absorption; - double thickness; - double refractive_index; +struct mirror_param { + double reflectivity; + double roughness; }; /******************************************************************************* @@ -105,57 +99,44 @@ mirror_get_roughness *val = param->roughness; } -static void -thin_dielectric_get_absorption - (struct ssol_device* dev, - struct ssol_param_buffer* buf, - const double wavelength, - const double P[3], - const double Ng[3], - const double Ns[3], - const double uv[2], - const double w[3], - double* val) +static res_T +create_material_dielectric + (struct solstice* solstice, + const struct solparser_material_dielectric* dielectric, + struct ssol_material** out_mtl) { - const struct thin_dielectric_param* param = ssol_param_buffer_get(buf); - (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; - *val = param->absorption; -} + const struct solparser_medium* medium_i; + const struct solparser_medium* medium_t; + struct ssol_medium ssol_medium_i; + struct ssol_medium ssol_medium_t; + struct ssol_dielectric_shader shader = SSOL_DIELECTRIC_SHADER_NULL; + struct ssol_material* mtl = NULL; + res_T res = RES_OK; + ASSERT(solstice && dielectric && out_mtl); -static void -thin_dielectric_get_thickness - (struct ssol_device* dev, - struct ssol_param_buffer* buf, - const double wavelength, - const double P[3], - const double Ng[3], - const double Ns[3], - const double uv[2], - const double w[3], - double* val) -{ - const struct thin_dielectric_param* param = ssol_param_buffer_get(buf); - (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; - *val = param->thickness; -} + res = ssol_material_create_dielectric(solstice->ssol, &mtl); + if(res != RES_OK) { + fprintf(stderr, + "Could not allocate the Solstice Solver dielectric material.\n"); + goto error; + } -static void -thin_dielectric_get_refractive_index - (struct ssol_device* dev, - struct ssol_param_buffer* buf, - const double wavelength, - const double P[3], - const double Ng[3], - const double Ns[3], - const double uv[2], - const double w[3], - double* val) -{ - const struct thin_dielectric_param* param = ssol_param_buffer_get(buf); - (void)dev, (void)wavelength, (void)P, (void)Ng, (void)Ns, (void)uv, (void)w; - *val = param->refractive_index; -} + medium_i = solparser_get_medium(solstice->parser, dielectric->medium_i); + medium_t = solparser_get_medium(solstice->parser, dielectric->medium_t); + shader.normal = mtl_get_normal; + ssol_medium_i.refractive_index = medium_i->refractive_index; + ssol_medium_i.absorptivity = medium_i->absorptivity; + ssol_medium_t.refractive_index = medium_t->refractive_index; + ssol_medium_t.absorptivity = medium_t->absorptivity; + SSOL(dielectric_setup(mtl, &shader, &ssol_medium_i, &ssol_medium_t)); +exit: + *out_mtl = mtl; + return res; +error: + if(mtl) SSOL(material_ref_put(mtl)), mtl = NULL; + goto exit; +} static res_T create_material_matte @@ -194,7 +175,7 @@ create_material_matte shader.normal = mtl_get_normal; shader.reflectivity = matte_get_reflectivity; - SSOL(matte_set_shader(mtl, &shader)); + SSOL(matte_setup(mtl, &shader)); SSOL(material_set_param_buffer(mtl, pbuf)); exit: @@ -245,7 +226,7 @@ create_material_mirror shader.normal = mtl_get_normal; shader.reflectivity = mirror_get_reflectivity; shader.roughness = mirror_get_roughness; - SSOL(mirror_set_shader(mtl, &shader)); + SSOL(mirror_setup(mtl, &shader)); SSOL(material_set_param_buffer(mtl, pbuf)); exit: @@ -264,9 +245,11 @@ create_material_thin_dielectric struct ssol_material** out_mtl) { struct ssol_thin_dielectric_shader shader = SSOL_THIN_DIELECTRIC_SHADER_NULL; + const struct solparser_medium* medium_i; + const struct solparser_medium* medium_t; + struct ssol_medium ssol_medium_i; + struct ssol_medium ssol_medium_t; struct ssol_material* mtl = NULL; - struct ssol_param_buffer* pbuf = NULL; - struct thin_dielectric_param* param; res_T res = RES_OK; ASSERT(solstice && thin && out_mtl); @@ -277,34 +260,17 @@ create_material_thin_dielectric goto error; } - res = ssol_param_buffer_create - (solstice->ssol, sizeof(struct thin_dielectric_param), &pbuf); - if(res != RES_OK) { - fprintf(stderr, "Could not create the Solstice Solver parameter buffer.\n"); - goto error; - } - - param = ssol_param_buffer_allocate(pbuf, - sizeof(struct thin_dielectric_param), ALIGNOF(struct thin_dielectric_param)); - if(!param) { - fprintf(stderr, "Could not allocate the thin dielectric parameters.\n"); - res = RES_MEM_ERR; - goto error; - } - - param->thickness = thin->thickness; - param->absorption = thin->absorption; - param->refractive_index = thin->refractive_index; - shader.normal = mtl_get_normal; - shader.absorption = thin_dielectric_get_absorption; - shader.thickness = thin_dielectric_get_thickness; - shader.refractive_index = thin_dielectric_get_refractive_index; - SSOL(thin_dielectric_set_shader(mtl, &shader)); - SSOL(material_set_param_buffer(mtl, pbuf)); + medium_i = solparser_get_medium(solstice->parser, thin->medium_i); + medium_t = solparser_get_medium(solstice->parser, thin->medium_t); + ssol_medium_i.refractive_index = medium_i->refractive_index; + ssol_medium_t.refractive_index = medium_t->refractive_index; + ssol_medium_i.absorptivity = medium_i->absorptivity; + ssol_medium_t.absorptivity = medium_t->absorptivity; + SSOL(thin_dielectric_setup + (mtl, &shader, &ssol_medium_i, &ssol_medium_t, thin->thickness)); exit: - if(pbuf) SSOL(param_buffer_ref_put(pbuf)); *out_mtl = mtl; return res; error: @@ -339,19 +305,27 @@ solstice_create_ssol_material if(pssol_mtl) { ssol_mtl = *pssol_mtl; } else { + const struct solparser_material_dielectric* dielectric; const struct solparser_material_matte* matte; const struct solparser_material_mirror* mirror; const struct solparser_material_thin_dielectric* thin_dielectric; switch(mtl->type) { - case SOLPARSER_MATERIAL_MIRROR: - mirror = solparser_get_material_mirror(solstice->parser, mtl->data.mirror); - res = create_material_mirror(solstice, mirror, &ssol_mtl); + case SOLPARSER_MATERIAL_DIELECTRIC: + dielectric = solparser_get_material_dielectric + (solstice->parser, mtl->data.dielectric); + res = create_material_dielectric(solstice, dielectric, &ssol_mtl); break; case SOLPARSER_MATERIAL_MATTE: - matte = solparser_get_material_matte(solstice->parser, mtl->data.matte); + matte = solparser_get_material_matte + (solstice->parser, mtl->data.matte); res = create_material_matte(solstice, matte, &ssol_mtl); break; + case SOLPARSER_MATERIAL_MIRROR: + mirror = solparser_get_material_mirror + (solstice->parser, mtl->data.mirror); + res = create_material_mirror(solstice, mirror, &ssol_mtl); + break; case SOLPARSER_MATERIAL_THIN_DIELECTRIC: thin_dielectric = solparser_get_material_thin_dielectric (solstice->parser, mtl->data.thin_dielectric);