Getting Started
This guide explains how to interact with L-SURF and covers the key concepts you need to understand for successful ray tracing simulations.
Interacting with L-SURF
L-SURF provides three ways to run simulations:
Command Line Interface (CLI) - Recommended for production simulations
Graphical User Interface (GUI) - Recommended for exploration and learning
Python Scripts - For custom studies and advanced use cases
CLI and GUI: The Preferred Approach
For most users, the CLI and GUI are the recommended ways to interact with L-SURF:
GUI (
lsurf gui): Best for learning, prototyping, and visualizing results. Provides immediate visual feedback and interactive configuration.CLI (
lsurf run): Best for production simulations, batch processing, and automation. Configurations are saved in portable YAML/TOML files.
# Start exploring with the GUI
lsurf gui
# Or build a configuration and run via CLI
lsurf build -o my_simulation.yaml
lsurf run my_simulation.yaml --progress
Numbered Example Scripts
The scripts/ directory contains numbered example scripts (01_basic.py,
02_sources.py, etc.) that demonstrate specific features and techniques.
These scripts are intended as educational examples and references, not as the primary way to run simulations. Use them when you need to:
Understand how a specific feature works
Create custom workflows not supported by the GUI/CLI
Run parameter sweeps or batch experiments
Integrate L-SURF into larger research pipelines
Note
For standard simulations, prefer the GUI or CLI over writing custom scripts. The GUI/CLI handle configuration management, validation, and output automatically.
Understanding Materials and Media
Material assignment is one of the most important concepts in L-SURF. Getting it right ensures physically accurate ray tracing results.
What is a Medium?
A medium is a named reference to a material. Materials define optical properties like refractive index, absorption, and scattering.
# Built-in materials
from lsurf import VACUUM, AIR_STP, WATER, BK7_GLASS
# Custom materials
from lsurf import HomogeneousMaterial, ExponentialAtmosphere
# Create a named medium
builder.register_medium("atmosphere", ExponentialAtmosphere())
builder.register_medium("ocean", WATER)
Why Use Named Media?
Named media provide several benefits:
Consistency - Multiple surfaces referencing the same medium are guaranteed to use identical material properties
Clarity - Names like “atmosphere” and “ocean” are self-documenting
Validation - The builder can detect inconsistent material assignments
Maintainability - Change a material in one place, update everywhere
Surface Material Assignment
Each optical surface has two materials: front and back.
Front - The material on the positive normal side
Back - The material on the negative normal side
from lsurf.surfaces import PlaneSurface, SurfaceRole
# A water surface with air above and water below
water_surface = PlaneSurface(
point=(0, 0, 0),
normal=(0, 0, 1), # Points "up"
role=SurfaceRole.OPTICAL,
name="water_interface",
)
# When normal points up (+z):
# - Front (positive normal) = above the surface = atmosphere
# - Back (negative normal) = below the surface = ocean
builder.add_surface(water_surface, front="atmosphere", back="ocean")
The Background Medium
The background medium is the material where rays propagate between surfaces. It’s typically the “ambient” medium of your simulation.
# Rays travel through atmosphere until they hit a surface
builder.set_background("atmosphere")
Important
Rays always propagate through the background medium. When a ray crosses a surface, the material on that side determines refraction behavior, but propagation continues through the background.
Material Checking and Validation
L-SURF includes automatic validation to catch common configuration errors.
The Intersection Problem
When two surfaces intersect (cross each other in space), they create ambiguous regions where it’s unclear which material should apply.
Consider two perpendicular planes at the origin:
Plane X: normal (1, 0, 0), front=air, back=water
Plane Y: normal (0, 1, 0), front=air, back=glass
At the intersection line, which material is correct? This ambiguity causes validation to fail.
When Validation Fails
The geometry builder raises IntersectingSurfacesError when:
Two surfaces intersect (are not parallel or nested), AND
They have different material assignments
# This FAILS - intersecting planes with different materials
builder.add_surface(plane_x, front="air", back="water")
builder.add_surface(plane_y, front="air", back="glass")
geometry = builder.build() # Raises IntersectingSurfacesError!
When Validation Passes
Intersecting surfaces are allowed when:
They have the same material on all sides (no optical discontinuity)
# This WORKS - same material everywhere
builder.add_surface(plane_x, front="air", back="air")
builder.add_surface(plane_y, front="air", back="air")
They are parallel (never intersect)
# This WORKS - parallel planes can have different materials
builder.add_surface(plane1, front="air", back="water")
builder.add_surface(plane2, front="water", back="glass")
They are nested (concentric spheres)
# This WORKS - concentric spheres are nested, not intersecting
builder.add_surface(inner_sphere, front="air", back="water")
builder.add_surface(outer_sphere, front="water", back="air")
Skipping Validation
For advanced use cases, validation can be disabled:
# Skip validation (use with caution!)
geometry = builder.build(validate=False)
Warning
Disabling validation may result in physically inconsistent simulations. Only use this if you understand the implications.
Cell-Based Geometry (Advanced)
For complex geometries with intersecting surfaces, use the cell-based API:
# Define surfaces without materials
builder.add_surface_only(plane_x)
builder.add_surface_only(plane_y)
# Define cells (regions) explicitly
builder.add_cell("air", ("plane_x", True), ("plane_y", True)) # Quadrant 1
builder.add_cell("water", ("plane_x", False), ("plane_y", True)) # Quadrant 2
builder.add_cell("glass", ("plane_x", True), ("plane_y", False)) # Quadrant 3
builder.add_cell("vacuum", ("plane_x", False), ("plane_y", False)) # Quadrant 4
This explicitly defines which material applies in each region of space.
Using the “Check Geometry” Feature
In the GUI, the Check Geometry button validates your configuration:
Verifies all optical surfaces have materials assigned
Checks for intersecting surfaces with inconsistent materials
Reports warnings and errors
Always check geometry before running large simulations to catch configuration problems early.
Common Material Configurations
Air-Water Interface
media:
air:
type: air
water:
type: water
surfaces:
- name: water_surface
type: plane
front_medium: air # Above (positive normal)
back_medium: water # Below (negative normal)
params:
point: [0, 0, 0]
normal: [0, 0, 1] # Points up
Atmospheric Simulation
media:
atmosphere:
type: exponential_atmosphere
params:
n_sea_level: 1.000293
scale_height: 8500.0
ocean:
type: water
surfaces:
- name: ocean
type: sphere
front_medium: atmosphere # Above ocean
back_medium: ocean # In ocean
params:
center: [0, 0, -6371000] # Earth center
radius: 6371000 # Earth radius
Glass Optics
media:
air:
type: air
glass:
type: glass
params:
refractive_index: 1.52
surfaces:
- name: lens_front
type: sphere
front_medium: air
back_medium: glass
params:
center: [0, 0, 0.1]
radius: 0.5
- name: lens_back
type: sphere
front_medium: glass # Inside lens
back_medium: air # Outside lens
params:
center: [0, 0, -0.1]
radius: 0.5
Next Steps
Command Line Interface (CLI) - Complete CLI reference
Graphical User Interface (GUI) - GUI walkthrough
Implementing Custom Materials - Detailed material documentation
Simulation Workflow - Advanced simulation techniques