SimulationParameters
SimulationParameters is the container that defines the coordinate system for every
calculation. It holds the coordinate axes (x, y), the wavelength and any additional
axes you declare.
Creating it
from_ranges
from svetlanna import SimulationParameters
from svetlanna.units import ureg
params = SimulationParameters.from_ranges(
x_range=(-1*ureg.mm, 1*ureg.mm), # range along X
x_points=512, # number of points
y_range=(-1*ureg.mm, 1*ureg.mm), # range along Y
y_points=512,
wavelength=632.8*ureg.nm
)Earlier versions used W/H for the transverse axes and w_range/h_range in
from_ranges. Those names are deprecated — use x/y and x_range/y_range.
Required axes
| Axis | Description | Type |
|---|---|---|
x | Horizontal coordinates | 1D tensor |
y | Vertical coordinates | 1D tensor |
wavelength | Wavelength | scalar or 1D tensor |
Accessing the axes
x = params.x # 1D tensor
y = params.y
wl = params.wavelength
# by name
x = params['x']
# names of all axes, in tensor order
print(params.axis_names) # ('y', 'x')
# does an axis exist?
print('pol' in params) # FalseMethods
meshgrid
Build the 2D coordinate grids:
X, Y = params.meshgrid(x_axis='x', y_axis='y')
# X.shape == Y.shape == (512, 512)
R = torch.sqrt(X**2 + Y**2)axis_sizes
Sizes of a selection of axes (cached):
size = params.axis_sizes(('y', 'x'))
# torch.Size([512, 512])cast
Reshape a tensor so it broadcasts against the full axis layout:
tensor = torch.rand(512, 512)
casted = params.cast(tensor, 'y', 'x')This is what elements use internally to stay compatible with extra axes such as several wavelengths.
index
Position of an axis in the tensor layout, counted from the right:
print(params.index('x')) # -1
print(params.index('y')) # -2clone
A deep copy:
params_copy = params.clone()
print(params.equal(params_copy)) # TrueAdditional axes
Any keyword argument to the constructor becomes an axis. This is how polarisation, time or an ensemble dimension are added:
import torch
from svetlanna import SimulationParameters
params = SimulationParameters(
x=torch.linspace(-1e-3, 1e-3, 256),
y=torch.linspace(-1e-3, 1e-3, 256),
wavelength=torch.tensor(632.8e-9),
pol=torch.tensor([1., 0.]), # Jones vector
)
print(params.axis_names) # ('pol', 'y', 'x')
print(params.pol) # tensor([1., 0.])Axes are fixed at construction time. To change the layout, build a new
SimulationParameters — this keeps every element that references it consistent.
Several wavelengths
# an RGB source
params = SimulationParameters(
x=torch.linspace(-1e-3, 1e-3, 256),
y=torch.linspace(-1e-3, 1e-3, 256),
wavelength=torch.tensor([630, 532, 465]) * 1e-9 # R, G, B
)
# the wavefront becomes three-dimensional automatically
wf = Wavefront.gaussian_beam(params, waist_radius=0.3e-3)
print(wf.shape) # torch.Size([3, 256, 256])Device (CPU/GPU)
Moving to the GPU
params.to('cuda') # in-place!
print(params.device) # cuda:0
print(params.x.device) # cuda:0to() works in-place and is idempotent — calling it again is safe.
Automatic propagation of the device
Elements created from params inherit its device:
params.to('cuda')
lens = ThinLens(params, focal_length=100*ureg.mm)
wf = Wavefront.gaussian_beam(params, waist_radius=0.3*ureg.mm)
print(wf.device) # cuda:0Properties
| Property | Description |
|---|---|
params.x, params.y | Coordinate tensors |
params.wavelength | Wavelength axis |
params.axis_names | Tuple of axis names in tensor order |
params.device | torch.device currently in use |
Example: chromatic dispersion
import torch
from svetlanna import SimulationParameters, Wavefront, LinearOpticalSetup
from svetlanna.elements import ThinLens, FreeSpace
from svetlanna.units import ureg
wavelengths = torch.tensor([630, 532, 465]) * 1e-9
params = SimulationParameters(
x=torch.linspace(-2e-3, 2e-3, 512),
y=torch.linspace(-2e-3, 2e-3, 512),
wavelength=wavelengths
)
wf = Wavefront.gaussian_beam(params, waist_radius=0.5e-3)
setup = LinearOpticalSetup([
ThinLens(params, focal_length=50*ureg.mm),
FreeSpace(params, distance=50*ureg.mm, method='zpASM'),
])
wf_focus = setup(wf)
print(wf_focus.shape) # torch.Size([3, 512, 512])Each wavelength diffracts differently, so the three focal spots differ in size — the simulation captures chromatic effects for free.
See also
- Wavefronts — creating fields
- Optical elements — the elements themselves