Skip to content

Beam groups ​

For convenience, the BeamletOptics.AbstractBeamGroup offers a container-like interface for groups of Beams as commonly used in other software packages. The following concrete implementations are currently provided:

julia
julia> BeamletOptics.list_subtypes(BeamletOptics.AbstractBeamGroup);
└── BeamletOptics.AbstractBeamGroup
    ├── AstigmaticBeamGroup{T, R} where {T<:Real, R<:BeamletOptics.AbstractRay{T}}
    ├── CollimatedSource{T, R} where {T<:Real, R<:BeamletOptics.AbstractRay{T}}
    └── PointSource{T, R} where {T<:Real, R<:BeamletOptics.AbstractRay{T}}

At least 3 types have been found.

Refer to the following sections for convenience constructors to generate the sources listed above.

Moving a beam group

Every beam group has a source position (center) and an orientation matrix, whose second column is the central source direction and whose first column is the sampling reference vector (basis). Both are updated when the group is moved. Refer to BeamletOptics.AbstractBeamGroup for the convention and to Moving sources for the kinematic API.

Center ray

The first beam of every CollimatedSource and PointSource generated by one of the constructors below is the center ray: it starts at the source position along the central source direction. This does not apply to sources that wrap given beams.

Collimated beam source ​

The collimated beam source is ideal to model light coming from a focal plane at infinity. This is useful for simulating plane wavefronts. You can define a collimated monochromatic Beam source as follows:

BeamletOptics.CollimatedSource Method
julia
CollimatedSource(pos, dir, diameter, λ; num_rings, num_rays, basis)

Spawns a bundle of collimated Beams at the specified position and direction. The source is modelled as a ring of concentric beam rings around the center beam. The amount of beam rings between the center ray and outer diameter can be specified via num_rings.

Info

Note that for correct sampling, the number of rays should be atleast 20x the number of rings.

Arguments

The following inputs and arguments can be used to configure the CollimatedSource:

Inputs

  • pos: center beam starting position

  • dir: center beam starting direction

  • diameter: outer beam bundle diameter in [m]

  • λ = 1e-6: wavelength in [m], default val. is 1000 nm

Keyword Arguments

  • num_rings: number of concentric beam rings, default is 10; the number of rings counts the center as the innermost one, i.e. num_rings - 1 rings lie around it

  • num_rays: total number of rays in the source, default is 100x num_rings

  • basis: Optional reference vector (e.g. [1,0,0]) to define the starting azimuthal angle for the beam rings.

Reproducible sampling

If no basis is passed, the orthogonal basis vectors spanning the pupil plane are derived from dir deterministically, so two sources sharing the same dir, diameter, num_rings and num_rays sample exactly the same ray positions. Pass a basis to rotate the azimuthal sampling of a source about its own axis, e.g. to interleave several otherwise identical sources.

source

Already existing beams, e.g. Beams of PolarizedRays as in the Vectorial focusing at high NA example, can be wrapped into a group with CollimatedSource(beams, diameter, pos, dir). PointSource(beams, NA, pos, dir) and AstigmaticBeamGroup(beams, pos, dir) work analogously; instead of dir, a full orientation matrix can be passed.

A special constructor called UniformDiscSource is available, which offers an equal-area sampling (Fibonacci pattern) and is thus favorable in situations where the weighting of the individual beams becomes important, e.g. for calculating a point spread function using the intensity function.

BeamletOptics.UniformDiscSource Function
julia
UniformDiscSource(pos, dir, diameter, λ; num_rays=1_000, basis)

Generates a ray fan with equal area per ray across a circular pupil using the deterministic sunflower (Fibonacci) pattern.

The spiral starts with the center ray at pos (k = 0). The radius of the k-th ray (k = 1 … N-1) is ρₖ = diameter/2 ⋅ √((k + ½)/N), its azimuth is k times the golden angle π(3 - √5).

Note

This is merely a CollimatedSource constructor which uses Fibonacci sampling instead of concentric rings. All rays are equally weighted samples of the pupil: ray k represents the part of the disc between the radii diameter/2 ⋅ √(k/N) and diameter/2 ⋅ √((k + 1)/N). The center ray represents the innermost of these parts, a disc, by its center.

Arguments

The following inputs and arguments can be used to configure the underlying CollimatedSource:

Inputs

  • pos: center of the pupil disc, i.e. the source position

  • dir: starting direction of all beams

  • diameter: outer beam bundle diameter in [m]

  • λ = 1e-6: wavelength in [m]

Keyword Arguments

  • num_rays=1000: total number of rays in the source, must be ≥ 1

  • basis: Optional reference vector (e.g. [1,0,0]) to define the starting azimuthal angle of the sunflower pattern.

Reproducible sampling

If no basis is passed, the orthogonal basis vectors spanning the pupil plane are derived from dir deterministically, so two sources sharing the same dir, diameter and num_rays sample exactly the same ray positions. Pass a basis to rotate the sunflower pattern about its own axis, e.g. to interleave several otherwise identical sources.

source

Point beam source ​

The PointSource type is used to model emission from a spatially localized source that radiates Beams in a range of directions. This is commonly used to simulate conical emission patterns, such as light emerging from a fiber tip or a light source for a lens objective with a known focal distance. You can specify the origin and a propagation direction, which are then used to construct the monochromatic PointSource.

BeamletOptics.PointSource Method
julia
PointSource(pos, dir, θ, λ; num_rings, num_rays, basis)

Spawns a point source of Beams at the specified position and direction. The point source is modelled as a collection of concentric beam fans centered around the center beam. The amount of beam rings between the center ray and half-spread-angle θ can be specified via num_rings.

Info

Note that for correct sampling, the number of rays should be atleast 20x the number of rings.

Arguments

The following inputs and arguments can be used to configure the PointSource:

Inputs

  • pos: center beam starting position

  • dir: center beam starting direction

  • θ: half spread angle in rad, must be < π

  • λ = 1e-6: wavelength in [m], default val. is 1000 nm

Keyword Arguments

  • num_rings: number of concentric beam rings, default is 10; the number of rings counts the center as the innermost one, i.e. num_rings - 1 rings lie around it

  • num_rays: total number of rays in the source, default is 100x num_rings

  • basis: Optional reference vector (e.g. [1,0,0]) to define the starting azimuthal angle for the source rings.

Reproducible sampling

If no basis is passed, the orthogonal basis vectors are derived from dir deterministically, so two sources sharing the same dir, θ, num_rings and num_rays sample exactly the same ray directions. Pass a basis to rotate the azimuthal sampling of a source about its own axis, e.g. to interleave several otherwise identical sources.

source

Below you can find an exemplary illustration of a PointSource.

Analogous to UniformDiscSource, a special constructor called UniformPointSource is available, which samples the spherical cap around dir with an equal solid angle per ray (Fibonacci/sunflower pattern), rather than in concentric rings. It returns a plain PointSource.

BeamletOptics.UniformPointSource Function
julia
UniformPointSource(pos, dir, θ, λ; num_rays=1_000, basis)

Generates a cone of Beams emitted from pos with equal solid angle per ray across the spherical cap 0 ≤ ϑ ≤ θ around dir, using the deterministic sunflower (Fibonacci) pattern. The spiral starts with the center ray along dir (k = 0). The polar angle ϑₖ of the k-th ray (k = 1 … N-1) follows from cos ϑₖ = 1 - (k + ½)/N ⋅ (1 - cos θ), its azimuth is k times the golden angle π(3 - √5).

Note

This is merely a PointSource constructor which uses Fibonacci sampling instead of concentric rings. All rays are equally weighted samples of the cap: ray k represents the part of the cap with 1 - (k + 1)/N ⋅ (1 - cos θ) ≤ cos ϑ ≤ 1 - k/N ⋅ (1 - cos θ). The center ray represents the innermost of these parts, a cap, by its center.

Arguments

The following inputs and arguments can be used to configure the underlying PointSource:

Inputs

  • pos: starting position of all beams

  • dir: central source direction, i.e. the cone axis

  • θ: half spread angle in rad, must be < π

  • λ = 1e-6: wavelength in [m], default val. is 1000 nm

Keyword Arguments

  • num_rays=1000: total number of rays in the source, must be ≥ 1

  • basis: Optional reference vector (e.g. [1,0,0]) to define the starting azimuthal angle of the sunflower pattern. Must not be zero or parallel to dir.

Reproducible sampling

If no basis is passed, the orthogonal basis vectors are derived from dir deterministically, so two sources sharing the same dir, θ and num_rays sample exactly the same ray directions. Pass a basis to rotate the sunflower pattern about its own axis, e.g. to interleave several otherwise identical sources.

source

Line and fan sources ​

For layout sketches, or to trace only one section of a system (e.g. the meridional plane), a two-dimensional source is often sufficient. The UniformLineSource is the two-dimensional counterpart of the collimated source: a plane sheet of parallel Beams that start equidistantly on a line. It returns a plain CollimatedSource.

BeamletOptics.UniformLineSource Function
julia
UniformLineSource(pos, dir, width, λ; num_rays=101, basis)

Generates a plane sheet of parallel Beams, i.e. a two-dimensional collimated source: the rays start equidistantly on a line of the length width centered at pos and travel along dir. The line lies along basis, such that all rays lie in the plane spanned by dir and basis. This is useful for layout sketches and for tracing a single (e.g. meridional or sagittal) section of a system.

The first ray is the center ray at pos. It is followed by h = (N - 1) ÷ 2 rays on each side of it, at pos + j/h ⋅ width/2 ⋅ basis for j = -h … h without j = 0, i.e. from one marginal ray at the end of the line to the other. A single ray starts at pos.

Use an odd number of rays

A pattern that is symmetric to its center ray has an odd number of rays. An even num_rays yields the pattern of num_rays - 1 rays and a second ray at pos.

Note

This is merely a CollimatedSource constructor which samples one diameter of the disc instead of concentric rings. width is stored as the diameter of the source.

Warning

The rays sample a line, not an area: they are not equal-area samples of a circular pupil. For a point spread function or an intensity use UniformDiscSource.

Arguments

The following inputs and arguments can be used to configure the underlying CollimatedSource:

Inputs

  • pos: center of the line, i.e. the source position

  • dir: starting direction of all beams

  • width: length of the line in [m], i.e. the distance between the marginal rays

  • λ = 1e-6: wavelength in [m]

Keyword Arguments

  • num_rays=101: total number of rays in the source, must be ≥ 1

  • basis: direction of the line (e.g. [1,0,0]), projected into the plane normal to dir. Must not be zero or parallel to dir.

Orientation of the line

If no basis is passed, the direction of the line is derived from dir deterministically via normal3d, which is rarely the section of interest: pass a basis to choose the plane of the rays. The line can also be turned about dir afterwards with rotate3d!.

source

The UniformFanSource is the two-dimensional counterpart of the point source: a plane fan of Beams from a single point with equidistant angles. It returns a plain PointSource.

BeamletOptics.UniformFanSource Function
julia
UniformFanSource(pos, dir, θ, λ; num_rays=101, basis)

Generates a plane fan of Beams emitted from pos, i.e. a two-dimensional point source: the rays lie in the plane spanned by dir and basis, with equidistant angles between -θ and θ to dir. This is useful for layout sketches and for tracing a single (e.g. meridional or sagittal) section of a system.

The first ray is the center ray along dir. It is followed by h = (N - 1) ÷ 2 rays on each side of it, which enclose the angles φⱼ = j/h ⋅ θ with dir for j = -h … h without j = 0 and point along cos φⱼ ⋅ dir + sin φⱼ ⋅ basis, i.e. from one marginal ray at the edge of the fan to the other. A single ray points along dir.

Use an odd number of rays

A pattern that is symmetric to its center ray has an odd number of rays. An even num_rays yields the pattern of num_rays - 1 rays and a second ray along dir.

Note

This is merely a PointSource constructor which samples one section of the cone instead of concentric rings.

Warning

The rays sample a plane angle, not a solid angle: they are not equal solid angle samples of a cone. For a point spread function or an intensity use UniformPointSource.

Arguments

The following inputs and arguments can be used to configure the underlying PointSource:

Inputs

  • pos: starting position of all beams

  • dir: central source direction, i.e. the axis of the fan

  • θ: half spread angle in rad, must be < π

  • λ = 1e-6: wavelength in [m], default val. is 1000 nm

Keyword Arguments

  • num_rays=101: total number of rays in the source, must be ≥ 1

  • basis: direction (e.g. [1,0,0]) that spans the plane of the fan together with dir, projected into the plane normal to dir. Rays with a positive angle are tilted towards it. Must not be zero or parallel to dir.

Orientation of the fan

If no basis is passed, the plane of the fan is derived from dir deterministically via normal3d, which is rarely the section of interest: pass a basis to choose the plane of the rays. The fan can also be turned about dir afterwards with rotate3d!.

source

Both sources include the marginal rays and should be used with an odd number of rays. The plane of the rays is spanned by dir and the basis keyword argument. The rays stay in this plane only if the system is symmetric with respect to it. Since the rays sample a line or a plane angle instead of an area or a solid angle, these sources are not suited for calculating a point spread function with the intensity function.

Astigmatic Beam Groups ​

For complex sources, the package provides the AstigmaticBeamGroup container. Several constructors are available for different scenarios:

A field that is close to one Gaussian mode and too small to be tiled into beamlets, e.g. the output of a single-mode fiber, is not turned into a group: GaussianModeDecomposition fits a single AstigmaticGaussianBeamlet to it.

OpticsBase fields as beam groups ​

With using OpticsBase, a PlaneField handed over by another solver (e.g. the exit field of a fiber computed by a beam propagation method) becomes BMO beams again. WavefrontBeamletDecomposition tiles it into one beamlet per sample, which needs beamlets much larger than λ. GaussianModeDecomposition fits a single Gaussian beamlet instead, for small fields close to one Gaussian mode such as single-mode fiber output. Both take only the forward-travelling part of the field and require the plane to lie in vacuum or air. The detector side, PlaneField(::Detector), is described under OpticsBase interoperability.

BeamletOptics.WavefrontBeamletDecomposition Method
julia
BeamletOptics.WavefrontBeamletDecomposition(f::OpticsBase.PlaneField; kwargs...)

Decomposes the forward-travelling part of a PlaneField f into an AstigmaticBeamGroup of AstigmaticGaussianBeamlets, placed on f's plane and travelling along f's normal n. This is the return path for OpticsBase.PlaneField(detector; ...): passing the result back into this constructor and tracing the resulting beam group reproduces the original field (round trip), up to beamlet-grid discretization error.

Arguments

  • f: the field to decompose. Only forward(f) (the part travelling along +n) is used; the backward part is dropped (a PlaneField has no ready single propagation direction for its backward part in this constructor, which needs one direction per call).

  • kwargs...: forwarded to WavefrontBeamletDecomposition(x, y, Eu, Ev, dir, λ; kwargs...) (threshold, overlap, randomize_axes, rng); basis is fixed to f's own (u, v) and R to f.R, neither can be overridden.

Conventions

  • The physical field used is forward(f).E .* reference_phase(f): the stored array with the local-plane-wave forward/backward split and the reference-sphere phase (if any) applied, in [V/m] peak amplitude, matching the units AstigmaticGaussianBeamlet's E0 expects. The samples and the sphere are handed on separately (R = f.R), so the grid only has to resolve the phase of the stored array, not that of the sphere.

  • forward splits each sample as a local plane wave along the reference direction; a beam at the angle θ to it loses an amplitude of the order (1 − cos θ)/2. Keep the plane close to normal to the beam, which the beamlet size requires anyway (see WavefrontBeamletDecomposition).

  • The beam group's sampling grid is f's own (u, v) grid (OpticsBase.coordinates), placed at f.origin with local axes f.axes[:, 1:2] (translate_to3d! after construction; WavefrontBeamletDecomposition itself always centers the undecomposed group on the global origin).

  • f must lie in vacuum or air (f.n == 1): BMO starts beams in vacuum, and a field in a medium would need a medium-to-vacuum conversion of amplitude and optical path. An ArgumentError is thrown otherwise.

Throws an ArgumentError if f has no forward-travelling light (e.g. a purely backward wave), and whatever WavefrontBeamletDecomposition(x, y, Eu, Ev, dir, λ) throws.

source
BeamletOptics.GaussianModeDecomposition Method
julia
BeamletOptics.GaussianModeDecomposition(f::OpticsBase.PlaneField)

Fits a single AstigmaticGaussianBeamlet to the forward-travelling part of a PlaneField, e.g. the output of a single-mode fiber. The beamlet starts on f's plane at the centroid of the field; see GaussianModeDecomposition for the fit. Use it for fields close to one Gaussian mode that are too small for WavefrontBeamletDecomposition (which needs beamlets much larger than λ).

optical_power(beamlet) / OpticsBase.power(f) is the fraction of the power captured by the Gaussian mode. The field used is forward(f).E .* reference_phase(f); the reference sphere enters the fit analytically (R = f.R), so the grid only has to resolve the phase of the stored array. f must lie in vacuum or air (f.n == 1), where BMO starts beams, and must contain forward-travelling light; an ArgumentError is thrown otherwise.

source