Skip to content

Config Reference

Complete reference for the COMPASS configuration schema. The composed Hydra config is validated by the Pydantic models in compass.core.config_schema before a simulation runs: unknown keys in any nested section (a typo like thicknes:) fail fast with a validation error. Only the top level accepts extra sections, so experiment overlays can add experiment, optimization, or sweep tables consumed by dedicated runners.

Top-level: CompassConfig

yaml
pixel: ...          # PixelConfig
solver: ...         # SolverConfig
source: ...         # SourceConfig
compute: ...        # ComputeConfig
experiment_name: "default"
output_dir: "./outputs"
seed: 42
FieldTypeDefaultDescription
experiment_namestr"default"Experiment identifier for output directory
output_dirstr"./outputs"Base output directory
seedint42Random seed for reproducibility

pixel: PixelConfig

yaml
pixel:
  pitch: 1.0
  unit_cell: [2, 2]
  bayer_map: [["R", "G"], ["G", "B"]]
  layers: ...       # LayersConfig
FieldTypeDefaultDescription
pitchfloat1.0Pixel pitch in um
unit_cell[int, int][2, 2]Unit cell size [rows, cols]
bayer_maplist[list[str]][["R","G"],["G","B"]]Color channel map

pixel.layers: LayersConfig

yaml
layers:
  air: {thickness: 1.0, material: "air"}
  microlens: ...
  planarization: {thickness: 0.3, material: "sio2"}
  color_filter: ...
  barl: ...
  silicon: ...

Interactive Pixel Stack Builder

Adjust the thickness of each layer in a BSI pixel cross-section. Patterned layers show their z envelope separately from the actual microlens, color filter, grid, and DTI material.

Total stack height:4.58 um
0.01.02.03.04.0Microlens0.60 umn=1.00 / 1.56Planarization0.30 umn=1.46Color Filter0.60 umn=1.46 / 1.55n=1.8Silicon3.00 umn=3.5DTI

pixel.layers.microlens: MicrolensConfig

FieldTypeDefaultDescription
enabledbooltrueEnable microlens
heightfloat0.6Lens sag height (um)
radius_xfloat0.48Semi-axis x (um)
radius_yfloat0.48Semi-axis y (um)
materialstr"polymer_n1p56"Lens material
profile.typestr"superellipse"Profile model
profile.nfloat2.5Squareness parameter
profile.alphafloat1.0Curvature parameter
shift.modestr"auto_cra"Shift mode: "none", "manual", "auto_cra"
shift.cra_degfloat0.0CRA for auto shift (degrees)
shift.shift_xfloat0.0Manual x-shift (um)
shift.shift_yfloat0.0Manual y-shift (um)
gapfloat0.0Inter-lens gap (um)

pixel.layers.color_filter: ColorFilterConfig

FieldTypeDefaultDescription
thicknessfloat0.6Legacy flat CFA thickness (um), used when per-channel thickness is absent
patternstr"bayer_rggb"Filter pattern
materialsdict{"R":"cf_red","G":"cf_green","B":"cf_blue"}Legacy color-to-material mapping
red.material, green.material, blue.materialstrcf_*Per-channel material name
red.thickness, green.thickness, blue.thicknessfloatthicknessPer-channel CFA height (um)
red.contact_angle, green.contact_angle, blue.contact_anglefloat90.0Sidewall angle in degrees for the trapezoid above the grid
grid.enabledbooltrueEnable metal grid
grid.widthfloat0.05Grid line width (um)
grid.thicknessfloatthicknessMetal grid height (um)
grid.heightfloat0.6Legacy alias for grid.thickness
grid.materialstr"tungsten"Grid material
grid.corner_radiusfloat0.0Rounded-rectangle corner radius r (um) for each CF cell, identical at all four corners. 0 = sharp; > 0 models the CF as a rounded rectangle and the grid as its complement. Clamped to (pitch - grid.width) / 2.
n_slicesint8 for tapered surfacesNumber of z-slices used to staircase the tapered color-filter relief

pixel.layers.barl: BarlConfig

yaml
barl:
  layers:
    - {thickness: 0.010, material: "sio2"}
    - {thickness: 0.025, material: "hfo2"}

List of {thickness, material} pairs, ordered top to bottom.

pixel.layers.silicon: SiliconConfig

FieldTypeDefaultDescription
thicknessfloat3.0Silicon thickness (um)
materialstr"silicon"Substrate material
photodiode.position[float, float, float][0, 0, 0.5]PD offset (x, y, z) um
photodiode.size[float, float, float][0.7, 0.7, 2.0]PD extent (dx, dy, dz) um
dti.enabledbooltrueEnable DTI
dti.modestr"fdti""fdti" (full) or "bdti" (backside partial)
dti.widthfloat0.1Trench width at the opening (um)
dti.depthfloat3.0Trench depth (um)
dti.materialstr"sio2"Core fill material
dti.liner.enabledboolfalseConformal high-k liner on trench sidewalls
dti.liner.materialstr"al2o3"Liner material
dti.liner.thicknessfloat0.0Liner thickness (um)
dti.taper_anglefloat90.0Sidewall angle from substrate plane (90 = vertical)
dti.n_slicesint6Staircase z-slices for tapered trenches
surface_texture.enabledboolfalseBackside inverted-pyramid array for NIR light trapping
surface_texture.heightfloat0.3Pyramid height (um)
surface_texture.periodfloat or nullnullPyramid period (um); defaults to pixel pitch
surface_texture.fill_materialstr"sio2"Pit back-fill material
surface_texture.n_slicesint8Staircase z-slices for the pyramids

solver: SolverConfig

yaml
solver:
  name: torcwa
  type: rcwa
  params:
    fourier_order: [9, 9]
    dtype: "complex64"
  stability: ...
FieldTypeDefaultDescription
namestr"torcwa"Solver backend name
typestr"rcwa""rcwa", "fdtd", or "tmm"
paramsdict{"fourier_order": [9,9]}Solver-specific parameters (see below)

solver.params semantics

params is passed through to the solver adapter, so the meaning of each key is solver-specific. The most important difference:

  • torcwa / meent / fmmax use a per-axis Fourier order fourier_order: [m, m](2m+1)² total plane waves.
  • grcwa truncates by TOTAL plane-wave count: set nG (e.g. nG: 49). fourier_order[0] is accepted as a legacy fallback with a warning, but it is not equivalent to the same number in the other RCWA solvers.
  • FDTD solvers use grid_spacing (um) or resolution (pixels/um, meep).

Every result records metadata["qe_method"] (field_integration, eps_imag_weight, tmm_1d_analytic) so cross-solver QE differences can be attributed to post-processing methodology rather than solver accuracy.

solver.stability: StabilityConfig

FieldTypeDefaultDescription
precision_strategystr"mixed""float32", "float64", "mixed", "adaptive" — consumed by the diagnostics pre-simulation checks
allow_tf32boolfalseAllow TF32 on Ampere+ GPUs (keep false for RCWA)
fourier_factorizationstr"li_inverse""naive", "li_inverse", "normal_vector"
energy_check.enabledbooltrueValidate R+T+A ≈ 1 after the run
energy_check.tolerancefloat0.02Max allowed |R+T+A-1|
energy_check.auto_retry_float64booltrueOn violation, rerun once with the dtype promoted (complex64→complex128, float32→float64); the retry is tagged metadata["energy_retry_dtype"]

source: SourceConfig

yaml
source:
  type: planewave
  wavelength:
    mode: single
    value: 0.55
  angle:
    theta_deg: 0.0
    phi_deg: 0.0
  polarization: unpolarized
FieldTypeDefaultDescription
typestr"planewave""planewave" or "cone_illumination"
wavelength.modestr"single""single", "sweep", or "list"
wavelength.valuefloat0.55Single wavelength (um)
wavelength.sweep.startfloat0.38Sweep start (um)
wavelength.sweep.stopfloat0.78Sweep stop (um)
wavelength.sweep.stepfloat0.01Sweep step (um)
wavelength.valueslist[float]nullExplicit wavelength list
angle.theta_degfloat0.0Polar angle (degrees)
angle.phi_degfloat0.0Azimuthal angle (degrees)
polarizationstr"unpolarized""TE", "TM", or "unpolarized"

compute: ComputeConfig

yaml
compute:
  backend: auto
  gpu_id: 0
  num_workers: 4
FieldTypeDefaultDescription
backendstr"auto""auto", "cuda", "cpu", "mps"
gpu_idint0GPU device index
num_workersint4Worker threads for parallel tasks

Hydra config structure

COMPASS uses Hydra for modular configuration:

configs/
  config.yaml           # Main config with defaults
  pixel/
    default_bsi_1um.yaml
    default_bsi_0p8um.yaml
  solver/
    torcwa.yaml
    grcwa.yaml            # + grcwa_fast.yaml, grcwa_converged.yaml presets
    meent.yaml
    fmmax.yaml
    fdtd_flaport.yaml
    fdtdz.yaml
    fdtdx.yaml
    meep.yaml
    tmm.yaml
  source/
    planewave.yaml
    wavelength_sweep.yaml
    cone_illumination.yaml
  compute/
    cuda.yaml
    cpu.yaml
    mps.yaml
  experiment/
    solver_comparison.yaml
    qe_benchmark.yaml
    roi_sweep.yaml
    optimize_microlens.yaml

Override any parameter from the command line:

bash
python scripts/run_simulation.py \
    pixel.pitch=0.8 \
    solver.params.fourier_order=[11,11] \
    source.wavelength.mode=sweep