solstice

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

solstice-input.5 (39537B)


      1 .\" SPDX-License-Identifier: GPL-3.0-or-later
      2 .\" Copyright (C) 2016-2018 CNRS, 2018-2019 |Méso|Star>
      3 .\"
      4 .\" This is free documentation: you can redistribute it and/or modify
      5 .\" it under the terms of the GNU General Public License as published by
      6 .\" the Free Software Foundation, either version 3 of the License, or
      7 .\" (at your option) any later version.
      8 .\"
      9 .\" This manual is distributed in the hope that it will be useful,
     10 .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12 .\" GNU General Public License for more details.
     13 .\"
     14 .\" You should have received a copy of the GNU General Public License
     15 .\" along with this program. If not, see <http://www.gnu.org/licenses/>.
     16 .Dd $Mdocdate$
     17 .Dt SOLSTICE-INPUT 5
     18 .Os
     19 .Sh NAME
     20 .Nm solstice-input
     21 .Nd solar plant description for solstice
     22 .Sh DESCRIPTION
     23 The
     24 .Nm
     25 format is used by the
     26 .Xr solstice 1
     27 program to represent a solar plant.
     28 It relies on the YAML 1.1 data serialization standard
     29 .Po
     30 see the
     31 .Sx NOTES
     32 section, reference 1
     33 .Pc ;
     34 assuming that the file is compatible with the
     35 .Nm
     36 semantic, a solar plant can be described by using the whole YAML 1.1
     37 functionalities including compact notation and data tagging.
     38 .Pp
     39 A solar plant is composed of a
     40 .Em sun ,
     41 an optional
     42 .Em atmosphere
     43 and a collection of
     44 .Em geometries ,
     45 i.e.\&
     46 .Em shapes
     47 with their associated
     48 .Em material .
     49 Beside the raw description of the aforementioned data, the
     50 .Nm
     51 format provides the
     52 .Em entity
     53 item to efficiently structure the geometries in the scene.
     54 An entity is a node in a tree data structure where the position of each
     55 child entity is relative to the position of its parent.
     56 An entity can either encapsulate a
     57 .Em geometry
     58 or a
     59 .Em pivot
     60 that controls the dynamic positioning of its child entities with respect
     61 to the pivot constraints and the sun direction submitted to the
     62 .Xr solstice 1
     63 program.
     64 .Sh GRAMMAR
     65 .Bd -literal
     66 <solar-plant>         ::= - <sun>
     67                           - <item>
     68                         [ - <item> ... ]
     69                         [ - <atmosphere> ]
     70 
     71 <item>                ::= <entity>
     72                         | <geometry>
     73                         | <material>
     74                         | <medium>
     75                         | <spectrum>
     76                         | <template>
     77 .Ed
     78 .Bd -literal
     79 <geometry>            ::= geometry:
     80                           - <object>
     81                         [ - <object> ... ]
     82 
     83 <object>              ::= <shape>
     84                           <material>
     85                         [ <transform> ]
     86 
     87 <x_pivot>             ::= x_pivot:
     88                             <target>
     89                         [   ref_point: <real3> ] # Default is [0,0,0]
     90 
     91 <zx_pivot>            ::= zx_pivot:
     92                             <target>
     93                         [   spacing: REAL ] # in [0, INF). Default 0
     94                         [   ref_point: <real3> ] # Default is [0,0,0]
     95 
     96 <target>              ::= target:
     97                             anchor: <anchor-identifier>
     98                         |   direction: <real3>
     99                         |   position: <real3>
    100                         |   <sun>
    101 .Ed
    102 .Bd -literal
    103 <shape>               ::= <cuboid>
    104                         | <cylinder>
    105                         | <hemisphere>
    106                         | <hyperbol>
    107                         | <parabol>
    108                         | <parabolic-cylinder>
    109                         | <plane>
    110                         | <sphere>
    111                         | <stl>
    112 
    113 <cuboid>              ::= cuboid:
    114                             size: <real3> # in ]0, INF]^3
    115 
    116 <cylinder>            ::= cylinder:
    117                             height: REAL # in ]0, INF)
    118                             radius: REAL # in ]0, INF)
    119                         [   slices: INTEGER ] # in [4, 4096]. Default is 16
    120                         [   stacks: INTEGER ] # in [1, 4096]. Default is 1
    121 
    122 <hemisphere>          ::= hemisphere:
    123                             radius: REAL # in ]0, INF)
    124                         [   clip: <polyclip-list> ]
    125                         [   slices: INTEGER ] # in [4, 4096]
    126 
    127 <hyperbol>            ::= hyperbol:
    128                             focals: <hyperboloid-focals>
    129                             clip: <polyclip-list>
    130                         [   slices: INTEGER ] # in [4, 4096]
    131 
    132 <parabol>             ::= parabol:
    133                             focal: REAL # in ]0, INF)
    134                             clip: <polyclip-list>
    135                         [   slices: INTEGER ] # in [4, 4096]
    136 
    137 <parabolic-cylinder>  ::= parabolic-cylinder:
    138                             focal: REAL # in ]0, INF)
    139                             clip: <polyclip-list>
    140                         [   slices: INTEGER ] # in [4, 4096]
    141 
    142 <plane>               ::= plane:
    143                             clip: <polyclip-list>
    144                         [   slices: INTEGER ] # in [1, 4096]. Default is 1
    145 
    146 <sphere>              ::= sphere:
    147                             radius: REAL # in ]0, INF)
    148                         [   slices: INTEGER ] # in [4, 4096]. Default is 16
    149                         [   stacks: INTEGER ] # in [2, 4096]. Default is slices/2
    150 
    151 <stl>                 ::= stl:
    152                             path: PATH
    153 
    154 <hyperboloid-focals>  ::= real: REAL # in ]0, INF)
    155                           image: REAL # in ]0, INF)
    156 .Ed
    157 .Bd -literal
    158 <polyclip-list>       ::= - <polyclip>
    159                         [ - <polyclip> ... ]
    160 
    161 <polyclip>            ::= operation: <AND|SUB>
    162                           <contour-descriptor>
    163 
    164 <contour-descriptor>  ::= <circle-descriptor>
    165                         | <vertices-descriptor>
    166 
    167 <vertices-descriptor> ::= vertices: <vertices-list>
    168 
    169 <circle-descriptor>   ::= circle:
    170                             radius: REAL # in ]0, INF)
    171                         [   center: <real2> ] # Default is 0,0
    172                         [   segments: INTEGER ] # in [3, 4096]. Default is 64
    173 
    174 <vertices-list>       ::= - <real2>
    175                           - <real2>
    176                           - <real2>
    177                         [ - <real2> ... ]
    178 .Ed
    179 .Bd -literal
    180 <material>            ::= material:
    181                             <material-descriptor>
    182                         |   <double-sided-mtl>
    183 
    184 <double-sided-mtl>    ::= front: <material-descriptor>
    185                           back: <material-descriptor>
    186 
    187 <material-descriptor> ::= <dielectric>
    188                         | <matte>
    189                         | <mirror>
    190                         | <thin-dielectric>
    191                         | <virtual>
    192 
    193 <dielectric>          ::= dielectric:
    194                             medium_i: <medium-descriptor>
    195                             medium_t: <medium-descriptor>
    196                         [   <normal-map> ]
    197 
    198 <matte>               ::= matte:
    199                             reflectivity: <mtl-data> # in [0, 1]
    200                         [   <normal-map> ]
    201 
    202 <mirror>              ::= mirror:
    203                             reflectivity: <mtl-data> # in [0, 1]
    204                             slope_error: <mtl-data>
    205                         [   microfacet: <normal-distrib> ] # Default is BECKMANN
    206                         [   <normal-map> ]
    207 
    208 <normal-distrib>      ::= BECKMANN
    209                         | PILLBOX
    210 
    211 <virtual>             ::= virtual: EMPTY-STRING
    212 
    213 <thin-dielectric>     ::= thin_dielectric:
    214                             thickness: REAL # in [0, INF)
    215                             medium_i: <medium-descriptor>
    216                             medium_t: <medium-descriptor>
    217                         [   <normal-map> ]
    218 
    219 <normal-map>          ::= normal_map:
    220                             path: PATH
    221 .Ed
    222 .Bd -literal
    223 <medium>              ::= medium: <medium-descriptor>
    224 
    225 <medium-descriptor>   ::= refractive_index: <mtl-data> # in ]0, INF)
    226                           extinction: <mtl-data> # in [0, INF)
    227 .Ed
    228 .Bd -literal
    229 <entity>              ::= entity: <entity-data>
    230 
    231 <template>            ::= template: <entity-data>
    232 
    233 <entity-data>         ::= name: STRING
    234                         [ <geometry-data> | <x_pivot> | <zx_pivot> ]
    235                         [ <anchors> ]
    236                         [ <transform> ]
    237                         [ <children>  ]
    238 
    239 <geometry-data>       ::= primary: INTEGER # in [0, 1]
    240                           <geometry>
    241 
    242 <children>            ::= children:
    243                           - <entity-data>
    244                         [ - <entity-data> ... ]
    245 
    246 <anchors>             ::= anchors:
    247                           - <anchor-data>
    248                         [ - <anchor-data> ... ]
    249 
    250 <anchor-data>         ::= name: STRING
    251                           <position-descriptor>
    252 
    253 <position-descriptor> ::= position: <real3>
    254                         | hyperboloid_image_focals: <hyperboloid_focals>
    255 
    256 <entity-identifier>   ::= <self|STRING>[.STRING ... ]
    257 
    258 <anchor-identifier>   ::= <entity-identifier>.STRING
    259 .Ed
    260 .Bd -literal
    261 <sun>                 ::= sun:
    262                             dni: REAL # Direct Normal Irradiance in ]0, INF)
    263                         [   <spectrum> ] # Default is the smarts295 spectrum
    264                         [   <sun-shape> ]
    265 
    266 <sun-shape>           ::= <pillbox> | <gaussian> | <buie>
    267 
    268 <buie>                ::= buie:
    269                             csr: REAL # in [1e-6, 0.849]
    270 
    271 <pillbox>             ::= pillbox:
    272                             half_angle: REAL # in ]0, 90]
    273 
    274 <gaussian>            ::= gaussian:
    275                             std_dev: REAL # in ]0, INF)
    276 .Ed
    277 .Bd -literal
    278 <atmosphere>          ::= atmosphere:
    279                             extinction: <mtl-data> # in [0, 1]
    280 .Ed
    281 .Bd -literal
    282 <mtl-data>            ::= REAL
    283                         | <spectrum-data-list>
    284 
    285 <transform>           ::= transform:
    286                             translation: <real3>
    287                             rotation: <real3>
    288 
    289 <real2>               ::= - REAL
    290                           - REAL
    291 
    292 <real3>               ::= - REAL
    293                           - REAL
    294                           - REAL
    295 
    296 <spectrum>            ::= spectrum: <spectrum-data-list>
    297 
    298 <spectrum-data-list>  ::= - <spectrum-data>
    299                         [ - <spectrum-data> ... ]
    300 
    301 <spectrum-data>       ::= wavelength: REAL # in [0, INF)
    302                           data: REAL # in [0, INF)
    303 .Ed
    304 .Sh SUN
    305 The
    306 .Em sun
    307 describes the source of the solar plant.
    308 Its direction is not defined in the
    309 .Nm
    310 file but is provided by the
    311 .Xr solstice 1
    312 command.
    313 This allows the same unmodified
    314 .Nm
    315 file to be used for several simulations with different sun directions.
    316 .Pp
    317 The main
    318 .Em sun
    319 property is its direct normal irradiance, or
    320 .Em dni
    321 in W/m².
    322 Its value is a scalar defining the direct irradiance received on a plane
    323 perpendicular to the main sun direction.
    324 This value, even though mandatory, can be superseded by another value provided
    325 by the
    326 .Xr solstice 1
    327 command.
    328 The optional
    329 .Em spectrum
    330 parameter describes the per-wavelength distribution of the sun
    331 .Em dni .
    332 Note that this distribution is automatically normalized by
    333 .Xr solstice 1 .
    334 If the
    335 .Em spectrum
    336 attribute is not defined,
    337 .Xr solstice 1
    338 uses a default spectrum computed with the SMARTS software
    339 .Po
    340 see the
    341 .Sx NOTES
    342 section, reference 2
    343 .Pc
    344 between 0.28 and 4 micrometres.
    345 The total
    346 .Em dni
    347 (integrated over the spectral range) was set to 1000 W/m².
    348 The standard Mid-Latitude-Summer atmosphere was used with most gas
    349 concentrations set as default (CO2 concentration assumed 400 ppmv).
    350 .Pp
    351 Even if an atmosphere is provided, the atmospheric effects from the top
    352 of the atmosphere to ground level are not computed using the atmosphere
    353 description.
    354 As a result, the sun description
    355 .Pq Em dni No and optional Em spectrum
    356 is expected to include all atmospheric effects (sun irradiance available
    357 at ground level).
    358 .Pp
    359 The
    360 .Em sun-shape
    361 parameter controls the angular distribution of the sun light intensity
    362 across the sun's disk.
    363 If not defined, the distribution is assumed to be a Dirac distribution
    364 (infinite directional source).
    365 The available sun shapes are:
    366 .Bl -tag -width Ds
    367 .It Em pillbox
    368 The
    369 .Em pillbox
    370 distribution defines a uniform intensity over the sun's disk.
    371 Its single
    372 .Em half_angle
    373 parameter is the sun's disk half-angle in degrees, linked to the
    374 apparent size of the sun.
    375 A typical
    376 .Em half_angle
    377 is 0.2664.
    378 .It Em gaussian
    379 The
    380 .Em gaussian
    381 distribution defines a Gaussian distribution of the solar incoming
    382 direction.
    383 Its single
    384 .Em std_dev
    385 parameter is the standard deviation of the distribution in degrees.
    386 Values around 0.2 are typical.
    387 As the Gaussian distribution is not truncated, the resulting sun vector
    388 can theoretically be oriented away from the sun, especially with a
    389 large, non-typical
    390 .Em std_dev
    391 value.
    392 .It Em buie
    393 The
    394 .Em buie
    395 distribution
    396 .Po
    397 see the
    398 .Sx NOTES
    399 section, reference 3
    400 .Pc .
    401 Its single
    402 .Em csr
    403 parameter is the ratio between the circumsolar irradiance and the sum
    404 of the circumsolar and sun's disk irradiance.
    405 An analysis of typical
    406 .Em csr
    407 values can be found in reference 4
    408 .Po see the
    409 .Sx NOTES
    410 section
    411 .Pc .
    412 .El
    413 .Sh ATMOSPHERE
    414 The
    415 .Em atmosphere ,
    416 when provided, describes the medium surrounding the solar plant.
    417 Its only parameter is its extinction coefficient in m⁻¹,
    418 which can either be a scalar if the extinction is constant over the
    419 spectrum, or can be spectrally described.
    420 The extinction along light paths is only computed after the first
    421 reflector, as the sun description must include all atmospheric effects
    422 before the first reflector (see
    423 .Sx SUN
    424 section for more details).
    425 .Pp
    426 If no atmosphere is provided, atmospheric extinction after the first
    427 reflector is not taken into account.
    428 .Sh MATERIAL
    429 A
    430 .Em material
    431 describes the properties of an interface.
    432 These properties can be the same for both sides of the interface or may
    433 be differentiated with a
    434 .Em double-sided-mtl .
    435 The material behaviour is controlled by a
    436 .Em material-descriptor
    437 that specifies the physical properties of the interface as well as its
    438 optional normal perturbation.
    439 Note that the physical properties can be either scalars or spectral data.
    440 .Ss Material descriptors
    441 The available material descriptors are:
    442 .Bl -tag -width Ds
    443 .It Em dielectric
    444 Interface between two dielectric media.
    445 Its
    446 .Em medium_i
    447 parameter defines the current medium (the medium the ray travels in),
    448 while
    449 .Em medium_t
    450 represents the opposite medium.
    451 Incoming rays are either specularly reflected or refracted according to
    452 a Fresnel term:
    453 .Bd -literal -offset indent
    454 Fr = 1/2 * (Rs^2 + Rp^2)
    455 .Ed
    456 .Pp
    457 with Rs and Rp the reflectance for light polarized with its electric
    458 field perpendicular or parallel to the plane of incidence, respectively:
    459 .Bd -literal -offset indent
    460 Rs = (n1 * |wi.N| - n2 * |wt.N|) / (n1 * |wi.N| + n2 * |wt.N|)
    461 Rp = (n2 * |wi.N| - n1 * |wt.N|) / (n2 * |wi.N| + n1 * |wt.N|)
    462 .Ed
    463 .Pp
    464 with n1 and n2 the indices of refraction of the incident and transmitted
    465 media, and wi and wt the incident and transmitted direction.
    466 .Pp
    467 Be careful to ensure media consistency in the
    468 .Nm
    469 file: a ray travelling in a medium
    470 .Em A
    471 can only encounter a medium interface whose
    472 .Em medium_i
    473 attribute is
    474 .Em A .
    475 Consequently, a
    476 .Em dielectric
    477 material must be defined as a double-sided material whose front and back
    478 interfaces are dielectrics with inverted media:
    479 .Bd -literal -offset indent
    480 material:
    481   front:
    482     dielectric:
    483       medium_i: &vacuum { refractive_index: 1, extinction: 0 }
    484       medium_t: &glass { refractive_index: 1.5, extinction: 20 }
    485   back:
    486     dielectric:
    487       medium_i: *glass
    488       medium_t: *vacuum
    489 .Ed
    490 .Pp
    491 If media consistency is not ensured,
    492 .Xr solstice 1
    493 will fail to run simulations.
    494 Note that by default, the surrounding medium is assumed to be vacuum,
    495 i.e.\& its refractive index and extinction are scalars with values 1 and
    496 0, respectively.
    497 If an atmosphere is defined, the refractive index of the surrounding
    498 medium is still the scalar 1 but its extinction is that of the
    499 atmosphere.
    500 .It Em matte
    501 Diffuse surface.
    502 Reflects the same intensity in all directions independently of the
    503 incoming direction.
    504 .It Em mirror
    505 Specular or glossy reflection, depending on whether the
    506 .Em slope_error
    507 parameter is 0 or not.
    508 Glossy reflections are controlled by a microfacet BRDF.
    509 The microfacet normals are distributed according to the Beckmann or
    510 Pillbox distribution, as specified by the
    511 .Em normal-distrib
    512 attribute.
    513 .Pp
    514 Let S be the
    515 .Em slope_error
    516 parameter in ]0,\ 1].
    517 The Beckmann distribution is defined as:
    518 .Bd -literal -offset indent
    519 D(wh) = exp(-tan^2(a) / m^2) / (PI * m^2 * cos^4(a))
    520 .Ed
    521 .Pp
    522 with a = arccos(wh.N) and m = sqrt(2)*S, while the Pillbox distribution
    523 is defined as:
    524 .Bd -literal -offset indent
    525         | 0;                         if |wh.N| >= S
    526 D(wh) = |
    527         | 1 / (PI * (1 - cos^2(S))); if |wh.N| < S
    528 .Ed
    529 .It Em thin-dielectric
    530 The interface is assumed to be a thin slab of a dielectric material.
    531 The
    532 .Em medium_i
    533 parameter defines the outside dielectric medium while
    534 .Em medium_t
    535 is the medium of the thin slab.
    536 Incoming rays are either specularly reflected or transmitted (without
    537 deviation) according to a Fresnel term (see
    538 .Em dielectric
    539 above for the formula).
    540 The underlying scattering function correctly handles the multiple
    541 refraction effects within the thin slab.
    542 .Pp
    543 The same media consistency rules as for
    544 .Em dielectric
    545 apply: if not ensured,
    546 .Xr solstice 1
    547 will fail to run simulations.
    548 By default, the surrounding medium is vacuum (refractive index 1,
    549 extinction 0).
    550 If an atmosphere is defined, the refractive index of the surrounding
    551 medium is still 1, but its extinction is that of the atmosphere.
    552 .It Em virtual
    553 Fully transparent interface.
    554 .El
    555 .Ss Normal map
    556 All material descriptors except
    557 .Em virtual
    558 provide an optional
    559 .Em normal-map
    560 attribute that defines a path to a Portable PixMap image
    561 .Po
    562 see the
    563 .Sx NOTES ,
    564 section, reference 5
    565 .Pc
    566 whose pixels store a normal expressed in the tangent space of the
    567 interface.
    568 By default, the unperturbed tangent space normal is {0,0,1}.
    569 The PPM image can be encoded on 8 or 16 bits per component either in
    570 ASCII or binary.
    571 The parameterization of this 2D image onto the shape surfaces depends
    572 on the type of shape.
    573 For the
    574 .Em hemisphere , hyperbol , parabol , plane
    575 and
    576 .Em parabolic-cylinder
    577 shapes, the image is mapped in the {X,Y} plane.
    578 Other shapes are not parameterized; applying a normal-mapped material to
    579 them leads to undefined behaviour.
    580 .Sh SHAPE
    581 A
    582 .Em shape
    583 describes a geometric model defined in its local coordinate system,
    584 whose origin is proper to the shape.
    585 No spatial transformation can be introduced through the declaration of
    586 a shape: it should be transformed externally through an
    587 .Em object
    588 and/or
    589 .Em entity .
    590 .Pp
    591 Two types of shape are provided: quadric and mesh.
    592 The former is used to declare parametric surfaces; the latter describes
    593 triangulated surfaces.
    594 .Ss Quadric
    595 A quadric shape is defined from a quadric equation and a set of 2D
    596 clipping operations performed in its {X,Y} plane.
    597 By convention, the front side of the quadric surface looks toward the
    598 positive Z axis.
    599 Internally, the clipped quadric surface is discretized into a triangular
    600 mesh according to the quadric's discretization parameters.
    601 This mesh is used by
    602 .Xr solstice 1
    603 as a proxy to speed up access to the quadric shape; the exact position
    604 and normal are ultimately computed from the quadric equation.
    605 .Pp
    606 The quadric surface is parameterized in the {X,Y} plane:
    607 .Bd -literal -offset indent
    608 u = (x - lowerX) / (upperX - lowerX)
    609 v = (y - lowerY) / (upperY - lowerY)
    610 .Ed
    611 .Pp
    612 with
    613 .Em u
    614 and
    615 .Em v
    616 the mapped 2D coordinates from a 3D position {x,y,z} onto the quadric,
    617 and
    618 .Em lower Ns <X|Y>
    619 and
    620 .Em upper Ns <X|Y>
    621 the lower and upper bounds of the clipped quadric along the X and Y
    622 axes.
    623 The available quadrics are:
    624 .Bl -tag -width Ds
    625 .It Em hemisphere
    626 Hemispheric shape defined along the Z axis whose minimum is at the
    627 origin.
    628 The
    629 .Em slices
    630 parameter controls the number of divisions along the Z axis.
    631 .Bd -literal -offset indent
    632 x^2 + y^2 + (z-radius)^2 = radius^2
    633 .Ed
    634 .It Em hyperbol
    635 Hyperbolic quadric defined along the Z axis whose minimum is at the
    636 origin.
    637 The
    638 .Em slices
    639 parameter controls the discretization of the hyperbol.
    640 If not defined, it is automatically computed from the hyperbol
    641 curvature.
    642 .Bd -literal -offset indent
    643 (x^2 + y^2) / a^2 - (z + z0 - g/2)^2 / b^2 + 1 = 0
    644 
    645 a^2 = g^2(f - f^2)
    646 b = g(f - 1/2)
    647 z0 = |b| + g/2
    648 g = focals.real + focals.image
    649 f = focals.real / g
    650 .Ed
    651 .It Em parabol
    652 Parabolic quadric defined along the Z axis whose minimum is at the
    653 origin.
    654 The
    655 .Em slices
    656 parameter controls the discretization of the parabol.
    657 If not defined, it is automatically computed from the parabol curvature.
    658 .Bd -literal -offset indent
    659 x^2 + y^2 - 4 * focal * z = 0
    660 .Ed
    661 .It Em parabolic-cylinder
    662 Parabolic cylinder oriented along the Z axis, with its main axis along
    663 the X axis and minimum at the origin.
    664 The
    665 .Em slices
    666 parameter controls the discretization.
    667 If not defined, it is automatically computed from the curvature.
    668 .Bd -literal -offset indent
    669 y^2 - 4 * focal * z = 0
    670 .Ed
    671 .It Em plane
    672 Plane whose normal points along the positive Z axis.
    673 The
    674 .Em slices
    675 attribute controls the discretization of the clipped plane.
    676 .El
    677 .Ss Clipping
    678 A clipping operation, or
    679 .Em polyclip ,
    680 removes parts of the quadric surface.
    681 It is defined by a 2D
    682 .Em contour-descriptor
    683 expressed in the {X,Y} plane and a clipping
    684 .Em operation .
    685 The
    686 .Em AND
    687 operand retains the portion of the quadric that intersects the
    688 contour; the
    689 .Em SUB
    690 operand removes the portion that intersects the contour.
    691 The available contour descriptors are:
    692 .Bl -tag -width Ds
    693 .It Em circle-descriptor
    694 Circular contour whose size is defined by the
    695 .Em radius
    696 parameter.
    697 .Xr solstice 1
    698 discretizes the circular contour using the
    699 .Em segments
    700 attribute as the number of segments used to approximate the circle.
    701 .It Em vertices-descriptor
    702 Polygonal contour described by a list of 2D vertices.
    703 Polygon edges connect each vertex to its predecessor; an additional
    704 edge automatically closes the polygon between the last and first vertex.
    705 Note that
    706 .Xr solstice 1
    707 assumes the polygon does not self-intersect.
    708 .El
    709 .Pp
    710 The
    711 .Em clip
    712 parameter of a quadric lists a set of
    713 .Em polyclips
    714 applied successively in declaration order.
    715 For example, the following uses 5 clipping operations on a plane to
    716 build a rectangle with a circular hole at each corner:
    717 .Bd -literal -offset indent
    718 plane:
    719   clip:
    720   - {operation: AND, vertices: [[-4,-2],[-4,2],[4,2],[4,-2]]}
    721   - {operation: SUB, circle: {radius: 0.5, center: [-3,-1]}}
    722   - {operation: SUB, circle: {radius: 0.5, center: [-3, 1]}}
    723   - {operation: SUB, circle: {radius: 0.5, center: [ 3,-1]}}
    724   - {operation: SUB, circle: {radius: 0.5, center: [ 3, 1]}}
    725 .Ed
    726 .Ss Triangular mesh
    727 Triangular meshes are generated by
    728 .Xr solstice 1
    729 from a shape description or loaded from a CAO file.
    730 Their normals are defined per triangle and are thus discontinuous even
    731 for smooth shapes.
    732 Triangular meshes are not parameterized; applying a normal-mapped
    733 material to them produces undefined behaviour.
    734 The available triangular meshes are:
    735 .Bl -tag -width Ds
    736 .It Em cuboid
    737 Axis-aligned cuboid centered at the origin, whose corner positions and
    738 dimensions along the three axes are defined by the
    739 .Em size
    740 parameter.
    741 The front side of the surface looks outside the cuboid.
    742 .It Em cylinder
    743 Cylinder centered at the origin whose
    744 .Em height
    745 is along the positive Z axis.
    746 Top and bottom are capped.
    747 The
    748 .Em stacks
    749 and
    750 .Em slices
    751 parameters control the number of divisions along and around the Z axis,
    752 respectively.
    753 The front side looks outside the cylinder.
    754 .It Em sphere
    755 Triangulated sphere centered at the origin.
    756 The
    757 .Em stacks
    758 and
    759 .Em slices
    760 parameters control the number of divisions along and around the Z axis,
    761 respectively.
    762 The front side looks outside the sphere.
    763 .It Em stl
    764 Path to an external mesh file in ASCII
    765 .Em ST Ns ereo Ns Em L Ns ithography
    766 (STL) format.
    767 The front side of each triangle is determined by the vertex ordering in
    768 the STL file: a triangle is front-facing when its vertices are
    769 clockwise-ordered.
    770 .El
    771 .Sh ENTITY
    772 An
    773 .Em entity
    774 is used to declare and position shapes in the solar plant.
    775 An entity is the only item that effectively instantiates a
    776 .Em geometry
    777 into the solar plant: a geometry declared but not referenced by an
    778 entity is ignored by
    779 .Xr solstice 1 .
    780 An entity is a hierarchical data structure whose child entities'
    781 transformation is relative to their parent.
    782 If not defined, the
    783 .Em transform
    784 of an entity is the identity (null rotation and translation).
    785 .Pp
    786 Each entity has a
    787 .Em name
    788 which must be unique per hierarchy level.
    789 The name string cannot contain dots, spaces or tabulations.
    790 A child entity is identified in the solar plant by concatenating, with
    791 the
    792 .Sq .\&
    793 character, the names of its ancestors with its own name.
    794 For instance, the identifier of a child entity named
    795 .Em level2
    796 is
    797 .Em level0.level1.level2 :
    798 .Bd -literal -offset indent
    799 entity:
    800   name: level0
    801   child:
    802   - name: level1
    803     child:
    804     - name: level2
    805 .Ed
    806 .Pp
    807 An entity encapsulates either a
    808 .Em geometry
    809 (a collection of
    810 .Em objects )
    811 or a
    812 .Em pivot .
    813 Each entity can also have a list of
    814 .Em anchors
    815 defining positions relative to the entity.
    816 .Pp
    817 For a geometric entity, one must specify whether the encapsulated
    818 geometry is a
    819 .Em primary
    820 geometry (i.e.\& directly lit by the sun and used to concentrate solar
    821 flux, such as a primary mirror).
    822 Correctly tagging primary geometries drastically improves the
    823 convergence speed of
    824 .Xr solstice 1
    825 simulations.
    826 .Ss Template
    827 A
    828 .Em template
    829 is a first-level entity with no existence in the solar plant itself.
    830 It is used to pre-declare an entity hierarchy that can then be
    831 instantiated multiple times by referencing it through common entities
    832 with YAML data tagging:
    833 .Bd -literal -offset indent
    834 - template: &my-template
    835     name: bar
    836     primary: 1
    837     geometry: ...
    838 - entity:
    839     name: foo0
    840     transform: {translation: [-10.5, 0, 0]}
    841     children: [*my-template]
    842 - entity:
    843     name: foo1
    844     transform: {translation: [0, 0, 0]}
    845     children: [*my-template]
    846 - entity:
    847     name: foo2
    848     transform: {translation: [10.5, 0, 0]}
    849     children: [*my-template]
    850 .Ed
    851 .Ss Pivot
    852 A
    853 .Em pivot
    854 is a special kind of node that automatically orients its child geometry
    855 according to the sun position and pivot parameters.
    856 It is typically (but not mandatorily) the parent of a reflector that,
    857 once pivoted, will redirect sun light toward a
    858 .Em target .
    859 A pivot cannot be the child of another pivot.
    860 .Pp
    861 The
    862 .Em target
    863 parameter is the most important pivot parameter.
    864 Four types of target are available:
    865 .Bl -tag -width Ds
    866 .It Em position
    867 The target is an absolute point in world coordinates.
    868 .It Em anchor
    869 The target is a position relative to an entity
    870 .Po
    871 see the
    872 .Sx ANCHOR
    873 section
    874 .Pc .
    875 .It Em sun
    876 The target is the center of the sun.
    877 .It Em direction
    878 The pivot reflects light in the given direction, specified in world
    879 coordinates.
    880 .El
    881 .Pp
    882 Pivots can also have an optional
    883 .Em ref_point
    884 parameter defining a 3D point in the coordinate system of the pivot's
    885 children that is used by the pointing algorithm.
    886 If not provided, it defaults to the origin.
    887 .Pp
    888 Two flavours of pivot are available:
    889 .Bl -tag -width Ds
    890 .It Em x_pivot
    891 Single-axis pivot rotating around the +X axis in its local coordinate
    892 system.
    893 Its pointing algorithm considers an incoming ray from the center of the
    894 sun and rotates its children so that a specular reflection at
    895 .Em ref_point
    896 using +Z as the local normal hits the target, or produces the specified
    897 direction.
    898 .It Em zx_pivot
    899 Two-axis pivot: first a rotation around the +Z axis in its local
    900 coordinate system, then a rotation around the +X axis in the resulting
    901 coordinate system.
    902 The optional
    903 .Em spacing
    904 parameter defines a translation along the +Y axis applied after the
    905 first rotation (default: 0).
    906 Its pointing algorithm considers an incoming ray from the center of the
    907 sun and rotates its children so that a specular reflection at
    908 .Em ref_point
    909 using +Y as the local normal hits the target, or produces the specified
    910 direction.
    911 .El
    912 .Ss Anchor
    913 An
    914 .Em anchor
    915 defines a relative position in the entity hierarchy.
    916 Anchors are particularly useful for pivots and hyperbolic shapes that
    917 must reference a position relative to an entity whose transformation may
    918 depend on its ancestors.
    919 An anchor's
    920 .Em name
    921 must be unique among all anchors in its entity and cannot contain dots,
    922 spaces or tabulations.
    923 An anchor is identified in the solar plant by concatenating its name to
    924 the
    925 .Em entity-identifier
    926 of the entity in which it is declared, using
    927 .Sq .\&
    928 as separator.
    929 For example, the identifier of an anchor named
    930 .Em anchor0
    931 declared in
    932 .Em level0.level1
    933 is
    934 .Em level0.level1.anchor0 .
    935 .Pp
    936 When the root entity name of a template is unknown (because the template
    937 has not yet been instantiated), the
    938 .Em self
    939 reserved keyword can be used to reference the unknown root entity.
    940 For example:
    941 .Bd -literal -offset indent
    942 - template: &my-template
    943     name: level0
    944     anchor: [{name: anchor0, position: [1, 2, 3]}]
    945     child:
    946     - name: level1
    947       pivot:
    948         x_pivot:
    949           ref_point: {0, 0, 0}
    950           target: {anchor: self.level0.anchor0}
    951 
    952 - entity: {name: entity0, child: [*my-template]}
    953 - entity: {name: entity1, child: [*my-template]}
    954 .Ed
    955 .Ss Transform
    956 A
    957 .Em transform
    958 moves an
    959 .Em object
    960 or an
    961 .Em entity
    962 in space.
    963 The
    964 .Em rotation
    965 parameter lists 3 angles in degrees defining rotations around the X, Y
    966 and Z axes.
    967 The
    968 .Em translation
    969 attribute describes offsets along the X, Y and Z axes.
    970 Given a local frame
    971 .Em p
    972 of an object,
    973 .Em p
    974 is transformed into
    975 .Em p'
    976 as:
    977 .Bd -literal -offset indent
    978 p' = Rx * Ry * Rz * (T + p)
    979 .Ed
    980 .Pp
    981 with
    982 .Em T
    983 the translation vector and
    984 .Em Rx , Ry , Rz
    985 the rotation matrices around the X, Y and Z axes:
    986 .Bd -literal -offset indent
    987      | 1  0   0 |        | cY  0 sY |        | cZ -sZ  0 |
    988 Rx = | 0 cX -sX |;  Ry = |  0  1  0 |;  Rz = | sZ  cZ  0 |
    989      | 0 sX  cX |        |-sY  0 cY |        |  0   0  1 |
    990 .Ed
    991 .Pp
    992 where
    993 .Em c Ns <X|Y|Z>
    994 and
    995 .Em s Ns <X|Y|Z>
    996 are the cosine and sine of the rotation angles around the X, Y and Z
    997 axes, respectively.
    998 .Sh EXAMPLES
    999 Declare 2 entities and a point-source sun.
   1000 The first entity is a purely specular square of size 10 centered at the
   1001 origin.
   1002 The second is a purely transparent square used as a receiver; its size
   1003 is 1 and its center is at {0,0,2}:
   1004 .Bd -literal -offset indent
   1005 - sun: {dni: 1000}
   1006 
   1007 - entity:
   1008     name: reflector
   1009     primary: 1
   1010     geometry:
   1011     - material:
   1012         mirror:
   1013           reflectivity: 1
   1014           slope_error: 0
   1015       plane:
   1016         clip:
   1017         - operation: AND
   1018           vertices:
   1019           - [-5.0,-5.0]
   1020           - [-5.0, 5.0]
   1021           - [ 5.0, 5.0]
   1022           - [ 5.0,-5.0]
   1023 
   1024 - entity:
   1025     name: receiver
   1026     primary: 0
   1027     transform:
   1028       translation: [0, 0, 2]
   1029     geometry:
   1030     - material:
   1031         virtual: # No attrib
   1032       plane:
   1033         clip:
   1034         - operation: AND
   1035           vertices:
   1036           - [-0.5,-0.5]
   1037           - [-0.5, 0.5]
   1038           - [ 0.5, 0.5]
   1039           - [ 0.5,-0.5]
   1040 .Ed
   1041 .Pp
   1042 Define a circular diffuse reflector surrounded by a virtual sphere, with
   1043 a pillbox-shaped sun of
   1044 .Em half_angle
   1045 0.1 degree.
   1046 Use anchors and YAML tags to reference a pre-declared geometry, and the
   1047 YAML compact notation to reduce the number of lines:
   1048 .Bd -literal -offset indent
   1049 - sun: {dni: 1000, pillbox: {half_angle: 0.1}}
   1050 
   1051 - geometry: &small-circle
   1052   - material: {matte: {reflectivity: 1}}
   1053     plane: {clip: [{operation: AND, circle: {radius: 0.5}}]}
   1054 
   1055 - geometry: &big-sphere
   1056   - material: {virtual: ""}
   1057     sphere: {radius: 2, slices: 128}
   1058 
   1059 - entity: {name: reflector, primary: 1, geometry: *small-circle}
   1060 - entity: {name: receiver,  primary: 0, geometry: *big-sphere}
   1061 .Ed
   1062 .Pp
   1063 Declare 2 parabolic reflectors from a templated parabola whose
   1064 orientation is controlled by a
   1065 .Em zx_pivot
   1066 targeting an anchor defined relative to the receiver:
   1067 .Bd -literal -offset indent
   1068 - sun: {dni: 1000}
   1069 
   1070 - entity: # Receiver
   1071     name: square_receiver
   1072     primary: 0
   1073     transform: { rotation: [0,90,0], translation: [100,0,10] }
   1074     anchors: [{name: anchor0, position: [0,0,0]}]
   1075     geometry:
   1076     - material: {virtual: ""}
   1077       plane:
   1078         clip:
   1079         - operation: AND
   1080           vertices: [[-.5,-.5],[-.5,.5],[.5,.5],[.5,-.5]]
   1081 
   1082 - template: &self_oriented_parabol # Reflector
   1083     name: pivot
   1084     transform: {translation: [0, 0, 4], rotation: [0, 0, 90]}
   1085     zx_pivot: {target: {anchor: square_receiver.anchor0}}
   1086     children:
   1087     - name: parabol
   1088       transform: {rotation: [-90, 0, 0]}
   1089       primary: 1
   1090       geometry:
   1091       - material: {mirror: {reflectivity: 1, slope_error: 0}}
   1092         parabol:
   1093           focal: 100
   1094           clip:
   1095           - operation: AND
   1096             vertices: [[-5,-5],[-5,5],[5,5],[5,-5]]
   1097 
   1098 # Instantiate the reflector template
   1099 - entity:
   1100     name: reflector1
   1101     transform: {translation: [0,0,0]}
   1102     children: [*self_oriented_parabol]
   1103 - entity:
   1104     name: reflector2
   1105     transform: {translation: [10,43.6,0]}
   1106     children: [*self_oriented_parabol]
   1107 .Ed
   1108 .Pp
   1109 Declare a solar furnace with 9 heliostats instantiated from the same
   1110 template.
   1111 Their position is controlled by a
   1112 .Em zx_pivot
   1113 to ensure that incoming sun rays are reflected toward the negative X
   1114 axis.
   1115 Reflected rays are then concentrated by a parabola toward a purely
   1116 absorptive receiver.
   1117 The heliostats and the parabola share the same double-sided material:
   1118 front faces are purely specular, back faces are diffuse:
   1119 .Bd -literal -offset indent
   1120 - sun: {dni: 1000}
   1121 
   1122 - material: &specular
   1123     front: {mirror: {reflectivity: 1, slope_error: 0}}
   1124     back: {matte: {reflectivity: 1}}
   1125 
   1126 - template: &H # Template of a heliostat
   1127     name: heliostat
   1128     transform: {translation: [0,0,5.5]}
   1129     zx_pivot: {target: {direction: [-1,0,0]}}
   1130     children:
   1131     - name: reflector
   1132       transform: {rotation: [-90,0,0]}
   1133       primary: 1
   1134       geometry:
   1135       - material: *specular
   1136         plane:
   1137           clip: [{operation: AND, vertices: [[-5,-5],[-5,5],[5,5],[5,-5]]}]
   1138 
   1139 - entity: # Receiver entity
   1140     name: receiver
   1141     primary: 0
   1142     transform: {translation: [18,0,20], rotation: [0,90,0]}
   1143     geometry:
   1144     - material: {matte: {reflectivity: 0}}
   1145       plane:
   1146         clip:
   1147         - operation: AND
   1148           vertices: [[-.5,-.5],[-.5,.5],[.5,.5],[.5,-.5]]
   1149 
   1150 - entity: # Great parabola
   1151     name: parabola
   1152     primary: 0
   1153     transform: {translation: [0,0,20], rotation: [0,90,90]}
   1154     geometry:
   1155     - material: *specular
   1156       parabol:
   1157         focal: 18
   1158         clip: [{operation: AND, vertices: [[-30,-20],[-30,20],[30,20],[30,-20]]}]
   1159 
   1160 # Instantiate the heliostat template
   1161 - entity: {name: H1, children: [*H], transform: {translation: [40,-20, 0]}}
   1162 - entity: {name: H2, children: [*H], transform: {translation: [40,  0, 0]}}
   1163 - entity: {name: H3, children: [*H], transform: {translation: [40, 20, 0]}}
   1164 - entity: {name: H4, children: [*H], transform: {translation: [60,-20,10]}}
   1165 - entity: {name: H5, children: [*H], transform: {translation: [60,  0,10]}}
   1166 - entity: {name: H6, children: [*H], transform: {translation: [60, 20,10]}}
   1167 - entity: {name: H7, children: [*H], transform: {translation: [80,-20,20]}}
   1168 - entity: {name: H8, children: [*H], transform: {translation: [80, 0, 20]}}
   1169 - entity: {name: H9, children: [*H], transform: {translation: [80, 20,20]}}
   1170 .Ed
   1171 .Pp
   1172 Three partial parabols with various focal distances concentrate incoming
   1173 radiation at a common focal position.
   1174 A hyperbol is located between the parabols and their common focal, which
   1175 is also one of the two focals of the hyperbol.
   1176 Radiation is redirected to the second focal of the hyperbol where the
   1177 square target is located.
   1178 A cuboid using a glass material is located between the hyperbol and the
   1179 target.
   1180 This example also illustrates the use of
   1181 .Em spectrum
   1182 for refractive index and extinction:
   1183 .Bd -literal -offset indent
   1184 # Spectra
   1185 - spectrum: &solar_spectrum
   1186   - {wavelength: 0.3, data: 1.0}
   1187   - {wavelength: 0.4, data: 2.0}
   1188   - {wavelength: 0.5, data: 0.5}
   1189   - {wavelength: 0.6, data: 3.5}
   1190   - {wavelength: 0.7, data: 1.5}
   1191   - {wavelength: 0.8, data: 0.8}
   1192 
   1193 - spectrum: &air_kabs
   1194   - {wavelength: 0.3, data: 1.0e-4}
   1195   - {wavelength: 0.4, data: 1.0e-5}
   1196   - {wavelength: 0.5, data: 2.0e-5}
   1197   - {wavelength: 0.6, data: 2.0e-4}
   1198   - {wavelength: 0.7, data: 3.0e-5}
   1199   - {wavelength: 0.8, data: 1.0e-4}
   1200 
   1201 - spectrum: &glass_kabs
   1202   - {wavelength: 0.3, data: 1.0e-2}
   1203   - {wavelength: 0.4, data: 1.0e-3}
   1204   - {wavelength: 0.5, data: 2.0e-3}
   1205   - {wavelength: 0.6, data: 2.0e-2}
   1206   - {wavelength: 0.7, data: 3.0e-3}
   1207   - {wavelength: 0.8, data: 1.0e-3}
   1208 
   1209 - spectrum: &glass_ref_index
   1210   - {wavelength: 0.30, data: 1.40}
   1211   - {wavelength: 0.40, data: 1.39}
   1212   - {wavelength: 0.50, data: 1.37}
   1213   - {wavelength: 0.60, data: 1.34}
   1214   - {wavelength: 0.70, data: 1.30}
   1215   - {wavelength: 0.80, data: 1.25}
   1216 
   1217 # Media
   1218 - medium: &air_medium
   1219     refractive_index: 1
   1220     extinction: *air_kabs
   1221 
   1222 - medium: &glass_medium
   1223     refractive_index: *glass_ref_index
   1224     extinction: *glass_kabs
   1225 
   1226 # Sun & atmosphere
   1227 - sun: {dni: 1, spectrum: *solar_spectrum}
   1228 - atmosphere: {extinction: *air_kabs}
   1229 
   1230 # Materials
   1231 - material: &specular {mirror: {reflectivity: 1, slope_error: 0}}
   1232 - material: &black {matte: {reflectivity: 0}}
   1233 - material: &glass
   1234     front: {dielectric: {medium_i: *air_medium, medium_t: *glass_medium}}
   1235     back:  {dielectric: {medium_i: *glass_medium, medium_t: *air_medium}}
   1236 
   1237 # Primary reflectors
   1238 - entity:
   1239     name: "primary_reflector1"
   1240     primary: 1
   1241     transform: {translation: [0, 0, -2.0]}
   1242     geometry:
   1243     - material: *specular
   1244       parabol:
   1245         focal: 12
   1246         clip:
   1247         - {operation: AND, circle: {radius: 10}}
   1248         - {operation: SUB, circle: {radius: 5}}
   1249 
   1250 - entity:
   1251     name: "primary_reflector2"
   1252     primary: 1
   1253     transform: {translation: [0, 0, -4]}
   1254     geometry:
   1255     - material: *specular
   1256       parabol:
   1257         focal: 14
   1258         clip:
   1259         - {operation: AND, circle: {radius: 15}}
   1260         - {operation: SUB, circle: {radius: 10}}
   1261 
   1262 - entity:
   1263     name: "primary_reflector3"
   1264     primary: 1
   1265     transform: {translation: [0, 0, -6]}
   1266     geometry:
   1267     - material: *specular
   1268       parabol:
   1269         focal: 16
   1270         clip:
   1271         - {operation: AND, circle: {radius: 20}}
   1272         - {operation: SUB, circle: {radius: 15}}
   1273 
   1274 # Secondary reflector
   1275 - entity:
   1276     name: "secondary_reflector"
   1277     primary: 0
   1278     transform: {translation: [0, 0, 6]}
   1279     geometry:
   1280     - material: *specular
   1281       hyperbol:
   1282         focals: {real: 16.0, image: 4}
   1283         clip: [{operation: AND, circle: {radius: 5}}]
   1284 
   1285 # Glass box
   1286 - entity:
   1287     name: "glass_slide"
   1288     primary: 0
   1289     geometry:
   1290     - material: *glass
   1291       cuboid: {size: [10,10,0.5]}
   1292       transform: {translation: [0, 0, 0.25]}
   1293 
   1294 # Receiver
   1295 - entity:
   1296     name: "square_receiver"
   1297     primary: 0
   1298     transform: {translation: [0, 0, -10] }
   1299     geometry:
   1300     - material: *black
   1301       plane:
   1302         clip:
   1303         - operation: AND
   1304           vertices: [[-0.5,-0.5],[-0.5,0.5],[0.5,0.5],[0.5,-0.5]]
   1305 .Ed
   1306 .Sh NOTES
   1307 .Bl -enum
   1308 .It
   1309 YAML Ain't Markup Language \(em
   1310 .Lk http://yaml.org
   1311 .It
   1312 SMARTS, Simple Model of the Atmospheric Radiative Transfer of Sunshine \(em
   1313 .Lk http://www.nrel.gov/rredc/smarts/
   1314 .It
   1315 D.\& Buie, A.G.\& Monger, C.J.\& Dey.
   1316 .Dq Sunshape distributions for terrestrial solar simulations .
   1317 .Em Solar Energy ,
   1318 2003, 74, pp.\& 113\(en122.
   1319 .It
   1320 D.\& Buie, C.J.\& Dey, S.\& Bosi.
   1321 .Dq The effective size of the solar cone for solar concentrating systems .
   1322 .Em Solar Energy ,
   1323 2003, 74, pp.\& 417\(en427.
   1324 .It
   1325 Portable PixMap \(em
   1326 .Lk http://netpbm.sourceforge.net/doc/ppm.html
   1327 .El
   1328 .Sh SEE ALSO
   1329 .Xr solstice 1 ,
   1330 .Xr solstice-receiver 5
   1331 .Sh HISTORY
   1332 .Nm
   1333 was initially developed with funding from the
   1334 .Em SOLSTICE LabEx
   1335 .Pq Laboratory of Excellence ,
   1336 in collaboration with the PROMES Laboratory of the
   1337 French National Centre for Scientific Research
   1338 .Pq CNRS .
   1339 Starting in 2026, a new development effort funded by Ademe is ongoing.