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:
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)