lightsmith 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lightsmith-0.2.0 → lightsmith-0.3.0}/.gitignore +2 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/AGENTS.md +5 -4
- lightsmith-0.3.0/CHANGELOG.md +268 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/CITATION.cff +4 -4
- {lightsmith-0.2.0 → lightsmith-0.3.0}/PKG-INFO +5 -5
- {lightsmith-0.2.0 → lightsmith-0.3.0}/README.md +3 -3
- lightsmith-0.3.0/docs/api/core.md +13 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/benchmarks/agents.md +6 -5
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/cli.md +1 -0
- lightsmith-0.3.0/docs/discretization.md +56 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/index.md +8 -6
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/install.md +2 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/materials.md +10 -10
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/mcp.md +15 -12
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/pdk.md +2 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/bands.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/circuit.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/device.md +7 -3
- lightsmith-0.3.0/docs/problems/emission.md +53 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/index.md +19 -16
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/layer-stack.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/mode.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/optimization.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/problems/periodic.md +1 -1
- lightsmith-0.3.0/docs/problems/scattering.md +120 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/quickstart.md +24 -18
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/bem.md +4 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/bpm.md +2 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/dda.md +2 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/fdfd.md +9 -2
- lightsmith-0.3.0/docs/solvers/fdtd.md +571 -0
- lightsmith-0.3.0/docs/solvers/in-development/fdtd-roadmap.md +140 -0
- lightsmith-0.3.0/docs/solvers/in-development/index.md +8 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/index.md +6 -4
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/inverse-3d.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/inverse.md +3 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/mie.md +6 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/quasistatic.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/tmm.md +1 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/llms.txt +6 -5
- {lightsmith-0.2.0 → lightsmith-0.3.0}/mkdocs.yml +5 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/pyproject.toml +2 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/__init__.py +3 -3
- lightsmith-0.3.0/src/lightsmith/api.py +227 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bem/mesh.py +49 -5
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fde/grid.py +176 -148
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fde/modes.py +8 -5
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fde/section.py +11 -6
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd/engine.py +17 -8
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd/grid.py +38 -16
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd3d/engine.py +3 -1
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/absorption.py +91 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/beam.py +190 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/device.py +601 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/emission.py +258 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/engine.py +923 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/grid.py +210 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/layered.py +482 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/layered_far.py +216 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/options.py +92 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdtd/periodic.py +40 -19
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/ports.py +378 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/scattering.py +736 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/setup.py +773 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/substrate.py +190 -0
- lightsmith-0.3.0/src/lightsmith/backends/_fdtd/symmetry.py +240 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdtd/tfsf.py +68 -48
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/base.py +17 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/bem.py +28 -3
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/bpm.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/circuit.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/dda.py +23 -9
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/eme.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/fde.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/fdfd.py +7 -6
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/fdtd.py +56 -11
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/mie.py +2 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/mie_native.py +91 -5
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/pwe.py +2 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/quasistatic.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/rcwa.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/tmatrix_treams.py +2 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/tmm.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/cli.py +16 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/device.py +16 -1
- lightsmith-0.3.0/src/lightsmith/discretize.py +513 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/backend.py +19 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/materials.py +22 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/_worker.py +19 -30
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/kinds.py +12 -2
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/remote.py +3 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/server.py +19 -7
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/summaries.py +1 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/problems.py +350 -306
- lightsmith-0.3.0/src/lightsmith/progress.py +57 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/raster.py +33 -0
- lightsmith-0.3.0/src/lightsmith/resonance.py +72 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/results.py +84 -3
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/spec.py +33 -1
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_bem.py +21 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_bpm.py +30 -0
- lightsmith-0.3.0/tests/test_core.py +248 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_dda.py +40 -0
- lightsmith-0.3.0/tests/test_discretization.py +208 -0
- lightsmith-0.3.0/tests/test_emission.py +114 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_fde.py +35 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_fdfd.py +136 -0
- lightsmith-0.3.0/tests/test_fdtd.py +618 -0
- lightsmith-0.3.0/tests/test_fdtd_device.py +277 -0
- lightsmith-0.3.0/tests/test_fdtd_graded.py +410 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_fdtd_periodic.py +14 -0
- lightsmith-0.3.0/tests/test_fdtd_substrate.py +611 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_materials.py +12 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_mcp_server.py +47 -2
- lightsmith-0.3.0/tests/test_optics.py +184 -0
- lightsmith-0.3.0/tests/test_progress.py +110 -0
- lightsmith-0.3.0/tests/test_resonance.py +41 -0
- lightsmith-0.2.0/CHANGELOG.md +0 -91
- lightsmith-0.2.0/docs/api/core.md +0 -9
- lightsmith-0.2.0/docs/problems/scattering.md +0 -82
- lightsmith-0.2.0/docs/solvers/fdtd.md +0 -145
- lightsmith-0.2.0/src/lightsmith/api.py +0 -114
- lightsmith-0.2.0/src/lightsmith/backends/_fdtd/engine.py +0 -470
- lightsmith-0.2.0/src/lightsmith/backends/_fdtd/options.py +0 -42
- lightsmith-0.2.0/src/lightsmith/backends/_fdtd/scattering.py +0 -235
- lightsmith-0.2.0/src/lightsmith/backends/_fdtd/setup.py +0 -261
- lightsmith-0.2.0/tests/test_core.py +0 -95
- lightsmith-0.2.0/tests/test_fdtd.py +0 -221
- {lightsmith-0.2.0 → lightsmith-0.3.0}/LICENSE +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/backends.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/circuits.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/index.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/inverse.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/layout.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/materials.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/pdk.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/problems.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/results.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/api/spec.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/benchmarks/index.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/changelog.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/contributing.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/conventions.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/landscape.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/circuit.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/eme.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/fde.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/pwe.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/rcwa.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/docs/solvers/tmatrix.md +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/circuit_mzi.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/circuit_ring.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/circuit_splitter_tree.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/drude_sphere.json +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/inverse_design_3d_mode_converter.json +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/inverse_design_3d_mode_converter.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/inverse_design_bend.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/mcp_client.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/metalens_rcwa.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/examples/pdk_mzi.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bem/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bem/fields.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bem/operators.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bem/singular.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bpm/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bpm/engine.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bpm/operator.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bpm/pade.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_bpm/tridiag.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_eme/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fde/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd/linsolve.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd/modes.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd/operators.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd/ports.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd3d/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd3d/grid.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd3d/linsolve.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd3d/modes.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd3d/operators.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdfd3d/ports.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdtd/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_fdtd/media.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_pwe/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_pwe/engine.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_pwe/geometry.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_pwe/solvers.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_rcwa/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_rcwa/core.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_rcwa/fourier.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/backends/_rcwa/linalg.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/circuits/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/circuits/engine.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/circuits/models.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/circuits/touchstone.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Ag/Johnson.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Ag/McPeak.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Ag/Rakic-LD.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Al/McPeak.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Al/Rakic-LD.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Al/Rakic.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Au/Johnson.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Au/McPeak.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Au/Rakic-LD.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Cu/Johnson.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Cu/McPeak.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Cu/Rakic-LD.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/H2O/Daimon-24.0C.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/H2O/Hale.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Si/Aspnes.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Si/Green-2008.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Si/Li-293K.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/Si/Schinke.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/SiO2/Lemarchand.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/SiO2/Malitson.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/TiO2/Devore-o.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/TiO2/Sarkar.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/TiO2/Siefke.yml +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/data/materials/manifest.json +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/export.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/objectives.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/optimizers.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/parametrization.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/spec.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/inverse/topopt.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/layout.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/materials_fit.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/__main__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/budget.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/config.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/jobs.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/mcp_server/matlib.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/optics/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/optics/propagation.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/pdk/__init__.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/pdk/cells.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/pdk/component.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/pdk/fitting.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/pdk/flow.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/pdk/technology.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/src/lightsmith/py.typed +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_circuit.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_eme.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_fdfd3d.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_inverse.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_layout.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_mie_native.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_pdk.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_pwe.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_quasistatic.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_rcwa.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_tmatrix_treams.py +0 -0
- {lightsmith-0.2.0 → lightsmith-0.3.0}/tests/test_tmm.py +0 -0
|
@@ -4,10 +4,10 @@ Guidance for AI agents (and humans) using or developing lightsmith.
|
|
|
4
4
|
|
|
5
5
|
## Using the library
|
|
6
6
|
|
|
7
|
-
1. Build a problem of one of the kinds in `lightsmith/problems.py` (scattering, layer_stack, periodic, mode, device, bands, circuit, optimization); `lightsmith schema` prints the JSON Schema of all of them. Units are **nm**; wavelengths are **vacuum** wavelengths.
|
|
7
|
+
1. Build a problem of one of the kinds in `lightsmith/problems.py` (scattering, emission, layer_stack, periodic, mode, device, bands, circuit, optimization); `lightsmith schema` prints the JSON Schema of all of them. Units are **nm**; wavelengths are **vacuum** wavelengths.
|
|
8
8
|
2. Call `estimate` before `solve` for grid-based solvers (DDA, FDTD, FDFD, RCWA, PWE): it reports problem size, precision and memory without solving.
|
|
9
9
|
3. `solve(problem, method="auto")` picks the preferred applicable method for the problem kind (see `AUTO_ORDER` in `api.py`). Errors explain why a backend was skipped and what to change.
|
|
10
|
-
4. `compare(problem, methods=[...])` cross-checks methods; Mie is the reference for single spheres, otherwise the first method listed.
|
|
10
|
+
4. `compare(problem, methods=[...])` cross-checks methods; Mie is the reference for single spheres, otherwise the first method listed (or, with no list, the one `auto` would pick).
|
|
11
11
|
5. Results carry `provenance` (backend versions, device, precision, iterations, residuals) and `warnings`. Check `warnings` before trusting numbers.
|
|
12
12
|
|
|
13
13
|
Component-to-circuit flow (`lightsmith.pdk`): `get_component(cell, **params)` builds layout + ports (port centres are the S-parameter reference planes; names o1, o2, ... as gdsfactory); `flow.simulate` solves its `DeviceProblem` via `solve` (2D effective-index plan view by default); `flow.component_model` fits and caches the S-parameters (key = cell, params, technology, band, solver, options); circuit netlists use `{"component": "pdk:<cell>", "settings": {<params>, <FlowSettings>}}`. Technologies are `Technology` JSON (`generic_soi()` uses only open data). Compare circuits with direct simulations only when both use the same solver and grid (`FlowSettings(method=..., waveguide_model="device")`): FDFD's numerical dispersion at the default grid is ~1e-2 in neff, and with the default 4x subpixel sampling the grid alignment of waveguide edges shifts neff by ~7e-3 between instances (use `subsamples: 16`).
|
|
@@ -15,10 +15,11 @@ Component-to-circuit flow (`lightsmith.pdk`): `get_component(cell, **params)` bu
|
|
|
15
15
|
Interfaces, all JSON in / JSON out:
|
|
16
16
|
|
|
17
17
|
- Python: `import lightsmith as ls`
|
|
18
|
-
- CLI: `lightsmith {doctor,backends,schema,estimate,solve,compare}` — errors are JSON on stderr, exit code 1.
|
|
18
|
+
- CLI: `lightsmith {doctor,backends,schema,estimate,discretization,solve,compare}` — errors are JSON on stderr, exit code 1.
|
|
19
|
+
`discretization` (`ls.discretization`) shows what a backend will discretise (grid, mesh, dipoles, harmonics, cells) without solving.
|
|
19
20
|
- MCP: `lightsmith-mcp` (stdio; `--http` for streamable HTTP). Tools:
|
|
20
21
|
- discovery: `list_problem_kinds`, `get_schema(kind)`, `list_backends`, `check_environment`, `validate_problem`;
|
|
21
|
-
- solving: `estimate`, `solve`, `start_solve`, `compare`;
|
|
22
|
+
- solving: `estimate`, `get_discretization`, `solve`, `start_solve`, `compare`;
|
|
22
23
|
- jobs: `get_job`, `list_jobs`, `cancel_job`, `get_result`;
|
|
23
24
|
- materials: `search_materials`, `get_material`, `fit_drude_lorentz`.
|
|
24
25
|
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `lightsmith` library are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
|
+
[semantic versioning](https://semver.org/) (while the version is 0.x, minor releases may break the API).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.3.0] - 2026-11-08
|
|
10
|
+
|
|
11
|
+
- `device="auto"` runs on the CPU, with a warning, when the problem will not fit in the GPU's free memory. Before,
|
|
12
|
+
`examples/pdk_mzi.py` took FDFD's block LU (12.9 GB) onto a 12 GB GPU, where Windows paged it for hours, although
|
|
13
|
+
SuperLU on the CPU needs 0.8 GB. `estimate` reports the same choice (`device`, `device_note`). Naming a device
|
|
14
|
+
still gets that device.
|
|
15
|
+
- The MCP server's solver process reports progress through `lightsmith.progress`: every wavelength or iteration of a
|
|
16
|
+
solve, and each method of a `compare`. Inverse design goes through `solve`, so `device="auto"` treats it the same.
|
|
17
|
+
- 2D FDFD rasterises the geometry once per solve, as 3D does, and tests each structure only inside its bounding box.
|
|
18
|
+
For the whole MZI of `examples/pdk_mzi.py` that took 690 of 846 s per wavelength, against 76 s for the factorisation.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- `method="auto"` passes over a 2D FDFD problem that exceeds `max_cells` and goes on to FDTD; the estimate now says
|
|
23
|
+
`fits: false` instead of raising, and only an explicit solve is refused.
|
|
24
|
+
- FDFD accepts 2D ports with z size 0, as the `Port` schema documents, and refuses only a true z normal. The MCP server's
|
|
25
|
+
device example now leaves room for absorbing layers, so it runs on EME, BPM, FDFD and FDTD.
|
|
26
|
+
- The MCP budget now covers 2D FDFD and 2D inverse design: their estimates report `memory_bytes` for the solver the device
|
|
27
|
+
will use.
|
|
28
|
+
- FDTD devices apply the same dispersive time-step limit as every other FDTD problem kind.
|
|
29
|
+
- The Mie refusal suggested `tmatrix` for non-spherical particles, which refuses them too; it now names `bem` and `dda`, as do
|
|
30
|
+
the MCP prompts.
|
|
31
|
+
- CLI usage errors are JSON on stderr with exit status 1, like every other failure.
|
|
32
|
+
- `discretization` no longer assumes a third-party backend has a built-in backend's internals; it reports no plan unless the
|
|
33
|
+
plugin overrides `Backend.discretization`.
|
|
34
|
+
- Backends' `differentiable` flag now means "has a torch-differentiable entry point", and native Mie and PWE set it.
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **Progress callbacks and cancellation**: `solve(..., progress=callback)` and `compare(..., progress=callback)` call back with
|
|
39
|
+
`{"stage", "fraction", ...}` while solving: DDA per wavelength and incidence, BEM and FDFD per wavelength, FDTD per chunk of
|
|
40
|
+
steps, inverse design per iteration. A callback may raise `lightsmith.progress.Cancelled` to stop.
|
|
41
|
+
- Backends declare `options_model`, so `list_backends` on the MCP server and `/v1/backends` on Cloud carry each backend's
|
|
42
|
+
options as a JSON Schema.
|
|
43
|
+
- Every result records `provenance.versions` (library, NumPy, PyTorch when used). Under `method="auto"`, results and estimates
|
|
44
|
+
record `auto_skipped`: why the earlier backends were passed over. DDA results keep their BiCGStab residuals.
|
|
45
|
+
- `tests/test_optics.py` validates `lightsmith.optics` against closed forms; tests for the DDA's `weighted` and
|
|
46
|
+
`extrapolate` modes, which also lose their "experimental" label in favour of what they do and where they fail.
|
|
47
|
+
- The agent benchmark gained an emission task (44 tasks; every problem kind is now covered, and a test enforces it). Its gold
|
|
48
|
+
nanorod task now asks for the resonance wavelength, on which BEM and DDA agree.
|
|
49
|
+
|
|
50
|
+
- **`lightsmith.discretization(problem, method)`**, `lightsmith discretization` and the MCP tool `get_discretization`: what a backend
|
|
51
|
+
will discretise, before any solve, with a common envelope (`layout_kind`, a labelled `summary`, a `payload`, the
|
|
52
|
+
estimate, warnings, and the library's refusal in `error`). FDTD: the Yee grid, TFSF and flux boxes, CPML,
|
|
53
|
+
refinement regions and mirror planes; unit cells of periodic structures and layer stacks; device grids and
|
|
54
|
+
ports. FDFD device grids and ports, inverse-design regions, the DDA dipole lattice, the BEM surface mesh, Mie
|
|
55
|
+
and T-matrix multipole orders, RCWA harmonics, FDE grids, EME and BPM cells, PWE k-paths and plane waves. Each
|
|
56
|
+
calls the backend's own planning code and never solves. `Backend.discretization` lets plugins answer too.
|
|
57
|
+
See `docs/discretization.md`.
|
|
58
|
+
|
|
59
|
+
- **FDTD graded grids for device problems**: `mesh_override` boxes and `grid: "auto"` (each structure refined
|
|
60
|
+
to `cells_per_wavelength` in its own material) now work for `kind: "device"`, in 2D and 3D. Ports sit in
|
|
61
|
+
uniform cells along their normals; across their windows the cells may be graded, and the port modes come
|
|
62
|
+
from the FDE problem on the same non-uniform cross-section (the FDE grid gained per-cell widths), so they stay
|
|
63
|
+
exact for the grid: a straight guide still transmits |S21| = 1 with the grid's phase (1e-10 rad). A
|
|
64
|
+
500 → 900 nm 2D step graded from 25 to 10 nm is within 2e-5 of a uniform 10 nm run with 63 % of the cells,
|
|
65
|
+
and a 3D wire step graded from 40 to 15 nm within 8e-6 of a uniform 15 nm run with 45 % of the cells.
|
|
66
|
+
- **FDTD graded grids** (scattering): `grid: "auto"` refines each particle's bounding box to the spacing its
|
|
67
|
+
material and size need, and `mesh_override: [{center_nm, size_nm, spacing_nm}]` adds refinement boxes. The
|
|
68
|
+
cells grade back to the base spacing at most `grading_ratio` (1.25) per cell. The grid is a tensor product
|
|
69
|
+
with independent per-axis widths. The Yee update uses primary and dual width arrays, so it conserves the
|
|
70
|
+
same discrete energy as the uniform one, on the CPU and on CUDA with CUDA graphs. The CPML, TFSF tables
|
|
71
|
+
(exact discrete background of the graded 1D problem, still leak-free), layered substrates, conformal
|
|
72
|
+
smoothing (metals' vertex tensor included), flux and far-field surfaces, near fields, particle absorption
|
|
73
|
+
and mirror planes all follow the widths. An n = 3.5, r = 20 nm sphere is within 0.11 % of a uniform 2 nm run, whose own error against Mie is
|
|
74
|
+
0.7 %, with 153 k cells instead of 242 k. A Drude sphere of r = 10 nm at 0.5 nm cells needs 488 k cells
|
|
75
|
+
instead of 1.74 M (2.1× faster in double precision). Its spectrum differs from the uniform run by at most
|
|
76
|
+
7e-4 of the peak, against a 13 % discretisation error. Particles on glass or on an absorbing substrate
|
|
77
|
+
agree within 0.34 %, and far fields within 0.1 % of the uniform run's. The coarsest cells must stay fine:
|
|
78
|
+
any change of cell size h reflects about (k h)²/16 of a wave, so `grid: "auto"` uses 60 cells per
|
|
79
|
+
background wavelength (`background_cells_per_wavelength`). A uniform grid gives today's run bit for bit.
|
|
80
|
+
Scattering only, with plane waves along an axis (or graded only along the axes the wave does not vary along).
|
|
81
|
+
- **FDTD device problems** (`kind: "device"`, 3D and 2D): S-parameters between waveguide ports. Each port
|
|
82
|
+
mode is an exact eigenmode of the FDTD grid itself: the FDE cross-section problem solved with the
|
|
83
|
+
leapfrog frequency, the discrete propagation constant and each node's discrete material response, then
|
|
84
|
+
interpolated over the band from Chebyshev nodes. So the TFSF mode sources launch one way only, and the
|
|
85
|
+
monitors split the fields into forward and backward modes exactly. A straight silicon wire transmits with
|
|
86
|
+
|S21| = 1 to 1e-6 and the grid's own phase. A 2D width step matches FDFD to 3e-5 (TE) and 3.4e-4 (TM) at
|
|
87
|
+
dl = 10 nm, and a 3D one is converged to 1e-4 between dx = 25 and 15 nm. Device problems default to
|
|
88
|
+
`subpixel` smoothing (port modes need a diagonal permittivity). `polarization` selects TE or TM in 2D.
|
|
89
|
+
- **FDTD mirror symmetries** (`symmetry: "auto"`, the default; `"off"` turns them off). A scattering run
|
|
90
|
+
whose particles are mirror-symmetric about their centre, lit by a plane wave that travels in the mirror
|
|
91
|
+
plane and is polarised in it (a PMC plane) or normal to it (a PEC plane), keeps half the grid per plane:
|
|
92
|
+
2× or 4× fewer cells. The conformal tensors, metals' vertex tensor included, are folded across the
|
|
93
|
+
planes, so cross sections, near fields and far fields match the full run to 1e-11 in double precision,
|
|
94
|
+
over substrates and absorbing substrates too. On the GPU, runs of 1–5 M cells are 1.55–2.3× faster (3.7×
|
|
95
|
+
in steady state at 15 M cells). The provenance and `estimate` report the planes used.
|
|
96
|
+
- **FDTD conformal meshing.** `mesh_refinement` (`staircase`, `volume_average`, `subpixel`, `conformal`). The
|
|
97
|
+
new default, `conformal`, adds the off-diagonal terms of tensor subpixel smoothing, symmetrised for
|
|
98
|
+
stability. Dielectric sphere C_ext error at dx = 6 nm falls from 1.1 % to 0.04 %. At metal interfaces
|
|
99
|
+
the full dispersive tensor is applied at grid vertices as a sum of passive congruences, so it is stable
|
|
100
|
+
by construction. On a Drude sphere's plasmon band it cuts the C_ext error 2–4× compared with diagonal
|
|
101
|
+
smoothing (2.5 % against 6.6 % RMS at dx = 2 nm), and the error now falls as the grid is refined.
|
|
102
|
+
- **FDTD far field** (`outputs.far_field`): near-to-far-field projection of the scattered fields, within
|
|
103
|
+
0.4 % of Mie.
|
|
104
|
+
- **Dipole emission** (`kind: "emission"`): Purcell factor, radiative enhancement, efficiency and
|
|
105
|
+
radiation pattern of a point dipole near particles. Exact for one sphere in native Mie; any geometry in
|
|
106
|
+
FDTD (within 0.2 % of Mie next to a dielectric sphere).
|
|
107
|
+
- **Gaussian beams** (`illumination: GaussianBeam`, FDTD): a focused beam as a sum of TFSF plane waves at
|
|
108
|
+
fixed angles (the waist scales with the wavelength, as for a lens of fixed NA); cross sections per unit
|
|
109
|
+
focal intensity. Within 0.13 % of Mie at the focus and 0.1 % of the beam profile off axis.
|
|
110
|
+
- **FDTD substrates** (`Simulation.substrate`): particles on or above a non-absorbing half-space, lit from
|
|
111
|
+
above at any angle or through the substrate, including total internal reflection. The TFSF box takes
|
|
112
|
+
the background field (incident, reflected and transmitted waves) from an auxiliary column at normal
|
|
113
|
+
incidence. At oblique incidence it comes from tables of the exact discrete background (a 1D discrete
|
|
114
|
+
problem along z per frequency, then an inverse FFT). Either way it does not leak where it cuts the
|
|
115
|
+
interface. C_sca is within 0.2–0.5 % of a dipole reference for a sphere above glass (1.7 % for p
|
|
116
|
+
under total internal reflection, where the dipole model is least exact). Near fields are supported;
|
|
117
|
+
absorbing substrates and far fields are not yet.
|
|
118
|
+
- **FDTD absorbing substrates and far fields over substrates.** Particles over metals or other absorbing
|
|
119
|
+
substrates. Over one, `c_abs` is the particles' own absorption, from the grid's exact discrete Poynting
|
|
120
|
+
balance on their nodes; it equals the inflow through a closed box around the particle to 1e-6. `c_sca` is
|
|
121
|
+
the power scattered upward, and `c_ext` the power taken from the reflected wave (the reflectance change).
|
|
122
|
+
`outputs.far_field` now works over any substrate, into both half-spaces, by reciprocity with the grid's
|
|
123
|
+
own layered background. Against a multipole reference, a sphere over an absorbing dielectric is within
|
|
124
|
+
0.1 %, and one over a Drude metal within 0.14 %. Over glass the new quantities reproduce the box fluxes
|
|
125
|
+
to 3e-4. `precision: "auto"` runs double over an absorbing substrate: in float32 a metal's long
|
|
126
|
+
ring-down left rounding noise of up to 1.2 % in C_sca.
|
|
127
|
+
- **Leak-free plane waves and Gaussian beams at any angle** (FDTD scattering). Every plane wave, and every
|
|
128
|
+
component of a Gaussian beam, is fed from tables of the grid's exact discrete plane wave (the oblique
|
|
129
|
+
substrate method, with a uniform background), so the TFSF box does not leak at any direction. A sphere's
|
|
130
|
+
C_ext agrees between directions to 4e-5 (0.35 % before). A 20 nm sphere is within 0.1 % of Mie: with the
|
|
131
|
+
1D-fed source, the incident flux through the box did not cancel, giving errors up to 22 % at 800 nm. A beam
|
|
132
|
+
on a 40 nm sphere is within 0.04 % of Mie at the focus and off axis (0.13 % before). Gaussian beams now
|
|
133
|
+
support near-field output.
|
|
134
|
+
- **Resonances** (`outputs.resonances`): wavelengths, Q factors and amplitudes from the FDTD ring-down,
|
|
135
|
+
through the new `lightsmith.resonance.harmonic_inversion` (multi-channel matrix pencil).
|
|
136
|
+
|
|
137
|
+
### Changed
|
|
138
|
+
|
|
139
|
+
- FDTD scattering stops when the scattered field has decayed, not the total field. The incident pulse
|
|
140
|
+
no longer sets the peak, so weak, sharp resonances are no longer cut off: a 15 nm Drude sphere's
|
|
141
|
+
spectrum rippled by ±10 %.
|
|
142
|
+
- FDTD `pml_cells` defaults to 16 with a substrate (10 otherwise).
|
|
143
|
+
- FDTD voxelisation evaluates the geometry once per point of the half-cell lattice, where it used to test each
|
|
144
|
+
field position's 26 neighbours separately for every component. The result is the same, and it is 4× faster
|
|
145
|
+
(45 s → 10 s for a 2.5 M-cell 3D MMI).
|
|
146
|
+
- FDTD scattering: the default TFSF padding and PML gap are now at least 3 % of the longest wavelength
|
|
147
|
+
in the medium, so refining the grid no longer moves the monitors closer to the particle.
|
|
148
|
+
- FDTD: the table-fed plane-wave source updates all face slabs of a kind in one gather and scatter, and
|
|
149
|
+
stops waiting once the pulse has passed (the wrapped edge of the table's inverse FFT had set it to the
|
|
150
|
+
whole table), so small scattering runs are 2.3–2.8× faster with the same results.
|
|
151
|
+
- Documentation describes problems through the Python models first; saving and loading them as JSON
|
|
152
|
+
files for the CLI and MCP server is covered in the quick start.
|
|
153
|
+
|
|
154
|
+
### Fixed
|
|
155
|
+
|
|
156
|
+
- Inverse design: `estimate` now applies the optimisation-level solver options (`OptimizationProblem.options`),
|
|
157
|
+
merged over the device's key by key as the optimiser merges them (`inverse.backend.device_problem`); it used
|
|
158
|
+
the device's options alone.
|
|
159
|
+
- FDTD options: the `pml_cells` description gives the device default (12), and the `mesh_override` description
|
|
160
|
+
no longer names another product.
|
|
161
|
+
- FDTD: the time step is reduced where a dispersive (Drude–Lorentz) material would make the update unstable
|
|
162
|
+
on a coarse grid, checked from the update's eigenvalues over the grid's spatial frequencies. The
|
|
163
|
+
Johnson–Christy gold fit diverged at dx ≥ 20 nm, and lossy constants at dx near half a wavelength.
|
|
164
|
+
- **3D devices with ports facing y** (FDE ports, EME, BPM): the cross-section's local x axis was global z,
|
|
165
|
+
so `"te"` selected the vertical-E mode and BPM's `bend_radius_nm` bent the guide out of the chip plane.
|
|
166
|
+
Local x is now the in-plane transverse axis for ports facing x or y, as it already was in 2D. Results for
|
|
167
|
+
ports facing x, and for all 2D devices, are unchanged.
|
|
168
|
+
- **`compare`**: device, circuit, mode and band results now report differences (they came back empty);
|
|
169
|
+
without a method list the reference is the method `auto` would pick, not the alphabetically first
|
|
170
|
+
backend; relative cross-section differences are floored at 0.1 % of the reference extinction, so a
|
|
171
|
+
lossless particle's near-zero absorption no longer gives huge relative errors. Results that cannot be
|
|
172
|
+
compared are listed under `not_compared`.
|
|
173
|
+
- **FDTD periodic and layer-stack transmission** into an absorbing substrate is referred to the interface,
|
|
174
|
+
as in TMM and RCWA. Before, T was taken a few cells inside the substrate (Si at 420 nm read 0.744 instead
|
|
175
|
+
of 0.815) and metal substrates reported T = 0.
|
|
176
|
+
- **BEM** checks particle overlap on the volume-corrected meshes the solve uses, so particles about 0.1 nm
|
|
177
|
+
apart no longer produce interpenetrating meshes, and warns when a gap is smaller than the mesh size.
|
|
178
|
+
- **`auto`** skips a backend whose estimate exceeds its own size limit (BEM `max_unknowns`, DDA
|
|
179
|
+
`max_dipoles`, T-matrix `max_modes`, ...) and falls through to the next method, instead of picking it and
|
|
180
|
+
failing at solve time.
|
|
181
|
+
- **`Tabulated`** materials sort their data by wavelength (energy-ordered files are descending, which
|
|
182
|
+
interpolation silently got wrong) and refuse duplicate wavelengths or mismatched column lengths.
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
## [0.2.0] - 2026-11-02
|
|
186
|
+
|
|
187
|
+
### Added
|
|
188
|
+
|
|
189
|
+
- **BEM** (`lightsmith-bem`): PMCHWT surface integral equations on RWG meshes for spheres, spheroids,
|
|
190
|
+
cylinders, layered spheres and disjoint clusters, with near and far fields, on CPU or GPU. `auto` tries
|
|
191
|
+
it after T-matrix for scattering.
|
|
192
|
+
- **BPM** (`lightsmith-bpm`): wide-angle Padé beam propagation for devices, 2D and 3D (semi- and
|
|
193
|
+
full-vectorial), with bends, on CPU or GPU.
|
|
194
|
+
- **FDTD oblique and conical incidence** on layer stacks and periodic structures, up to 85° from the
|
|
195
|
+
normal, with Bloch-periodic boundaries at fixed in-plane wavevector. Scattering accepts any incidence
|
|
196
|
+
direction.
|
|
197
|
+
- **PDK flow** (`lightsmith.pdk`): technologies as JSON (`generic_soi` from open data), parametric cells
|
|
198
|
+
with GDS output, simulation at the port reference planes, fitted and cached compact models, and
|
|
199
|
+
`pdk:<cell>` instances in circuit netlists.
|
|
200
|
+
- **MCP server rewrite** on MCP SDK 2.x: jobs, budgets, resources, prompts, materials tools, and remote
|
|
201
|
+
mode. The `mcp` extra is now `mcp>=2.3,<3`.
|
|
202
|
+
- **3D inverse design** on a full-vector 3D FDFD solver (`lightsmith-fdfd` with `dimension=3` devices):
|
|
203
|
+
exact discrete port modes, TF/SF mode sources, batched BiCGStab on CPU or GPU, and adjoint gradients
|
|
204
|
+
with warm starts across iterations.
|
|
205
|
+
- **Agent benchmark** (`benchmarks/agents/`): 43 graded tasks for agents using the MCP server.
|
|
206
|
+
|
|
207
|
+
### Changed
|
|
208
|
+
|
|
209
|
+
- The documentation moved to <https://docs.lightsmith.dev/>. The old GitHub Pages address redirects there.
|
|
210
|
+
|
|
211
|
+
### Fixed
|
|
212
|
+
|
|
213
|
+
- Multilayer Mie: avoid cancellation near zeros of ψₙ, which gave errors up to 12% for coated spheres
|
|
214
|
+
whose interface sits on such a zero.
|
|
215
|
+
- RCWA: grazing diffraction orders (kz = 0) inside uniform layers no longer make the layer S-matrix
|
|
216
|
+
singular.
|
|
217
|
+
- FDTD: runs whose fields grow without bound now raise, also on CPU in float64, where they used to stay
|
|
218
|
+
finite and return cross sections off by many orders of magnitude.
|
|
219
|
+
- Topology optimisation: `OptimizationProblem.options` now merges into the device's options key by key
|
|
220
|
+
within each method, instead of replacing the method's whole dictionary (which dropped `dl_nm`,
|
|
221
|
+
`pml_cells` and the like).
|
|
222
|
+
- `device="auto"` falls back to CPU when CUDA is available but no device is visible
|
|
223
|
+
(`CUDA_VISIBLE_DEVICES=""`), instead of failing with "Invalid device id".
|
|
224
|
+
|
|
225
|
+
## [0.1.0] - 2026-11-01
|
|
226
|
+
|
|
227
|
+
First public release.
|
|
228
|
+
|
|
229
|
+
### Added
|
|
230
|
+
|
|
231
|
+
- **One problem spec for every method.** Pydantic models with a `kind` discriminator: `scattering`,
|
|
232
|
+
`layer_stack`, `periodic`, `mode`, `device`, `bands`, `circuit`, `optimization`. Any of them can be
|
|
233
|
+
passed as a model, dict or JSON string. `lightsmith schema` prints the JSON Schema. Lengths are in nm,
|
|
234
|
+
wavelengths are vacuum wavelengths, and the time convention is `exp(-iωt)`.
|
|
235
|
+
- **Entry points** `solve`, `estimate`, `compare`, `choose_method` and `doctor`. `method="auto"` picks
|
|
236
|
+
the preferred applicable solver and explains why the others were skipped.
|
|
237
|
+
- **Solvers.** All are MIT, and all are native unless noted.
|
|
238
|
+
- Scattering: Mie (native, homogeneous and layered spheres, GPU and autodiff), Mie through
|
|
239
|
+
`miepython`, T-matrix through `treams` (`tmatrix` extra), DDA, FDTD, and the quasistatic dipole
|
|
240
|
+
approximation.
|
|
241
|
+
- Thin films and periodic structures: TMM (coherent and incoherent layers, differentiable), RCWA
|
|
242
|
+
(1D/2D lattices, conical incidence, Li and normal-vector factorisation, differentiable), and
|
|
243
|
+
FDTD for periodic and layer-stack problems at normal incidence.
|
|
244
|
+
- Waveguides and devices: FDE (full-vector, bends, PML), EME, and 2D FDFD with adjoint gradients.
|
|
245
|
+
- Photonic crystals: PWE (2D TE/TM and 3D, dense and LOBPCG solvers).
|
|
246
|
+
- Circuits: S-matrix netlist solver with compact models and Touchstone I/O, differentiable.
|
|
247
|
+
- Inverse design: density-based topology optimisation on FDFD (filters, projection, minimum
|
|
248
|
+
feature size, MMA, Adam and L-BFGS-B), exported to polygons and GDS.
|
|
249
|
+
- **Materials.** Bundled CC0 datasets from refractiveindex.info (Au, Ag, Al, Cu, Si, SiO2, TiO2,
|
|
250
|
+
water), online fetch of any database entry, and passive Drude–Lorentz fitting for time-domain solvers.
|
|
251
|
+
- **Layout.** Built-in GDSII reader and writer, extrusion of GDS layers into device problems, and an
|
|
252
|
+
optional gdsfactory bridge (`layout` extra).
|
|
253
|
+
- **Interfaces.** The `lightsmith` CLI (JSON on stdout, JSON errors on stderr) and the `lightsmith-mcp`
|
|
254
|
+
MCP server (`mcp` extra) for AI agents.
|
|
255
|
+
- **Plugins.** The `lightsmith.backends` entry-point group, so GPL-licensed solvers can live in separate
|
|
256
|
+
packages (`lightsmith-adda`, `lightsmith-scattnlay`).
|
|
257
|
+
- **Typing.** A `py.typed` marker; the public API is annotated.
|
|
258
|
+
- **Documentation** site (MkDocs Material), `CITATION.cff` and `.zenodo.json`.
|
|
259
|
+
|
|
260
|
+
### Notes
|
|
261
|
+
|
|
262
|
+
- The `mcp` extra is pinned to `mcp>=1.2,<2`: the server uses the mcp 1.x `FastMCP` API, which mcp 2.x
|
|
263
|
+
renamed.
|
|
264
|
+
|
|
265
|
+
[Unreleased]: https://github.com/lightsmith-photonics/lightsmith/compare/v0.3.0...HEAD
|
|
266
|
+
[0.3.0]: https://github.com/lightsmith-photonics/lightsmith/compare/v0.2.0...v0.3.0
|
|
267
|
+
[0.2.0]: https://github.com/lightsmith-photonics/lightsmith/compare/v0.1.0...v0.2.0
|
|
268
|
+
[0.1.0]: https://github.com/lightsmith-photonics/lightsmith/releases/tag/v0.1.0
|
|
@@ -4,16 +4,16 @@ type: software
|
|
|
4
4
|
title: "Lightsmith: an open, GPU-native photonics suite built for AI agents"
|
|
5
5
|
abstract: >-
|
|
6
6
|
Lightsmith describes a photonics problem once, as typed JSON, and solves it
|
|
7
|
-
with Mie, T-matrix, DDA, FDTD, TMM, RCWA, FDE, EME, FDFD, PWE and
|
|
8
|
-
circuit solvers on CPU or GPU, with differentiable inverse design. Every
|
|
7
|
+
with Mie, T-matrix, BEM, DDA, FDTD, TMM, RCWA, FDE, EME, BPM, FDFD, PWE and
|
|
8
|
+
S-matrix circuit solvers on CPU or GPU, with differentiable inverse design. Every
|
|
9
9
|
result uses the same units and conventions and carries provenance, so methods
|
|
10
10
|
can be cross-checked directly. Python, CLI and MCP interfaces are JSON in,
|
|
11
11
|
JSON out.
|
|
12
12
|
authors:
|
|
13
13
|
- family-names: Feghali
|
|
14
14
|
given-names: Alexander
|
|
15
|
-
version: 0.
|
|
16
|
-
date-released: "2026-11-
|
|
15
|
+
version: 0.3.0
|
|
16
|
+
date-released: "2026-11-08"
|
|
17
17
|
license: MIT
|
|
18
18
|
repository-code: "https://github.com/lightsmith-photonics/lightsmith"
|
|
19
19
|
url: "https://docs.lightsmith.dev/"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: lightsmith
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Open photonics suite: one typed
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Open photonics suite: one typed problem description solved by Mie, T-matrix, BEM, DDA, FDTD, TMM, RCWA, FDE, EME, BPM, FDFD, PWE and circuit solvers on CPU or GPU, with differentiable inverse design, built for humans and AI agents.
|
|
5
5
|
Project-URL: Homepage, https://lightsmith.dev/
|
|
6
6
|
Project-URL: Documentation, https://docs.lightsmith.dev/
|
|
7
7
|
Project-URL: Repository, https://github.com/lightsmith-photonics/lightsmith
|
|
@@ -45,7 +45,7 @@ Description-Content-Type: text/markdown
|
|
|
45
45
|
|
|
46
46
|
**The open photonics suite — GPU-native, differentiable, and built for AI agents.**
|
|
47
47
|
|
|
48
|
-
Describe a photonics problem once
|
|
48
|
+
Describe a photonics problem once and solve it with whichever method fits: from nanoparticles and thin films to metasurfaces, waveguides, photonic crystals, devices and circuits. Every result comes back in the same units and conventions, with provenance, so methods can be cross-checked directly. Many solvers run on GPU and can be differentiated, which is what powers inverse design.
|
|
49
49
|
|
|
50
50
|
Documentation: <https://docs.lightsmith.dev/>
|
|
51
51
|
|
|
@@ -85,7 +85,7 @@ res = ls.solve(sim) # auto -> exact Mie for a sphere
|
|
|
85
85
|
cmp = ls.compare(sim, ["mie", "dda", "fdtd"]) # cross-check methods
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
The same from the shell,
|
|
88
|
+
The same from the shell, with the problem saved to a file:
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
uv run lightsmith solve examples/drude_sphere.json --method dda --device gpu
|
|
@@ -114,7 +114,7 @@ FDTD handles oblique and conical incidence on layer stacks and periodic structur
|
|
|
114
114
|
|
|
115
115
|
## From components to circuits (`lightsmith.pdk`)
|
|
116
116
|
|
|
117
|
-
An open design kit: a technology as data (`generic_soi()`: 220 nm Si on 2 µm oxide, open material data only; define
|
|
117
|
+
An open design kit: a technology as data (`generic_soi()`: 220 nm Si on 2 µm oxide, open material data only; define your own in Python or load one from a file), parametric cells (straight, circular/Euler bends, taper, MMI 1×2/2×2, directional coupler, ring/racetrack, Y-branch, crossing, grating coupler, MZI) with gdsfactory-style ports and GDS output, and a flow that simulates each component through `solve` (EME, FDFD or whatever `AUTO_ORDER` picks), fits a compact model, caches it by parameter hash and uses it in netlists as `pdk:<cell>`:
|
|
118
118
|
|
|
119
119
|
```python
|
|
120
120
|
from lightsmith.pdk import get_component
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**The open photonics suite — GPU-native, differentiable, and built for AI agents.**
|
|
4
4
|
|
|
5
|
-
Describe a photonics problem once
|
|
5
|
+
Describe a photonics problem once and solve it with whichever method fits: from nanoparticles and thin films to metasurfaces, waveguides, photonic crystals, devices and circuits. Every result comes back in the same units and conventions, with provenance, so methods can be cross-checked directly. Many solvers run on GPU and can be differentiated, which is what powers inverse design.
|
|
6
6
|
|
|
7
7
|
Documentation: <https://docs.lightsmith.dev/>
|
|
8
8
|
|
|
@@ -42,7 +42,7 @@ res = ls.solve(sim) # auto -> exact Mie for a sphere
|
|
|
42
42
|
cmp = ls.compare(sim, ["mie", "dda", "fdtd"]) # cross-check methods
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
The same from the shell,
|
|
45
|
+
The same from the shell, with the problem saved to a file:
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
uv run lightsmith solve examples/drude_sphere.json --method dda --device gpu
|
|
@@ -71,7 +71,7 @@ FDTD handles oblique and conical incidence on layer stacks and periodic structur
|
|
|
71
71
|
|
|
72
72
|
## From components to circuits (`lightsmith.pdk`)
|
|
73
73
|
|
|
74
|
-
An open design kit: a technology as data (`generic_soi()`: 220 nm Si on 2 µm oxide, open material data only; define
|
|
74
|
+
An open design kit: a technology as data (`generic_soi()`: 220 nm Si on 2 µm oxide, open material data only; define your own in Python or load one from a file), parametric cells (straight, circular/Euler bends, taper, MMI 1×2/2×2, directional coupler, ring/racetrack, Y-branch, crossing, grating coupler, MZI) with gdsfactory-style ports and GDS output, and a flow that simulates each component through `solve` (EME, FDFD or whatever `AUTO_ORDER` picks), fits a compact model, caches it by parameter hash and uses it in netlists as `pdk:<cell>`:
|
|
75
75
|
|
|
76
76
|
```python
|
|
77
77
|
from lightsmith.pdk import get_component
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Top level
|
|
2
|
+
|
|
3
|
+
::: lightsmith.api
|
|
4
|
+
options:
|
|
5
|
+
members: [solve, estimate, discretization, compare, choose_method, AUTO_ORDER]
|
|
6
|
+
|
|
7
|
+
::: lightsmith.progress
|
|
8
|
+
options:
|
|
9
|
+
members: [report, reporting, scaled, Cancelled]
|
|
10
|
+
|
|
11
|
+
::: lightsmith.device
|
|
12
|
+
options:
|
|
13
|
+
members: [doctor, resolve_device, Device]
|
|
@@ -13,11 +13,12 @@ agent pushed back on requests that cannot be answered as asked.
|
|
|
13
13
|
|
|
14
14
|
## Tasks
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
44 tasks cover every problem kind:
|
|
17
17
|
|
|
18
18
|
| Kind | Tasks |
|
|
19
19
|
|---|---:|
|
|
20
20
|
| scattering | 12 |
|
|
21
|
+
| emission | 1 |
|
|
21
22
|
| layer_stack | 8 |
|
|
22
23
|
| mode | 7 |
|
|
23
24
|
| circuit | 5 |
|
|
@@ -31,8 +32,8 @@ They fall into four categories:
|
|
|
31
32
|
- **Standard** (23): a well-posed question, such as the plasmon peak of a gold sphere in water, an
|
|
32
33
|
antireflection coating, a Bragg mirror, grating efficiencies, waveguide modes, a 2D MMI, the TM gap of a
|
|
33
34
|
photonic crystal, the FSR of an MZI or a ring, or a small topology optimisation.
|
|
34
|
-
- **Trap** (
|
|
35
|
-
wants a radius; a wavelength given in the medium; energies, wavenumbers, frequencies or µm instead of
|
|
35
|
+
- **Trap** (16): answerable, but the obvious setup is wrong. Examples: a diameter given where the schema
|
|
36
|
+
wants a radius; an emitter's distance given from a particle's surface; a wavelength given in the medium; energies, wavenumbers, frequencies or µm instead of
|
|
36
37
|
nm; a complex index in the e^{+jωt} convention; light incident from the substrate; a 1 mm slide that must
|
|
37
38
|
be an incoherent layer; group index versus effective index; normalised frequency a/λ; a material
|
|
38
39
|
dataset that does not cover the wavelength; cm versus nm in a link budget.
|
|
@@ -41,7 +42,7 @@ They fall into four categories:
|
|
|
41
42
|
lossless 1×2 splitter with 70 % in each arm.
|
|
42
43
|
- **Warning** (2): the tools warn about the answer and the agent must pass the warning on.
|
|
43
44
|
|
|
44
|
-
11 tasks use grid-based solvers (
|
|
45
|
+
11 tasks use grid-based solvers (BEM, RCWA, EME, PWE, inverse design) and are also graded on whether the
|
|
45
46
|
agent estimated before solving.
|
|
46
47
|
|
|
47
48
|
Each task file in `benchmarks/agents/tasks/` holds the prompt, the answer fields with units, a hidden
|
|
@@ -114,7 +115,7 @@ uv run --no-sync pytest benchmarks/agents/tests
|
|
|
114
115
|
```
|
|
115
116
|
|
|
116
117
|
The tests check that the task files match `taskdefs.py`, that the graders work on hand-made transcripts,
|
|
117
|
-
that the oracle passes all
|
|
118
|
+
that the oracle passes all 44 tasks over stdio MCP with no failed tool call, and that the Claude adapter's
|
|
118
119
|
loop works against a scripted stand-in for the API (no key, no cost). They also check that deliberately
|
|
119
120
|
wrong behaviour fails: numbers off by 25 %, skipped estimates, dropped concerns, no answer, the right
|
|
120
121
|
numbers without a simulation, every naive problem, and answers to the unphysical requests.
|
|
@@ -20,6 +20,7 @@ lightsmith compare SPEC [--methods mie,dda] [--device auto] [-o comparison.json
|
|
|
20
20
|
| `backends` | One entry per backend: `name`, `method`, `problem_kinds`, `license`, `gpu`, `differentiable`, `available`, `unavailable_reason`, `citation` |
|
|
21
21
|
| `schema` | The JSON Schema of every problem kind |
|
|
22
22
|
| `estimate` | Backend, device, problem size and memory, without solving |
|
|
23
|
+
| `discretization` | What the backend will discretise: grid, mesh, dipole lattice, harmonics, cells ([Discretisation](discretization.md)) |
|
|
23
24
|
| `solve` | The result model as JSON |
|
|
24
25
|
| `compare` | `reference`, `results` (one per method) and `relative_difference` |
|
|
25
26
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Discretisation: what a solver will discretise
|
|
2
|
+
|
|
3
|
+
`lightsmith.discretization(problem, method="auto")` reports what a backend will discretise for a problem, before any
|
|
4
|
+
solve: the FDTD Yee grid and its boxes, a device grid and its ports, the DDA dipole lattice, the BEM surface mesh,
|
|
5
|
+
the Mie or T-matrix multipole order, the RCWA harmonics, an FDE cross-section grid, the EME or BPM cells along a
|
|
6
|
+
device, the PWE k-path and plane waves. It calls each backend's own planning code (the code `estimate` and
|
|
7
|
+
`solve` call) and never runs a solver, so it is as cheap as `estimate`. GUIs use it to draw the discretisation,
|
|
8
|
+
and agents use it to check a set-up.
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
import lightsmith as ls
|
|
12
|
+
|
|
13
|
+
out = ls.discretization(problem, method="dda")
|
|
14
|
+
out["summary"] # {"dipoles": 2176, "spacing (nm)": 4.98, "dipoles per diameter": 16, ...}
|
|
15
|
+
out["payload"] # {"points_nm": [[x, y, z], ...], "spacing_nm": 4.98, ...}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
lightsmith discretization spec.json --method fdtd
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The MCP server has the same call as the read-only tool `get_discretization(problem, method)`.
|
|
23
|
+
|
|
24
|
+
## The envelope
|
|
25
|
+
|
|
26
|
+
Every backend answers with the same keys:
|
|
27
|
+
|
|
28
|
+
| Key | Meaning |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `backend`, `method`, `problem_kind` | The backend that `method` resolves to (as for `solve`) and the problem kind |
|
|
31
|
+
| `layout_kind` | Which payload follows (table below) |
|
|
32
|
+
| `summary` | Labelled key figures, in display order |
|
|
33
|
+
| `payload` | The geometry, in nm and world coordinates |
|
|
34
|
+
| `estimate` | The backend's `estimate` for the same problem (on the CPU) |
|
|
35
|
+
| `warnings` | The planning code's and the estimate's warnings |
|
|
36
|
+
| `error` | The library's refusal of the problem, or `null`. The geometry is still returned where it can be computed, for example for a graded FDTD grid with a Gaussian beam. |
|
|
37
|
+
|
|
38
|
+
A backend the problem does not suit raises, as `solve` would. Backends with nothing to discretise (TMM,
|
|
39
|
+
quasistatic, circuits) return `layout_kind: "none"` and the estimate's figures in `summary`. Plugins can answer
|
|
40
|
+
by overriding `Backend.discretization(problem, device)`.
|
|
41
|
+
|
|
42
|
+
## Payloads
|
|
43
|
+
|
|
44
|
+
| `layout_kind` | Backends | Payload |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `yee_grid` | FDTD scattering, emission | `grid` (`kind`, `shape`, `cells`, `nodes_nm` per axis, min/max spacing, `max_ratio`), `domain_nm`, `pml`, `boxes` (TFSF, total- and scattered-field flux; emission: the radiated-power box), `regions` (from `grid: "auto"` and `mesh_override`), `symmetry` (mirror planes, `planes_nm`). The grid is whole; the run steps one mirror image of it (`estimate.cells`). |
|
|
47
|
+
| `unit_cell` | FDTD periodic, layer stacks | Cell nodes `x_nm`, `y_nm`, `z_nm` (depth below the top of the stack), `planes_nm` (reflection monitor, source, stack top and bottom, transmission monitor), `pml_cells`, layer tops and thicknesses |
|
|
48
|
+
| `device_grid` | FDTD and FDFD devices, inverse design | `nodes_nm` per axis, PML inner faces, `ports` (`axis`, `direction`, `source_nm`, FDTD `monitor_nm`, `window_nm`, `num_modes`), `two_d`; inverse design: `design_regions` (shape, extent, filter radius in cells) |
|
|
49
|
+
| `dipole_lattice` | DDA | `points_nm` (occupied dipoles, subsampled by `stride` beyond 20 000), `material_slot`, `spacing_nm`, `dipoles_per_diameter`, `grid`, `n_dipoles`, `extrapolate` |
|
|
50
|
+
| `surface_mesh` | BEM | `verts_nm`, `tris` (subsampled beyond 40 000), `tri_surface`, `mesh_size_nm`, `n_triangles`, `n_edges` |
|
|
51
|
+
| `multipoles` | Mie (`lightsmith-mie`, `miepython`), T-matrix | Mie: `n_max` and `size_parameter` per wavelength and the rule used; T-matrix: `lmax` per particle, `modes`, `lmax_global` |
|
|
52
|
+
| `harmonics` | RCWA | `harmonics` (m, n), `orders_max`, `layers` (each uniform in z: the problem's own layers) |
|
|
53
|
+
| `cross_section_grid` | FDE | `x_nm`, `y_nm`, spacings, `pml_cells`, `symmetry`, `boundary`, `num_modes` |
|
|
54
|
+
| `cells` | EME, BPM | `axis`, `lo_nm`, `hi_nm`, `cells` (`start_nm`, `stop_nm`; BPM: `steps`, `dz_nm`), the cross-section grid; EME: `modes_per_cell`; BPM: `step_nm` |
|
|
55
|
+
| `plane_waves` | PWE | `k_reduced`, `k_distance`, `k_labels`, per polarisation the solver, plane-wave count, matrix size, FFT grid and (dense) G indices |
|
|
56
|
+
| `none` | TMM, quasistatic, circuits | `note` |
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**The open photonics suite — GPU-native, differentiable, and built for AI agents.**
|
|
4
4
|
|
|
5
|
-
Lightsmith lets you describe a photonics problem once
|
|
6
|
-
|
|
7
|
-
circuits. Every result uses the same units and conventions and records its provenance, so you can
|
|
5
|
+
Lightsmith lets you describe a photonics problem once and solve it with whichever method fits. It covers
|
|
6
|
+
nanoparticles, thin films, metasurfaces, waveguides, photonic crystals, devices and circuits. Every result uses the same units and conventions and records its provenance, so you can
|
|
8
7
|
cross-check methods directly. Many solvers run on a GPU and can be differentiated, which is what powers
|
|
9
8
|
inverse design.
|
|
10
9
|
|
|
@@ -21,7 +20,7 @@ cmp = ls.compare(sim, ["mie", "dda", "fdtd"]) # cross-check methods
|
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
!!! warning "Pre-alpha"
|
|
24
|
-
Lightsmith 0.
|
|
23
|
+
Lightsmith 0.2 is pre-alpha, so the API may still change between minor versions. Each solver page
|
|
25
24
|
lists the validation behind it, with numbers taken from the test suite. Read the `warnings` on every
|
|
26
25
|
result before you trust its numbers.
|
|
27
26
|
|
|
@@ -33,12 +32,15 @@ cmp = ls.compare(sim, ["mie", "dda", "fdtd"]) # cross-check methods
|
|
|
33
32
|
| [`layer_stack`](problems/layer-stack.md): thin films | [TMM](solvers/tmm.md), [RCWA](solvers/rcwa.md), FDTD | ✅ | TMM, RCWA |
|
|
34
33
|
| [`periodic`](problems/periodic.md): gratings, metasurfaces | [RCWA](solvers/rcwa.md), FDTD (rectangular lattices) | ✅ | RCWA |
|
|
35
34
|
| [`mode`](problems/mode.md): waveguide cross-sections | [FDE](solvers/fde.md) | — | — |
|
|
36
|
-
| [`device`](problems/device.md): S-parameters between ports | [EME](solvers/eme.md), [BPM](solvers/bpm.md), [FDFD](solvers/fdfd.md)
|
|
35
|
+
| [`device`](problems/device.md): S-parameters between ports | [EME](solvers/eme.md), [BPM](solvers/bpm.md), [FDFD](solvers/fdfd.md) | BPM, FDFD | FDFD (adjoint) |
|
|
37
36
|
| [`bands`](problems/bands.md): photonic crystals | [PWE](solvers/pwe.md) | ✅ | dense path |
|
|
38
37
|
| [`circuit`](problems/circuit.md): netlists of compact models | [S-matrix circuit solver](solvers/circuit.md) | ✅ | ✅ |
|
|
39
38
|
| [`optimization`](problems/optimization.md): inverse design | [Topology optimisation on FDFD](solvers/inverse.md) | ✅ | — |
|
|
40
39
|
|
|
41
|
-
## Three ways in
|
|
40
|
+
## Three ways in
|
|
41
|
+
|
|
42
|
+
All three take the same problem description, so a problem you build in Python can be saved to a file,
|
|
43
|
+
run from the shell, or handed to an agent unchanged.
|
|
42
44
|
|
|
43
45
|
- **Python**: `import lightsmith as ls`, then `ls.solve`, `ls.estimate` and `ls.compare`. See the
|
|
44
46
|
[quick start](quickstart.md).
|
|
@@ -83,7 +83,8 @@ lightsmith doctor
|
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
The output should show the GPU under `"cuda_gpus"`, and `"auto_device"` should name `cuda:0`. With
|
|
86
|
-
`device="auto"`, which is the default, solvers that support a GPU use it
|
|
86
|
+
`device="auto"`, which is the default, solvers that support a GPU use it, unless `estimate` says the problem
|
|
87
|
+
will not fit in the GPU's free memory: then the solve runs on the CPU and says so in `warnings`. Pass `device="cpu"` to force the
|
|
87
88
|
CPU, `device="cuda:1"` to pick a specific GPU, or `device="torch-cpu"` to run the PyTorch code path on
|
|
88
89
|
the CPU, for example to get gradients without a GPU.
|
|
89
90
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Materials
|
|
2
2
|
|
|
3
|
-
You can use a material anywhere a problem asks for one
|
|
4
|
-
|
|
3
|
+
You can use a material anywhere a problem asks for one: pass one of the models below. Permittivities
|
|
4
|
+
follow the `exp(-iωt)` convention, so loss means `Im(ε) > 0` and `Im(n) > 0`.
|
|
5
5
|
|
|
6
|
-
|
|
|
6
|
+
| Model | Fields | Saved as `kind` |
|
|
7
7
|
|---|---|---|
|
|
8
|
-
| `
|
|
9
|
-
| `
|
|
10
|
-
| `
|
|
11
|
-
| `
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
8
|
+
| `ConstantIndex` | `n_real`, `n_imag` (≥ 0) | `constant_index` |
|
|
9
|
+
| `ConstantPermittivity` | `eps_real`, `eps_imag` (≥ 0) | `constant_permittivity` |
|
|
10
|
+
| `Drude` | `eps_inf`, `wp_ev`, `gamma_ev`: ε(ω) = ε∞ − ωp² / (ω² + iγω), with energies in eV | `drude` |
|
|
11
|
+
| `DrudeLorentz` | `eps_inf`, `wp_ev`, `gamma_ev`, `poles: [{delta_eps, omega0_ev, gamma_ev}]` | `drude_lorentz` |
|
|
12
|
+
| `Tabulated` | `wavelength_nm`, `n_real`, `n_imag`, `source`: linear interpolation, no extrapolation. Data in any order is sorted by wavelength; duplicate wavelengths are refused. | `tabulated` |
|
|
13
|
+
| `LibraryMaterial` | `name`, `dataset`: a bundled measured dataset (below) | `library` |
|
|
14
14
|
|
|
15
15
|
## Bundled datasets
|
|
16
16
|
|
|
@@ -47,7 +47,7 @@ material's default is filled in, so a stored spec stays reproducible.
|
|
|
47
47
|
```python
|
|
48
48
|
import lightsmith as ls
|
|
49
49
|
|
|
50
|
-
ls.list_materials("Au") # datasets, ranges
|
|
50
|
+
ls.list_materials("Au") # datasets, ranges and references
|
|
51
51
|
gold = ls.LibraryMaterial(name="Au", dataset="McPeak")
|
|
52
52
|
tab = ls.load_material("Au") # the default dataset as a Tabulated material
|
|
53
53
|
```
|