# solstice-output(5) Manual Page

## NAME

solstice-output - output format of solstice(1) results

## DESCRIPTION

The solstice-output describes the output format of the solstice(1) program. All the data generated by a solstice(1) invocation are written in a single file or on the standard output whether an output file is defined through the -o option or not, respectively. Note that submitting several sun directions to solstice(1), through the -D option, will produce as many outputs as sun directions. In other words, invoking solstice(1) with N sun directions looks like calling solstice(1) N times and concatenating their associated output.

The type of the data that are generated depends on the mode in which solstice(1) is invoked. By default, solstice(1) evaluates the power collected by the submitted solar plant. When invoked with the -g option, solstice(1) converts the solar plant geometries in a list of CAO files. The -p option is used to track the sampled radiative paths while, finally, the -r option allows to render an image of the solar facility.

## GRAMMAR

The output values are mainly ASCII data formatted line by line. By convention, in the following grammar the line data are listed between quote marks. The grammar may use new lines for formatting constraints, but data are actually on the same line while a closed quote mark is not defined.

    <output>              ::= <simulation-output>
                            | <dump-geometry-output> # -g option
                            | <dump-radiative-paths-output> # -p option
                            | <rendering-output> # -r option

    <simulation-output>   ::= <sun-direction>
                              <counts>
                              <global>
                            [ <receivers-list> ]
                            [ <primaries-list> ]
                            [ <rcvXprims-list> ]
                            [ <receiver-maps> ]
                            [ <simulation-output> … ]

    <dump-geometry-output>
                          ::= <sun-direction>
                              <geometry-data>
                            [ <dump-geometry-output> … ]

    <dump-radiative-paths-output>
                          ::= <sun-direction>
                              VTK-RADIATIVE-PATHS
                            [ <dump-radiative-paths-output> … ]

    <rendering-output>    ::= <sun-direction>
                              PPM-FILE # ASCII PPM with 8-bits per component [1]
                            [ <rendering-output> … ]

    -------------------------------------

    <sun-direction>       ::= "#--- Sun direction: <alpha> <beta> (<sun-vector>)"

    <counts>              ::= "<#globals> <#receivers> <#primaries>
                               <#samples> <#failed>"

    <#globals>            ::= 7
    <#receivers>          ::= INTEGER # in [0, INF)
    <#primaries>          ::= INTEGER # in [0, INF)
    <#samples>            ::= INTEGER # in [0, INF)
    <#failed>             ::= INTEGER # in [0, INF)

    <global>              ::= <potential-flux>
                              <absorbed-flux>
                              <cos-factor>
                              <shadow-loss>
                              <missing-loss>
                              <materials-loss>
                              <atmospheric-loss>

    -------------------------------------

    <receivers-list>      ::= <receiver>
                            [ <receiver> … ]

    <receiver>            ::= "<receiver-name> <receiver-id> <area>
                               <front> <back>"

    <receiver-name>       ::= <entity-identifier>

    <receiver-id>         ::= INTEGER

    <front>               ::= <side>
    <back>                ::= <side>

    <side>                ::= "<incoming-flux> <in-if-no-mat-loss>
                               <in-if-no-atm-loss> <in-mat-loss> <in-atm-loss>
                               <absorbed-flux> <abs-if-no-mat-loss>
                               <abs-if-no-atm-loss> <abs-mat-loss> <abs-atm-loss>
                               <efficiency>"

    -------------------------------------

    <primaries-list>      ::= <primary>
                            [ <primary> … ]

    <primary>             ::= "<primary-name> <primary-id> <area> <#samples>
                               <cos-factor> <shadow-loss>"

    <primary-name>        ::= <entity-identifier>

    <primary-id>          ::= INTEGER

    -------------------------------------

    <rcvXprims-list>      ::= <rcvXprim>
                            [ <rcvXprim> … ]

    <rcvXprim>            ::= "<receiver-id> <primary-id>
                               <rcvXprim-front> <rcvXprim-back>"

    <rcvXprim-front>      ::= <rcvXprim-side>
    <rcvXprim-back>       ::= <rcvXprim-side>

    <rcvXprim-side>       ::= "<incoming-flux> <in-if-no-mat-loss>
                               <in-if-no-atm-loss> <in-mat-loss> <in-atm-loss>
                               <absorbed-flux> <abs-if-no-mat-loss>
                               <abs-if-no-atm-loss> <abs-mat-loss> <abs-atm-loss>"

    -------------------------------------

    <receiver-maps>       ::= VTK-RECEIVER-MAP
                            [ <receiver-maps> … ]

    <geometry-data>       ::= OBJ-FILE
                            [ ---
                              <geometry-data> … ]

    -------------------------------------

    <area>                ::= REAL # in ]0, INF)

    <real3>               ::= REAL REAL REAL

    <alpha>               ::= REAL # Degrees in [0, 360[
    <beta>                ::= REAL # Degrees in [0, 90]
    <sun-vector>          ::= <real3>

    <incoming-flux>       ::= <estimate>
    <in-if-no-mat-loss>   ::= <estimate>
    <in-if-no-atm-loss>   ::= <estimate>
    <in-mat-loss>         ::= <estimate>
    <in-atm-loss>         ::= <estimate>
    <absorbed-flux>       ::= <estimate>
    <abs-if-no-mat-loss>  ::= <estimate>
    <abs-if-no-atm-loss>  ::= <estimate>
    <abs-mat-loss>        ::= <estimate>
    <abs-atm-loss>        ::= <estimate>
    <cos-factor>          ::= <estimate>
    <missing-loss>        ::= <estimate>
    <materials-loss>      ::= <estimate>
    <atmospheric-loss>    ::= <estimate>
    <shadow-loss>         ::= <estimate>
    <efficiency>          ::= <estimate>

    <estimate>            ::= <expected-value> <standard-error>
    <expected-value>      ::= REAL
    <standard-error>      ::= REAL # in [0, INF)

    <entity-identifier>   # Defined in solstice-input(5)

## SIMULATION

A simulation-output begins with two header lines. The first one reports the sun direction used in the simulation (two angles in degrees, plus the corresponding sun vector), and the second one lists the numbers of global, per receiver and per primary results as well as the overall number of Monte-Carlo experiments used by the simulation and the number of experiments that failed due to unforeseen errors as numerical imprecisions. As soon as the number of failed experiments reaches 1% of the required number of Monte-Carlo experiments, the code exits with a "Error in integrating the solar flux" message, and the validity of subsequent results is questionable: estimates are produced using the number of Monte-Carlo experiments that have been successful, which is necessarily smaller than the required number of experiments.

### Global results

After the 2 header lines, the output includes various global result lines, the exact number of lines being part of the headers. Currently this number is 7. Each global result is a pair of real numbers: the expected value and its standard error. The global results are, in this order:

- potential-flux: maximum flux that all the primary geometries could intercept if properly oriented and flat-shaped;

- absorbed-flux: absorbed part of the flux reaching any receiver geometry. At most equal to the potential flux;

- cos-factor: cos of the angle between the sun direction and the normal of the primary surfaces (average cos over all primary geometries);

- shadow-loss: potential flux intercepted by another geometry before reaching a primary geometry;

- missing-loss: part of the flux that reaches a primary geometry, follows a radiative path, but is not absorbed; this flux could have bounced on geometries, including receivers, but without being absorbed;

- materials-loss: total flux absorbed by non-receivers along radiative paths; includes both surface and volume absorption;

- atmospheric-loss: total flux extinction by the atmosphere along radiative paths.

This results can be used to check conservation of energy:

potential-flux * cos-factor and (absorbed-flux + shadow-loss
missing-loss + materials-loss + atmospheric-loss) should be equal within their respective uncertainty ranges.

### Per receiver results

Following global results, the output includes various per-receiver lines, one line per receiver, the exact number of lines being part of the headers. The per-receiver results are sorted according to the order of the receivers as defined in the submitted solstice-receiver(5) file. Each line contains the following data:

- receiver-name: name of the receiver, i.e. entity-identifier of the entity in which the receiving geometry is defined (see the solstice-input(5) format);

- receiver-id: unique integer identifying the receiver;

- area: area of the receiver;

- front: estimated results for the front side of the receiver;

- back: estimated results for the back side of the receiver.

The estimates of the front and back sides are listed bellow. Note that each of the following estimates is actually a pair of real numbers: the expected value and its standard error.

- incoming-flux: flux that reaches the receiver side;

- in-if-no-mat-loss: incoming-flux if absorption on non-receivers is not taken into account;

- in-if-no-atm-loss: incoming-flux if atmospheric extinction is not taken into account;

- in-mat-loss: in-if-no-mat-loss - incoming-flux;

- in-atm-loss: in-if-no-atm-loss - incoming-flux;

- absorbed-flux: flux absorbed by the receiver side;

- abs-if-no-mat-loss: absorbed-flux if absorption by non-receivers is not taken into account;

- abs-if-no-atm-loss: absorbed-flux if atmospheric extinction is not taken into account;

- abs-mat-loss: abs-if-no-mat-loss - absorbed-flux;

- abs-atm-loss: abs-if-no-atm-loss - absorbed-flux;

- efficiency: fraction of the potential flux absorbed by this receiver side.

Both front and back side estimates are output, even if the receiver has only a single receiving side. In this case, the results of the non-receiving side are meaningless (invalid -1 value).

### Per primary results

Following the per-receiver results, the output includes various per-primary result lines, one line per primary geometry, the exact number of lines being part of the headers. Each line contains:

- primary-name: name of the primary geometry, i.e. entity-identifier of the entity in in which the primary geometry is defined (see the solstice-input(5) format);

- primary-id: unique integer identifying the primary geometry;

- area: area of the primary geometry;

- #sample: number of Monte-Carlo experiments sampled on the primary geometry;

- cos-factor: cos of the angle between the sun direction and the normal of the primary surface (average cos on the primary geometry);

- shadow-loss: potential flux intercepted by another geometry before reaching the primary geometry of interest.

### Per receiver and per primary results

Following the per-primary results, the output includes various result lines, each describing the contribution of a primary geometry to a given receiver. The total number of such lines is the number of receivers times the number of primary geometries. Each line contains:

- receiver-id: identifier of the involved receiver;

- primary-id: identifier of the involved primary geometry;

- rcvXprim-front: estimated results for the receiver front side;

- rcvXprim-back: estimated results for the receiver back side;

The estimated values of rcvXprim-front and rcvXprim-back are listed bellow. Each of these estimates is actually a pair of real numbers: the expected value and its standard error.

- incoming-flux: flux that reaches the receiver side;

- in-if-no-mat-loss: incoming-flux if absorption on non-receivers is not taken into account;

- in-if-no-atm-loss: incoming-flux if atmospheric extinction is not taken into account;

- in-mat-loss: in-if-no-mat-loss - incoming-flux;

- in-atm-loss: in-if-no-atm-loss - incoming-flux;

- absorbed-flux: flux absorbed by the receiver side;

- abs-if-no-mat-loss: absorbed-flux if absorption by non-receivers is not taken into account;

- abs-if-no-atm-loss: absorbed-flux if atmospheric extinction is not taken into account;

- abs-mat-loss: abs-if-no-mat-loss - absorbed-flux;

- abs-atm-loss: abs-if-no-atm-loss - absorbed-flux;

Both front and back side estimates are output, even if the receiver has only a single receiving side. In this case, the results of the non-receiving side are meaningless (invalid -1 value).

### Receiver map

A receiver defined in the submitted solstice-receiver(5) file, can have a per-primitive estimate of its incoming flux density and/or absorbed flux density if its per_primitive flag is active. In this case, solstice(1) generates a receiver-map that is actually an ASCII VTK file [2] that stores the triangular mesh of the receiver and, for each triangle, the estimate of its associated incoming flux density and/or absorbed flux density. The "definition" of the receiver map is thus controlled by the discretisation of the receiver’s shape, as described in the solstice-input(5) file. Note that to obtain a good estimate of the per-triangle flux densities, one have to ensure that the number of per-triangle experiments is sufficient regarding the targeted accuracy. Since only a small fraction of the overall sampled radiative paths reach a given triangle, the total number of experiments required through the -n option of solstice(1) should be increased significantly, as 1 or 2 order of magnitude.

The number of written per-triangle flux density estimates depends on the receiver’s parameters: both front and back sides of the receiver can be active and each side can produce an estimate both for the incoming flux density and for the absorbed flux density. As a consequence, the output can include up to 4 different estimates that are written in the order: incoming front, absorbed front, incoming back, absorbed back. The following grammar gives a brief description of the formatting of a VTK-RECEIVER-MAP. Please refer to the VTK format specification [2] for more informations on the VTK file format.

    VTK-RECEIVER-MAP      ::= # vtk DataFile Version 2.0
                              <receiver-name>
                              ASCII
                              DATASET POLYDATA
                              POINTS <#vertices> float
                              <map-vertices>
                              POLYGONS <#triangles> <#triangles*4>
                              <map-triangles>
                              CELL_DATA <#triangles>
                              <map-triangle-data>

    <map-vertices>        ::= <real3>
                            [ <real3> … ] # up to <#vertices>

    <map-triangles>       ::= 3 <triangle-indices>
                            [ 3 <triangle-indices> … ] # up to <#triangles>

    <map-triangle-data>   ::= <map-front-data>
                            | <map-back-data>
                            | <map-front-data> <map-back-data>

    <map-front-data>      ::= <map-side-data>
    <map-back-data>       ::= <map-side-data>

    <map-side-data>       ::= <incoming-flux>
                            | <absorbed-flux>
                            | <incoming-flux> <absorbed-flux>

    <incoming-flux>       ::= <flux-density-data>
    <absorbed-flux>       ::= <flux-density-data>

    <flux-density-data>   ::= SCALARS <side-and-flux-names> float 2
                              LOOKUP_TABLE default
                              <estimate>
                            [ <estimate> … ]

    <side-and-flux-names> ::= Front_faces_Incoming_flux
                            | Front_faces_Absorbed_flux
                            | Back_faces_Incoming_flux
                            | Back_faces_Absorbed_flux

    <#triangles>          ::= INTEGER
    <#vertices>           ::= INTEGER
    <triangle-indices>    ::= INTEGER INTEGER INTEGER

## DUMP GEOMETRY

A dump-geometry-output is generated when solstice(1) is invoked with the -g option. In this mode, for each submitted sun direction, solstice(1) converts the geometry of the submitted solstice-input(5) file in triangular meshes that are then written to the output with respect to the format provided by the format parameter of the -g option. The only format currently supported by solstice(1) is the Alias Wavefront OBJ [3] format. With no more sub-option, solstice(1) will thus generate one OBJ file containing the whole mesh of the solar plant. However, the split parameter of the -g option allows to generate several OBJ files: one description is generated per geometry or per object, as defined in the solstice-input(5) format, whether the split sub-option is set to geometry or object. In this situation, each OBJ description is followed by a line with 3 minus characters in order to identify the end of the current OBJ.

Independently of the split strategy, each solstice-input(1) geometry is an OBJ group whose name is the entity-identifier of the entity in which it is encapsulated. Finally, the dump-geometry-output uses the usemtl directive of the OBJ format to associate to a mesh the name of its material type. The following grammar succinctly describes the formatting of an OBJ-FILE. Please refer to the OBJ format specification [3] for more informations on the OBJ file format.

    OBJ-FILE              ::= g <entity-identifier>
                              <obj-mesh>
                            [ <obj-mesh> … ]

    <obj-mesh>            ::= usemtl <material-type>
                              <obj-vertices>
                              <obj-faces>

    <obj-vertices>        ::= v <real3>
                            [ v <real3> … ]

    <obj-indices>         ::= f <triangle-indices>
                            [ f <triangle-indices> … ]

    <material-type>       ::= dielectric
                            | matte
                            | mirror
                            | thin_dielectric
                            | virtual

## DUMP RADIATIVE PATHS

For each sun direction, the dump-radiative-paths-output lists the geometric data of the radiative paths sampled during a simulation. Each path is colored with respect to its type: the path is yellow if its first segment, i.e. the ray starting from the sun towards a primary geometry, is occluded by a non virtual object. If not occluded, the path can be blue or turquoise whether it reaches a receiver or not, respectively. Finally, the path can also be red if it was canceled due to a topologically incoherent impact (i.e. an impact on a surface not at the boundary of the medium in which the rays was propagating). The following grammar describes the formatting of a VTK-RADIATIVE-PATHS file. Refer to the VTK format specification [2] for more informations on the VTK file format.

    VTK-RADIATIVE-PATHS   ::= # vtk DataFile Version 2.0
                              Radiative paths
                              ASCII
                              DATASET POLYDATA
                              POINTS <#vertices> float
                              <paths-vertices>
                              LINES <#paths> <#paths+#vertices>
                              <paths-lists>
                              CELL_DATA <#paths>
                              SCALAR Radiative_path_type float 1
                              LOOKUP_TABLE path_type
                              <paths-type>
                              LOOKUP_TABLE path_type 5
                              <color-error>
                              <color-unused>
                              <color-success>
                              <color-missing>
                              <color-occluded>

    <paths-vertices>      ::= <real3>
                            [ <real3> … ] # up to <#vertices>

    <paths-lists>         ::= <radiative-path>
                            [ <radiative-path> … ] # up to <#path>

    <radiative-path>      ::= <#path-segments> <path-vertex-id> …

    <paths-type>          ::= <color-id>
                            [ <color-id> … ] # up to <#paths>

    <color-id>            ::= 0.0  # Red: for error paths
                            | 0.25 # Green: unused
                            | 0.5  # Blue: for success paths
                            | 0.75 # Turquoise: for missing paths
                            | 1.0  # Yellow: for occluded paths

    <color-error>         ::= 1.0 0.0 0.0 1.0
    <color-unused>        ::= 0.0 1.0 0.0 1.0
    <color-success>       ::= 0.0 0.0 1.0 1.0
    <color-missing>       ::= 0.0 1.0 1.0 1.0
    <color-occluded>      ::= 1.0 1.0 0.0 1.0

    <#paths>              ::= INTEGER
    <#path-segments>      ::= INTEGER
    <path-vertex-id>      ::= INTEGER

## RENDERING

When invoked with the -r option, solstice(1) generates an image of the solar facility for each submitted sun direction. Each image is preceded by its associated sun direction and is saved with respect to the ASCII PPM file format [1]. The output images are actually greyscale images whose pixels store the average normalized radiance that reaches them.

## NOTES

1. Portable PixMap - http://netpbm.sourceforge.net/doc/ppm.html

2. VTK file format - http://www.vtk.org/wp-content/uploads/2015/04/file-formats.pdf

3. OBJ file format - http://www.martinreddy.net/gfx/3d/OBJ.spec

## SEE ALSO

solstice(1), solstice-input(5), solstice-receiver(5)