In this tutorial, we show how to generate reflectors/elements. You might have wondered why we use the terms "reflector" and "element" interchangeably. This is because PyPO
allows to define planar geometries to be defined in the far-field. This means that, instead of having an optical element defined as a set of points in xyz space, we have an element defined on an angular grid, consisting of Azimuth and Elevation angles. Since these elements cannot reflect, we use these terms quite interchangeably. However, a far-field element will always be labelled an "element". For reflectors, we try to make clear that these are also elements, but sometimes we will use these terms interchangeably.
It should also be noted that we use the term "quadrics" to describe a class of geometries which are commonly called "conics" in optics. We do this to stay as mathematically accurate as possible, since a "conic" in the strict sense refers to a one-dimensional "quadric".
In PyPO
, reflectors or optical elements in general are specified using dictionaries. These dictionaries contain information such as the parameters defining the shape, the type of parametrisation to use for the gridding and the name of the reflector. Upon adding a reflector dictionary to the System
object, it will be stored in the internal dictionary for reflectors and elements, called the system dictionary.
Before we dive into the specific reflector/element geometries supported by PyPO
, we will first discuss some general information common to all reflectors. The following entries in a reflectordictionary are common to all geometries:
Reflectors and elements are identified in a System
by their names. It is therefore important to give your reflectors and elements sensible names. If the "name" field is not specified, PyPO
will name it with the geometry of the reflector. For example, if a paraboloid reflector is made but no name is given, it will automatically be named "Paraboloid". If a name already occurs in the system dictionary, PyPO
will overwrite the reflector dictionary at this name with the new one, unless the System
object is instantiated with the "override" argument set to "False":
Now, PyPO
will append "_<N>" to the duplicate name, with "<N>" being the amount of times the name has already occured in the system dictionary.
A paraboloid is a quadric surface parameterised by two positive real numbers 'a' and 'b' and defined as the locus of the following equation in 3D Cartesian (xyz, for short) space:
\[ Paraboloid(x,y,z) = \left( \frac{x}{a} \right)^2 + \left( \frac{y}{b} \right)^2 - z = 0 \]
A special case arises when 'a' = 'b'. In this case, the paraboloid is a so-called surface of revolution and is symmetric around the central symmetry axis. In this case, the paraboloid has a single focus at a finite distance from the vertex (the bottom of the 'bowl' of the paraboloid) along the axis of symmetry.
The basic template for a dictionary for defining a paraboloid contains, in addition to the general fields:
Also not that PyPO
will always define reflectors/elements from the xy-plane and orient the reflectors along the z-axis if "pmode" is set to "manual". Translations and rotations (transformations) can only be applied after defining the reflector/element.
If "pmode" is set to "focus", PyPO
will first generate the paraboloid from the xy-plane by calculating the absolute distance between the specified "vertex" and "focus_1" co-ordinates, placing the vertex at the origin and the focus along the z-axis, with the calculated distance in between. Then, it finds the rotation of the paraboloid by calculating the angle between the vector connecting the vertex to the focus. The rotation is applied to the generated reflector and the reflector is translated such that the vertex co-ordinate again co-incides with the specified co-ordinate in the "vertex" field of the reflector dictionary.
A hyperboloid is a quadric surface parameterised by three positive real numbers 'a', 'b' and 'c' and defined as the locus of the following equation in xyz:
\[ Hyperboloid(x,y,z) = \left( \frac{x}{a} \right)^2 + \left( \frac{y}{b} \right)^2 - \left( \frac{z}{c} \right)^2 + 1 = 0 \]
In PyPO
, the only hyperboloid surface that is supported is a hyperboloid of two sheets. Specifically, the upper sheet is used in PyPO
.
When 'a' = 'b', we again have a surface of revolution. In this case, the hyperboloid has two focal points. The vertex depth of the hyperboloid is determined by the eccentricity, which should be larger than 1.
The reflector dictionary for the hyperboloid supports the following fields, in addition to the general ones:
PyPO
will do the same as for the paraboloid, except that now "focus_1" and "focus_2" are used, instead of "vertex" and "focus_1", which was the case for the paraboloid.An ellipsoid is a quadric surface parameterised by three positive real numbers 'a', 'b' and 'c' and defined as the locus of the following equation in xyz:
\[ Ellipsoid(x,y,z) = \left( \frac{x}{a} \right)^2 + \left( \frac{y}{b} \right)^2 + \left( \frac{z}{c} \right)^2 - 1 = 0 \]
The ellipsoid has a few interesting cases, all belonging to either one of three equivalence classes:
The extra fields for the reflector dictionary for an ellipsoid are largely the same as for the hyperboloid. Only the "ecc" field should now have a value between 0 and 1. The ellipsoid does contain an extra optional field however, which has an effect when "pmode" is set to "focus":
PyPO
, the only way to get a rotationally symmetric ellipsoidal reflector is to orient the long axis along the z-axis, i.e. with "orient" set to "z". If "orient" is set to "x", the long axis lies along the x-axis, and one short axis lies along the y-axis. If the reflector is then generated from an xy-plane parameterisation, the resulting segment of the ellipsoid cannot be rotationally symmetric.The simplest of all, reflector dictionaries for planes do not contain a "pmode" field. Rather, all planes are defined in the xy-plane, with the z co-ordinate set to 0. Planes do play a very special role, however, which can be read about in the next tutorial.