stardis

Perform coupled heat transfer calculations
git clone git://git.meso-star.fr/stardis.git
Log | Files | Refs | README | LICENSE

commit f2e468c6a3ca77c77de26bfeaca4ce8fa874eae3
parent c68eddff02ebac31c673556d3553aa95998667f4
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Sun, 29 Mar 2020 15:13:15 +0200

Add doc; fake at this time

Diffstat:
Mcmake/CMakeLists.txt | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Acmake/doc/CMakeLists.txt | 149+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/stardis-input.5.txt | 1179+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/stardis-man.css | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/stardis-output.5.txt | 541+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/stardis.1.txt.in | 272+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-parsing.c | 2+-
Dsrc/stardis-version.h | 14--------------
Asrc/stardis-version.h.in | 24++++++++++++++++++++++++
9 files changed, 2330 insertions(+), 33 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2018 |Meso|Star> +# Copyright (C) 2018-2020 |Meso|Star> # # 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 @@ -18,24 +18,63 @@ project(stardis-app C) set(SDIS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) +if(CMAKE_HOST_UNIX) + set(STARDIS_DOC "TROFF & HTML" CACHE STRING + "Type of documentation to generate and install.") +else() + set(STARDIS_DOC "HTML" CACHE STRING + "Type of documentation to generate and install.") +endif() + +set_property(CACHE STARDIS_DOC PROPERTY STRINGS + "HTML" + "TROFF" + "TROFF & HTML" + "NONE") + +############################################################################### +# Generate files +###############################################################################set(SOLSTICE_ARGS_DEFAULT_NREALISATIONS "10000") +set(SOLSTICE_ARGS_DEFAULT_CAMERA_POS "0,0,0") +set(SOLSTICE_ARGS_DEFAULT_CAMERA_TGT "0,0,-1") +set(SOLSTICE_ARGS_DEFAULT_CAMERA_UP "0,1,0") +set(SOLSTICE_ARGS_DEFAULT_CAMERA_FOV "70") # In degrees +set(SOLSTICE_ARGS_DEFAULT_IMG_WIDTH "800") +set(SOLSTICE_ARGS_DEFAULT_IMG_HEIGHT "600") +set(SOLSTICE_ARGS_DEFAULT_IMG_SPP "1") + +configure_file(${SDIS_SOURCE_DIR}/../doc/stardis.1.txt.in + ${CMAKE_CURRENT_BINARY_DIR}/doc/stardis.1.txt @ONLY) + +set(VERSION_MAJOR 0) +set(VERSION_MINOR 4) +set(VERSION_PATCH 0) +set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) + +configure_file(${SDIS_SOURCE_DIR}/stardis-version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/stardis-version.h @ONLY) + ############################################################################### # Check dependencies ############################################################################### find_package(RCMake 0.4 REQUIRED) find_package(RSys 0.9 REQUIRED) find_package(StarGeom3D 0.1 REQUIRED) -find_package(StarEnc3D 0.3.1 REQUIRED) -find_package(Stardis 0.7.1 REQUIRED) +find_package(StarEnc3D 0.4.2 REQUIRED) +find_package(Stardis 0.8.2 REQUIRED) find_package(StarSTL 0.3 REQUIRED) +if(MSVC) + find_package(MuslGetopt REQUIRED) +endif() include_directories( ${RSys_INCLUDE_DIR} ${StarGeom3D_INCLUDE_DIR} ${StarEnc3D_INCLUDE_DIR} ${Stardis_INCLUDE_DIR} - ${StarSTL_INCLUDE_DIR}) + ${StarSTL_INCLUDE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) if(MSVC) - find_package(MuslGetopt REQUIRED) include_directories(${MuslGetopt_INCLUDE_DIR}) endif() @@ -46,13 +85,15 @@ include(rcmake_runtime) rcmake_append_runtime_dirs(_runtime_dirs RSys Stardis StarGeom3D StarEnc3D StarSTL) ############################################################################### -# Configure and define targets +# Build subprojects ############################################################################### -set(VERSION_MAJOR 0) -set(VERSION_MINOR 4) -set(VERSION_PATCH 0) -set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) +if(NOT STARDIS_DOC STREQUAL "NONE") + add_subdirectory(doc) +endif() +############################################################################### +# Configure and define targets +############################################################################### set(SDIS_FILES_SRC stardis-app.c stardis-compute.c @@ -70,7 +111,8 @@ set(SDIS_FILES_INC stardis-intface.h stardis-output.h stardis-parsing.h - stardis-solid.h) + stardis-solid.h + stardis-version.h.in) set(SDIS_FILES_DOC COPYING README.md) @@ -84,20 +126,24 @@ add_executable(sdis-app ${SDIS_FILES_INC}) if(CMAKE_COMPILER_IS_GNUCC) + set(MATH_LIB m) +endif() +if(MSVC) + set(GETOPT_LIB MuslGetopt) +endif() + +if(CMAKE_COMPILER_IS_GNUCC) set_target_properties(sdis-app PROPERTIES - COMPILE_FLAGS "-std=c99 ${TE_DEFAULTS}" + COMPILE_FLAGS "-std=c99" VERSION ${VERSION}) - target_link_libraries(sdis-app - Stardis StarGeom3D StarEnc3D StarSTL RSys m) elseif(MSVC) set_target_properties(sdis-app PROPERTIES - COMPILE_FLAGS "${TE_DEFAULTS}" VERSION ${VERSION}) - target_link_libraries(sdis-app - Stardis StarGeom3D StarEnc3D StarSTL RSys MuslGetopt) endif() -rcmake_copy_runtime_libraries(sdis-app) +target_link_libraries(sdis-app + Stardis StarGeom3D StarEnc3D StarSTL RSys ${GETOPT_LIB} ${MATH_LIB}) + ############################################################################### # Define output & install directories @@ -106,4 +152,7 @@ install(TARGETS sdis-app ARCHIVE DESTINATION bin LIBRARY DESTINATION lib RUNTIME DESTINATION bin) + install(FILES ${SDIS_FILES_DOC} DESTINATION share/doc/stardis-app) + +rcmake_copy_runtime_libraries(sdis-app) +\ No newline at end of file diff --git a/cmake/doc/CMakeLists.txt b/cmake/doc/CMakeLists.txt @@ -0,0 +1,149 @@ +# Copyright (C) 2018-2020 |Meso|Star> +# +# 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/>. + +cmake_minimum_required(VERSION 3.0) + +string(REGEX MATCH ".*HTML.*" _html ${STARDIS_DOC}) +string(REGEX MATCH ".*ROFF.*" _roff ${STARDIS_DOC}) + +set(STARDIS_DOC_DIR ${PROJECT_SOURCE_DIR}/../doc) + +################################################################################ +# Look for asciidoc and a2x programs +################################################################################ +if(_html) + find_program(ASCIIDOC NAMES asciidoc asciidoc.py) + if(NOT ASCIIDOC) + unset(_html) + message(WARNING + "The `asciidoc' program is missing. " + "The stardis HTML documentation cannot be generated.") + endif() +endif() + +if(_roff) + find_program(A2X NAMES a2x a2x.py) + if(NOT A2X) + unset(_roff) + message(WARNING + "The `a2x' program is missing. " + "The stardis man pages cannot be generated.") + endif() +endif() + +################################################################################ +# Copy doc files +################################################################################ +set(MAN_NAMES + stardis-input.5 + stardis-output.5) + +if(_roff OR _html) + set(MAN_FILES) + foreach(_name IN LISTS MAN_NAMES) + set(_src ${STARDIS_DOC_DIR}/${_name}.txt) + set(_dst ${CMAKE_CURRENT_BINARY_DIR}/${_name}.txt) + add_custom_command( + OUTPUT ${_dst} + COMMAND ${CMAKE_COMMAND} -E copy ${_src} ${_dst} + DEPENDS ${_src} + COMMENT "Copy the asciidoc ${_src}" + VERBATIM) + list(APPEND MAN_FILES ${_dst}) + endforeach() + add_custom_target(man-copy ALL DEPENDS ${MAN_FILES}) +endif() + +list(APPEND MAN_NAMES stardis.1) + +################################################################################ +# ROFF man pages +################################################################################ +if(_roff) + set(A2X_OPTS -dmanpage -fmanpage) + set(MAN_FILES) + set(MAN5_FILES) + set(MAN1_FILES) + foreach(_name IN LISTS MAN_NAMES) + set(_man ${CMAKE_CURRENT_BINARY_DIR}/${_name}) + set(_txt ${CMAKE_CURRENT_BINARY_DIR}/${_name}.txt) + + add_custom_command( + OUTPUT ${_man} + COMMAND ${A2X} ${A2X_OPTS} ${_txt} + DEPENDS man-copy ${_txt} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Build ROFF man page ${_man}" + VERBATIM) + list(APPEND MAN_FILES ${_man}) + + string(REGEX MATCH "^.*.5$" _man5 ${_man}) + string(REGEX MATCH "^.*.1$" _man1 ${_man}) + if(_man1) + list(APPEND MAN1_FILES ${_man1}) + elseif(_man5) + list(APPEND MAN5_FILES ${_man5}) + else() + message(FATAL_ERROR "Unexpected man type") + endif() + endforeach() + add_custom_target(man-roff ALL DEPENDS ${MAN_FILES}) + + install(FILES ${MAN1_FILES} DESTINATION share/man/man1) + install(FILES ${MAN5_FILES} DESTINATION share/man/man5) +endif() + +################################################################################ +# HTML documentation +################################################################################ +if(_html) + set(ASCIIDOC_OPTS + -bxhtml11 + -dmanpage + --attribute themedir=${STARDIS_DOC_DIR} + --theme=stardis-man) + + set(MAN_FILES) + set(MAN5_FILES) + set(MAN1_FILES) + foreach(_name IN LISTS MAN_NAMES) + set(_man ${CMAKE_CURRENT_BINARY_DIR}/${_name}.html) + set(_txt ${CMAKE_CURRENT_BINARY_DIR}/${_name}.txt) + + add_custom_command( + OUTPUT ${_man} + COMMAND ${ASCIIDOC} ${ASCIIDOC_OPTS} ${_txt} + DEPENDS man-copy ${_txt} ${STARDIS_DOC_DIR}/stardis-man.css + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Build HTML man page ${_man}" + VERBATIM) + list(APPEND MAN_FILES ${_man}) + + string(REGEX MATCH "^.*.5.html$" _man5 ${_man}) + string(REGEX MATCH "^.*.1.html$" _man1 ${_man}) + if(_man1) + list(APPEND MAN1_FILES ${_man1}) + elseif(_man5) + list(APPEND MAN5_FILES ${_man5}) + else() + message(FATAL_ERROR "Unexpected man type") + endif() + endforeach() + add_custom_target(man-html ALL DEPENDS ${MAN_FILES}) + + install(FILES ${MAN1_FILES} DESTINATION share/man/man1) + install(FILES ${MAN5_FILES} DESTINATION share/man/man5) +endif() + diff --git a/doc/stardis-input.5.txt b/doc/stardis-input.5.txt @@ -0,0 +1,1179 @@ +// Copyright (C) 2016-2018 CNRS, 2018-2019 |Meso|Star> +// +// This is free documentation: 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 manual 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/>. +:toc: + +solstice-input(5) +================= + +NAME +---- +solstice-input - solar plant description for solstice(1) + +DESCRIPTION +----------- +The *solstice-input* is the format used by the *solstice*(1) program to +represent a solar plant. It relies on the YAML 1.1 data serialization standard +[1]; assuming that the file is compatible with the *solstice-input* semantic, a +solar plant can be described by using the whole YAML 1.1 functionalities +including compact notation and data tagging. + +A solar plant is composed of a *sun*, an optional *atmosphere* and a collection +of *geometries*, i.e. *shapes* with their associated *material*. Beside the raw +description of the aforementioned data, the *solstice-input* format provides +the *entity* item to efficiently structure the geometries in the scene. An +entity is a node in a tree data structure where the position of each child +entity is relative to the position of its parent. An entity can either +encapsulate a *geometry* or a *pivot* that controls the dynamic positioning of +its child entities with respect to the pivot constraints and the sun direction +submitted to the *solstice*(1) program. + +GRAMMAR +------- + +[verse] +_______ +<solar-plant> ::= - <sun> + - <item> + [ - <item> ... ] + [ - <atmosphere> ] + +<item> ::= <entity> + | <geometry> + | <material> + | <medium> + | <spectrum> + | <template> + +------------------------------------- + +<geometry> ::= geometry: + - <object> + [ - <object> ... ] + +<object> ::= <shape> + <material> + [ <transform> ] + +<x_pivot> ::= x_pivot: + <target> + [ ref_point: <real3> ] # Default is [0,0,0] + +<zx_pivot> ::= zx_pivot: + <target> + [ spacing: REAL ] # in [0, INF). Default 0 + [ ref_point: <real3> ] # Default is [0,0,0] + +<target> ::= target: + anchor: <anchor-identifier> + | direction: <real3> + | position: <real3> + | <sun> + +------------------------------------- + +<shape> ::= <cuboid> + | <cylinder> + | <hemisphere> + | <hyperbol> + | <parabol> + | <parabolic-cylinder> + | <plane> + | <sphere> + | <stl> + +<cuboid> ::= cuboid: + size: <real3> # in ]0, INF]^3 + +<cylinder> ::= cylinder: + height: REAL # in ]0, INF) + radius: REAL # in ]0, INF) + [ slices: INTEGER ] # in [4, 4096]. Default is 16 + [ stacks: INTEGER ] # in [1, 4096]. Default is 1 + +<hemisphere> ::= hemisphere: + radius: REAL # in ]0, INF) + [ clip: <polyclip-list> ] + [ slices: INTEGER ] # in [4, 4096] + +<hyperbol> ::= hyperbol: + focals: <hyperboloid-focals> + clip: <polyclip-list> + [ slices: INTEGER ] # in [4, 4096] + +<parabol> ::= parabol: + focal: REAL # in ]0, INF) + clip: <polyclip-list> + [ slices: INTEGER ] # in [4, 4096] + +<parabolic-cylinder> ::= parabolic-cylinder: + focal: REAL # in ]0, INF) + clip: <polyclip-list> + [ slices: INTEGER ] # in [4, 4096] + +<plane> ::= plane: + clip: <polyclip-list> + [ slices: INTEGER ] # in [1, 4096]. Default is 1 + +<sphere> ::= sphere: + radius: REAL # in ]0, INF) + [ slices: INTEGER ] # in [4, 4096]. Default is 16 + [ stacks: INTEGER ] # in [2, 4096]. Default is slices/2 + +<stl> ::= stl: + path: PATH + +<hyperboloid-focals> ::= real: REAL # in ]0, INF) + image: REAL # in ]0, INF) + +---------------------------------------- + +<polyclip-list> ::= - <polyclip> + [ - <polyclip> ... ] + +<polyclip> ::= operation: <AND|SUB> + <contour-descriptor> + +<contour-descriptor> ::= <circle-descriptor> + | <vertices-descriptor> + +<vertices-descriptor> ::= vertices: <vertices-list> + +<circle-descriptor> ::= circle: + radius: REAL # in ]0, INF) + [ center: <real2> ] # Default is 0,0 + [ segments: INTEGER ] # in [3, 4096]. Default is 64 + +<vertices-list> ::= - <real2> + - <real2> + - <real2> + [ - <real2> ... ] + +---------------------------------------- + +<material> ::= material: + <material-descriptor> + | <double-sided-mtl> + +<double-sided-mtl> ::= front: <material-descriptor> + back: <material-descriptor> + +<material-descriptor> ::= <dielectric> + | <matte> + | <mirror> + | <thin-dielectric> + | <virtual> + +<dielectric> ::= dielectric: + medium_i: <medium-descriptor> + medium_t: <medium-descriptor> + [ <normal-map> ] + +<matte> ::= matte: + reflectivity: <mtl-data> # in [0, 1] + [ <normal-map> ] + +<mirror> ::= mirror: + reflectivity: <mtl-data> # in [0, 1] + slope_error: <mtl-data> + [ microfacet: <normal-distrib> ] # Default is BECKMANN + [ <normal-map> ] + +<normal-distrib> ::= BECKMANN + | PILLBOX + +<virtual> ::= virtual: EMPTY-STRING + +<thin-dielectric> ::= thin_dielectric: + thickness: REAL # in [0, INF) + medium_i: <medium-descriptor> + medium_t: <medium-descriptor> + [ <normal-map> ] + +<normal-map> ::= normal_map: + path: PATH + +---------------------------------------- + +<medium> ::= medium: <medium-descriptor> + +<medium-descriptor> ::= refractive_index: <mtl-data> # in ]0, INF) + extinction: <mtl-data> # in [0, INF) + +---------------------------------------- + +<entity> ::= entity: <entity-data> + +<template> ::= template: <entity-data> + +<entity-data> ::= name: STRING + [ <geometry-data> | <x_pivot> | <zx_pivot> ] + [ <anchors> ] + [ <transform> ] + [ <children> ] + +<geometry-data> ::= primary: INTEGER # in [0, 1] + <geometry> + +<children> ::= children: + - <entity-data> + [ - <entity-data> ... ] + +<anchors> ::= anchors: + - <anchor-data> + [ - <anchor-data> ... ] + +<anchor-data> ::= name: STRING + <position-descriptor> + +<position-descriptor> ::= position: <real3> + | hyperboloid_image_focals: <hyperboloid_focals> + +<entity-identifier> ::= <self|STRING>[.STRING ... ] + +<anchor-identifier> ::= <entity-identifier>.STRING + +---------------------------------------- + +<sun> ::= sun: + dni: REAL # Direct Normal Irradiance in ]0, INF) + [ <spectrum> ] # Default is the smarts295 spectrum + [ <sun-shape> ] + +<sun-shape> ::= <pillbox> | <gaussian> | <buie> + +<buie> ::= buie: + csr: REAL # in [1e-6, 0.849] + +<pillbox> ::= pillbox: + half_angle: REAL # in ]0, 90] + +<gaussian> ::= gaussian: + std_dev: REAL # in ]0, INF) + +---------------------------------------- + +<atmosphere> ::= atmosphere: + extinction: <mtl-data> # in [0, 1] + +---------------------------------------- + +<mtl-data> ::= REAL + | <spectrum-data-list> + +<transform> ::= transform: + translation: <real3> + rotation: <real3> + +<real2> ::= - REAL + - REAL + +<real3> ::= - REAL + - REAL + - REAL + +<spectrum> ::= spectrum: <spectrum-data-list> + +<spectrum-data-list> ::= - <spectrum-data> + [ - <spectrum-data> ... ] + +<spectrum-data> ::= wavelength: REAL # in [0, INF) + data: REAL # in [0, INF) +_______ + +SUN +--- + +The *sun* describes the source of the solar plant. Its direction is not defined +into the *solstice-input*(5) file but is provided by the *solstice*(1) command. +This allows to use the same unmodified *solstice-input*(5) file for several +simulations with different sun directions. + +The main *sun* property is its direct normal irradiance, or *dni* in W.m\^-2. +Its value is a scalar defining the direct irradiance received on a plane +perpendicular to the main sun direction. The optional *spectrum* parameter +describes the per wavelength distribution of the sun *dni*. Note that this +distribution is automatically normalized by *solstice*(1). If the *spectrum* +attribute is not defined, *solstice*(1) uses a default spectrum computed with +the SMARTS software [2] between 0.28 and 4 micro-meters. The total *dni* +(integrated over the spectral range) was set to 1000 W.m^-2. The standard +Mid-Latitude-Summer atmosphere was used with most of gases concentration set +as default (the CO2 concentration was assumed 400ppmv in the atmosphere +column). + +Even if an atmosphere is provided, the atmospheric effects from the top of the +atmosphere to ground level are not computed using the atmosphere description. +As a result, the sun description (*dni* and optional *spectrum*) is expected to +include all the atmospheric effects (sun irradiance available at ground +level). + +The *sun-shape* parameter controls the angular distribution of the sun light +intensity across the sun's disk. If not defined, the distribution is assumed to +be a dirac distribution (infinite directional source). The available sun +shapes are: + +*pillbox*:: + The *pillbox* distribution defines an uniform intensity over the sun's disk. + Its single *half_angle* parameter is the sun's disk half-angle in degrees, that + is linked to the apparent size of the sun. A typical half_angle is 0.2664. + +*gaussian*:: + The *gaussian* distribution defines a gaussian distribution of the solar + incoming direction. Its single *std_dev* parameter is the standard deviation + of the distribution in degrees. Values around 0.2 are typical. + As the gaussian distribution is not truncated, the resulting sun vector can + theoreticaly be oriented towards the sun, especially with a big, non-typical + *std_dev* value. + +*buie*:: + The *buie* distribution, as first discribed in [3]. Its single *csr* + parameter is the ratio between the circumsolar irradiance and the sum of + the circumsolar and sun's disk irradiance. An analysis on typical *csr* + values can be found in [4]. + +ATMOSPHERE +---------- + +The *atmosphere*, when provided, describes the medium surrounding the +solar plant. Its only parameter is its extinction coefficient in m^-1, that +can either be a scalar if the *extinction* is constant over the spectrum, or +can be spectrally described. The extinction along light paths is only computed +after the first reflector, as sun description must include all the atmospheric +effects before the first reflector (see sun description for more details). + +If no atmosphere is provided, atmospheric extinction after the first reflector +is not taken into account. + +MATERIAL +-------- + +A *material* describes the properties of an interface. These properties can be +the same for the two sides of the interface or may be differentiated with a +*double-sided-mtl*. The material comportment is controlled by a +*material-descriptor* that specifies the physical properties of the interface +as well as its optional normal perturbation. Note that the physical properties +can be either scalars or spectral data. + +Material descriptors +~~~~~~~~~~~~~~~~~~~~ + +The available material descriptors are: + +*dielectric*:: +Interface between 2 dielectric media. Its *medium_i* parameter defines the +current medium, i.e. the medium the ray travels in, while *medium_t* +represents the opposite medium. Incoming rays are either specularly reflected +or refracted according to a Fresnel term computed with respect to the +refractive indices of the 2 media as: ++ +....... +Fr = 1/2 * (Rs^2 + Rp^2) +....... ++ +with Rs and Rp the reflectance for the light polarized with its electric +field perpendicular or parallel to the plane of incidence, respectively. ++ +....... +Rs = (n1 * |wi.N| - n2 * |wt.N|) / (n1 * |wi.N| + n2 * |wt.N|) +Rp = (n2 * |wi.N| - n1 * |wt.N|) / (n2 * |wi.N| + n1 * |wt.N|) +....... ++ +with n1 and n2 the indices of refraction of the incident and transmitted +media, and wi and wt the incident and transmitted direction. ++ +Be careful to ensure the media consistency in the *solstice-input*(5) file; a +ray travelling in a medium _A_ can only encounter a medium interface whose +*medium_i* attribute is _A_. Consequently, a *dielectric* material must be +defined as a double sided material whose front and back interfaces are +dielectrics with inverted media: ++ +....... +material: + front: + dielectric: + medium_i: &vacuum { refractive_index: 1, extinction: 0 } + medium_t: &glass { refractive_index: 1.5, extinction: 20 } + back: + dielectric: + medium_i: *glass + medium_t: *vacuum +....... ++ +If the media consistency is not ensured, *solstice*(1) will fail to run +simulations. Note that by default, the surrounding medium is assumed to be +the vacuum, i.e. its refractive index and its extinction are scalars whose +values are 1 and 0, respectively. If an atmosphere is defined, the refractive +index of the surrounding medium is still the scalar 1 but its extinction is +the one of the atmosphere. In other words, to reference the surrounding medium +in the *medium_i* or the *medium_t* attribute of a *dielectric* interface, one +has to define a medium whose refractive index is the scalar 1 and extinction +is either 0 or the extinction of the atmosphere if the latter is defined or +not, respectively. + +*matte*:: +Diffuse surface. Reflects the same intensity in all directions independently +of the incoming direction. + +*mirror*:: +Specular or glossy reflection whether the *slope_error* parameter is 0 or not, +respectively. Glossy reflections are controlled by a microfacet BRDF. The +microfacet normals are distributed with respect to the Beckmann or the Pillbox +distribution according to the *normal-distrib* attribute. ++ +Let S the *slope_error* parameter in ]0, 1]. The Beckmann distribution is +defined as: ++ +....... +D(wh) = exp(-tan^2(a) / m^2) / (PI * m^2 * cos^4(a)) +....... ++ +with a = arccos(wh.N), and m = sqrt(2)*S while the pillbox distribution is +defined as: ++ +....... + | 0; if |wh.N| >= S +D(wh) = | + | 1 / (PI * (1 - cos^2(S))); if |wh.N| < S +....... + +*thin-dielectric*:: +The interface is assumed to be a thin slab of a dielectric material. The +*medium_i* parameter defines the outside dielectric medium while *medium_t* +is the medium of the thin slab. Incoming rays are either specularly reflected +or transmitted (without deviation) according to a Fresnel term computed with +respect to the refractive indices of the 2 media as: ++ +....... +Fr = 1/2 * (Rs^2 + Rp^2) +....... ++ +with Rs and Rp the reflectance for the light polarized with its electric +field perpendicular or parallel to the plane of incidence, respectively. ++ +....... +Rs = (n1 * |wi.N| - n2 * |wt.N|) / (n1 * |wi.N| + n2 * |wt.N|) +Rp = (n2 * |wi.N| - n1 * |wt.N|) / (n2 * |wi.N| + n1 * |wt.N|) +....... ++ +with n1 and n2 the indices of refraction of the incident and transmitted +media, and wi and wt the incident and transmitted direction. Note that the +underlying scattering function correctly handles the multiple refraction +effects into the thin slab. ++ +Be careful to ensure the media consistency in the *solstice-input*(5) file; a +ray travelling in a medium _A_ can only encounter a medium interface whose +*medium_i* attribute is _A_. If the media consistency is not ensured, +*solstice*(1) will fail to run simulations. Note that by default, the +surrounding medium is assumed to be the vacuum, i.e. its refractive index and +its extinction are scalars whose values are 1 and 0, respectively. If an +atmosphere is defined, the refractive index of the surrounding medium is still +the scalar 1 but its extinction is the one of the atmosphere. In other words, +to reference the surrounding medium in the *medium_i* attribute of a +*thin-dielectric* interface, one has to define a medium whose refractive +index is the scalar 1 and extinction is either 0 or the extinction of the +atmosphere if the latter is defined. + +*virtual*:: +Fully transparent interface. + +Normal map +~~~~~~~~~~ + +All the material descriptors, excepted the *virtual*, provide an optional +*normal-map* attribute that defines a path toward a Portable PixMap image [5] +whose pixels store a normal expressed in the tangent space of the interface. By +default the unperturbed tangent space normal is {0,0,1}. The PPM image can +be encoded on 8 or 16-bits per component either in ASCII or binary. The +parameterization of this 2D image onto the shape surfaces depends on the type +of the shape. For the *hemisphere*, *hyperbol*, *parabol*, *plane* and +*parabolic-cylinder* shapes, the image is mapped in the {X,Y} plane. The other +shapes are not parameterized and consequently, applying a normal-mapped +material on these shapes leads to undefined behaviors. + +SHAPE +----- + +A *shape* describes a geometric model. It is defined in its local space, i.e. +in a coordinate system whose origin is proper to the shape. No space +transformation can be introduced through the declaration of a shape: it should +be transformed externally through an *object* and/or *entities*. +*solstice-input*(1) provides 2 types of shape: quadric and mesh. The former is +used to declare parametric surfaces, while the latter describes triangulated +surfaces. + +Quadric +~~~~~~~ + +A quadric shape is defined from a quadric equation and a set of 2D clipping +operations performed in their {X,Y} plane. By convention, the front side of the +quadric surface looks toward the positive Z axis. Internally, the clipped +quadric surface is discretized in a triangular mesh with respect to the +discretisation parameters of the quadric. This mesh is used by *solstice*(1) +as a "proxy" to speed up the access toward the quadric shape: the quadric +position and its associated normal are in fine computed from the quadric +equation. + +The quadric surface is parameterized in the {X,Y} plane. Its parameterization +domain is defined from the bounds of its clipped mesh in the {X,Y} plane: + + u = (x - lowerX) / (upperX-lowerX) + v = (y - lowerY) / (upperY-lowerY) + +with *u* and *v* the mapped 2D coordinates from a 3D position {*x*,*y*,*z*} +onto the quadric, and *lower*<**X**|**Y**> and *upper*<**X**|**Y**> the lower +and upper bounds of the clipped quadric along the X and Y axis. The available +quadrics are: + +*hemisphere*:: +Hemispheric shape defined along the Z axis whose minimum is positioned at +the origin. The *slices* parameter controls the number of divisions along +the Z axis. ++ +....... +x^2 + y^2 + (z-radius)^2 = radius^2 +....... + +*hyperbol*:: +Hyperbolic quadric defined along the Z axis whose minimum is positioned at +the origin. The *slices* parameter controls the discretisation of the +hyperbol. If not defined, it is automatically computed with respect to the +hyperbol curvature. ++ +....... +(x^2 + y^2) / a^2 - (z + z0 - g/2)^2 / b^2 + 1 = 0 + +a^2 = g^2(f - f^2) +b = g(f - 1/2) +z0 = |b| + g/2 +g = focals.real + focals.image +f = focals.real / g +....... + +*parabol*:: +Parabolic quadric defined along the Z axis whose minimum is positioned at the +origin. The *slices* parameter controls the discretisation of the parabol. If +not defined, it is automatically computed with respect to the parabol +curvature. ++ +....... +x^2 + y^2 - 4 * focal * z = 0 +....... + +*parabolic-cylinder*:: +Parabolic cylinder oriented along the Z axis whose main axis is along the X +axis and minimum is positioned at the origin. The *slices* parameter +controls the discretisation of the parabolic cylinder. If not defined, it is +automatically computed with respect to the parabolic cylinder curvature. ++ +....... +y^2 - 4 * focal * z = 0 +....... + +*plane*:: +Plane whose normal points along the positive Z axis. The *slices* attribute +controls the discretisation of the clipped plane. + +Clipping +~~~~~~~~ + +A clipping operation, or *polyclip*, is used to remove some parts of the +quadric surface. It is defined by a 2D *contour-descriptor* expressed in the +{X,Y} plane and a clipping *operation*. The *AND* and *SUB* clip operands, +remove the quadric surface that intersects or does not intersect the +*contour-descriptor*, respectively. The available *countour-descriptors* are: + +*circle-descriptor*:: +Circular contour whose size is defined by the *radius* parameter. Actually, +*solstice*(1) discretized the circular contour with respect to the *segments* +attribute that defines the overall number of segments used to approximate the +circle. + +*vertices-descriptor*:: +Polygonal contour described by a list of 2D vertices. The polygon edges are +defined by connecting each vertex to its previous one. To ensure that the +polygon is closed, an additional edge is automatically created between the +first and the last vertex. Note that *solstice*(1) assumes that the defined +polygon does not overlap itself, i.e. their non consecutive edges are not +intersecting. + +The *clip* parameter of the quadrics lists a set of the aforementioned 2D +*polyclips*. Each of these clipping operations is successively applied on the +remaining quadric surface, in the order on which they are declared. For +instance, the following example uses 5 clipping operations on a plane to build +a rectangle with a circular hole at each of its corner. The first *polyclip* +limits the infinite plane to a rectangle centered in 0 whose size in X and Y is +8 and 4, respectively. The 4 subsequent *polyclips* drill the +rectangle near of its corner with circles whose radius is 0.5: + +....... +plane: + clip: + - {operation: AND, vertices: [[-4,-2],[-4,2],[4,2],[4,-2]]} + - {operation: SUB, circle: {radius: 0.5, center: [-3,-1]}} + - {operation: SUB, circle: {radius: 0.5, center: [-3, 1]}} + - {operation: SUB, circle: {radius: 0.5, center: [ 3,-1]}} + - {operation: SUB, circle: {radius: 0.5, center: [ 3, 1]}} +....... + +Triangular mesh +~~~~~~~~~~~~~~~ + +Triangular meshes are generated by *solstice*(1) from a shape description or +loaded from a CAO file. Their normals are defined per triangle and are thus +discontinuous even for smooth shapes as spheres. The triangular meshes are not +parameterized, i.e. they do not provide a mapping from a 3D position onto its +surface to a 2D coordinates. Applying a normal-mapped material to a triangular +mesh will thus produce undefined behaviors. + +The available triangular meshes are: + +*cuboid*:: + Axis aligned cuboid centered in 0 whose corner positions and dimensions along + the 3 axis are defined by the *size* parameter. The front side of the cuboid + surface looks outside the cuboid. + +*cylinder*:: + Cylinder centered in 0 whose *height* is along the positive Z axis. The top + and the bottom of the cylinder is capped. The *stacks* and *slices* + parameters control the discretisation, i.e. the number of divisions, along or + around the Z axis, respectively. The front side of the cylinder surface looks + outside the cylinder. + +*sphere*:: + Triangulated sphere centered in 0. The *stacks* and *slices* parameters + control the discretisation, i.e. the number of divisions, along or around the + Z axis, respectively. The front side of the sphere surface looks outside the + sphere. + +*stl*:: + Path toward an external mesh file defined with respect to the ASCII + **ST**ereo **L**ithography file format. The front side of the loaded + triangles is defined with respect to their vertex ordering into the STL + file: a triangle is front facing when their vertices are clock wise ordered. + +ENTITY +------ + +An *entity* is used to declare and position shapes into the solar plant. +Actually, the entity is the only item that effectively spawns a *geometry* into +the solar plant: if a geometry is declared but not referenced by an entity, it +is ignored by *solstice*(1). An entity is a hierarchical data structure that +can have child entities whose transformation is relative to their parent. If +not defined, the *transform* parameter of an entity is assumed to be the +identity, i.e. its *rotation* and *translation* are nulls. + +Each entity has a *name* which must be unique per hierarchy level: 2 root +entities (i.e. entities without parent) cannot have the same name as well as +the children of a same parent entity. In addition, the name string cannot +contain dots, spaces or tabulations. A child entity is identified into the +solar plant by successively concatenating, with the \'.' character, the name +of its ancestors with its own name. This naming convention is used in the +*solstice-receiver*(5) format to define the entities to track during the +*solstice*(1) computations. For instance, in the following example, the +*entity-identifier* of the child entity named *level2* is +*level0.level1.level2*: +....... +entity: + name: level0 + child: + - name: level1 + child: + - name: level2 +....... + +An entity encapsulates either a *geometry* or a *pivot*. The former is a +collection of *objects*, i.e. *shapes* with their associated *material* and an +optional *transformation*. The latter is used to control the dynamic +positioning of the child entities with respect to some constraints defined by +the pivot type, and the sun directions submitted by *solstice*(1). Each entity +can also have a list of *anchors*. An anchor is used to define a position +relative to the entity into which it is declared. + +For a geometric entity one has to define if the encapsulated geometry is a +*primary* geometry, i.e. a geometry directly lit by the sun and used to +concentrate the solar flux (e.g. a primary mirror). One can define all the +solar plant geometric entities as primaries but a well designed solar plant +with correctly tagged primary geometries will drastically improve the +convergence speed of the *solstice*(1) simulations. + +Template +~~~~~~~~ + +A *template* is a first level entity with no existence into the solar plant. It +is used to pre-declare an entity hierarchy that can then be instantiated +several times in the solar plant by referencing it through common entities with +YAML data tagging. In the following example, the templated entity *my-template* +is instantiated 3 times into the scene: +....... +- template: &my-template + name: bar + primary: 1 + geometry: ... +- entity: + name: foo0 + transform: {translation: [-10.5, 0, 0]} + children: [*my-template] +- entity: + name: foo1 + transform: {translation: [0, 0, 0]} + children: [*my-template] +- entity: + name: foo2 + transform: {translation: [10.5, 0, 0]} + children: [*my-template] +....... + +Pivot +~~~~~ + +A *pivot* is a special kind of node that can be used in the tree data +structure describing an entity to automatically point its child geometry +according to the sun position and to the pivot parameters. It is supposed (but +not mandatory) that the children of a pivot includes a reflector, that, +once pivoted, will reflect the sun light towards a *target*. You should +note that a pivot cannot be the child of another pivot. + +The most noticeable pivot parameter is its *target*. Four different types of +targets are available: + +*position*:: + Define the target as being an absolute point in world coordinates. + +*anchor*:: + Define the target as being a position relative to an entity (see the + *anchor* section). + +*sun*:: + Define the target as being the center of the sun. + +*direction*:: + The pivot reflects light in the given direction, specified in world + coordinates. + +Pivots can also have a *ref_point* optional parameter defining a 3D point in +the coordinate system the pivot children that will be used by the pointing algorithm. +If not provided, it is set to the origin. + +Two different flavours of *pivots* are available: *x_pivot* and *zx_pivot*, +each with its own set of parameters and behaviour. + +*x_pivot*:: + Pivot with a single rotation axis: the +X axis in its local coordinate + system. It has a *target* and can have a *ref_point*. Its pointing algorithm + considers an incoming ray of light from the center of the sun and rotates + its children so that a specular reflection at *ref_point* using +Z as + local normal will hit the target point of the pivot, or will have the + specified direction (depending of the kind of target). + +*zx_pivot*:: + Pivot with two rotation axis: the +Z axis in its local coordinate system, + then the +X axis in the coordinate system resulting of the Z rotation. + It has a *target* and can have a *ref_point* and a *spacing* that defines + the translation along the +Y axis after the first rotation. If not + defined, *spacing* is 0. The *zx_pivot* pointing algorithm considers an + incoming ray of light from the center of the sun and rotates its + children so that a specular reflection at *ref_point* using + +Y as local normal will hit the target point of the pivot, or will have + the specified direction (depending of the kind of target). + +Anchor +~~~~~~ + +An *anchor* defines a relative position into the entity hierarchy. They are +particularly useful for pivots and hyperbolic shapes that may have to +reference a position relative to an entity whose transformations may also +depends of its ancestor. An anchor has a *name* that must be unique for the +whole sets of per entity anchors. In addition, a name cannot contain +dots, spaces or tabulations. An anchor is identified into the solar plant by +concatenating, with the \'.' character, its name to the *entity-identifier* of +the entity into which it is declared. For instance, in the following example, +the *anchor-identifier* of the anchor named *anchor0* is +*level0.level1.anchor0*: +....... +entity: + name: level0 + child: + - name: level1 + anchor: + - {name: anchor0, position: [0, 0, 0]} + - {name: anchor1, position: [1, 2, 3]} +....... + +In some situations, the *anchor-identifier* cannot be fully determined. Let a +templated entity with a descendant referencing an anchor of one of its +ancestors. On its declaration, the template is still not instantiated through a +parent entity and consequently the name of the root entity is unknown. +Moreover, the name of the root entity cannot be fixed since it changes for each +instance of the template. To handle these cases, the *self* reserved keyword +allows to reference the unknown root entity of the currently declared +hierarchy. In the following example, the entities *entity0.level0.level1* and +*entity1.level0.level1* encapsulate a pivot that references the anchor +*anchor0* defined in their respective parent *entity0.level0* and +*entity1.level0*: +....... +- template: &my-template + name: level0 + anchor: [{name: anchor0, position: [1, 2, 3]}] + child: + - name: level1 + pivot: + x_pivot: + ref_point: {0, 0, 0} + target: {anchor: self.level0.anchor0} + +- entity: {name: entity0, child: [*my-template]} +- entity: {name: entity1, child: [*my-template]} +....... + +Transform +~~~~~~~~~ + +A *transform* is used to move an *object* or an *entity* in space. The +*rotation* parameter list 3 angles in degrees defining the rotation to perform +around the X, Y and Z axis. The *translation* attribute describes the offsets +to apply along the X, Y and Z axis. Let the local repair *p* of an object, *p* +is transformed in *p'* with respect to its associated *transform* as follow: + + p' = Rx * Ry * Rz * (T + p) + +with *T* the translation vector and *Rx*, *Ry* and *Rz* the rotation matrices +around the X, Y and Z axis defined as: + + | 1 0 0 | | cY 0 sY | | cZ -sZ 0 | + Rx = | 0 cX -sX |; Ry = | 0 1 0 |; Rz = | sZ cZ 0 | + | 0 sX cX | |-sY 0 cY | | 0 0 1 | + +where *c*<**X**|**Y**|**Z**> and *s*<**X**|**Y**|**Z**> are the cosine and the +sinus, respectively, of the rotation angles around the X, Y and Z axis. + +EXAMPLES +-------- + +Declare 2 entities and a point source sun. The first entity is a purely +specular square of size 10, whose center is at the origin. The second entity +is a purely transparent square used as a receiver of the solar flux. Its size +is 1 and its center is positioned at {0,0,2}: +....... +- sun: {dni: 1000} + +- entity: + name: reflector + primary: 1 + geometry: + - material: + mirror: + reflectivity: 1 + slope_error: 0 + plane: + clip: + - operation: AND + vertices: + - [-5.0,-5.0] + - [-5.0, 5.0] + - [ 5.0, 5.0] + - [ 5.0,-5.0] + +- entity: + name: receiver + primary: 0 + transform: + translation: [0, 0, 2] + geometry: + - material: + virtual: # No attrib + plane: + clip: + - operation: AND + vertices: + - [-0.5,-0.5] + - [-0.5, 0.5] + - [ 0.5, 0.5] + - [ 0.5,-0.5] +....... + +Define a circular diffuse reflector surrounded by a virtual sphere and a +pillbox-shaped sun whose *half_angle* is 0.1 degree. Use anchors and tags of the +YAML format to reference into the entities a pre-declared geometry. Rely on +the YAML compact notation to reduce the number of lines required to describe +the scene: +....... +- sun: {dni: 1000, pillbox: {half_angle: 0.1}} + +- geometry: &small-circle + - material: {matte: {reflectivity: 1}} + plane: {clip: [{operation: AND, circle: {radius: 0.5}}]} + +- geometry: &big-sphere + - material: {?virtual} + sphere: {radius: 2, slices: 128} + +- entity: {name: reflector, primary: 1, geometry: *small-circle} +- entity: {name: receiver, primary: 0, geometry: *big-sphere} +....... + +Declare 2 parabolic reflectors from a *templated* parabola whose orientation is +controlled by a *zx_pivot*. This pivot ensures that the reflector points toward +the receiver, independently of its position, by targeting an *anchor* whose +position is defined relatively to the receiver: +....... +- sun: {dni: 1000} + +- entity: # Receiver + name: square_receiver + primary: 0 + transform: { rotation: [0,90,0], translation: [100,0,10] } + anchors: [{name: anchor0, position: [0,0,0]}] + geometry: + - material: {?virtual} + plane: + clip: + - operation: AND + vertices: [[-.5,-.5],[-.5,.5],[.5,.5],[.5,-.5]] + +- template: &self_oriented_parabol # Reflector + name: pivot + transform: {translation: [0, 0, 4], rotation: [0, 0, 90]} + zx_pivot: {target: {anchor: square_receiver.anchor0}} + children: + - name: parabol + transform: {rotation: [-90, 0, 0]} + primary: 1 + geometry: + - material: {mirror: {reflectivity: 1, slope_error: 0}} + parabol: + focal: 100 + clip: + - operation: AND + vertices: [[-5,-5],[-5,5],[5,5],[5,-5]] + +# Instantiate the reflector template +- entity: + name: reflector1 + transform: {translation: [0,0,0]} + children: [*self_oriented_parabol] +- entity: + name: reflector2 + transform: {translation: [10,43.6,0]} + children: [*self_oriented_parabol] +....... + +Declare a solar furnace with 9 heliostats instantiated from the same +*template*. Their position is controlled by a *zx_pivot* to ensure that the +incoming sun rays are reflected toward the negative X axis. Reflected rays are +then concentrated by a parabola toward a purely absorptive receiver. The +heliostats and the parabola share the same material: the front faces are +purely specular while the back faces are diffuse: +....... +- sun: {dni: 1000} + +- material: &specular + front: {mirror: {reflectivity: 1, slope_error: 0}} + back: {matte: {reflectivity: 1}} + +- template: &H # Template of an heliostat + name: heliostat + transform: {translation: [0,0,5.5]} + zx_pivot: {target: {direction: [-1,0,0]}} + children: + - name: reflector + transform: {rotation: [-90,0,0]} + primary: 1 + geometry: + - material: *specular + plane: + clip: [{operation: AND, vertices: [[-5,-5],[-5,5],[5,5],[5,-5]]}] + +- entity: # Receiver entity + name: receiver + primary: 0 + transform: {translation: [18,0,20], rotation: [0,90,0]} + geometry: + - material: {matte: {reflectivity: 0}} + plane: + clip: + - operation: AND + vertices: [[-.5,-.5],[-.5,.5],[.5,.5],[.5,-.5]] + +- entity: # Great parabola + name: parabola + primary: 0 + transform: {translation: [0,0,20], rotation: [0,90,90]} + geometry: + - material: *specular + parabol: + focal: 18 + clip: [{operation: AND, vertices: [[-30,-20],[-30,20],[30,20],[30,-20]]}] + +# Instantiate the heliostat template +- entity: {name: H1, children: [*H], transform: {translation: [40,-20, 0]}} +- entity: {name: H2, children: [*H], transform: {translation: [40, 0, 0]}} +- entity: {name: H3, children: [*H], transform: {translation: [40, 20, 0]}} +- entity: {name: H4, children: [*H], transform: {translation: [60,-20,10]}} +- entity: {name: H5, children: [*H], transform: {translation: [60, 0,10]}} +- entity: {name: H6, children: [*H], transform: {translation: [60, 20,10]}} +- entity: {name: H7, children: [*H], transform: {translation: [80,-20,20]}} +- entity: {name: H8, children: [*H], transform: {translation: [80, 0, 20]}} +- entity: {name: H9, children: [*H], transform: {translation: [80, 20,20]}} +....... + +This example illustrates the use of quadrics and refractive materials: in this +example, three partial *parabols* with various focal distances and positions +concentrate incoming radiation at a common focal position. But a *hyperbol* is +located between the parabols and their common focal position, which is also +one of the two focals of the hyperbol. Radiation is therefore redirected to +the second focal of the hyperbol, where the square target is located. Finally, +a *cuboid* using a glass material is located between the hyperbol and the +target. In this example, a small fraction of incoming power is absorbed by the +target. The rest is either missing the target, absorbed or refracted by the +glass. Furthermore, this example illustrates the use of a *spectrum* for +*refractive index* and *extinction* by various *media* (air and glass). +....... +# Spectra +- spectrum: &solar_spectrum + - {wavelength: 0.3, data: 1.0} + - {wavelength: 0.4, data: 2.0} + - {wavelength: 0.5, data: 0.5} + - {wavelength: 0.6, data: 3.5} + - {wavelength: 0.7, data: 1.5} + - {wavelength: 0.8, data: 0.8} + +- spectrum: &air_kabs + - {wavelength: 0.3, data: 1.0e-4} + - {wavelength: 0.4, data: 1.0e-5} + - {wavelength: 0.5, data: 2.0e-5} + - {wavelength: 0.6, data: 2.0e-4} + - {wavelength: 0.7, data: 3.0e-5} + - {wavelength: 0.8, data: 1.0e-4} + +- spectrum: &glass_kabs + - {wavelength: 0.3, data: 1.0e-2} + - {wavelength: 0.4, data: 1.0e-3} + - {wavelength: 0.5, data: 2.0e-3} + - {wavelength: 0.6, data: 2.0e-2} + - {wavelength: 0.7, data: 3.0e-3} + - {wavelength: 0.8, data: 1.0e-3} + +- spectrum: &glass_ref_index + - {wavelength: 0.30, data: 1.40} + - {wavelength: 0.40, data: 1.39} + - {wavelength: 0.50, data: 1.37} + - {wavelength: 0.60, data: 1.34} + - {wavelength: 0.70, data: 1.30} + - {wavelength: 0.80, data: 1.25} + +# Media +- medium: &air_medium + refractive_index: 1 + extinction: *air_kabs + +- medium: &glass_medium + refractive_index: *glass_ref_index + extinction: *glass_kabs + +# Sun & atmosphere +- sun: {dni: 1, spectrum: *solar_spectrum} +- atmosphere: {extinction: *air_kabs} + +# Materials +- material: &specular {mirror: {reflectivity: 1, slope_error: 0}} +- material: &black {matte: {reflectivity: 0}} +- material: &glass + front: {dielectric: {medium_i: *air_medium, medium_t: *glass_medium}} + back: {dielectric: {medium_i: *glass_medium, medium_t: *air_medium}} + +# Primary reflectors +- entity: + name: "primary_reflector1" + primary: 1 + transform: {translation: [0, 0, -2.0]} + geometry: + - material: *specular + parabol: + focal: 12 + clip: + - {operation: AND, circle: {radius: 10}} + - {operation: SUB, circle: {radius: 5}} + +- entity: + name: "primary_reflector2" + primary: 1 + transform: {translation: [0, 0, -4]} + geometry: + - material: *specular + parabol: + focal: 14 + clip: + - {operation: AND, circle: {radius: 15}} + - {operation: SUB, circle: {radius: 10}} + +- entity: + name: "primary_reflector3" + primary: 1 + transform: {translation: [0, 0, -6]} + geometry: + - material: *specular + parabol: + focal: 16 + clip: + - {operation: AND, circle: {radius: 20}} + - {operation: SUB, circle: {radius: 15}} + +# Secondary reflector +- entity: + name: "secondary_reflector" + primary: 0 + transform: {translation: [0, 0, 6]} + geometry: + - material: *specular + hyperbol: + focals: {real: 16.0, image: 4} + clip: [{operation: AND, circle: {radius: 5}}] + +# Glass box +- entity: + name: "glass_slide" + primary: 0 # The entity is not sampled as a primary reflector + geometry: + - material: *glass + cuboid: {size: [10,10,0.5]} + transform: {translation: [0, 0, 0.25]} + +# Receiver +- entity: + name: "square_receiver" + primary: 0 # The entity is not sampled as a primary reflector + transform: {translation: [0, 0, -10] } + geometry: + - material: *black + plane: + clip: + - operation: AND + vertices: [[-0.5,-0.5],[-0.5,0.5],[0.5,0.5],[0.5,-0.5]] +....... + + +NOTES +----- +1. YAML Ain't Markup Language - <http://yaml.org> +2. SMARTS, Simple Model of the Atmospheric Radiative Transfer of Sunshine - + <http://www.nrel.gov/rredc/smarts/> +3. D. Buie, A.G. Monger, C.J. Dey. "Sunshape distributions for + terrestrial solar simulations". Solar Energy, 2003, 74, pp. 113-122. +4. D. Buie, C.J. Dey, S. Bosi. "The effective size of the solar cone for + solar concentrating systems". Solar Energy, 2003, 74, pp. 417-427. +5. Portable PixMap - <http://netpbm.sourceforge.net/doc/ppm.html> + +SEE ALSO +-------- +*solstice*(1), *solstice-receiver*(5) diff --git a/doc/stardis-man.css b/doc/stardis-man.css @@ -0,0 +1,96 @@ +/* Copyright (C) 2016-2018 CNRS + * + * This is free style sheet: 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 CSS 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/. */ + +body.manpage { + font-family:"Liberation Sans",sans-serif; + font-size:10pt; + text-align: justify; + max-width: 55em; + margin: 1em; + background: #ffffff +} + +body.manpage .monospaced, .literalblock { + margin: 2em; + color: #636261 +} + +body.manpage em { + color: #660000 +} + +body.manpage div.verseblock > pre.content { + font-family: "Liberation Mono",monospace; +} + +body.manpage h1 { + padding-bottom: 0.5em; +} +body.manpage h2 { + border-style: none; +} +body.manpage div.sectionbody { + margin-left: 3em; +} + +body.manpage code { + font-family: "Liberation Mono",monospace; +} + +body.manpage #footer { display: none; } + +body.manpage div#toctitle { display: none; } + +body.manpage div#toc { + display: block; + position:fixed; + top:0; + left:60em; + height:100%; + width: 100%; + padding:3em 0 0 0; + border-left:1px solid #dbdbdb; + background: #eeeeee +} + +body.manpage a { + font-weight: bold; + color: #225588; +} + +body.manpage div#toc a, div#toc a:link, div#toc a:visited { + margin:0; + padding-left: 2em; + color:#999999; + text-decoration:none; + font-weight: normal; +} + +body.manpage div.toclevel1 { + line-height: 1.5em; +} + +body.manpage div.toclevel2 { + margin-left: 2em; +} + +body.manpage div#toc a:hover { + color:#666666; +} + +@media print { + body.manpage div#toc { display: none; } +} + diff --git a/doc/stardis-output.5.txt b/doc/stardis-output.5.txt @@ -0,0 +1,541 @@ +// Copyright (C) 2016-2018 CNRS, 2018-2019 |Meso|Star> +// +// This is free documentation: 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 manual 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/>. +:toc: + +solstice-output(5) +================== + +NAME +---- +solstice-output - output format of solstice(1) results + +DESCRIPTION +----------- +The *solstice-output* describes the output format of the *solstice*(1) program. +All the data generated by a *solstice*(1) invocation are written in a single +file or on the standard output whether an _output_ file is defined through the +*-o* option or not, respectively. Note that submitting several sun directions +to *solstice*(1), through the *-D* option, will produce as many outputs as sun +directions. In other words, invoking *solstice*(1) with _N_ sun directions +looks like calling *solstice*(1) _N_ times and concatenating their associated +output. + +The type of the data that are generated depends on the mode in which +*solstice*(1) is invoked. By default, *solstice*(1) evaluates the power +collected by the submitted solar plant. When invoked with the *-g* option, +*solstice*(1) converts the solar plant geometries in a list of CAO files. The +*-p* option is used to track the sampled radiative paths while, finally, the +*-r* option allows to render an image of the solar facility. + +GRAMMAR +------- +The output values are mainly ASCII data formatted line by line. By convention, +in the following grammar the line data are listed between quote marks. The +grammar may use new lines for formatting constraints, but data are actually on +the same line while a closed quote mark is not defined. + +[verse] +_______ +<output> ::= <simulation-output> + | <dump-geometry-output> # -g option + | <dump-radiative-paths-output> # -p option + | <rendering-output> # -r option + +<simulation-output> ::= <sun-direction> + <counts> + <global> + [ <receivers-list> ] + [ <primaries-list> ] + [ <rcvXprims-list> ] + [ <receiver-maps> ] + [ <simulation-output> ... ] + +<dump-geometry-output> + ::= <sun-direction> + <geometry-data> + [ <dump-geometry-output> ... ] + +<dump-radiative-paths-output> + ::= <sun-direction> + VTK-RADIATIVE-PATHS + [ <dump-radiative-paths-output> ... ] + +<rendering-output> ::= <sun-direction> + PPM-FILE # ASCII PPM with 8-bits per component [1] + [ <rendering-output> ... ] + +------------------------------------- + +<sun-direction> ::= "#--- Sun direction: <alpha> <beta> (<sun-vector>)" + +<counts> ::= "<#globals> <#receivers> <#primaries> + <#samples> <#failed>" + +<#globals> ::= 7 +<#receivers> ::= INTEGER # in [0, INF) +<#primaries> ::= INTEGER # in [0, INF) +<#samples> ::= INTEGER # in [0, INF) +<#failed> ::= INTEGER # in [0, INF) + +<global> ::= <potential-flux> + <absorbed-flux> + <cos-factor> + <shadow-loss> + <missing-loss> + <materials-loss> + <atmospheric-loss> + +------------------------------------- + +<receivers-list> ::= <receiver> + [ <receiver> ... ] + +<receiver> ::= "<receiver-name> <receiver-id> <area> + <front> <back>" + +<receiver-name> ::= <entity-identifier> + +<receiver-id> ::= INTEGER + +<front> ::= <side> +<back> ::= <side> + +<side> ::= "<incoming-flux> <in-if-no-mat-loss> + <in-if-no-atm-loss> <in-mat-loss> <in-atm-loss> + <absorbed-flux> <abs-if-no-mat-loss> + <abs-if-no-atm-loss> <abs-mat-loss> <abs-atm-loss> + <efficiency>" + +------------------------------------- + +<primaries-list> ::= <primary> + [ <primary> ... ] + +<primary> ::= "<primary-name> <primary-id> <area> <#samples> + <cos-factor> <shadow-loss>" + +<primary-name> ::= <entity-identifier> + +<primary-id> ::= INTEGER + +------------------------------------- + +<rcvXprims-list> ::= <rcvXprim> + [ <rcvXprim> ... ] + +<rcvXprim> ::= "<receiver-id> <primary-id> + <rcvXprim-front> <rcvXprim-back>" + +<rcvXprim-front> ::= <rcvXprim-side> +<rcvXprim-back> ::= <rcvXprim-side> + +<rcvXprim-side> ::= "<incoming-flux> <in-if-no-mat-loss> + <in-if-no-atm-loss> <in-mat-loss> <in-atm-loss> + <absorbed-flux> <abs-if-no-mat-loss> + <abs-if-no-atm-loss> <abs-mat-loss> <abs-atm-loss>" + +------------------------------------- + +<receiver-maps> ::= VTK-RECEIVER-MAP + [ <receiver-maps> ... ] + +<geometry-data> ::= OBJ-FILE + [ --- + <geometry-data> ... ] + +------------------------------------- + +<area> ::= REAL # in ]0, INF) + +<real3> ::= REAL REAL REAL + +<alpha> ::= REAL # Degrees in [0, 360[ +<beta> ::= REAL # Degrees in [0, 90] +<sun-vector> ::= <real3> + +<incoming-flux> ::= <estimate> +<in-if-no-mat-loss> ::= <estimate> +<in-if-no-atm-loss> ::= <estimate> +<in-mat-loss> ::= <estimate> +<in-atm-loss> ::= <estimate> +<absorbed-flux> ::= <estimate> +<abs-if-no-mat-loss> ::= <estimate> +<abs-if-no-atm-loss> ::= <estimate> +<abs-mat-loss> ::= <estimate> +<abs-atm-loss> ::= <estimate> +<cos-factor> ::= <estimate> +<missing-loss> ::= <estimate> +<materials-loss> ::= <estimate> +<atmospheric-loss> ::= <estimate> +<shadow-loss> ::= <estimate> +<efficiency> ::= <estimate> + +<estimate> ::= <expected-value> <standard-error> +<expected-value> ::= REAL +<standard-error> ::= REAL # in [0, INF) + +<entity-identifier> # Defined in *solstice-input*(5) +_______ + +SIMULATION +---------- + +A *simulation-output* begins with two header lines. The first one reports the +sun direction used in the simulation (two angles in degrees, plus the +corresponding sun vector), +and the second one lists the numbers of global, per receiver and per +primary results as well as the overall number of Monte-Carlo experiments used +by the simulation and the number of experiments that failed due to unforeseen +errors as numerical imprecisions. As soon as the number of failed experiments +reaches 1% of the required number of Monte-Carlo experiments, the code exits +with a "Error in integrating the solar flux" message, and the validity of +subsequent results is questionable: estimates are produced using the number of +Monte-Carlo experiments that have been successful, which is necessarily smaller +than the required number of experiments. + +Global results +~~~~~~~~~~~~~~ + +After the 2 header lines, the output includes various *global* result lines, +the exact number of lines being part of the headers. Currently this number is +7. Each global result is a pair of real numbers: the expected value and its +standard error. The global results are, in this order: + +- *potential-flux*: maximum flux that all the primary geometries could + intercept if properly oriented and flat-shaped; +- *absorbed-flux*: absorbed part of the flux reaching any receiver geometry. + At most equal to the potential flux; +- *cos-factor*: cos of the angle between the sun direction and the normal of + the primary surfaces (average cos over all primary geometries); +- *shadow-loss*: potential flux intercepted by another geometry before + reaching a primary geometry; +- *missing-loss*: part of the flux that reaches a primary geometry, follows a + radiative path, but is not absorbed; this flux could have bounced on + geometries, including receivers, but without being absorbed; +- *materials-loss*: total flux absorbed by non-receivers along radiative + paths; includes both surface and volume absorption; +- *atmospheric-loss*: total flux extinction by the atmosphere along radiative + paths. + +This results can be used to check conservation of energy: + +potential-flux * cos-factor and (absorbed-flux + shadow-loss + +missing-loss + materials-loss + atmospheric-loss) +should be equal within their respective uncertainty ranges. + +Per receiver results +~~~~~~~~~~~~~~~~~~~~ + +Following global results, the output includes various per-receiver lines, one +line per receiver, the exact number of lines being part of the headers. The +per-receiver results are sorted according to the order of the receivers as +defined in the submitted *solstice-receiver*(5) file. Each line contains the +following data: + +- *receiver-name*: name of the receiver, i.e. *entity-identifier* of the + entity in which the receiving geometry is defined (see the + *solstice-input*(5) format); +- *receiver-id*: unique integer identifying the receiver; +- *area*: area of the receiver; +- *front*: estimated results for the front side of the receiver; +- *back*: estimated results for the back side of the receiver. + +The estimates of the *front* and *back* sides are listed bellow. Note that +each of the following estimates is actually a pair of real numbers: the +expected value and its standard error. + +- *incoming-flux*: flux that reaches the receiver side; +- *in-if-no-mat-loss*: incoming-flux if absorption on non-receivers is not + taken into account; +- *in-if-no-atm-loss*: incoming-flux if atmospheric extinction is not taken + into account; +- *in-mat-loss*: in-if-no-mat-loss - incoming-flux; +- *in-atm-loss*: in-if-no-atm-loss - incoming-flux; +- *absorbed-flux*: flux absorbed by the receiver side; +- *abs-if-no-mat-loss*: absorbed-flux if absorption by non-receivers is not + taken into account; +- *abs-if-no-atm-loss*: absorbed-flux if atmospheric extinction is not taken + into account; +- *abs-mat-loss*: abs-if-no-mat-loss - absorbed-flux; +- *abs-atm-loss*: abs-if-no-atm-loss - absorbed-flux; +- *efficiency*: fraction of the potential flux absorbed by this receiver side. + +Both *front* and *back* side estimates are output, even if the receiver has +only a single receiving side. In this case, the results of the non-receiving +side are meaningless (invalid -1 value). + +Per primary results +~~~~~~~~~~~~~~~~~~~ + +Following the per-receiver results, the output includes various per-primary +result lines, one line per primary geometry, the exact number of lines being +part of the headers. Each line contains: + +- *primary-name*: name of the primary geometry, i.e. *entity-identifier* of + the entity in in which the primary geometry is defined (see the + *solstice-input*(5) format); +- *primary-id*: unique integer identifying the primary geometry; +- *area*: area of the primary geometry; +- *#sample*: number of Monte-Carlo experiments sampled on the primary + geometry; +- *cos-factor*: cos of the angle between the sun direction and the normal of + the primary surface (average cos on the primary geometry); +- *shadow-loss*: potential flux intercepted by another geometry before reaching + the primary geometry of interest. + +Per receiver and per primary results +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Following the per-primary results, the output includes various result lines, +each describing the contribution of a primary geometry to a given receiver. +The total number of such lines is the number of receivers times the number of +primary geometries. Each line contains: + +- *receiver-id*: identifier of the involved receiver; +- *primary-id*: identifier of the involved primary geometry; +- *rcvXprim-front*: estimated results for the receiver front side; +- *rcvXprim-back*: estimated results for the receiver back side; + +The estimated values of *rcvXprim-front* and *rcvXprim-back* are listed +bellow. Each of these estimates is actually a pair of real numbers: the +expected value and its standard error. + +- *incoming-flux*: flux that reaches the receiver side; +- *in-if-no-mat-loss*: incoming-flux if absorption on non-receivers is not + taken into account; +- *in-if-no-atm-loss*: incoming-flux if atmospheric extinction is not taken + into account; +- *in-mat-loss*: in-if-no-mat-loss - incoming-flux; +- *in-atm-loss*: in-if-no-atm-loss - incoming-flux; +- *absorbed-flux*: flux absorbed by the receiver side; +- *abs-if-no-mat-loss*: absorbed-flux if absorption by non-receivers is not + taken into account; +- *abs-if-no-atm-loss*: absorbed-flux if atmospheric extinction is not taken + into account; +- *abs-mat-loss*: abs-if-no-mat-loss - absorbed-flux; +- *abs-atm-loss*: abs-if-no-atm-loss - absorbed-flux; + +Both front and back side estimates are output, even if the receiver has only a +single receiving side. In this case, the results of the non-receiving side are +meaningless (invalid -1 value). + +Receiver map +~~~~~~~~~~~~ + +A receiver defined in the submitted *solstice-receiver*(5) file, can have a +per-primitive estimate of its incoming flux density and/or absorbed flux +density if its *per_primitive* flag is active. In this case, *solstice*(1) +generates a *receiver-map* that is actually an ASCII VTK file [2] that stores +the triangular mesh of the receiver and, for each triangle, the estimate of +its associated incoming flux density and/or absorbed flux density. The +"definition" of the receiver map is thus controlled by the discretisation of +the receiver's shape, as described in the *solstice-input*(5) file. Note that +to obtain a good estimate of the per-triangle flux densities, one have to +ensure that the number of per-triangle experiments is sufficient regarding the +targeted accuracy. Since only a small fraction of the overall sampled +radiative paths reach a given triangle, the total number of experiments +required through the *-n* option of *solstice*(1) should be increased +significantly, as 1 or 2 order of magnitude. + +The number of written per-triangle flux density estimates depends on the +receiver's parameters: both front and back sides of the receiver can be active +and each side can produce an estimate both for the incoming flux density and +for the absorbed flux density. As a consequence, the output can include up to +4 different estimates that are written in the order: incoming front, absorbed +front, incoming back, absorbed back. The following grammar gives a brief +description of the formatting of a *VTK-RECEIVER-MAP*. Please refer to the VTK +format specification [2] for more informations on the VTK file format. + +[verse] +_______ +VTK-RECEIVER-MAP ::= # vtk DataFile Version 2.0 + <receiver-name> + ASCII + DATASET POLYDATA + POINTS <#vertices> float + <map-vertices> + POLYGONS <#triangles> <#triangles*4> + <map-triangles> + CELL_DATA <#triangles> + <map-triangle-data> + +<map-vertices> ::= <real3> + [ <real3> ... ] # up to <#vertices> + +<map-triangles> ::= 3 <triangle-indices> + [ 3 <triangle-indices> ... ] # up to <#triangles> + +<map-triangle-data> ::= <map-front-data> + | <map-back-data> + | <map-front-data> <map-back-data> + +<map-front-data> ::= <map-side-data> +<map-back-data> ::= <map-side-data> + +<map-side-data> ::= <incoming-flux> + | <absorbed-flux> + | <incoming-flux> <absorbed-flux> + +<incoming-flux> ::= <flux-density-data> +<absorbed-flux> ::= <flux-density-data> + +<flux-density-data> ::= SCALARS <side-and-flux-names> float 2 + LOOKUP_TABLE default + <estimate> + [ <estimate> ... ] + +<side-and-flux-names> ::= Front_faces_Incoming_flux + | Front_faces_Absorbed_flux + | Back_faces_Incoming_flux + | Back_faces_Absorbed_flux + +<#triangles> ::= INTEGER +<#vertices> ::= INTEGER +<triangle-indices> ::= INTEGER INTEGER INTEGER +_______ + +DUMP GEOMETRY +------------- + +A *dump-geometry-output* is generated when *solstice*(1) is invoked with the +*-g* option. In this mode, for each submitted sun direction, *solstice*(1) +converts the geometry of the submitted *solstice-input*(5) file in triangular +meshes that are then written to the output with respect to the format provided +by the *format* parameter of the *-g* option. The only format currently +supported by *solstice*(1) is the Alias Wavefront OBJ [3] format. With no more +sub-option, *solstice*(1) will thus generate one OBJ file containing the whole +mesh of the solar plant. However, the *split* parameter of the *-g* option +allows to generate several OBJ files: one description is generated per +*geometry* or per *object*, as defined in the *solstice-input*(5) format, +whether the *split* sub-option is set to *geometry* or *object*. In this +situation, each OBJ description is followed by a line with 3 minus characters +in order to identify the end of the current OBJ. + +Independently of the *split* strategy, each *solstice-input*(1) geometry is an +OBJ group whose name is the *entity-identifier* of the entity in which it is +encapsulated. Finally, the *dump-geometry-output* uses the *usemtl* directive +of the OBJ format to associate to a mesh the name of its material type. The +following grammar succinctly describes the formatting of an *OBJ-FILE*. Please +refer to the OBJ format specification [3] for more informations on the OBJ file +format. + +[verse] +_______ +OBJ-FILE ::= g <entity-identifier> + <obj-mesh> + [ <obj-mesh> ... ] + +<obj-mesh> ::= usemtl <material-type> + <obj-vertices> + <obj-faces> + +<obj-vertices> ::= v <real3> + [ v <real3> ... ] + +<obj-indices> ::= f <triangle-indices> + [ f <triangle-indices> ... ] + +<material-type> ::= dielectric + | matte + | mirror + | thin_dielectric + | virtual +_______ + +DUMP RADIATIVE PATHS +-------------------- + +For each sun direction, the *dump-radiative-paths-output* lists the geometric +data of the radiative paths sampled during a simulation. Each path is colored +with respect to its type: the path is yellow if its first segment, i.e. +the ray starting from the sun towards a primary geometry, is occluded by a non +virtual object. If not occluded, the path can be blue or turquoise whether it +reaches a receiver or not, respectively. Finally, the path can also be red if +it was canceled due to a topologically incoherent impact (i.e. an impact on a +surface not at the boundary of the medium in which the rays was propagating). +The following grammar describes the formatting of a *VTK-RADIATIVE-PATHS* +file. Refer to the VTK format specification [2] for more informations on the +VTK file format. + +[verse] +_______ +VTK-RADIATIVE-PATHS ::= # vtk DataFile Version 2.0 + Radiative paths + ASCII + DATASET POLYDATA + POINTS <#vertices> float + <paths-vertices> + LINES <#paths> <#paths+#vertices> + <paths-lists> + CELL_DATA <#paths> + SCALAR Radiative_path_type float 1 + LOOKUP_TABLE path_type + <paths-type> + LOOKUP_TABLE path_type 5 + <color-error> + <color-unused> + <color-success> + <color-missing> + <color-occluded> + +<paths-vertices> ::= <real3> + [ <real3> ... ] # up to <#vertices> + +<paths-lists> ::= <radiative-path> + [ <radiative-path> ... ] # up to <#path> + +<radiative-path> ::= <#path-segments> <path-vertex-id> ... + +<paths-type> ::= <color-id> + [ <color-id> ... ] # up to <#paths> + +<color-id> ::= 0.0 # Red: for error paths + | 0.25 # Green: unused + | 0.5 # Blue: for success paths + | 0.75 # Turquoise: for missing paths + | 1.0 # Yellow: for occluded paths + +<color-error> ::= 1.0 0.0 0.0 1.0 +<color-unused> ::= 0.0 1.0 0.0 1.0 +<color-success> ::= 0.0 0.0 1.0 1.0 +<color-missing> ::= 0.0 1.0 1.0 1.0 +<color-occluded> ::= 1.0 1.0 0.0 1.0 + +<#paths> ::= INTEGER +<#path-segments> ::= INTEGER +<path-vertex-id> ::= INTEGER +_______ + +RENDERING +--------- +When invoked with the *-r* option, *solstice*(1) generates an image of the +solar facility for each submitted sun direction. Each image is preceded by its +associated sun direction and is saved with respect to the ASCII PPM file +format [1]. The output images are actually greyscale images whose pixels store +the average normalized radiance that reaches them. + +NOTES +----- +1. Portable PixMap - <http://netpbm.sourceforge.net/doc/ppm.html> +2. VTK file format - + <http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf> +3. OBJ file format - + <http://www.martinreddy.net/gfx/3d/OBJ.spec> + +SEE ALSO +-------- +*solstice*(1), +*solstice-input*(5), +*solstice-receiver*(5) diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in @@ -0,0 +1,272 @@ +// Copyright (C) 2016-2018 CNRS, 2018-2019 |Meso|Star> +// +// This is free documentation: 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 manual 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/>. +:toc: + +solstice(1) +=========== + +NAME +---- +solstice - compute the power collected by a concentrated solar plant + +SYNOPSIS +-------- +[verse] +*solstice* +*solstice* [_option_]... [_file_] +*solstice* *-g* <__sub-option__[:...]> [_option_]... [_file_] +*solstice* *-p* <__sub-option__[:...]> [_option_]... [_file_] +*solstice* *-r* <__sub-option__[:...]> [_option_]... [_file_] + +DESCRIPTION +----------- +*solstice* computes the total power collected by a concentrated solar plant, as +described in the *solstice-input*(5) _file_. If the _file_ argument is not +provided, the solar plant is read from standard input. To evaluate various +efficiencies for each primary reflector, it computes losses due to cosine +effect, shadowing and masking, orientation and surface irregularities, +materials properties and atmospheric extinction. The efficiency for each +one of these effects is subsequently computed for each reflector. + +The entities on which computations must be performed are listed in the +*solstice-receiver*(5) file submitted through the *-R* option. The estimated +results follow the *solstice-output*(5) format and are written to the _output_ +file or to the standard output whether the *-o* _output_ option is defined or +not, respectively. Note that the *solstice* algorithm is based on the +Monte-Carlo method, which means that every result is provided with its +numerical accuracy. + +*solstice* is designed to efficiently handle complex solar facilities: several +reflectors can be specified (planes, conics, cylindro-parabolic, etc.) and +positioned in 3D space, with a possibility for 1-axis and 2-axis +auto-orientation. Multiple materials can be used, as long as the relevant +physical properties are provided. Spectral effects are also taken into account: +it is possible to define the spectral distribution of any physical property, +including the input solar spectrum and the transmissivity of the atmosphere, at +any spectral resolution. Refer to *solstice-input*(5) for more informations. + +In addition of the aforementioned computations, *solstice* provides three +other functionalities. The *-g* option can be used to convert the +*solstice-input*(5) geometries in CAO files. The *-p* option saves the sampled +radiative paths used by the estimates, allowing to visualise them externally +which may be a great help to identify a design issue. Finally, the *-r* option +is used to render an image of the submitted solar facility. Note that these +three options are mutually exclusives, and once defined, they replace the +default *solstice* behaviour. + +Please note that any coordinate-related question in Solstice must be +considered with the right-handed convention in mind. + +OPTIONS +------- +*-D* <__alpha__,__beta__[:...]>:: + List of sun directions. A direction is defined by two angles in degrees. The + first one, here refered to as _alpha_, is an azimuthal angle in [0, 360[ and + the second one, here refered to as _beta_, is an elevation in [0, 90]. + Each provided sun direction triggers a new computation whose results are + concatenated to the _output_ file. ++ +Following the right-handed convention, Solstice azimuthal rotation is +counter-clockwise, with 0° on the X axis. Solstice elevation starts from 0° for +directions in the XY plane, up to 90° at zenith. Thus -D0,0 -D90,0 -D180,0 and +-D270,0 will produce solar vectors {-1,0,0} {0,-1,0} {+1,0,0} and {0,+1,0} +respectively, while -D__alpha__,90 will produce {0,0,-1} regardless of _alpha_ +value. + +*-f*:: + Force overwrite of the output files, i.e. the _output_ file and the file + where the state of the random number generator is saved (see the *-G* + option). + +*-G* <__sub-option__:...>:: + Save and restore the state of the random number generator. This option can be + used to ensure the statistical independence between successive simulations + on the same system. For instance, one can run a new simulation and + initialising its random number generator with the final state of the + generator as defined by the previous run. Available sub options are: + + **istate=**_input_rng_state_;; + Define the file from which the initial state of the random number generator + is read. If not defined, the random number generator is initialised with + its default seed. + + **ostate=**_output_rng_state_;; + Define the file where the final state of the random number generator is + written. If not defined, this state is simply discarded. + +*-g* <__sub-option__:...>:: + Generate the shape of the geometry defined in the submitted _file_ and store + it in _output_. Available sub-options are: + + *format=obj*;; + Define the file format in which the meshes are stored. Currently, only the + Alias Wavefront OBJ file format is supported. + + *split=*<**geometry**|*object*|*none*>;; + Define how the output mesh is split in sub meshes. A sub mesh can be + generated for each *geometry* or for each *object* as defined in the + *solstice-input*(5) file format. The *none* option means that only one + mesh is generated for the whole solar facility. By default, the *split* + option is set to *none*. + +*-h*:: + List short help and exit. + +*-n* _experiments-count_:: + Number of Monte-Carlo experiments used to estimate the solar flux. By + default _experiments-count_ is set to @SOLSTICE_ARGS_DEFAULT_NREALISATIONS@. + +*-o* _output_:: + Write results to _output_ with respect to the *solstice-output*(5) format. If + not defined, write results to standard output. + +*-p* <__sub-option__:...>:: + Register the sampled radiative paths for each sun direction and write them to + _output_. Available sub-options are: + + *default*;; + Use default sub-options. + + **irlen=**_length_;; + Length of the radiative path segments going to the infinity. By default, it + is computed relatively to the scene size. + + **srlen=**_length_;; + Length of the radiative path segments coming from the sun. By default, it + is computed relatively to the scene size. + +*-q*:: + Do not print the helper message when no _file_ is submitted. + +*-R* _receivers_:: + *solstice-receiver*(5) file defining the scene receivers, i.e. the solar + plant entities for which *solstice* computes Monte-Carlo estimates. + +*-r* <__sub-option__:...>:: + Render an image of the scene through a pinhole camera, for each submitted + sun direction. Write the resulting images to _output_. Available sub-options + are: + + **fov=**_angle_;; + Horizontal field of view of the camera in [30, 120] degrees. By default + _angle_ is @SOLSTICE_ARGS_DEFAULT_CAMERA_FOV@ degrees. + + **img=**_width_**x**_height_;; + Definition of the rendered image in pixels. By default the image definition + is @SOLSTICE_ARGS_DEFAULT_IMG_WIDTH@x@SOLSTICE_ARGS_DEFAULT_IMG_HEIGHT@. + + **pos=**_x_**,**_y_**,**_z_;; + Position of the camera. By default it is set to + {@SOLSTICE_ARGS_DEFAULT_CAMERA_POS@} or it is automatically computed to + ensure that the whole scene is visible, whether *tgt* is set or not, + respectively. + + **rmode=**<**draft**|**pt**>;; + Rendering mode. In *draft* mode, images are computed by ray-casting; all + materials are lambertian, the sun is ignored and the only light source is + positioned at the camera position. In *pt* mode, the scene is rendered with + the un-biased path-tracing Monte-Carlo algorithm; the materials described + in the committed _file_ as well as the submitted sun directions are + correctly handled and an uniform skydome is added to simulate the diffuse + infinite lighting. By default *rmode* is set to *draft*. + + **spp=**_samples-count_;; + Number of samples per pixel. If *rmode* is *draft*, the samples position + into a pixel are the same for all pixels. With *rmode=pt* the pixel + samples are generated independently for each pixel. By default, use 1 + sample per pixel. + + **tgt=**_x_**,**_y_**,**_z_;; + Position targeted by the camera. By default, it is set to + {@SOLSTICE_ARGS_DEFAULT_CAMERA_TGT@} or it is automatically computed to + ensure that the whole scene is visible, whether *pos* is set or not, + respectively. + + **up=**_x_**,**_y_**,**_z_;; + Up vector of the camera. If *rmode* is *pt*, this vector also defines the + direction toward the top of the skydome. By default, *up* is set to + {@SOLSTICE_ARGS_DEFAULT_CAMERA_UP@}. + +*-t* _threads-count_:: + Hint on the number of threads to use. By default use as many threads as CPU + cores. + +*-v*:: + Make solstice more verbose. + +*--version*:: + Output version information and exit. + +EXAMPLES +-------- + +Launch two simulations for sun directions whose azimuthal and elevation angles +are {*45*,*70*} and {*50*,*75*}. The solar facility is described in +*input.yaml* and the receivers on which the integrations must be performed are +declared in the *rcvs.yaml* file. *10000* experiments are used by the +Monte-Carlo estimates and the results are written to *output* even though this +file already exists: + + $ solstice -D45,70:50,75 -R rcvs.yaml -n 10000 -f -o output input.yaml + +Generate a mesh for each geometry described in *input.yaml*, and save them in +the *output* file with respect to the Alias Wavefront OBJ format. The meshes +are positioned according to their orientation constraints, with respect to the +sun direction whose azimuthal and elevation angles are {*30*,*60*}. Use the +*csplit*(1) Unix command to generate an Alias Wavefront OBJ file per geometry +stored in *output*. The name of the generated Alias Wavefront OBJ files are +*geom*<__NUM__>**.obj** with __NUM__ in [0, N-1] where N is the number of +geometries described in *input.yaml*. Refer to *solstice-output*(5) for +informations on the regular expression *^---$* used to split the output file: + + $ solstice -D30,60 -g format=obj:split=geometry -f -o output input.yaml + $ csplit -f geom -b %02d.obj -z --suppress-matched output /^---$/ {*} + +Trace 100 radiative paths into the solar plant described in *input.yaml*, with +respect to the sun direction whose azimuthal and elevations angles are *0* and +*90* degrees, respectively. Write the *solstice-output*(5) result to the +standard output and postprocess it with the *sed*(1) Unix command to remove the +first line that stores the sun direction from which the radiative paths come +from. The remaining data that list the radiative paths geometry are redirected +into the *paths.vtk* file: + + $ solstice -n 100 -D0,90 -R rcvs.yaml -p default input.yaml | sed '1d'>paths.vtk + +Use the path-tracing rendering algorithm to draw the solar plant +*solplant.yaml* with respect to the sun direction whose azimuthal and elevation +angles are *180* and *45* degrees, respectively. Use *64* samples per pixel to +estimate the per-pixel radiance and fix the up camera vector to {*0*,*0*,*1*}. +Write the *solstice-output*(5) result to standard output and use the *sed*(1) +Unix command to remove the first line which stores the sun direction used to +draw the image. Finally, visualise the rendered picture by redirecting the +remaining data to the *feh*(1) image viewer. + + $ solstice -D180,45 -r up=0,0,1:rmode=pt:spp=64 solplant.yaml | sed '1d' | feh - + +COPYRIGHT +--------- +Copyright &copy; 2016-2018 CNRS, 2018-2019 |Meso|Star>. License GPLv3+: GNU GPL +version 3 or later <http://gnu.org/licenses/gpl.html>. This is free software. +You are free to change and redistribute it. There is NO WARRANTY, to the extent +permitted by law. + +SEE ALSO +-------- +*csplit*(1), +*feh*(1), +*sed*(1), +*solstice-input*(5), +*solstice-output*(5), +*solstice-receiver*(5) diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -97,7 +97,7 @@ print_version ASSERT(stream); fprintf(stream, "Stardis version %i.%i.%i built on stardis solver version %i.%i.%i\n", - StardisApp_VERSION_MAJOR, StardisApp_VERSION_MINOR, StardisApp_VERSION_PATCH, + STARDIS_APP_VERSION_MAJOR, STARDIS_APP_VERSION_MINOR, STARDIS_APP_VERSION_PATCH, Stardis_VERSION_MAJOR, Stardis_VERSION_MINOR, Stardis_VERSION_PATCH); } diff --git a/src/stardis-version.h b/src/stardis-version.h @@ -1,14 +0,0 @@ -/* Copying and distribution of this file, with or without modification, - * are permitted in any medium without royalty provided the copyright - * notice and this notice are preserved. This file is offered as-is, - * without any warranty. */ - -#ifndef StardisApp_VERSION_H -#define StardisApp_VERSION_H - -#define StardisApp_VERSION_MAJOR 0 -#define StardisApp_VERSION_MINOR 1 -#define StardisApp_VERSION_PATCH 0 - -#endif /* StardisApp_VERSION_H */ - diff --git a/src/stardis-version.h.in b/src/stardis-version.h.in @@ -0,0 +1,24 @@ +/* Copyright (C) 2018-2020 |Meso|Star> + * + * 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/>. */ + +#ifndef STARDIS_VERSION_H +#define STARDIS_VERSION_H + +#define STARDIS_APP_VERSION_MAJOR @VERSION_MAJOR@ +#define STARDIS_APP_VERSION_MINOR @VERSION_MINOR@ +#define STARDIS_APP_VERSION_PATCH @VERSION_PATCH@ + +#endif /* STARDIS_VERSION_H */ +