Skip to Content

Quickstart

The basics of SVETlANNa in five minutes.

Imports

import torch from svetlanna import SimulationParameters, Wavefront, LinearOpticalSetup from svetlanna.elements import FreeSpace, ThinLens, RoundAperture from svetlanna.units import ureg

Simulation parameters

Everything starts with SimulationParameters — the description of your coordinate grid:

params = SimulationParameters.from_ranges( x_range=(-2*ureg.mm, 2*ureg.mm), x_points=512, # X: from -2 to 2 mm y_range=(-2*ureg.mm, 2*ureg.mm), y_points=512, # Y: from -2 to 2 mm wavelength=632.8*ureg.nm # HeNe laser )

ureg is the SVETlANNa unit registry. It provides mm, um, nm, cm, m and more.

Creating a wavefront

# Gaussian beam with a 0.5 mm waist radius wf = Wavefront.gaussian_beam(params, waist_radius=0.5*ureg.mm) print(f"Shape: {wf.shape}") # torch.Size([512, 512]) print(f"Dtype: {wf.dtype}") # torch.complex64 print(f"Max I: {wf.max_intensity}") # ~1.0

Optical elements

# round aperture aperture = RoundAperture(params, radius=1*ureg.mm) # thin lens lens = ThinLens(params, focal_length=100*ureg.mm) # free space (zero-padded angular spectrum method) propagate = FreeSpace(params, distance=100*ureg.mm, method='zpASM')

method is required in FreeSpace. Choose from 'ASM', 'zpASM', 'RSC' and 'zpRSC'. The zero-padded variants are slower but avoid wrap-around artefacts — prefer them unless you have measured that you do not need them.

Propagating through the system

Optical elements are nn.Modules, so they are called like functions:

# option 1: element by element wf = aperture(wf) wf = lens(wf) wf = propagate(wf) # option 2: as a LinearOpticalSetup setup = LinearOpticalSetup([ RoundAperture(params, radius=1*ureg.mm), ThinLens(params, focal_length=100*ureg.mm), FreeSpace(params, distance=100*ureg.mm, method='zpASM'), ]) wf_focus = setup(wf)

Analysing the result

# intensity intensity = wf.intensity # |E|² # phase phase = wf.phase # arg(E) # full width at half maximum fwhm_x, fwhm_y = wf.fwhm(params) print(f"FWHM: {fwhm_x*1e6:.1f} × {fwhm_y*1e6:.1f} um")

Visualisation

import matplotlib.pyplot as plt fig, axes = plt.subplots(1, 2, figsize=(12, 5)) extent = [ params.x[0].item()*1e3, params.x[-1].item()*1e3, params.y[0].item()*1e3, params.y[-1].item()*1e3 ] im0 = axes[0].imshow(intensity.cpu(), cmap='hot', extent=extent) axes[0].set_title('Intensity') axes[0].set_xlabel('x, mm') axes[0].set_ylabel('y, mm') plt.colorbar(im0, ax=axes[0]) im1 = axes[1].imshow(phase.cpu(), cmap='twilight', extent=extent) axes[1].set_title('Phase') axes[1].set_xlabel('x, mm') plt.colorbar(im1, ax=axes[1]) plt.tight_layout() plt.show()

Full code

import torch import matplotlib.pyplot as plt from svetlanna import SimulationParameters, Wavefront, LinearOpticalSetup from svetlanna.elements import FreeSpace, ThinLens, RoundAperture from svetlanna.units import ureg # 1. parameters params = SimulationParameters.from_ranges( x_range=(-2*ureg.mm, 2*ureg.mm), x_points=512, y_range=(-2*ureg.mm, 2*ureg.mm), y_points=512, wavelength=632.8*ureg.nm ) # 2. wavefront wf = Wavefront.gaussian_beam(params, waist_radius=0.5*ureg.mm) # 3. optical system setup = LinearOpticalSetup([ RoundAperture(params, radius=1*ureg.mm), ThinLens(params, focal_length=100*ureg.mm), FreeSpace(params, distance=100*ureg.mm, method='zpASM'), ]) # 4. focus wf_focus = setup(wf) # 5. result print(f"FWHM: {wf_focus.fwhm(params)[0]*1e6:.1f} um") print(f"Max I: {wf_focus.max_intensity:.2e}")

What next?