| SOLSTICE-INPUT(5) | File Formats Manual | SOLSTICE-INPUT(5) |
NAME
solstice-input —
solar plant description for solstice
DESCRIPTION
The solstice-input format is used by the
solstice(1) program to
represent a solar plant. It relies on the YAML 1.1 data serialization
standard (see the NOTES section, reference
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]
slope_error: <mtl-data>
[ microfacet: <normal-distrib> ] # Default is BECKMANN
[ <normal-map> ]
<normal-distrib> ::= BECKMANN
| PILLBOX
<virtual> ::= virtual: EMPTY-STRING
<thin-dielectric> ::= thin_dielectric:
thickness: REAL # in [0, INF)
medium_i: <medium-descriptor>
medium_t: <medium-descriptor>
[ <normal-map> ]
<normal-map> ::= normal_map:
path: PATH
<medium> ::= medium: <medium-descriptor>
<medium-descriptor> ::= refractive_index: <mtl-data> # in ]0, INF)
extinction: <mtl-data> # in [0, INF)
<entity> ::= entity: <entity-data>
<template> ::= template: <entity-data>
<entity-data> ::= name: STRING
[ <geometry-data> | <x_pivot> | <zx_pivot> ]
[ <anchors> ]
[ <transform> ]
[ <children> ]
<geometry-data> ::= primary: INTEGER # in [0, 1]
<geometry>
<children> ::= children:
- <entity-data>
[ - <entity-data> ... ]
<anchors> ::= anchors:
- <anchor-data>
[ - <anchor-data> ... ]
<anchor-data> ::= name: STRING
<position-descriptor>
<position-descriptor> ::= position: <real3>
| hyperboloid_image_focals: <hyperboloid_focals>
<entity-identifier> ::= <self|STRING>[.STRING ... ]
<anchor-identifier> ::= <entity-identifier>.STRING
<sun> ::= sun:
dni: REAL # Direct Normal Irradiance in ]0, INF)
[ <spectrum> ] # Default is the smarts295 spectrum
[ <sun-shape> ]
<sun-shape> ::= <pillbox> | <gaussian> | <buie>
<buie> ::= buie:
csr: REAL # in [1e-6, 0.849]
<pillbox> ::= pillbox:
half_angle: REAL # in ]0, 90]
<gaussian> ::= gaussian:
std_dev: REAL # in ]0, INF)
<atmosphere> ::= atmosphere:
extinction: <mtl-data> # in [0, 1]
<mtl-data> ::= REAL
| <spectrum-data-list>
<transform> ::= transform:
translation: <real3>
rotation: <real3>
<real2> ::= - REAL
- REAL
<real3> ::= - REAL
- REAL
- REAL
<spectrum> ::= spectrum: <spectrum-data-list>
<spectrum-data-list> ::= - <spectrum-data>
[ - <spectrum-data> ... ]
<spectrum-data> ::= wavelength: REAL # in [0, INF)
data: REAL # in [0, INF)
SUN
The sun describes the source of the solar plant.
Its direction is not defined in the solstice-input
file but is provided by the
solstice(1) command. This
allows the same unmodified solstice-input file to be
used for several simulations with different sun directions.
The main sun property is its direct normal irradiance, or dni in W/m². Its value is a scalar defining the direct irradiance received on a plane perpendicular to the main sun direction. The optional spectrum parameter describes the per-wavelength distribution of the sun dni. Note that this distribution is automatically normalized by solstice(1). If the spectrum attribute is not defined, solstice(1) uses a default spectrum computed with the SMARTS software (see the NOTES section, reference 2) between 0.28 and 4 micrometres. The total dni (integrated over the spectral range) was set to 1000 W/m². The standard Mid-Latitude-Summer atmosphere was used with most gas concentrations set as default (CO2 concentration assumed 400 ppmv).
Even if an atmosphere is provided, the atmospheric effects from the top of the atmosphere to ground level are not computed using the atmosphere description. As a result, the sun description (dni and optional spectrum) is expected to include all atmospheric effects (sun irradiance available at ground level).
The sun-shape parameter controls the angular distribution of the sun light intensity across the sun's disk. If not defined, the distribution is assumed to be a Dirac distribution (infinite directional source). The available sun shapes are:
- pillbox
- The pillbox distribution defines a uniform intensity over the sun's disk. Its single half_angle parameter is the sun's disk half-angle in degrees, linked to the apparent size of the sun. A typical half_angle is 0.2664.
- gaussian
- The gaussian distribution defines a Gaussian distribution of the solar incoming direction. Its single std_dev parameter is the standard deviation of the distribution in degrees. Values around 0.2 are typical. As the Gaussian distribution is not truncated, the resulting sun vector can theoretically be oriented away from the sun, especially with a large, non-typical std_dev value.
- buie
- The buie distribution (see the NOTES section, reference 3). Its single csr parameter is the ratio between the circumsolar irradiance and the sum of the circumsolar and sun's disk irradiance. An analysis of typical csr values can be found in reference 4 (see the NOTES section).
ATMOSPHERE
The atmosphere, when provided, describes the medium surrounding the solar plant. Its only parameter is its extinction coefficient in m⁻¹, which can either be a scalar if the extinction is constant over the spectrum, or can be spectrally described. The extinction along light paths is only computed after the first reflector, as the sun description must include all atmospheric effects before the first reflector (see SUN section for more details).
If no atmosphere is provided, atmospheric extinction after the first reflector is not taken into account.
MATERIAL
A material describes the properties of an interface. These properties can be the same for both sides of the interface or may be differentiated with a double-sided-mtl. The material behaviour 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 two dielectric media. Its medium_i
parameter defines the current medium (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:
Fr = 1/2 * (Rs^2 + Rp^2)
with Rs and Rp the reflectance for light polarized with its electric field perpendicular or parallel to the plane of incidence, respectively:
Rs = (n1 * |wi.N| - n2 * |wt.N|) / (n1 * |wi.N| + n2 * |wt.N|) Rp = (n2 * |wi.N| - n1 * |wt.N|) / (n2 * |wi.N| + n1 * |wt.N|)
with n1 and n2 the indices of refraction of the incident and transmitted media, and wi and wt the incident and transmitted direction.
Be careful to ensure media consistency in the
solstice-inputfile: a ray travelling in a medium A can only encounter a medium interface whose medium_i attribute is A. Consequently, a dielectric material must be defined as a double-sided material whose front and back interfaces are dielectrics with inverted media:material: front: dielectric: medium_i: &vacuum { refractive_index: 1, extinction: 0 } medium_t: &glass { refractive_index: 1.5, extinction: 20 } back: dielectric: medium_i: *glass medium_t: *vacuumIf media consistency is not ensured, solstice(1) will fail to run simulations. Note that by default, the surrounding medium is assumed to be vacuum, i.e. its refractive index and extinction are scalars with values 1 and 0, respectively. If an atmosphere is defined, the refractive index of the surrounding medium is still the scalar 1 but its extinction is that of the atmosphere.
- matte
- Diffuse surface. Reflects the same intensity in all directions independently of the incoming direction.
- mirror
- Specular or glossy reflection, depending on whether the
slope_error parameter is 0 or not. Glossy reflections
are controlled by a microfacet BRDF. The microfacet normals are
distributed according to the Beckmann or Pillbox distribution, as
specified by the
normal-distrib
attribute.
Let S be the slope_error parameter in ]0, 1]. The Beckmann distribution is defined as:
D(wh) = exp(-tan^2(a) / m^2) / (PI * m^2 * cos^4(a))
with a = arccos(wh.N) and m = sqrt(2)*S, while the Pillbox distribution is defined as:
| 0; if |wh.N| >= S D(wh) = | | 1 / (PI * (1 - cos^2(S))); if |wh.N| < S - thin-dielectric
- The interface is assumed to be a thin slab of a dielectric material. The
medium_i parameter defines the outside dielectric medium
while medium_t is the medium of the thin slab. Incoming
rays are either specularly reflected or transmitted (without deviation)
according to a Fresnel term (see dielectric above for
the formula). The underlying scattering function correctly handles the
multiple refraction effects within the thin slab.
The same media consistency rules as for dielectric apply: if not ensured, solstice(1) will fail to run simulations. By default, the surrounding medium is vacuum (refractive index 1, extinction 0). If an atmosphere is defined, the refractive index of the surrounding medium is still 1, but its extinction is that of the atmosphere.
- virtual
- Fully transparent interface.
Normal map
All material descriptors except virtual provide an optional normal-map attribute that defines a path to a Portable PixMap image (see the NOTES, section, reference 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 shape. For the hemisphere, hyperbol, parabol, plane and parabolic-cylinder shapes, the image is mapped in the {X,Y} plane. Other shapes are not parameterized; applying a normal-mapped material to them leads to undefined behaviour.
SHAPE
A shape describes a geometric model defined in its local coordinate system, whose origin is proper to the shape. No spatial transformation can be introduced through the declaration of a shape: it should be transformed externally through an object and/or entity.
Two types of shape are provided: quadric and mesh. The former is used to declare parametric surfaces; the latter describes triangulated surfaces.
Quadric
A quadric shape is defined from a quadric equation and a set of 2D clipping operations performed in its {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 into a triangular mesh according to the quadric's discretization parameters. This mesh is used by solstice(1) as a proxy to speed up access to the quadric shape; the exact position and normal are ultimately computed from the quadric equation.
The quadric surface is parameterized 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 axes. The available quadrics are:
- hemisphere
- Hemispheric shape defined along the Z axis whose minimum is 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 at the
origin. The slices parameter controls the discretization
of the hyperbol. If not defined, it is automatically computed from 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 at the origin.
The slices parameter controls the discretization of the
parabol. If not defined, it is automatically computed from the parabol
curvature.
x^2 + y^2 - 4 * focal * z = 0
- parabolic-cylinder
- Parabolic cylinder oriented along the Z axis, with its main axis along the
X axis and minimum at the origin. The slices parameter
controls the discretization. If not defined, it is automatically computed
from the curvature.
y^2 - 4 * focal * z = 0
- plane
- Plane whose normal points along the positive Z axis. The slices attribute controls the discretization of the clipped plane.
Clipping
A clipping operation, or polyclip, removes 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 operand retains the portion of the quadric that intersects the contour; the SUB operand removes the portion that intersects the contour. The available contour descriptors are:
- circle-descriptor
- Circular contour whose size is defined by the radius parameter. solstice(1) discretizes the circular contour using the segments attribute as the number of segments used to approximate the circle.
- vertices-descriptor
- Polygonal contour described by a list of 2D vertices. Polygon edges connect each vertex to its predecessor; an additional edge automatically closes the polygon between the last and first vertex. Note that solstice(1) assumes the polygon does not self-intersect.
The clip parameter of a quadric lists a set of polyclips applied successively in declaration order. For example, the following uses 5 clipping operations on a plane to build a rectangle with a circular hole at each corner:
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. Triangular meshes are not parameterized; applying a normal-mapped material to them produces undefined behaviour. The available triangular meshes are:
- cuboid
- Axis-aligned cuboid centered at the origin, whose corner positions and dimensions along the three axes are defined by the size parameter. The front side of the surface looks outside the cuboid.
- cylinder
- Cylinder centered at the origin whose height is along the positive Z axis. Top and bottom are capped. The stacks and slices parameters control the number of divisions along and around the Z axis, respectively. The front side looks outside the cylinder.
- sphere
- Triangulated sphere centered at the origin. The stacks and slices parameters control the number of divisions along and around the Z axis, respectively. The front side looks outside the sphere.
- stl
- Path to an external mesh file in ASCII STereoLithography (STL) format. The front side of each triangle is determined by the vertex ordering in the STL file: a triangle is front-facing when its vertices are clockwise-ordered.
ENTITY
An entity is used to declare and position shapes in the solar plant. An entity is the only item that effectively instantiates a geometry into the solar plant: a geometry declared but not referenced by an entity is ignored by solstice(1). An entity is a hierarchical data structure whose child entities' transformation is relative to their parent. If not defined, the transform of an entity is the identity (null rotation and translation).
Each entity has a name which must be unique per hierarchy level. The name string cannot contain dots, spaces or tabulations. A child entity is identified in the solar plant by concatenating, with the ‘.’ character, the names of its ancestors with its own name. For instance, the identifier of a child entity named level2 is level0.level1.level2:
entity:
name: level0
child:
- name: level1
child:
- name: level2
An entity encapsulates either a geometry (a collection of objects) or a pivot. Each entity can also have a list of anchors defining positions relative to the entity.
For a geometric entity, one must specify whether the encapsulated geometry is a primary geometry (i.e. directly lit by the sun and used to concentrate solar flux, such as a primary mirror). Correctly tagging primary geometries drastically improves the convergence speed of solstice(1) simulations.
Template
A template is a first-level entity with no existence in the solar plant itself. It is used to pre-declare an entity hierarchy that can then be instantiated multiple times by referencing it through common entities with YAML data tagging:
- 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 automatically orients its child geometry according to the sun position and pivot parameters. It is typically (but not mandatorily) the parent of a reflector that, once pivoted, will redirect sun light toward a target. A pivot cannot be the child of another pivot.
The target parameter is the most important pivot parameter. Four types of target are available:
- position
- The target is an absolute point in world coordinates.
- anchor
- The target is a position relative to an entity (see the ANCHOR section).
- sun
- The target is the center of the sun.
- direction
- The pivot reflects light in the given direction, specified in world coordinates.
Pivots can also have an optional ref_point parameter defining a 3D point in the coordinate system of the pivot's children that is used by the pointing algorithm. If not provided, it defaults to the origin.
Two flavours of pivot are available:
- x_pivot
- Single-axis pivot rotating around the +X axis in its local coordinate system. Its pointing algorithm considers an incoming ray from the center of the sun and rotates its children so that a specular reflection at ref_point using +Z as the local normal hits the target, or produces the specified direction.
- zx_pivot
- Two-axis pivot: first a rotation around the +Z axis in its local coordinate system, then a rotation around the +X axis in the resulting coordinate system. The optional spacing parameter defines a translation along the +Y axis applied after the first rotation (default: 0). Its pointing algorithm considers an incoming ray from the center of the sun and rotates its children so that a specular reflection at ref_point using +Y as the local normal hits the target, or produces the specified direction.
Anchor
An anchor defines a relative position in the entity hierarchy. Anchors are particularly useful for pivots and hyperbolic shapes that must reference a position relative to an entity whose transformation may depend on its ancestors. An anchor's name must be unique among all anchors in its entity and cannot contain dots, spaces or tabulations. An anchor is identified in the solar plant by concatenating its name to the entity-identifier of the entity in which it is declared, using ‘.’ as separator. For example, the identifier of an anchor named anchor0 declared in level0.level1 is level0.level1.anchor0.
When the root entity name of a template is unknown (because the template has not yet been instantiated), the self reserved keyword can be used to reference the unknown root entity. For example:
- 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 moves an object or an entity in space. The rotation parameter lists 3 angles in degrees defining rotations around the X, Y and Z axes. The translation attribute describes offsets along the X, Y and Z axes. Given a local frame p of an object, p is transformed into p' as:
p' = Rx * Ry * Rz * (T + p)
with T the translation vector and Rx, Ry, Rz the rotation matrices around the X, Y and Z axes:
| 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 sine of the rotation angles around the X, Y and Z axes, respectively.
EXAMPLES
Declare 2 entities and a point-source sun. The first entity is a purely specular square of size 10 centered at the origin. The second is a purely transparent square used as a receiver; its size is 1 and its center is at {0,0,2}:
- sun: {dni: 1000}
- entity:
name: reflector
primary: 1
geometry:
- material:
mirror:
reflectivity: 1
slope_error: 0
plane:
clip:
- operation: AND
vertices:
- [-5.0,-5.0]
- [-5.0, 5.0]
- [ 5.0, 5.0]
- [ 5.0,-5.0]
- entity:
name: receiver
primary: 0
transform:
translation: [0, 0, 2]
geometry:
- material:
virtual: # No attrib
plane:
clip:
- operation: AND
vertices:
- [-0.5,-0.5]
- [-0.5, 0.5]
- [ 0.5, 0.5]
- [ 0.5,-0.5]
Define a circular diffuse reflector surrounded by a virtual sphere, with a pillbox-shaped sun of half_angle 0.1 degree. Use anchors and YAML tags to reference a pre-declared geometry, and the YAML compact notation to reduce the number of lines:
- sun: {dni: 1000, pillbox: {half_angle: 0.1}}
- geometry: &small-circle
- material: {matte: {reflectivity: 1}}
plane: {clip: [{operation: AND, circle: {radius: 0.5}}]}
- geometry: &big-sphere
- material: {virtual: ""}
sphere: {radius: 2, slices: 128}
- entity: {name: reflector, primary: 1, geometry: *small-circle}
- entity: {name: receiver, primary: 0, geometry: *big-sphere}
Declare 2 parabolic reflectors from a templated parabola whose orientation is controlled by a zx_pivot targeting an anchor defined relative to the receiver:
- sun: {dni: 1000}
- entity: # Receiver
name: square_receiver
primary: 0
transform: { rotation: [0,90,0], translation: [100,0,10] }
anchors: [{name: anchor0, position: [0,0,0]}]
geometry:
- material: {virtual: ""}
plane:
clip:
- operation: AND
vertices: [[-.5,-.5],[-.5,.5],[.5,.5],[.5,-.5]]
- template: &self_oriented_parabol # Reflector
name: pivot
transform: {translation: [0, 0, 4], rotation: [0, 0, 90]}
zx_pivot: {target: {anchor: square_receiver.anchor0}}
children:
- name: parabol
transform: {rotation: [-90, 0, 0]}
primary: 1
geometry:
- material: {mirror: {reflectivity: 1, slope_error: 0}}
parabol:
focal: 100
clip:
- operation: AND
vertices: [[-5,-5],[-5,5],[5,5],[5,-5]]
# Instantiate the reflector template
- entity:
name: reflector1
transform: {translation: [0,0,0]}
children: [*self_oriented_parabol]
- entity:
name: reflector2
transform: {translation: [10,43.6,0]}
children: [*self_oriented_parabol]
Declare a solar furnace with 9 heliostats instantiated from the same template. Their position is controlled by a zx_pivot to ensure that 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 double-sided material: front faces are purely specular, back faces are diffuse:
- sun: {dni: 1000}
- material: &specular
front: {mirror: {reflectivity: 1, slope_error: 0}}
back: {matte: {reflectivity: 1}}
- template: &H # Template of a 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]}}
Three partial parabols with various focal distances concentrate incoming radiation at a common focal position. A hyperbol is located between the parabols and their common focal, which is also one of the two focals of the hyperbol. Radiation is redirected to the second focal of the hyperbol where the square target is located. A cuboid using a glass material is located between the hyperbol and the target. This example also illustrates the use of spectrum for refractive index and extinction:
# Spectra
- spectrum: &solar_spectrum
- {wavelength: 0.3, data: 1.0}
- {wavelength: 0.4, data: 2.0}
- {wavelength: 0.5, data: 0.5}
- {wavelength: 0.6, data: 3.5}
- {wavelength: 0.7, data: 1.5}
- {wavelength: 0.8, data: 0.8}
- spectrum: &air_kabs
- {wavelength: 0.3, data: 1.0e-4}
- {wavelength: 0.4, data: 1.0e-5}
- {wavelength: 0.5, data: 2.0e-5}
- {wavelength: 0.6, data: 2.0e-4}
- {wavelength: 0.7, data: 3.0e-5}
- {wavelength: 0.8, data: 1.0e-4}
- spectrum: &glass_kabs
- {wavelength: 0.3, data: 1.0e-2}
- {wavelength: 0.4, data: 1.0e-3}
- {wavelength: 0.5, data: 2.0e-3}
- {wavelength: 0.6, data: 2.0e-2}
- {wavelength: 0.7, data: 3.0e-3}
- {wavelength: 0.8, data: 1.0e-3}
- spectrum: &glass_ref_index
- {wavelength: 0.30, data: 1.40}
- {wavelength: 0.40, data: 1.39}
- {wavelength: 0.50, data: 1.37}
- {wavelength: 0.60, data: 1.34}
- {wavelength: 0.70, data: 1.30}
- {wavelength: 0.80, data: 1.25}
# Media
- medium: &air_medium
refractive_index: 1
extinction: *air_kabs
- medium: &glass_medium
refractive_index: *glass_ref_index
extinction: *glass_kabs
# Sun & atmosphere
- sun: {dni: 1, spectrum: *solar_spectrum}
- atmosphere: {extinction: *air_kabs}
# Materials
- material: &specular {mirror: {reflectivity: 1, slope_error: 0}}
- material: &black {matte: {reflectivity: 0}}
- material: &glass
front: {dielectric: {medium_i: *air_medium, medium_t: *glass_medium}}
back: {dielectric: {medium_i: *glass_medium, medium_t: *air_medium}}
# Primary reflectors
- entity:
name: "primary_reflector1"
primary: 1
transform: {translation: [0, 0, -2.0]}
geometry:
- material: *specular
parabol:
focal: 12
clip:
- {operation: AND, circle: {radius: 10}}
- {operation: SUB, circle: {radius: 5}}
- entity:
name: "primary_reflector2"
primary: 1
transform: {translation: [0, 0, -4]}
geometry:
- material: *specular
parabol:
focal: 14
clip:
- {operation: AND, circle: {radius: 15}}
- {operation: SUB, circle: {radius: 10}}
- entity:
name: "primary_reflector3"
primary: 1
transform: {translation: [0, 0, -6]}
geometry:
- material: *specular
parabol:
focal: 16
clip:
- {operation: AND, circle: {radius: 20}}
- {operation: SUB, circle: {radius: 15}}
# Secondary reflector
- entity:
name: "secondary_reflector"
primary: 0
transform: {translation: [0, 0, 6]}
geometry:
- material: *specular
hyperbol:
focals: {real: 16.0, image: 4}
clip: [{operation: AND, circle: {radius: 5}}]
# Glass box
- entity:
name: "glass_slide"
primary: 0
geometry:
- material: *glass
cuboid: {size: [10,10,0.5]}
transform: {translation: [0, 0, 0.25]}
# Receiver
- entity:
name: "square_receiver"
primary: 0
transform: {translation: [0, 0, -10] }
geometry:
- material: *black
plane:
clip:
- operation: AND
vertices: [[-0.5,-0.5],[-0.5,0.5],[0.5,0.5],[0.5,-0.5]]
NOTES
- YAML Ain't Markup Language — http://yaml.org
- SMARTS, Simple Model of the Atmospheric Radiative Transfer of Sunshine — http://www.nrel.gov/rredc/smarts/
- D. Buie, A.G. Monger, C.J. Dey. “Sunshape distributions for terrestrial solar simulations”. Solar Energy, 2003, 74, pp. 113–122.
- 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.
- Portable PixMap — http://netpbm.sourceforge.net/doc/ppm.html
SEE ALSO
HISTORY
solstice-input was initially developed
with funding from the
SOLSTICE
LabEx (Laboratory of Excellence), in collaboration with the PROMES
Laboratory of the French National Centre for Scientific Research (CNRS).
Starting in 2026, a new development effort funded by Ademe is ongoing.
AUTHORS
solstice-input was written and is
maintained by |Méso|Star>
<contact@meso-star.com>.
| August 17, 2026 | UNIX |