Version 1.8.15

Release of COPHASAL version 1.8.15.

The main focus of this release is the addition of gradient-index support. There are two additional notable updates: an overhaul of system-wide zoom functions, and a replacement of add_myglass() with ins_myglass() so that user-defined glasses behave consistently with other items such as surfaces and fields.

Gradient-index support

For gradient-index glasses, the index of refraction depends on the ray’s position inside the glass, so each glass has an associated coordinate system. By default this matches the surface coordinate system. For example, consider a lens whose first and second surfaces sandwich a gradient-index glass: no matter which surface a ray enters from, it should be transformed according to a consistent glass coordinate system. The glass coordinate system of one surface can be referenced to another surface coordinate system using set_glb_ref(). The same function is also used to reference surface coordinate systems.

Another important aspect of gradient-index glasses is the use of custom parameters that define the gradient profile. We need the ability to set, zoom, and vary these parameters during optimization. This required an extensive update to the glasses subsystem so they behave more like thin-film layers, surfaces, etc. Glasses can now expose parameters as needed (gp0, gp1, …). Currently only user-defined gradient glasses can expose parameters; gradient-index glasses must be defined as user glasses. The following example demonstrates these features.

Example

A gradient-index lens example file has been supplied in the examples folder. We will start with it and add apertures and edges to complete the GRIN rod lens. We will also use labels to make it easier to identify surfaces. First, here is the surface listing for the supplied example, radgrad.lua.

CPH> runfile"radgrad"
CPH> list"s"
S:
 Z1:     LBL        TYP       RDY          THI          MED          RFR      AUT_APE    COMMENT
 S 1             SPHERE         0            0          AIR     TRANSMIT          0.2
 S 2   G1P14     SPHERE         0         4.18       radgrd     TRANSMIT          0.2
 S 3             SPHERE         0         0.25          AIR     TRANSMIT       0.8182
 S 4             SPHERE         0            0          AIR     TRANSMIT       0.8451
Stop: 3

Radial gradient rod lens

Glass Parameters

Within the file radgrad.lua, the glass for surface 2, "radgrd" is defined like so.

local tmp_info = {
 grin = "RADIAL",
 glass = "radgrd"
}
local tmp_data = {
 dispersion_data = {
  {0.4, 0.5, 0.7},
  {1.666, 1.666, 1.666}
 }
}
ins_myglass(tmp_info, tmp_data)
set("GP1 G 'radgrd'", -0.07069, 1)  -- Set GP1 parameter. 

Notice the last line. GP1 can also be set as g[ radgrd ].gp1 = -0.07069. Note the lowercase g at the start. The manual lists the details about this radial gradient glass parameter. Parameter GP0 is always the numerical integration step size and defaults to 0.1. Glass parameters follow all parametric actions, except for one: they cannot react.

Next we will add apertures and labels to the sequential (SEQ) surfaces.

runfile"radgrad"

local diam = 1.0        -- diameter, delibratly smaller
local len = s[2].thi    -- length of the rod lens

set_label("s 2", "in")
s['in'].ape = "cir"
s['in'].mx_ape = diam / 2
s['in'].szy = diam / 2

set_label("s 3", "out")
s['out'].ape = "cir"
s['out'].mx_ape = diam / 2
s['out'].szy = diam / 2

Add Lens Edges

Now we will complete the lens by defining the edges that close the volume of the cylindrical lens. To define the cylinder around the lens we insert two half-cylinders, one for the top and one for the bottom. Currently there is no hyperhemisphere support. For such edge surfaces that do not play a role in SEQ-mode design, the non-sequential (NSEQ) list is appropriate. We will define these as NSEQ surfaces and the cylinders will be realized by the "TORIC" surface type.

-- Top cylinder, up
ins_surf("n 1", {type="toric", glass="radgrd"})
set_label("n 1", "up")
n['up'].ape = "rec"
n['up'].szx = diam / 2
n['up'].szy = len / 2
n['up'].mx_ape = math.sqrt((diam/2)^2 + (len/2)^2)
set_glb_ref("n 'up'", "s 'in'")         -- Surface global reference
set_glb_ref("gls2 n 'up'", "s 'in'")    -- GLS2 global reference
n['up'].repos = "basic"
n['up'].z = len / 2
n['up'].y = diam / 2
n['up'].alpha = 90
n['up'].rdx = diam / 2
n['up'].rfr = "tir_only"                -- Refract mode is TIR only

-- Bottom cylinder, down
ins_surf("n 2", {type="toric", glass="radgrd"})
set_label("n 2", "dn")
n['dn'].ape = "rec"
n['dn'].szx = diam / 2
n['dn'].szy = len / 2
n['dn'].mx_ape = math.sqrt((diam/2)^2 + (len/2)^2)
set_glb_ref("n 'dn'", "s 'in'")
set_glb_ref("gls2 n 'dn'", "s 'in'")
n['dn'].repos = "basic"
n['dn'].z = len / 2
n['dn'].y = -diam / 2
n['dn'].alpha = -90
n['dn'].rdx = diam / 2
n['dn'].rfr = "tir_only"

Edges defined

Add NSEQ Rays

As expected, SEQ rays do not interact with NSEQ surfaces. To see the light-pipe-like behavior, we will add user rays which are NSEQ. These rays are located symmetrically opposite to the second field point. Note that currently add_ray() generates rays that start in GLS1 of the surface.

reset_user_rays()       -- Always a good practice to reset user rays
local y_pos = -f[2].y   -- Note the negative sign
local l, m, n = ray_dir({r = "yp"}, "s 'in'")
local tny = math.tan(math.acos(n))

local num_rays = 3      -- Ray fan size
for i = -num_rays, num_rays do
  local dir_y = (tny / num_rays) * i
  add_ray({
    pos = {0, y_pos}, 
    dir = {0, dir_y},
    seq = false,        -- NSEQ rays
    sur = "s 'in'"      -- Currently rays start in GLS1
  })
end

GRIN light pipe rod lens

showlens({sym = "none"})    -- Show full 3D layout. 

3D layout

Final Note

Radial gradient and the Maxwell’s Fish-Eye gradient has been implemented. Additional profiles will be added as needed. Currently, dispersion is not modeled for the parameters that define the gradient profile; however, these parameters can be zoomed. Profile-parameter dispersion, along with the ability to add GRIN glasses as catalogs, will be included in a future release.

Note that there is no separate SEQ or NSEQ mode in COPHASAL — both modes of design are intended to work seamlessly together.