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 4e58257d592a60ff19852f5e1b68425ee210c965
parent 1d73e013d21dcb43c59f5648faf6c2c7b521c400
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 22 May 2017 14:26:38 +0200

Convert the solstice-input man page from ronn to asciidoc

Diffstat:
Mcmake/doc/CMakeLists.txt | 11++++++++---
Ddoc/solstice-input.5.ronn | 918-------------------------------------------------------------------------------
Adoc/solstice-input.5.txt | 975+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 983 insertions(+), 921 deletions(-)

diff --git a/cmake/doc/CMakeLists.txt b/cmake/doc/CMakeLists.txt @@ -37,10 +37,15 @@ if(CMAKE_HOST_UNIX) endif() ################################################################################ -# Generate the TROFF man pages +# Define doc files ################################################################################ -set(MAN_TXT ${CMAKE_CURRENT_BINARY_DIR}/solstice.1.txt) +set(MAN_TXT + # ${CMAKE_CURRENT_BINARY_DIR}/solstice.1.txt + ${SOLSTICE_DOC_DIR}/solstice-input.5.txt) +################################################################################ +# Generate the TROFF man pages +################################################################################ if(A2X) set(A2X_OPTS -dmanpage -fmanpage) @@ -51,7 +56,7 @@ if(A2X) COMMAND ${A2X} ${A2X_OPTS} ${_txt} DEPENDS ${_txt} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Build troff man page ${_txt}" + COMMENT "Build TROFF man page ${_txt}" VERBATIM) list(APPEND MAN_FILES ${_txt}.troff) endforeach() diff --git a/doc/solstice-input.5.ronn b/doc/solstice-input.5.ronn @@ -1,918 +0,0 @@ -solstice-input(5) -- 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 - - <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] - roughness: <mtl-data> # in [0, 1] - [ <normal-map> ] - - <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) - absorptivity: <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> | <buie> - - <buie> ::= buie: - csr: REAL # in [1e-6, 0.849] - - <pillbox> ::= pillbox: - aperture: REAL # in ]0, 90] - - ---------------------------------------- - - <atmosphere> ::= atmosphere: - absorption: <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 solar-plant's source. 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 normal -to the sun. The optional `spectrum` parameter describes the per wavelength -distribution of the sun's `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 effetcs 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's 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 (point source sun). The available sun shapes are: - -* `pillbox`: - The `pillbox` distribution defines an uniform intensity over the sun's disk. - Its single `aperture` parameter is the sun's disk half-angle in degrees, that - is linked to the apparent size of the sun. A typical aperture is 0.2664. - -* `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 irradiances. 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 absorption coefficient in m\^-1, that -can either be a scalar if the `absorption` is constant over the spectrum, or -can be spectrally described. The absorption along light paths is only computed -after the first reflector, as sun's description must include all the -atmospheric effects before the first reflector (see sun's description for more -details). - -If no atmosphere is provided, atmospheric absorption 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|)<br/> - 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 - `solstice-input`(5) file must ensure that the description of the scene media - is consistent; a ray travelling in a medium _A_ can only encounter a medium - interface whose `medium_i` attribute is _A_. The default medium is assumed to - be the vacuum, i.e. its refractive index is 1 and its absorptivity is 0. - -* `matte`: - Diffuse surface. Reflects the same intensity in all directions independently - of the incoming direction. - -* `mirror`: - Specular or glossy reflection whether the `roughness` parameter is 0 or not, - respectively. Glossy reflections are controlled by a microfacet BRDF with the - Beckmann normal distribution defined as: - - D(wh) = exp(-tan\^2(a) / m\^2) / (PI * m\^2 * cos\^4(a)) - - with a = arccos(wh.N) and m the `roughness` in ]0,1] of the interface. - -* `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|)<br/> - 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. - -* `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 whose up direction is along the negative Z axis and its - polar coordinate 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)<br/> - b = g(f - 1/2)<br/> - z0 = |b| + g/2<br/> - g = `focals.real` + `focals.image`<br/> - 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 describes 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 operation 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 -meshes 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 `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. 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 geometric entity one have 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's position and to the pivot's parameters. It is supposed (but not -mandatory) that the pivot's child geometry includes a reflector, that, once -pivoted, will reflect sun's light towards a `target`. You should note that a -pivot cannot be child of a pivot. - -The most noticeable pivot's parameter is its `target`. Four different types of -targets are available: - -* `position`: - Defines the pivot's target as being an absolute point in world coordinates. - -* `anchor`: - Defines the pivot's target as being a point defined through an anchor's name - (see below). - -* `sun`: - Defines the pivot's target as being the center of the sun. - -* `direction`: - Points the pivot to reflect light in the given direction, specified in world - coordinates. - -Pivots can also have a `ref_point` optional parameter defining a 3D point in -pivot's child coordinate system that will be used by the pointing algorithm. -If not provided, the origin of the coordinate system is used instead. - -Two different flavours of `pivots` are available: `x_pivot` and `zx_pivot`, -each with its own set of parameters and behaviour. - -* `x_pivot`: - A `x_pivot` is a pivot with a single rotation axis: the `O`,`X` axis in its - local coordinate system. It has a `target` and can have a `ref_point`. - - The `x_pivot` pointing algorithm considers an incoming ray of light from the - center of the sun and rotates the pivot's child geometry so that a specular - reflection at `ref_point` using `+Z` as local normal will hit the pivot's - target point, or will have the specified direction (depending of the kind - of target). - -* `zx_pivot`: - A `zx_pivot` is a pivot with two rotation axis: the `O`,`Z` axis in its local - coordinate system, then the `O'`,`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 `|O O'|` distance along the `Y` axis. If not - defined, `spacing` is 0 and `O` and `O'` are the same point. - - The `zx_pivot` pointing algorithm considers an incoming ray of light from the - center of the sun and rotates the pivot's child geometry so that a specular - reflection at `ref_point` using `+Y` as local normal will hit the pivot's - target point, 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. 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 - roughness: 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 aperture 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 requires to describe the -scene: - - - sun: {dni: 1000, pillbox: {aperture: 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-square} - - 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, roughness: 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, roughness: 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]}} - -## 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/solstice-input.5.txt b/doc/solstice-input.5.txt @@ -0,0 +1,975 @@ +// Copyright (C) CNRS 2016-2017 +// +// 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] + roughness: <mtl-data> # in [0, 1] + [ <normal-map> ] + +<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) + absorptivity: <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> | <buie> + +<buie> ::= buie: + csr: REAL # in [1e-6, 0.849] + +<pillbox> ::= pillbox: + aperture: REAL # in ]0, 90] + +---------------------------------------- + +<atmosphere> ::= atmosphere: + absorption: <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 solar-plant's source. 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 normal +to the sun. The optional *spectrum* parameter describes the per wavelength +distribution of the sun's *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 effetcs 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's 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 (point source sun). The available sun shapes are: + +*pillbox*:: + The *pillbox* distribution defines an uniform intensity over the sun's disk. + Its single *aperture* parameter is the sun's disk half-angle in degrees, that + is linked to the apparent size of the sun. A typical aperture is 0.2664. + +*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 irradiances. 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 absorption coefficient in m^-1, that +can either be a scalar if the *absorption* is constant over the spectrum, or +can be spectrally described. The absorption along light paths is only computed +after the first reflector, as sun's description must include all the +atmospheric effects before the first reflector (see sun's description for more +details). + +If no atmosphere is provided, atmospheric absorption 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. Note that the +*solstice-input*(5) file must ensure that the description of the scene media +is consistent; a ray travelling in a medium _A_ can only encounter a medium +interface whose *medium_i* attribute is _A_. The default medium is assumed to +be the vacuum, i.e. its refractive index is 1 and its absorptivity is 0. + +*matte*:: +Diffuse surface. Reflects the same intensity in all directions independently +of the incoming direction. + +*mirror*:: +Specular or glossy reflection whether the *roughness* parameter is 0 or not, +respectively. Glossy reflections are controlled by a microfacet BRDF with the +Beckmann normal distribution defined as: ++ +....... +D(wh) = exp(-tan^2(a) / m^2) / (PI * m^2 * cos^4(a)) +....... ++ +with a = arccos(wh.N) and m the *roughness* in ]0,1] of the interface. + +*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. + +*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 whose up direction is along the negative Z axis and its +polar coordinate 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 describes 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 operation 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 +meshes 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 *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. 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 geometric entity one have 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's position and to the pivot's parameters. It is supposed (but not +mandatory) that the pivot's child geometry includes a reflector, that, once +pivoted, will reflect sun's light towards a *target*. You should note that a +pivot cannot be child of a pivot. + +The most noticeable pivot's parameter is its *target*. Four different types of +targets are available: + +*position*:: + Defines the pivot's target as being an absolute point in world coordinates. + +*anchor*:: + Defines the pivot's target as being a point defined through an anchor's name + (see below). + +*sun*:: + Defines the pivot's target as being the center of the sun. + +*direction*:: + Points the pivot to reflect light in the given direction, specified in world + coordinates. + +Pivots can also have a *ref_point* optional parameter defining a 3D point in +pivot's child coordinate system that will be used by the pointing algorithm. +If not provided, the origin of the coordinate system is used instead. + +Two different flavours of *pivots* are available: *x_pivot* and *zx_pivot*, +each with its own set of parameters and behaviour. + +*x_pivot*:: + A *x_pivot* is a pivot with a single rotation axis: the *O*,*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 the pivot's child geometry so that a specular reflection at + *ref_point* using *+Z* as local normal will hit the pivot's target point, or + will have the specified direction (depending of the kind of target). + +*zx_pivot*:: + A *zx_pivot* is a pivot with two rotation axis: the *O*,*Z* axis in its local + coordinate system, then the *O'*,*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 *|O O'|* distance along the *Y* axis. If not + defined, *spacing* is 0 and *O* and *O'* are the same point. The *zx_pivot* + pointing algorithm considers an incoming ray of light from the center of the + sun and rotates the pivot's child geometry so that a specular reflection at + *ref_point* using *+Y* as local normal will hit the pivot's target point, 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. 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 + roughness: 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 aperture 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 requires to describe +the scene: +....... +- sun: {dni: 1000, pillbox: {aperture: 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-square} +- 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, roughness: 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, roughness: 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]}} +....... + +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)