PyFiberModes 0.13.2__tar.gz → 0.14.1__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.
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.github/workflows/quality.yml +1 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.zenodo.json +1 -1
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/CHANGELOG.md +20 -1
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/Makefile +1 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PKG-INFO +17 -5
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/__init__.py +38 -3
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/_version.py +2 -2
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/analysis.py +22 -12
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/factory.py +0 -6
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber.py +11 -2
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fundamentals.py +83 -28
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/loader.py +37 -14
- pyfibermodes-0.14.1/PyFiberModes/materials.py +118 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/plotting.py +0 -3
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/services.py +2 -10
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/solver/__init__.py +6 -6
- pyfibermodes-0.14.1/PyFiberModes/solver/multilayer/__init__.py +5 -0
- pyfibermodes-0.13.2/PyFiberModes/solver/mlsif/neff.py → pyfibermodes-0.14.1/PyFiberModes/solver/multilayer/effective_index.py +162 -51
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/solver/protocols.py +16 -1
- {pyfibermodes-0.13.2/PyFiberModes/solver/tlsif → pyfibermodes-0.14.1/PyFiberModes/solver/three_layer}/__init__.py +2 -0
- {pyfibermodes-0.13.2/PyFiberModes/solver/tlsif → pyfibermodes-0.14.1/PyFiberModes/solver/three_layer}/cutoff.py +14 -16
- pyfibermodes-0.14.1/PyFiberModes/solver/two_layer/__init__.py +6 -0
- {pyfibermodes-0.13.2/PyFiberModes/solver/ssif → pyfibermodes-0.14.1/PyFiberModes/solver/two_layer}/cutoff.py +1 -6
- pyfibermodes-0.13.2/PyFiberModes/solver/ssif/neff.py → pyfibermodes-0.14.1/PyFiberModes/solver/two_layer/effective_index.py +54 -16
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes.egg-info/PKG-INFO +17 -5
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes.egg-info/SOURCES.txt +25 -11
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes.egg-info/requires.txt +2 -1
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/README.rst +14 -3
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/conda.recipe/meta.yaml +1 -2
- pyfibermodes-0.14.1/docs/examples/analysis/plot_guided_mode_discovery.py +22 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_mode_field_1.py +1 -1
- pyfibermodes-0.14.1/docs/examples/benchmarks/plot_component_batching_speedup.py +33 -0
- pyfibermodes-0.14.1/docs/examples/benchmarks/plot_modal_cache_speedup.py +28 -0
- pyfibermodes-0.14.1/docs/examples/fields/plot_confinement_by_radius.py +28 -0
- pyfibermodes-0.14.1/docs/examples/fields/plot_polarization_rotation.py +27 -0
- pyfibermodes-0.14.1/docs/examples/specialty_fibers/README.rst +7 -0
- pyfibermodes-0.14.1/docs/examples/specialty_fibers/plot_refractive_index_profile.py +26 -0
- pyfibermodes-0.14.1/docs/examples/specialty_fibers/plot_specialty_fiber_catalog.py +33 -0
- pyfibermodes-0.14.1/docs/examples/specialty_fibers/plot_specialty_mode_indices.py +25 -0
- pyfibermodes-0.14.1/docs/examples/validation/plot_field_area_convergence.py +26 -0
- pyfibermodes-0.14.1/docs/examples/validation/plot_normalized_effective_index.py +31 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/_static/default.css +7 -0
- pyfibermodes-0.14.1/docs/source/api_policy.rst +59 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/architecture.rst +5 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/code/analysis.rst +12 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/code.rst +3 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/conf.py +1 -1
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/examples.rst +2 -2
- pyfibermodes-0.14.1/docs/source/index.rst +25 -0
- pyfibermodes-0.14.1/docs/source/migration_guide.rst +69 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/pyproject.toml +13 -4
- pyfibermodes-0.14.1/tests/api_snapshot.json +54 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_architecture.py +34 -6
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_architecture_enhancements.py +2 -2
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_file_loading.py +15 -3
- pyfibermodes-0.14.1/tests/test_public_api.py +44 -0
- pyfibermodes-0.14.1/tests/test_three_layer_solver.py +42 -0
- pyfibermodes-0.13.2/tests/test_ssif.py → pyfibermodes-0.14.1/tests/test_two_layer_solver.py +1 -1
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_validation.py +1 -1
- pyfibermodes-0.13.2/PyFiberModes/solver/mlsif/__init__.py +0 -3
- pyfibermodes-0.13.2/PyFiberModes/solver/ssif/__init__.py +0 -4
- pyfibermodes-0.13.2/docs/examples/DCF/README.rst +0 -6
- pyfibermodes-0.13.2/docs/examples/DCF/plot_DCF_fields.py +0 -35
- pyfibermodes-0.13.2/docs/source/index.rst +0 -23
- pyfibermodes-0.13.2/tests/test_tlsif.py +0 -20
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.coveragerc +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.github/dependabot.yml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.github/workflows/deploy_PyPi.yml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.github/workflows/deploy_anaconda.yml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.github/workflows/deploy_coverage.yml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.github/workflows/deploy_documentation.yml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.github/workflows/tests.yml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/.gitignore +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/CITATION.cff +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/CONTRIBUTING.md +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/LICENSE +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/MANIFEST.in +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/coordinates.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/directories.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/exceptions.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/1550BHP.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/DCF13.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/DCF1300S_20.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/DCF1300S_26.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/DCF1300S_33.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/DCF1300S_42.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/F2028M12.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/F2028M21.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/F2028M24.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/F2058G1.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/F2058L1.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/HI1060.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/HP630.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/SM1950.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/SMF28.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/fluorine_doped_1%_capillary.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/fluorine_doped_2%_capillary.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/test_fiber.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/fiber_files/test_multimode_fiber.yaml +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/field.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/mode.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/mode_instances.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/models.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/optimization.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/propagation.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/solver/base_solver.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/solver/results.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/source.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes/stepindex.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes.egg-info/dependency_links.txt +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/PyFiberModes.egg-info/top_level.txt +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/benchmarks/README.md +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/benchmarks/test_field_performance.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/Makefile +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/README.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/SMF28/README.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/SMF28/plot_smf28.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/SMF28/plot_smf28_dispersion_vs_wavelength.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/SMF28/plot_smf28_group_index_vs_wavelength.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/analysis/README.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/analysis/plot_coupled_mode_exchange.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/analysis/plot_structured_wavelength_sweep.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/README.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_U_vs_V.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_comparison_solvers.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_dispersion.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_effective_index.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_fiber_LP_modes.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_group_index.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_mode_field.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_mode_field_2.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/basic/plot_neff_tapered_fiber.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/benchmarks/README.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/benchmarks/plot_field_grid_scaling.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/fields/README.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/fields/plot_vector_components.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/validation/README.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/examples/validation/plot_effective_index_bounds.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/make.bat +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/_static/favicon.png +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/_static/logo.png +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/_static/thumbnail.png +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/code/fibers.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/code/fields.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/code/fundamentals.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/getting_started.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/performance.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/references.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/theory.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/troubleshooting.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/docs/source/workflows.rst +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/pytest.ini +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/setup.cfg +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/__init__.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/helpers.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_advanced_features.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_api.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_coordinates.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_docstrings.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_fiber.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_field.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_physics_regression.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tests/test_release_tools.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tools/check_release.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tools/next_release_version.py +0 -0
- {pyfibermodes-0.13.2 → pyfibermodes-0.14.1}/tools/release_tag.py +0 -0
|
@@ -6,6 +6,23 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.14.1] - 2026-09-23
|
|
10
|
+
|
|
11
|
+
## [0.14.0] - 2026-09-23
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Expanded the specialty-fiber, field, analysis, validation, and performance
|
|
16
|
+
galleries so every documentation series contains multiple examples.
|
|
17
|
+
- Defined a stable root-level public API, compatibility and deprecation policy,
|
|
18
|
+
API snapshot regression test, and migration guide.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Replaced the opaque `ssif`, `tlsif`, `mlsif`, and `NeffSolver` names with
|
|
23
|
+
descriptive two-layer, three-layer, multilayer, and effective-index solver
|
|
24
|
+
namespaces and class names.
|
|
25
|
+
|
|
9
26
|
## [0.13.2] - 2026-09-23
|
|
10
27
|
|
|
11
28
|
### Changed
|
|
@@ -86,7 +103,9 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
86
103
|
|
|
87
104
|
- Established the current tagged baseline for subsequent documented releases.
|
|
88
105
|
|
|
89
|
-
[Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/v0.
|
|
106
|
+
[Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/v0.14.1...HEAD
|
|
107
|
+
[0.14.1]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.14.1
|
|
108
|
+
[0.14.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.14.0
|
|
90
109
|
[0.13.2]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.13.2
|
|
91
110
|
[0.13.1]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.13.1
|
|
92
111
|
[0.13.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.13.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyFiberModes
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.1
|
|
4
4
|
Summary: Guided-mode analysis and design for circular optical fibers.
|
|
5
5
|
Author-email: Martin Poinsinet de Sivry-Houle <martin.poinsinet.de.sivry@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -697,7 +697,6 @@ Classifier: Intended Audience :: Science/Research
|
|
|
697
697
|
Requires-Python: >=3.11
|
|
698
698
|
Description-Content-Type: text/x-rst
|
|
699
699
|
License-File: LICENSE
|
|
700
|
-
Requires-Dist: PyOptik<3,>=2
|
|
701
700
|
Requires-Dist: PyFinitDiff
|
|
702
701
|
Requires-Dist: pyyaml
|
|
703
702
|
Requires-Dist: numpy
|
|
@@ -709,6 +708,7 @@ Requires-Dist: pytest-json-report~=1.5; extra == "testing"
|
|
|
709
708
|
Requires-Dist: coverage~=7.6; extra == "testing"
|
|
710
709
|
Requires-Dist: ruff<1,>=0.8; extra == "testing"
|
|
711
710
|
Requires-Dist: matplotlib>=3.8; extra == "testing"
|
|
711
|
+
Requires-Dist: mypy<2,>=1.15; extra == "testing"
|
|
712
712
|
Provides-Extra: plotting
|
|
713
713
|
Requires-Dist: matplotlib>=3.8; extra == "plotting"
|
|
714
714
|
Provides-Extra: benchmarking
|
|
@@ -723,6 +723,7 @@ Requires-Dist: sphinx-rtd-theme==3.1.0; extra == "documentation"
|
|
|
723
723
|
Requires-Dist: pydata-sphinx-theme==0.17.1; extra == "documentation"
|
|
724
724
|
Provides-Extra: dev
|
|
725
725
|
Requires-Dist: ruff<1,>=0.8; extra == "dev"
|
|
726
|
+
Requires-Dist: mypy<2,>=1.15; extra == "dev"
|
|
726
727
|
Dynamic: license-file
|
|
727
728
|
|
|
728
729
|
.. image:: https://raw.githubusercontent.com/MartinPdeS/PyFiberModes/master/docs/source/_static/logo.png
|
|
@@ -813,9 +814,9 @@ simulations:
|
|
|
813
814
|
|
|
814
815
|
python -c "import PyFiberModes; print(PyFiberModes.__version__)"
|
|
815
816
|
|
|
816
|
-
|
|
817
|
-
PyOptik
|
|
818
|
-
|
|
817
|
+
Fiber material names are resolved through a lightweight, pluggable registry.
|
|
818
|
+
PyOptik is not required; applications can register their own dispersive model
|
|
819
|
+
objects or simple wavelength-to-index callables.
|
|
819
820
|
|
|
820
821
|
First mode calculation
|
|
821
822
|
----------------------
|
|
@@ -1012,6 +1013,17 @@ contains the API reference and executable example gallery, including:
|
|
|
1012
1013
|
* double-clad fiber field analysis; and
|
|
1013
1014
|
* comparisons between supported analytical solvers.
|
|
1014
1015
|
|
|
1016
|
+
API stability
|
|
1017
|
+
-------------
|
|
1018
|
+
|
|
1019
|
+
Supported imports come from the package root, for example
|
|
1020
|
+
``from PyFiberModes import Fiber, LP01``. The
|
|
1021
|
+
`public API policy <https://martinpdes.github.io/PyFiberModes/latest/api_policy.html>`_
|
|
1022
|
+
defines compatibility guarantees and the deprecation period. Review the
|
|
1023
|
+
`migration guide <https://martinpdes.github.io/PyFiberModes/latest/migration_guide.html>`_
|
|
1024
|
+
when upgrading across minor or major versions. Internal solver modules are not
|
|
1025
|
+
covered by the compatibility guarantee.
|
|
1026
|
+
|
|
1015
1027
|
Development and testing
|
|
1016
1028
|
-----------------------
|
|
1017
1029
|
|
|
@@ -1,7 +1,27 @@
|
|
|
1
1
|
"""Public API for circular optical-fiber mode analysis."""
|
|
2
2
|
|
|
3
|
-
from PyFiberModes.mode import
|
|
4
|
-
from PyFiberModes.mode_instances import
|
|
3
|
+
from PyFiberModes.mode import Family, Mode
|
|
4
|
+
from PyFiberModes.mode_instances import (
|
|
5
|
+
EH11,
|
|
6
|
+
HE11,
|
|
7
|
+
HE12,
|
|
8
|
+
HE21,
|
|
9
|
+
HE22,
|
|
10
|
+
HE31,
|
|
11
|
+
HE32,
|
|
12
|
+
LP01,
|
|
13
|
+
LP02,
|
|
14
|
+
LP03,
|
|
15
|
+
LP11,
|
|
16
|
+
LP12,
|
|
17
|
+
LP21,
|
|
18
|
+
LP22,
|
|
19
|
+
LP31,
|
|
20
|
+
LP32,
|
|
21
|
+
LP41,
|
|
22
|
+
TE01,
|
|
23
|
+
TM01,
|
|
24
|
+
)
|
|
5
25
|
from PyFiberModes.factory import FiberFactory
|
|
6
26
|
from PyFiberModes.fiber import Fiber, load_fiber
|
|
7
27
|
from PyFiberModes.field import Field
|
|
@@ -12,6 +32,13 @@ from PyFiberModes.solver.results import SolverResult
|
|
|
12
32
|
from PyFiberModes.analysis import ModeSweepResult, find_modes, sweep_modes
|
|
13
33
|
from PyFiberModes.optimization import DesignParameter, DesignResult, optimize_fiber
|
|
14
34
|
from PyFiberModes.propagation import CoupledModeSystem, PropagationResult, coupling_matrix, overlap
|
|
35
|
+
from PyFiberModes.materials import (
|
|
36
|
+
CallableIndex,
|
|
37
|
+
ConstantIndex,
|
|
38
|
+
FusedSilica,
|
|
39
|
+
MaterialRegistry,
|
|
40
|
+
RefractiveIndexModel,
|
|
41
|
+
)
|
|
15
42
|
|
|
16
43
|
|
|
17
44
|
try:
|
|
@@ -21,7 +48,7 @@ except ImportError:
|
|
|
21
48
|
__version__ = "0.0.0"
|
|
22
49
|
|
|
23
50
|
|
|
24
|
-
__all__ = [
|
|
51
|
+
__all__ = [
|
|
25
52
|
'Mode',
|
|
26
53
|
'Family',
|
|
27
54
|
'Fiber',
|
|
@@ -34,10 +61,17 @@ __all__ = [ # noqa: F405
|
|
|
34
61
|
'ModeSweepResult', 'find_modes', 'sweep_modes',
|
|
35
62
|
'DesignParameter', 'DesignResult', 'optimize_fiber',
|
|
36
63
|
'CoupledModeSystem', 'PropagationResult', 'coupling_matrix', 'overlap',
|
|
64
|
+
'RefractiveIndexModel', 'ConstantIndex', 'CallableIndex', 'FusedSilica',
|
|
65
|
+
'MaterialRegistry',
|
|
37
66
|
'HE11',
|
|
38
67
|
'HE12',
|
|
68
|
+
'HE21',
|
|
39
69
|
'HE22',
|
|
40
70
|
'HE31',
|
|
71
|
+
'HE32',
|
|
72
|
+
'EH11',
|
|
73
|
+
'TE01',
|
|
74
|
+
'TM01',
|
|
41
75
|
'LP01',
|
|
42
76
|
'LP11',
|
|
43
77
|
'LP21',
|
|
@@ -47,4 +81,5 @@ __all__ = [ # noqa: F405
|
|
|
47
81
|
'LP22',
|
|
48
82
|
'LP03',
|
|
49
83
|
'LP32',
|
|
84
|
+
'LP41',
|
|
50
85
|
]
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0,
|
|
21
|
+
__version__ = version = '0.14.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 14, 1)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -64,7 +64,7 @@ class ModeSweepResult:
|
|
|
64
64
|
index = self.modes.index(mode)
|
|
65
65
|
return {name: value[:, index] for name, value in self.values.items()}
|
|
66
66
|
|
|
67
|
-
def as_records(self) -> list[dict]:
|
|
67
|
+
def as_records(self) -> list[dict[str, float | Mode]]:
|
|
68
68
|
"""Convert the dense result into row-oriented records.
|
|
69
69
|
|
|
70
70
|
Returns
|
|
@@ -133,9 +133,13 @@ def find_modes(fiber, families=("LP",), max_nu=6, max_m=6) -> tuple[Mode, ...]:
|
|
|
133
133
|
found = []
|
|
134
134
|
for mode in candidate_modes(families, max_nu, max_m):
|
|
135
135
|
try:
|
|
136
|
-
|
|
137
|
-
guided =
|
|
138
|
-
|
|
136
|
+
effective_index = fiber.get_effective_index(mode)
|
|
137
|
+
guided = (
|
|
138
|
+
fiber.last_layer.refractive_index
|
|
139
|
+
< effective_index
|
|
140
|
+
<= fiber.maximum_index
|
|
141
|
+
)
|
|
142
|
+
if np.isfinite(effective_index) and guided:
|
|
139
143
|
found.append(mode)
|
|
140
144
|
except (ArithmeticError, AssertionError, RuntimeError, ValueError):
|
|
141
145
|
continue
|
|
@@ -191,7 +195,6 @@ def sweep_modes(
|
|
|
191
195
|
parameters = np.asarray(tuple(parameters), dtype=float)
|
|
192
196
|
if parameters.ndim != 1 or not len(parameters):
|
|
193
197
|
raise ValueError("parameters must be a non-empty one-dimensional sequence")
|
|
194
|
-
working_fiber = deepcopy(fiber)
|
|
195
198
|
if setter is None:
|
|
196
199
|
if parameter_name != "wavelength":
|
|
197
200
|
raise ValueError("a setter is required for non-wavelength sweeps")
|
|
@@ -202,19 +205,26 @@ def sweep_modes(
|
|
|
202
205
|
if modes is None:
|
|
203
206
|
discovered = []
|
|
204
207
|
for parameter in parameters:
|
|
205
|
-
|
|
206
|
-
|
|
208
|
+
parameter_fiber = deepcopy(fiber)
|
|
209
|
+
setter(parameter_fiber, float(parameter))
|
|
210
|
+
for mode in find_modes(parameter_fiber, families, max_nu, max_m):
|
|
207
211
|
if mode not in discovered:
|
|
208
212
|
discovered.append(mode)
|
|
209
213
|
modes = discovered
|
|
210
214
|
modes = tuple(modes)
|
|
211
215
|
values = {metric: np.full((len(parameters), len(modes)), np.nan) for metric in metrics}
|
|
212
|
-
for
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
parameter_fibers = tuple(deepcopy(fiber) for _ in parameters)
|
|
217
|
+
for parameter_fiber, parameter in zip(parameter_fibers, parameters, strict=True):
|
|
218
|
+
setter(parameter_fiber, float(parameter))
|
|
219
|
+
|
|
220
|
+
for i, parameter_fiber in enumerate(parameter_fibers):
|
|
221
|
+
metric_functions = {
|
|
222
|
+
metric: getattr(parameter_fiber, f"get_{metric}") for metric in metrics
|
|
223
|
+
}
|
|
224
|
+
for metric, metric_function in metric_functions.items():
|
|
225
|
+
for j, mode in enumerate(modes):
|
|
216
226
|
try:
|
|
217
|
-
value =
|
|
227
|
+
value = metric_function(mode)
|
|
218
228
|
values[metric][i, j] = value if np.isfinite(value) else np.nan
|
|
219
229
|
except (ArithmeticError, AssertionError, RuntimeError, ValueError):
|
|
220
230
|
pass
|
|
@@ -55,10 +55,6 @@ class FiberFactory:
|
|
|
55
55
|
----------
|
|
56
56
|
layers_list : list[ProxyLayer]
|
|
57
57
|
List of ProxyLayer objects representing the layers of the fiber.
|
|
58
|
-
neff_solver : None
|
|
59
|
-
Placeholder for a solver object (if required).
|
|
60
|
-
cutoff_solver : None
|
|
61
|
-
Placeholder for a cutoff solver object (if required).
|
|
62
58
|
wavelength : float
|
|
63
59
|
Wavelength used in simulations.
|
|
64
60
|
"""
|
|
@@ -72,8 +68,6 @@ class FiberFactory:
|
|
|
72
68
|
Vacuum wavelength in meters for generated fibers.
|
|
73
69
|
"""
|
|
74
70
|
self.layers_list = []
|
|
75
|
-
self.neff_solver = None
|
|
76
|
-
self.cutoff_solver = None
|
|
77
71
|
self.wavelength = wavelength
|
|
78
72
|
|
|
79
73
|
def add_layer(self, index: float, name: str = "", radius: float = 0.0):
|
|
@@ -22,6 +22,7 @@ from PyFiberModes.fundamentals import (
|
|
|
22
22
|
from PyFiberModes import loader
|
|
23
23
|
from PyFiberModes.coordinates import CylindricalCoordinates
|
|
24
24
|
from PyFiberModes.exceptions import ValidationError
|
|
25
|
+
from PyFiberModes.materials import DEFAULT_MATERIALS, MaterialRegistry
|
|
25
26
|
from PyFiberModes.services import FieldAnalysis, ModalAnalysis
|
|
26
27
|
|
|
27
28
|
|
|
@@ -1004,7 +1005,12 @@ def get_fiber_from_delta_and_V0(delta: float, V0: float, wavelength: float) -> F
|
|
|
1004
1005
|
return fiber
|
|
1005
1006
|
|
|
1006
1007
|
|
|
1007
|
-
def load_fiber(
|
|
1008
|
+
def load_fiber(
|
|
1009
|
+
fiber_name: str,
|
|
1010
|
+
wavelength: float | None = None,
|
|
1011
|
+
add_air_layer: bool = False,
|
|
1012
|
+
materials: MaterialRegistry = DEFAULT_MATERIALS,
|
|
1013
|
+
) -> Fiber:
|
|
1008
1014
|
"""Load a named YAML fiber definition.
|
|
1009
1015
|
|
|
1010
1016
|
Parameters
|
|
@@ -1015,6 +1021,8 @@ def load_fiber(fiber_name: str, wavelength: float = None, add_air_layer: bool =
|
|
|
1015
1021
|
Vacuum wavelength in meters used to evaluate material indices.
|
|
1016
1022
|
add_air_layer : bool, optional
|
|
1017
1023
|
Add an outer air layer when true.
|
|
1024
|
+
materials : MaterialRegistry, optional
|
|
1025
|
+
Registry used to resolve material names in the YAML definition.
|
|
1018
1026
|
|
|
1019
1027
|
Returns
|
|
1020
1028
|
-------
|
|
@@ -1024,7 +1032,8 @@ def load_fiber(fiber_name: str, wavelength: float = None, add_air_layer: bool =
|
|
|
1024
1032
|
fiber_dict = loader.load_fiber_as_dict(
|
|
1025
1033
|
fiber_name=fiber_name,
|
|
1026
1034
|
wavelength=wavelength,
|
|
1027
|
-
order='out-to-in'
|
|
1035
|
+
order='out-to-in',
|
|
1036
|
+
materials=materials,
|
|
1028
1037
|
)
|
|
1029
1038
|
|
|
1030
1039
|
fiber = Fiber(wavelength=wavelength)
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
"""Fundamental normalized-frequency and propagation relations."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import numpy
|
|
4
6
|
import numpy as np
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
5
8
|
from PyFiberModes.mode import Mode
|
|
6
9
|
from PyFiberModes.mode_instances import HE11, LP01
|
|
7
10
|
from scipy.constants import c
|
|
8
11
|
|
|
9
12
|
from PyFiberModes.coordinates import CylindricalCoordinates
|
|
10
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from PyFiberModes.solver.results import SolverResult
|
|
16
|
+
|
|
11
17
|
|
|
12
18
|
def get_delta_from_fiber(fiber) -> float:
|
|
13
19
|
r"""
|
|
@@ -31,7 +37,7 @@ def get_delta_from_fiber(fiber) -> float:
|
|
|
31
37
|
return 0.5 * (1 - n_ratio)
|
|
32
38
|
|
|
33
39
|
|
|
34
|
-
def get_wavelength_from_V0(fiber: object,
|
|
40
|
+
def get_wavelength_from_V0(fiber: object, normalized_frequency: float) -> float:
|
|
35
41
|
r"""
|
|
36
42
|
Compute the wavelength corresponding to a given V-number, \(V_0\).
|
|
37
43
|
|
|
@@ -46,7 +52,7 @@ def get_wavelength_from_V0(fiber: object, V0: float) -> float:
|
|
|
46
52
|
----------
|
|
47
53
|
fiber : Fiber
|
|
48
54
|
The fiber object.
|
|
49
|
-
|
|
55
|
+
normalized_frequency : float
|
|
50
56
|
The V-number.
|
|
51
57
|
|
|
52
58
|
Returns
|
|
@@ -56,7 +62,7 @@ def get_wavelength_from_V0(fiber: object, V0: float) -> float:
|
|
|
56
62
|
"""
|
|
57
63
|
NA = fiber.get_NA()
|
|
58
64
|
last_layer = fiber.last_layer
|
|
59
|
-
wavelength = 2 * np.pi /
|
|
65
|
+
wavelength = 2 * np.pi / normalized_frequency * last_layer.radius_in * NA
|
|
60
66
|
return wavelength
|
|
61
67
|
|
|
62
68
|
|
|
@@ -95,11 +101,14 @@ def get_propagation_constant_from_omega(
|
|
|
95
101
|
|
|
96
102
|
from PyFiberModes import solver
|
|
97
103
|
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
effective_index_solver = (
|
|
105
|
+
solver.two_layer.EffectiveIndexSolver(fiber=fiber, wavelength=wavelength)
|
|
106
|
+
if fiber.n_layer == 2
|
|
107
|
+
else solver.multilayer.EffectiveIndexSolver(fiber=fiber, wavelength=wavelength)
|
|
108
|
+
)
|
|
100
109
|
|
|
101
|
-
|
|
102
|
-
return
|
|
110
|
+
effective_index = effective_index_solver.solve(mode=mode, delta_neff=delta_neff)
|
|
111
|
+
return effective_index * (2 * numpy.pi / wavelength)
|
|
103
112
|
|
|
104
113
|
|
|
105
114
|
def get_U_parameter(
|
|
@@ -132,9 +141,11 @@ def get_U_parameter(
|
|
|
132
141
|
from PyFiberModes import solver
|
|
133
142
|
assert fiber.n_layer == 2, "U-parameter can only be calculated for two-layer fibers."
|
|
134
143
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
144
|
+
effective_index_solver = solver.two_layer.EffectiveIndexSolver(
|
|
145
|
+
fiber=fiber, wavelength=wavelength
|
|
146
|
+
)
|
|
147
|
+
effective_index = effective_index_solver.solve(mode=mode, delta_neff=delta_neff)
|
|
148
|
+
U, _, _ = effective_index_solver.get_U_W_V_parameter(neff=effective_index)
|
|
138
149
|
return U
|
|
139
150
|
|
|
140
151
|
|
|
@@ -165,11 +176,49 @@ def get_effective_index(
|
|
|
165
176
|
from PyFiberModes import solver
|
|
166
177
|
|
|
167
178
|
if fiber.n_layer == 2:
|
|
168
|
-
|
|
179
|
+
effective_index_solver = solver.two_layer.EffectiveIndexSolver(
|
|
180
|
+
fiber=fiber, wavelength=wavelength
|
|
181
|
+
)
|
|
169
182
|
else:
|
|
170
|
-
|
|
183
|
+
effective_index_solver = solver.multilayer.EffectiveIndexSolver(
|
|
184
|
+
fiber=fiber, wavelength=wavelength
|
|
185
|
+
)
|
|
171
186
|
|
|
172
|
-
return
|
|
187
|
+
return effective_index_solver.solve(mode=mode, delta_neff=delta_neff)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def get_effective_index_result(
|
|
191
|
+
fiber,
|
|
192
|
+
wavelength: float,
|
|
193
|
+
mode: Mode,
|
|
194
|
+
delta_neff: float = 1e-6) -> "SolverResult[float]":
|
|
195
|
+
"""Compute an effective index with structured convergence diagnostics.
|
|
196
|
+
|
|
197
|
+
Parameters
|
|
198
|
+
----------
|
|
199
|
+
fiber : Fiber
|
|
200
|
+
Fiber to solve.
|
|
201
|
+
wavelength : float
|
|
202
|
+
Vacuum wavelength in meters.
|
|
203
|
+
mode : Mode
|
|
204
|
+
Mode to solve.
|
|
205
|
+
delta_neff : float, optional
|
|
206
|
+
Maximum effective-index search step.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
SolverResult[float]
|
|
211
|
+
Effective index, residual, bracket, iteration count, and explanation.
|
|
212
|
+
"""
|
|
213
|
+
from PyFiberModes import solver
|
|
214
|
+
|
|
215
|
+
solver_class = (
|
|
216
|
+
solver.two_layer.EffectiveIndexSolver
|
|
217
|
+
if fiber.n_layer == 2
|
|
218
|
+
else solver.multilayer.EffectiveIndexSolver
|
|
219
|
+
)
|
|
220
|
+
effective_index_solver = solver_class(fiber=fiber, wavelength=wavelength)
|
|
221
|
+
return effective_index_solver.solve_result(mode=mode, delta_neff=delta_neff)
|
|
173
222
|
|
|
174
223
|
|
|
175
224
|
def get_mode_cutoff_v0(
|
|
@@ -199,12 +248,14 @@ def get_mode_cutoff_v0(
|
|
|
199
248
|
return 0
|
|
200
249
|
|
|
201
250
|
match fiber.n_layer:
|
|
202
|
-
case 2:
|
|
203
|
-
cutoff_solver = solver.
|
|
204
|
-
case 3:
|
|
205
|
-
cutoff_solver = solver.
|
|
206
|
-
case _:
|
|
207
|
-
|
|
251
|
+
case 2:
|
|
252
|
+
cutoff_solver = solver.two_layer.CutoffSolver(fiber=fiber, wavelength=wavelength)
|
|
253
|
+
case 3:
|
|
254
|
+
cutoff_solver = solver.three_layer.CutoffSolver(fiber=fiber, wavelength=wavelength)
|
|
255
|
+
case _:
|
|
256
|
+
raise NotImplementedError(
|
|
257
|
+
"Cutoff calculations are currently available for two- and three-layer fibers"
|
|
258
|
+
)
|
|
208
259
|
|
|
209
260
|
cutoff = cutoff_solver.solve(mode=mode)
|
|
210
261
|
|
|
@@ -241,10 +292,14 @@ def get_radial_field(
|
|
|
241
292
|
"""
|
|
242
293
|
from PyFiberModes import solver
|
|
243
294
|
|
|
244
|
-
if fiber.n_layer == 2:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
295
|
+
if fiber.n_layer == 2:
|
|
296
|
+
effective_index_solver = solver.two_layer.EffectiveIndexSolver(
|
|
297
|
+
fiber=fiber, wavelength=wavelength
|
|
298
|
+
)
|
|
299
|
+
else:
|
|
300
|
+
effective_index_solver = solver.multilayer.EffectiveIndexSolver(
|
|
301
|
+
fiber=fiber, wavelength=wavelength
|
|
302
|
+
)
|
|
248
303
|
|
|
249
304
|
neff = get_effective_index(
|
|
250
305
|
fiber=fiber,
|
|
@@ -260,15 +315,15 @@ def get_radial_field(
|
|
|
260
315
|
|
|
261
316
|
match mode.family:
|
|
262
317
|
case 'LP':
|
|
263
|
-
(er, ephi, ez), (hr, hphi, hz) =
|
|
318
|
+
(er, ephi, ez), (hr, hphi, hz) = effective_index_solver.get_LP_field(**kwargs)
|
|
264
319
|
case 'TE':
|
|
265
|
-
(er, ephi, ez), (hr, hphi, hz) =
|
|
320
|
+
(er, ephi, ez), (hr, hphi, hz) = effective_index_solver.get_TE_field(**kwargs)
|
|
266
321
|
case 'TM':
|
|
267
|
-
(er, ephi, ez), (hr, hphi, hz) =
|
|
322
|
+
(er, ephi, ez), (hr, hphi, hz) = effective_index_solver.get_TM_field(**kwargs)
|
|
268
323
|
case 'EH':
|
|
269
|
-
(er, ephi, ez), (hr, hphi, hz) =
|
|
324
|
+
(er, ephi, ez), (hr, hphi, hz) = effective_index_solver.get_EH_field(**kwargs)
|
|
270
325
|
case 'HE':
|
|
271
|
-
(er, ephi, ez), (hr, hphi, hz) =
|
|
326
|
+
(er, ephi, ez), (hr, hphi, hz) = effective_index_solver.get_HE_field(**kwargs)
|
|
272
327
|
|
|
273
328
|
e_field = CylindricalCoordinates(rho=er, phi=ephi, z=ez)
|
|
274
329
|
h_field = CylindricalCoordinates(rho=hr, phi=hphi, z=hz)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"""Load and normalize YAML fiber definitions."""
|
|
2
2
|
|
|
3
|
-
import yaml
|
|
4
|
-
import numpy as np
|
|
5
3
|
from pathlib import Path
|
|
6
|
-
from
|
|
4
|
+
from typing import Any, TypeAlias
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
from PyFiberModes.materials import DEFAULT_MATERIALS, MaterialRegistry
|
|
10
|
+
|
|
11
|
+
LayerData: TypeAlias = dict[str, Any]
|
|
12
|
+
LayerCollection: TypeAlias = dict[str, LayerData]
|
|
7
13
|
|
|
8
14
|
|
|
9
15
|
def get_fiber_file_path(fiber_name: str) -> Path:
|
|
@@ -23,7 +29,7 @@ def get_fiber_file_path(fiber_name: str) -> Path:
|
|
|
23
29
|
return Path(__file__).parent / 'fiber_files' / f'{fiber_name}.yaml'
|
|
24
30
|
|
|
25
31
|
|
|
26
|
-
def load_yaml_configuration(file_path: Path) -> dict:
|
|
32
|
+
def load_yaml_configuration(file_path: Path) -> dict[str, Any]:
|
|
27
33
|
"""
|
|
28
34
|
Load and parse a YAML configuration file.
|
|
29
35
|
|
|
@@ -44,7 +50,12 @@ def load_yaml_configuration(file_path: Path) -> dict:
|
|
|
44
50
|
return yaml.safe_load(file)
|
|
45
51
|
|
|
46
52
|
|
|
47
|
-
def calculate_layer_index(
|
|
53
|
+
def calculate_layer_index(
|
|
54
|
+
layer: LayerData,
|
|
55
|
+
wavelength: float | None,
|
|
56
|
+
outer_layer: LayerData | None = None,
|
|
57
|
+
materials: MaterialRegistry = DEFAULT_MATERIALS,
|
|
58
|
+
) -> float:
|
|
48
59
|
"""
|
|
49
60
|
Calculate the refractive index for a layer.
|
|
50
61
|
|
|
@@ -62,14 +73,21 @@ def calculate_layer_index(layer: dict, wavelength: float, outer_layer: dict = No
|
|
|
62
73
|
float
|
|
63
74
|
Computed refractive index for the layer.
|
|
64
75
|
"""
|
|
65
|
-
if 'material' in layer and wavelength:
|
|
66
|
-
return
|
|
76
|
+
if 'material' in layer and wavelength is not None:
|
|
77
|
+
return materials.refractive_index(str(layer['material']), wavelength)
|
|
67
78
|
elif 'NA' in layer and outer_layer:
|
|
68
79
|
return np.sqrt(layer['NA']**2 + outer_layer['index']**2)
|
|
69
|
-
|
|
80
|
+
index = layer.get('index')
|
|
81
|
+
if index is None:
|
|
82
|
+
raise ValueError("layer must define material, numerical aperture, or index")
|
|
83
|
+
return float(index)
|
|
70
84
|
|
|
71
85
|
|
|
72
|
-
def process_layers(
|
|
86
|
+
def process_layers(
|
|
87
|
+
layers: LayerCollection,
|
|
88
|
+
wavelength: float | None = None,
|
|
89
|
+
materials: MaterialRegistry = DEFAULT_MATERIALS,
|
|
90
|
+
) -> LayerCollection:
|
|
73
91
|
"""
|
|
74
92
|
Process and calculate refractive indices for all layers.
|
|
75
93
|
|
|
@@ -89,14 +107,14 @@ def process_layers(layers: dict, wavelength: float = None) -> dict:
|
|
|
89
107
|
outer_layer = None
|
|
90
108
|
|
|
91
109
|
for idx, layer in layers.items():
|
|
92
|
-
layer_index = calculate_layer_index(layer, wavelength, outer_layer)
|
|
110
|
+
layer_index = calculate_layer_index(layer, wavelength, outer_layer, materials)
|
|
93
111
|
processed_layers[idx] = {**layer, 'index': layer_index}
|
|
94
112
|
outer_layer = processed_layers[idx]
|
|
95
113
|
|
|
96
114
|
return processed_layers
|
|
97
115
|
|
|
98
116
|
|
|
99
|
-
def cleanup_layers(layers:
|
|
117
|
+
def cleanup_layers(layers: LayerCollection) -> LayerCollection:
|
|
100
118
|
"""
|
|
101
119
|
Remove unnecessary keys from layer dictionaries.
|
|
102
120
|
|
|
@@ -116,7 +134,7 @@ def cleanup_layers(layers: dict) -> dict:
|
|
|
116
134
|
return layers
|
|
117
135
|
|
|
118
136
|
|
|
119
|
-
def reorder_layers(layers:
|
|
137
|
+
def reorder_layers(layers: LayerCollection, order: str) -> LayerCollection:
|
|
120
138
|
"""
|
|
121
139
|
Reorder layers based on the specified order.
|
|
122
140
|
|
|
@@ -137,7 +155,12 @@ def reorder_layers(layers: dict, order: str) -> dict:
|
|
|
137
155
|
return layers
|
|
138
156
|
|
|
139
157
|
|
|
140
|
-
def load_fiber_as_dict(
|
|
158
|
+
def load_fiber_as_dict(
|
|
159
|
+
fiber_name: str,
|
|
160
|
+
wavelength: float | None = None,
|
|
161
|
+
order: str = 'in-to-out',
|
|
162
|
+
materials: MaterialRegistry = DEFAULT_MATERIALS,
|
|
163
|
+
) -> dict[str, LayerCollection]:
|
|
141
164
|
"""
|
|
142
165
|
Load and process a fiber configuration file.
|
|
143
166
|
|
|
@@ -167,7 +190,7 @@ def load_fiber_as_dict(fiber_name: str, wavelength: float = None, order: str = '
|
|
|
167
190
|
config = load_yaml_configuration(file_path)
|
|
168
191
|
layers = config.get('layers', {})
|
|
169
192
|
|
|
170
|
-
processed_layers = process_layers(layers, wavelength)
|
|
193
|
+
processed_layers = process_layers(layers, wavelength, materials)
|
|
171
194
|
cleaned_layers = cleanup_layers(processed_layers)
|
|
172
195
|
reordered_layers = reorder_layers(cleaned_layers, order)
|
|
173
196
|
|