PyFiberModes 0.14.3__tar.gz → 0.16.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.
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.zenodo.json +1 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/CHANGELOG.md +29 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PKG-INFO +1 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/__init__.py +7 -2
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/_version.py +2 -2
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/analysis.py +5 -2
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/exceptions.py +4 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber.py +16 -3
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fundamentals.py +8 -2
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/mode.py +26 -7
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/services.py +12 -3
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/multilayer/effective_index.py +14 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/three_layer/cutoff.py +11 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/two_layer/cutoff.py +11 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/two_layer/effective_index.py +37 -15
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes.egg-info/PKG-INFO +1 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes.egg-info/SOURCES.txt +1 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/conda.recipe/meta.yaml +1 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_dispersion.py +7 -2
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_fiber_LP_modes.py +10 -5
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_group_index.py +10 -5
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/api_policy.rst +5 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/code.rst +1 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/index.rst +1 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/migration_guide.rst +15 -0
- pyfibermodes-0.16.0/docs/source/public_api_contract.rst +164 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/pyproject.toml +1 -1
- pyfibermodes-0.16.0/tests/api_snapshot.json +72 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_advanced_features.py +24 -2
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_public_api.py +38 -1
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_validation.py +25 -1
- pyfibermodes-0.14.3/tests/api_snapshot.json +0 -54
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.coveragerc +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.github/dependabot.yml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.github/workflows/deploy_PyPi.yml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.github/workflows/deploy_anaconda.yml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.github/workflows/deploy_coverage.yml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.github/workflows/deploy_documentation.yml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.github/workflows/quality.yml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.github/workflows/tests.yml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/.gitignore +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/CITATION.cff +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/CONTRIBUTING.md +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/LICENSE +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/MANIFEST.in +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/Makefile +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/coordinates.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/directories.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/factory.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/1550BHP.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/DCF13.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/DCF1300S_20.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/DCF1300S_26.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/DCF1300S_33.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/DCF1300S_42.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/F2028M12.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/F2028M21.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/F2028M24.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/F2058G1.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/F2058L1.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/HI1060.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/HP630.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/SM1950.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/SMF28.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/fluorine_doped_1%_capillary.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/fluorine_doped_2%_capillary.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/test_fiber.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/fiber_files/test_multimode_fiber.yaml +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/field.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/loader.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/materials.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/mode_instances.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/models.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/optimization.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/plotting.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/propagation.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/__init__.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/base_solver.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/multilayer/__init__.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/protocols.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/results.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/three_layer/__init__.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/two_layer/__init__.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/source.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/stepindex.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes.egg-info/dependency_links.txt +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes.egg-info/requires.txt +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes.egg-info/top_level.txt +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/benchmarks/README.md +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/benchmarks/test_field_performance.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/Makefile +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/SMF28/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/SMF28/plot_smf28.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/SMF28/plot_smf28_dispersion_vs_wavelength.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/SMF28/plot_smf28_group_index_vs_wavelength.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/analysis/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/analysis/plot_coupled_mode_exchange.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/analysis/plot_guided_mode_discovery.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/analysis/plot_structured_wavelength_sweep.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_U_vs_V.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_comparison_solvers.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_effective_index.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_mode_field.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_mode_field_1.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_mode_field_2.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/basic/plot_neff_tapered_fiber.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/benchmarks/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/benchmarks/plot_component_batching_speedup.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/benchmarks/plot_field_grid_scaling.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/benchmarks/plot_modal_cache_speedup.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/fields/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/fields/plot_confinement_by_radius.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/fields/plot_polarization_rotation.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/fields/plot_vector_components.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/specialty_fibers/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/specialty_fibers/plot_refractive_index_profile.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/specialty_fibers/plot_specialty_fiber_catalog.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/specialty_fibers/plot_specialty_mode_indices.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/validation/README.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/validation/plot_effective_index_bounds.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/validation/plot_field_area_convergence.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/examples/validation/plot_normalized_effective_index.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/make.bat +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/_static/default.css +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/_static/favicon.png +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/_static/logo.png +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/_static/thumbnail.png +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/architecture.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/code/analysis.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/code/fibers.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/code/fields.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/code/fundamentals.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/conf.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/examples.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/getting_started.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/performance.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/references.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/theory.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/troubleshooting.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/user_guide/fibers.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/user_guide/fields.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/user_guide/index.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/user_guide/modes.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/user_guide/reproducibility.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/user_guide/sweeps.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/user_guide/units.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/docs/source/workflows.rst +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/pytest.ini +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/setup.cfg +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/__init__.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/helpers.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_api.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_architecture.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_architecture_enhancements.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_coordinates.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_docstrings.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_fiber.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_field.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_file_loading.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_physics_regression.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_release_tools.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_three_layer_solver.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tests/test_two_layer_solver.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tools/check_release.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tools/next_release_version.py +0 -0
- {pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/tools/release_tag.py +0 -0
|
@@ -6,6 +6,32 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.16.0] - 2026-09-23
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Handle expected higher-order mode cutoff in derivative gallery examples by
|
|
14
|
+
plotting unavailable values as gaps instead of failing the documentation
|
|
15
|
+
build.
|
|
16
|
+
|
|
17
|
+
## [0.15.0] - 2026-09-23
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Published the definitive 1.0 public API table with units, mutation rules,
|
|
22
|
+
failure semantics, compatibility names, and CI-enforced signatures/defaults.
|
|
23
|
+
- Added ``UnsupportedGeometryError`` to distinguish valid but unsupported
|
|
24
|
+
calculations from invalid input and numerical non-convergence.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- ``Mode`` accepts both strings and ``Family`` members, requires positive
|
|
29
|
+
radial order, and raises ``ValidationError`` instead of runtime assertions.
|
|
30
|
+
- Standardized expected missing roots, unsupported geometry, invalid input,
|
|
31
|
+
derivative failures, and structured solver diagnostics across analysis APIs.
|
|
32
|
+
- Completed two-layer and multilayer solver assumptions, characteristic
|
|
33
|
+
equation residual documentation, units, and primary-reference attribution.
|
|
34
|
+
|
|
9
35
|
## [0.14.3] - 2026-09-23
|
|
10
36
|
|
|
11
37
|
### Fixed
|
|
@@ -123,7 +149,9 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
123
149
|
|
|
124
150
|
- Established the current tagged baseline for subsequent documented releases.
|
|
125
151
|
|
|
126
|
-
[Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/v0.
|
|
152
|
+
[Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/v0.16.0...HEAD
|
|
153
|
+
[0.16.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.16.0
|
|
154
|
+
[0.15.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.15.0
|
|
127
155
|
[0.14.3]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.14.3
|
|
128
156
|
[0.14.2]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.14.2
|
|
129
157
|
[0.14.1]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.14.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyFiberModes
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
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
|
|
@@ -26,7 +26,12 @@ from PyFiberModes.factory import FiberFactory
|
|
|
26
26
|
from PyFiberModes.fiber import Fiber, load_fiber
|
|
27
27
|
from PyFiberModes.field import Field
|
|
28
28
|
from PyFiberModes.coordinates import CartesianCoordinates, CylindricalCoordinates
|
|
29
|
-
from PyFiberModes.exceptions import
|
|
29
|
+
from PyFiberModes.exceptions import (
|
|
30
|
+
ConvergenceError,
|
|
31
|
+
SolverError,
|
|
32
|
+
UnsupportedGeometryError,
|
|
33
|
+
ValidationError,
|
|
34
|
+
)
|
|
30
35
|
from PyFiberModes.models import LayerSpec, SolverSettings
|
|
31
36
|
from PyFiberModes.solver.results import SolverResult
|
|
32
37
|
from PyFiberModes.analysis import ModeSweepResult, find_modes, sweep_modes
|
|
@@ -57,7 +62,7 @@ __all__ = [
|
|
|
57
62
|
'Field',
|
|
58
63
|
'CartesianCoordinates', 'CylindricalCoordinates',
|
|
59
64
|
'LayerSpec', 'SolverSettings', 'SolverResult',
|
|
60
|
-
'ValidationError', 'SolverError', 'ConvergenceError',
|
|
65
|
+
'ValidationError', 'SolverError', 'ConvergenceError', 'UnsupportedGeometryError',
|
|
61
66
|
'ModeSweepResult', 'find_modes', 'sweep_modes',
|
|
62
67
|
'DesignParameter', 'DesignResult', 'optimize_fiber',
|
|
63
68
|
'CoupledModeSystem', 'PropagationResult', 'coupling_matrix', 'overlap',
|
|
@@ -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.16.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 16, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -6,6 +6,7 @@ from typing import Callable, Iterable, Sequence
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
|
|
9
|
+
from PyFiberModes.exceptions import ConvergenceError, ValidationError
|
|
9
10
|
from PyFiberModes.mode import Mode
|
|
10
11
|
|
|
11
12
|
|
|
@@ -100,6 +101,8 @@ def candidate_modes(
|
|
|
100
101
|
tuple of Mode
|
|
101
102
|
Candidates ordered by family, azimuthal order, and radial order.
|
|
102
103
|
"""
|
|
104
|
+
if max_nu < 0 or max_m < 1:
|
|
105
|
+
raise ValidationError("max_nu must be non-negative and max_m must be positive")
|
|
103
106
|
modes = []
|
|
104
107
|
for family in families:
|
|
105
108
|
nus = (0,) if family in ("TE", "TM") else range(max_nu + 1)
|
|
@@ -141,7 +144,7 @@ def find_modes(fiber, families=("LP",), max_nu=6, max_m=6) -> tuple[Mode, ...]:
|
|
|
141
144
|
)
|
|
142
145
|
if np.isfinite(effective_index) and guided:
|
|
143
146
|
found.append(mode)
|
|
144
|
-
except
|
|
147
|
+
except ConvergenceError:
|
|
145
148
|
continue
|
|
146
149
|
return tuple(found)
|
|
147
150
|
|
|
@@ -226,6 +229,6 @@ def sweep_modes(
|
|
|
226
229
|
try:
|
|
227
230
|
value = metric_function(mode)
|
|
228
231
|
values[metric][i, j] = value if np.isfinite(value) else np.nan
|
|
229
|
-
except
|
|
232
|
+
except ConvergenceError:
|
|
230
233
|
pass
|
|
231
234
|
return ModeSweepResult(parameter_name, parameters, modes, values)
|
|
@@ -15,3 +15,7 @@ class SolverError(PyFiberModesError, RuntimeError):
|
|
|
15
15
|
|
|
16
16
|
class ConvergenceError(SolverError):
|
|
17
17
|
"""Indicate that a numerical solver did not converge to a valid root."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class UnsupportedGeometryError(SolverError):
|
|
21
|
+
"""Indicate that a requested calculation does not support the fiber geometry."""
|
|
@@ -21,7 +21,7 @@ from PyFiberModes.fundamentals import (
|
|
|
21
21
|
|
|
22
22
|
from PyFiberModes import loader
|
|
23
23
|
from PyFiberModes.coordinates import CylindricalCoordinates
|
|
24
|
-
from PyFiberModes.exceptions import ValidationError
|
|
24
|
+
from PyFiberModes.exceptions import ConvergenceError, ValidationError
|
|
25
25
|
from PyFiberModes.materials import DEFAULT_MATERIALS, MaterialRegistry
|
|
26
26
|
from PyFiberModes.services import FieldAnalysis, ModalAnalysis
|
|
27
27
|
|
|
@@ -668,7 +668,10 @@ class Fiber(object):
|
|
|
668
668
|
function_kwargs=dict(fiber=self, mode=mode)
|
|
669
669
|
)
|
|
670
670
|
|
|
671
|
-
|
|
671
|
+
value = derivative * constants.c
|
|
672
|
+
if not numpy.isfinite(value):
|
|
673
|
+
raise ConvergenceError(f"group-index derivative failed for {mode}")
|
|
674
|
+
return value
|
|
672
675
|
|
|
673
676
|
def get_group_velocity(self, mode: Mode) -> float:
|
|
674
677
|
"""Compute the correctly named modal group velocity.
|
|
@@ -712,6 +715,10 @@ class Fiber(object):
|
|
|
712
715
|
function_kwargs=dict(fiber=self, mode=mode)
|
|
713
716
|
)
|
|
714
717
|
|
|
718
|
+
if not numpy.isfinite(derivative):
|
|
719
|
+
raise ConvergenceError(
|
|
720
|
+
f"group-velocity-dispersion derivative failed for {mode}"
|
|
721
|
+
)
|
|
715
722
|
return derivative
|
|
716
723
|
|
|
717
724
|
def get_dispersion(self, mode: Mode) -> float:
|
|
@@ -778,6 +785,9 @@ class Fiber(object):
|
|
|
778
785
|
function_kwargs=dict(fiber=self, mode=mode)
|
|
779
786
|
)
|
|
780
787
|
|
|
788
|
+
if not numpy.isfinite(derivative):
|
|
789
|
+
raise ConvergenceError(f"dispersion-slope derivative failed for {mode}")
|
|
790
|
+
|
|
781
791
|
factor = 2 * numpy.pi * constants.c / self.wavelength**2
|
|
782
792
|
|
|
783
793
|
return 1e-3 * derivative * factor**2
|
|
@@ -965,7 +975,10 @@ class Fiber(object):
|
|
|
965
975
|
print(first_line, "-" * len(first_line))
|
|
966
976
|
for mode in mode_list:
|
|
967
977
|
data_type_string = f"get_{data_type.lower()}"
|
|
968
|
-
|
|
978
|
+
try:
|
|
979
|
+
data = getattr(self, data_type_string)(mode=mode)
|
|
980
|
+
except ConvergenceError:
|
|
981
|
+
data = numpy.nan
|
|
969
982
|
output_string = f"{mode = } \t {data_type}: {data}"
|
|
970
983
|
print(output_string)
|
|
971
984
|
|
|
@@ -10,6 +10,7 @@ from PyFiberModes.mode_instances import HE11, LP01
|
|
|
10
10
|
from scipy.constants import c
|
|
11
11
|
|
|
12
12
|
from PyFiberModes.coordinates import CylindricalCoordinates
|
|
13
|
+
from PyFiberModes.exceptions import ConvergenceError, UnsupportedGeometryError
|
|
13
14
|
|
|
14
15
|
if TYPE_CHECKING:
|
|
15
16
|
from PyFiberModes.solver.results import SolverResult
|
|
@@ -139,7 +140,10 @@ def get_U_parameter(
|
|
|
139
140
|
The \(U\) parameter.
|
|
140
141
|
"""
|
|
141
142
|
from PyFiberModes import solver
|
|
142
|
-
|
|
143
|
+
if fiber.n_layer != 2:
|
|
144
|
+
raise UnsupportedGeometryError(
|
|
145
|
+
"U-parameter calculations require exactly two fiber layers"
|
|
146
|
+
)
|
|
143
147
|
|
|
144
148
|
effective_index_solver = solver.two_layer.EffectiveIndexSolver(
|
|
145
149
|
fiber=fiber, wavelength=wavelength
|
|
@@ -253,7 +257,7 @@ def get_mode_cutoff_v0(
|
|
|
253
257
|
case 3:
|
|
254
258
|
cutoff_solver = solver.three_layer.CutoffSolver(fiber=fiber, wavelength=wavelength)
|
|
255
259
|
case _:
|
|
256
|
-
raise
|
|
260
|
+
raise UnsupportedGeometryError(
|
|
257
261
|
"Cutoff calculations are currently available for two- and three-layer fibers"
|
|
258
262
|
)
|
|
259
263
|
|
|
@@ -306,6 +310,8 @@ def get_radial_field(
|
|
|
306
310
|
wavelength=fiber.wavelength,
|
|
307
311
|
mode=mode
|
|
308
312
|
)
|
|
313
|
+
if not numpy.isfinite(neff):
|
|
314
|
+
raise ConvergenceError(f"no guided effective-index solution for {mode}")
|
|
309
315
|
|
|
310
316
|
kwargs = dict(
|
|
311
317
|
nu=mode.nu,
|
|
@@ -3,7 +3,15 @@
|
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
class Family(str, Enum):
|
|
8
|
+
"""Supported scalar and vector mode families."""
|
|
9
|
+
|
|
10
|
+
LP = "LP"
|
|
11
|
+
HE = "HE"
|
|
12
|
+
EH = "EH"
|
|
13
|
+
TE = "TE"
|
|
14
|
+
TM = "TM"
|
|
7
15
|
|
|
8
16
|
|
|
9
17
|
@dataclass(frozen=True, eq=True)
|
|
@@ -19,7 +27,7 @@ class Mode():
|
|
|
19
27
|
m : int
|
|
20
28
|
Non-negative radial order.
|
|
21
29
|
"""
|
|
22
|
-
family: str
|
|
30
|
+
family: str | Family
|
|
23
31
|
""" Family of the mode """
|
|
24
32
|
nu: int
|
|
25
33
|
""" Parameter of the mode. It often corresponds to the parameter of the radial Bessel functions. """
|
|
@@ -31,14 +39,25 @@ class Mode():
|
|
|
31
39
|
|
|
32
40
|
Raises
|
|
33
41
|
------
|
|
34
|
-
|
|
35
|
-
If the family is unknown
|
|
42
|
+
ValidationError
|
|
43
|
+
If the family is unknown, ``nu`` is negative, or ``m`` is not a
|
|
44
|
+
positive integer.
|
|
36
45
|
"""
|
|
37
|
-
|
|
46
|
+
from PyFiberModes.exceptions import ValidationError
|
|
38
47
|
|
|
39
|
-
|
|
48
|
+
try:
|
|
49
|
+
family = self.family if isinstance(self.family, Family) else Family(self.family)
|
|
50
|
+
except (TypeError, ValueError) as error:
|
|
51
|
+
choices = ", ".join(member.value for member in Family)
|
|
52
|
+
raise ValidationError(
|
|
53
|
+
f"unknown mode family {self.family!r}; expected one of {choices}"
|
|
54
|
+
) from error
|
|
55
|
+
if not isinstance(self.nu, int) or isinstance(self.nu, bool) or self.nu < 0:
|
|
56
|
+
raise ValidationError("nu must be a non-negative integer")
|
|
57
|
+
if not isinstance(self.m, int) or isinstance(self.m, bool) or self.m < 1:
|
|
58
|
+
raise ValidationError("m must be a positive integer")
|
|
40
59
|
|
|
41
|
-
|
|
60
|
+
object.__setattr__(self, "family", family.value)
|
|
42
61
|
|
|
43
62
|
def __repr__(self) -> str:
|
|
44
63
|
"""Return the compact family-and-order representation.
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
|
-
from PyFiberModes.exceptions import
|
|
5
|
+
from PyFiberModes.exceptions import (
|
|
6
|
+
ConvergenceError,
|
|
7
|
+
UnsupportedGeometryError,
|
|
8
|
+
ValidationError,
|
|
9
|
+
)
|
|
10
|
+
from PyFiberModes.mode import Mode
|
|
6
11
|
from PyFiberModes.models import SolverSettings
|
|
7
12
|
from PyFiberModes.solver.results import SolverResult
|
|
8
13
|
|
|
@@ -45,6 +50,8 @@ class ModalAnalysis:
|
|
|
45
50
|
SolverResult[float]
|
|
46
51
|
Cached value and convergence status.
|
|
47
52
|
"""
|
|
53
|
+
if not isinstance(mode, Mode):
|
|
54
|
+
raise ValidationError("mode must be a Mode instance")
|
|
48
55
|
key = self._key("effective_index", mode)
|
|
49
56
|
if key in self._cache:
|
|
50
57
|
return self._cache[key]
|
|
@@ -58,6 +65,8 @@ class ModalAnalysis:
|
|
|
58
65
|
mode=mode,
|
|
59
66
|
delta_neff=self.settings.effective_index_step,
|
|
60
67
|
)
|
|
68
|
+
except (ValidationError, UnsupportedGeometryError):
|
|
69
|
+
raise
|
|
61
70
|
except (ArithmeticError, RuntimeError, ValueError) as error:
|
|
62
71
|
result = SolverResult(value=None, converged=False, message=str(error))
|
|
63
72
|
|
|
@@ -100,7 +109,7 @@ class ModalAnalysis:
|
|
|
100
109
|
converged=converged,
|
|
101
110
|
message="converged" if converged else f"no cutoff solution for {mode}",
|
|
102
111
|
)
|
|
103
|
-
except (ArithmeticError,
|
|
112
|
+
except (ArithmeticError, ValueError) as error:
|
|
104
113
|
self._cache[key] = SolverResult(
|
|
105
114
|
value=None, converged=False, message=str(error)
|
|
106
115
|
)
|
|
@@ -145,7 +154,7 @@ class FieldAnalysis:
|
|
|
145
154
|
from PyFiberModes.field import Field
|
|
146
155
|
|
|
147
156
|
if n_point < 2:
|
|
148
|
-
raise
|
|
157
|
+
raise ValidationError("n_point must be at least two")
|
|
149
158
|
return Field(
|
|
150
159
|
fiber=self.fiber,
|
|
151
160
|
mode=mode,
|
{pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/multilayer/effective_index.py
RENAMED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Transfer-matrix solver for isotropic concentric step-index fibers.
|
|
2
|
+
|
|
3
|
+
Each homogeneous annulus is represented by cylindrical Bessel or modified
|
|
4
|
+
Bessel solutions and tangential fields are matched at every interface. The
|
|
5
|
+
model assumes circular symmetry, scalar real refractive indices, lossless
|
|
6
|
+
materials, and a longitudinally invariant cross-section. See Snyder and Love,
|
|
7
|
+
*Optical Waveguide Theory*, chapters 12 and 19.
|
|
8
|
+
"""
|
|
2
9
|
|
|
3
10
|
import numpy
|
|
4
11
|
from scipy.special import kn, kvp, k0, k1, jn, jvp, yn, yvp, iv, ivp
|
|
@@ -20,6 +27,12 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
20
27
|
Multilayer fiber to solve.
|
|
21
28
|
wavelength : float
|
|
22
29
|
Vacuum wavelength in meters.
|
|
30
|
+
|
|
31
|
+
Notes
|
|
32
|
+
-----
|
|
33
|
+
LP, TE, TM, HE, and EH families are supported. The solver does not model
|
|
34
|
+
anisotropy, material loss, stress birefringence, non-circular interfaces,
|
|
35
|
+
or longitudinal tapering within a solve.
|
|
23
36
|
"""
|
|
24
37
|
def get_neff_lower_boundary(self, mode: Mode, delta_neff: float = 1e-6) -> float:
|
|
25
38
|
"""Gets the lower boundary for neff value.
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Cutoff solver for isotropic three-layer step-index fibers.
|
|
2
|
+
|
|
3
|
+
The solver matches cylindrical solutions across two concentric interfaces and
|
|
4
|
+
returns dimensionless normalized cutoff frequencies. It assumes homogeneous,
|
|
5
|
+
lossless, isotropic layers with scalar real refractive indices.
|
|
6
|
+
"""
|
|
2
7
|
|
|
3
8
|
from PyFiberModes.mode import Mode
|
|
4
9
|
from PyFiberModes.mode_instances import HE11, LP01, LP11, TE01
|
|
@@ -35,6 +40,11 @@ class CutoffSolver(BaseSolver):
|
|
|
35
40
|
Three-layer fiber to solve.
|
|
36
41
|
wavelength : float
|
|
37
42
|
Reference vacuum wavelength in meters.
|
|
43
|
+
|
|
44
|
+
Notes
|
|
45
|
+
-----
|
|
46
|
+
Only cutoff calculations are provided by this backend. Effective indices
|
|
47
|
+
and fields for the same geometry are handled by the multilayer solver.
|
|
38
48
|
"""
|
|
39
49
|
|
|
40
50
|
def get_lower_neff_mode(self, mode: Mode) -> Mode:
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Analytical cutoff solver for isotropic two-layer step-index fibers.
|
|
2
|
+
|
|
3
|
+
Cutoffs are zeros of the appropriate cylindrical Bessel characteristic
|
|
4
|
+
equation and are returned as dimensionless normalized frequencies. The
|
|
5
|
+
formulation follows Snyder and Love, *Optical Waveguide Theory*, chapter 12.
|
|
6
|
+
"""
|
|
2
7
|
|
|
3
8
|
import numpy
|
|
4
9
|
import logging
|
|
@@ -21,6 +26,11 @@ class CutoffSolver(BaseSolver):
|
|
|
21
26
|
Standard step-index fiber.
|
|
22
27
|
wavelength : float
|
|
23
28
|
Reference vacuum wavelength in meters.
|
|
29
|
+
|
|
30
|
+
Notes
|
|
31
|
+
-----
|
|
32
|
+
The fiber must contain exactly one circular core and one homogeneous
|
|
33
|
+
exterior cladding. LP cutoffs use the weak-guidance approximation.
|
|
24
34
|
"""
|
|
25
35
|
logger = logging.getLogger(__name__)
|
|
26
36
|
|
{pyfibermodes-0.14.3 → pyfibermodes-0.16.0}/PyFiberModes/solver/two_layer/effective_index.py
RENAMED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Exact scalar and vector solver for isotropic two-layer step-index fibers.
|
|
2
|
+
|
|
3
|
+
The implementation matches cylindrical Bessel solutions across one circular
|
|
4
|
+
core-cladding interface. LP equations use the weak-guidance approximation;
|
|
5
|
+
TE, TM, HE, and EH equations retain the vector boundary conditions. Material
|
|
6
|
+
indices are real, lossless, and evaluated at one vacuum wavelength. See
|
|
7
|
+
Snyder and Love, *Optical Waveguide Theory*, chapters 11--12.
|
|
8
|
+
"""
|
|
2
9
|
|
|
3
10
|
import numpy
|
|
4
11
|
import logging
|
|
@@ -22,6 +29,12 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
22
29
|
Standard step-index fiber.
|
|
23
30
|
wavelength : float
|
|
24
31
|
Vacuum wavelength in meters.
|
|
32
|
+
|
|
33
|
+
Notes
|
|
34
|
+
-----
|
|
35
|
+
The solver requires exactly two concentric, homogeneous, isotropic layers
|
|
36
|
+
with a higher-index inner core. Characteristic functions are dimensionless;
|
|
37
|
+
their roots give the dimensionless effective index.
|
|
25
38
|
"""
|
|
26
39
|
|
|
27
40
|
def get_mode_with_lower_neff(self, mode: Mode) -> Mode:
|
|
@@ -542,10 +555,11 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
542
555
|
return value
|
|
543
556
|
|
|
544
557
|
def get_TE_equation(self, neff: float, nu: int) -> float:
|
|
545
|
-
"""Return the
|
|
558
|
+
r"""Return the TE characteristic-equation residual.
|
|
546
559
|
|
|
547
560
|
.. math::
|
|
548
|
-
|
|
561
|
+
|
|
562
|
+
U J_0(U) K_1(W) + W J_1(U) K_0(W)
|
|
549
563
|
|
|
550
564
|
Parameters
|
|
551
565
|
----------
|
|
@@ -557,17 +571,20 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
557
571
|
Returns
|
|
558
572
|
-------
|
|
559
573
|
float
|
|
560
|
-
|
|
574
|
+
Dimensionless boundary-condition residual. A guided TE solution
|
|
575
|
+
occurs at a root.
|
|
561
576
|
"""
|
|
562
577
|
U, W, _ = self.get_U_W_V_parameter(neff=neff)
|
|
563
578
|
|
|
564
579
|
return U * j0(U) * k1(W) + W * j1(U) * k0(W)
|
|
565
580
|
|
|
566
581
|
def get_TM_equation(self, neff: float, nu: int) -> float:
|
|
567
|
-
"""Return the
|
|
582
|
+
r"""Return the TM characteristic-equation residual.
|
|
568
583
|
|
|
569
584
|
.. math::
|
|
570
|
-
|
|
585
|
+
|
|
586
|
+
U J_0(U) K_1(W)n_\mathrm{clad}^2
|
|
587
|
+
+ W J_1(U) K_0(W)n_\mathrm{core}^2
|
|
571
588
|
|
|
572
589
|
Parameters
|
|
573
590
|
----------
|
|
@@ -579,7 +596,8 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
579
596
|
Returns
|
|
580
597
|
-------
|
|
581
598
|
float
|
|
582
|
-
|
|
599
|
+
Dimensionless boundary-condition residual. A guided TM solution
|
|
600
|
+
occurs at a root.
|
|
583
601
|
"""
|
|
584
602
|
core, clad = self.fiber.layers
|
|
585
603
|
|
|
@@ -591,8 +609,8 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
591
609
|
|
|
592
610
|
return U * j0(U) * k1(W) * n_clad**2 + W * j1(U) * k0(W) * n_core**2
|
|
593
611
|
|
|
594
|
-
def get_HE_EH_terms(self, neff, nu: int) -> float:
|
|
595
|
-
"""Return the
|
|
612
|
+
def get_HE_EH_terms(self, neff, nu: int) -> tuple[float, float]:
|
|
613
|
+
"""Return the common and splitting terms of the hybrid equations.
|
|
596
614
|
|
|
597
615
|
Parameters
|
|
598
616
|
----------
|
|
@@ -603,8 +621,10 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
603
621
|
|
|
604
622
|
Returns
|
|
605
623
|
-------
|
|
606
|
-
float
|
|
607
|
-
|
|
624
|
+
tuple of float
|
|
625
|
+
Dimensionless common boundary term and non-negative hybrid
|
|
626
|
+
splitting term. Their sum and difference form the HE and EH
|
|
627
|
+
characteristic residuals, respectively.
|
|
608
628
|
"""
|
|
609
629
|
core, clad = self.fiber.layers
|
|
610
630
|
|
|
@@ -628,7 +648,7 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
628
648
|
return term_0, term_4
|
|
629
649
|
|
|
630
650
|
def get_HE_equation(self, neff: float, nu: int) -> float:
|
|
631
|
-
"""Return the
|
|
651
|
+
"""Return the dimensionless HE characteristic-equation residual.
|
|
632
652
|
|
|
633
653
|
Parameters
|
|
634
654
|
----------
|
|
@@ -640,7 +660,8 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
640
660
|
Returns
|
|
641
661
|
-------
|
|
642
662
|
float
|
|
643
|
-
|
|
663
|
+
Boundary-condition residual; a guided HE solution occurs at a
|
|
664
|
+
root.
|
|
644
665
|
"""
|
|
645
666
|
term_0, term_1 = self.get_HE_EH_terms(
|
|
646
667
|
neff=neff,
|
|
@@ -652,7 +673,7 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
652
673
|
return value
|
|
653
674
|
|
|
654
675
|
def get_EH_equation(self, neff: float, nu: int) -> float:
|
|
655
|
-
"""Return the
|
|
676
|
+
"""Return the dimensionless EH characteristic-equation residual.
|
|
656
677
|
|
|
657
678
|
Parameters
|
|
658
679
|
----------
|
|
@@ -664,7 +685,8 @@ class EffectiveIndexSolver(BaseSolver):
|
|
|
664
685
|
Returns
|
|
665
686
|
-------
|
|
666
687
|
float
|
|
667
|
-
|
|
688
|
+
Boundary-condition residual; a guided EH solution occurs at a
|
|
689
|
+
root.
|
|
668
690
|
"""
|
|
669
691
|
term_0, term_1 = self.get_HE_EH_terms(
|
|
670
692
|
neff=neff,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyFiberModes
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
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
|
|
@@ -123,6 +123,7 @@ docs/source/getting_started.rst
|
|
|
123
123
|
docs/source/index.rst
|
|
124
124
|
docs/source/migration_guide.rst
|
|
125
125
|
docs/source/performance.rst
|
|
126
|
+
docs/source/public_api_contract.rst
|
|
126
127
|
docs/source/references.rst
|
|
127
128
|
docs/source/theory.rst
|
|
128
129
|
docs/source/troubleshooting.rst
|
|
@@ -7,7 +7,7 @@ Dispersion VS core index
|
|
|
7
7
|
# %%
|
|
8
8
|
# Imports
|
|
9
9
|
# ~~~~~~~
|
|
10
|
-
from PyFiberModes import FiberFactory, HE11, HE12, HE22
|
|
10
|
+
from PyFiberModes import ConvergenceError, FiberFactory, HE11, HE12, HE22
|
|
11
11
|
import matplotlib.pyplot as plt
|
|
12
12
|
import numpy
|
|
13
13
|
|
|
@@ -34,7 +34,12 @@ ax.set(
|
|
|
34
34
|
for mode in [HE11, HE12, HE22]:
|
|
35
35
|
data = []
|
|
36
36
|
for fiber in factory:
|
|
37
|
-
|
|
37
|
+
try:
|
|
38
|
+
effective_index = fiber.get_dispersion(mode)
|
|
39
|
+
except ConvergenceError:
|
|
40
|
+
# Higher-order modes can be unguided below cutoff. Use NaN so the
|
|
41
|
+
# plot shows a gap without obscuring other guided solutions.
|
|
42
|
+
effective_index = numpy.nan
|
|
38
43
|
data.append(effective_index)
|
|
39
44
|
|
|
40
45
|
ax.plot(core_indexes, data, label=str(mode))
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
Group index vs core index
|
|
3
|
+
=========================
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
# %%
|
|
8
8
|
# Imports
|
|
9
9
|
# ~~~~~~~
|
|
10
|
-
from PyFiberModes import FiberFactory, HE11, HE12, HE22
|
|
10
|
+
from PyFiberModes import ConvergenceError, FiberFactory, HE11, HE12, HE22
|
|
11
11
|
import matplotlib.pyplot as plt
|
|
12
12
|
import numpy
|
|
13
13
|
|
|
@@ -26,7 +26,7 @@ factory.add_layer(name="cladding", index=1.4444)
|
|
|
26
26
|
figure, ax = plt.subplots(1, 1)
|
|
27
27
|
|
|
28
28
|
ax.set(
|
|
29
|
-
title='
|
|
29
|
+
title='Group index vs core index',
|
|
30
30
|
xlabel='Core refractive index',
|
|
31
31
|
ylabel='Group index'
|
|
32
32
|
)
|
|
@@ -34,7 +34,12 @@ ax.set(
|
|
|
34
34
|
for mode in [HE11, HE12, HE22]:
|
|
35
35
|
neff = []
|
|
36
36
|
for fiber in factory:
|
|
37
|
-
|
|
37
|
+
try:
|
|
38
|
+
effective_index = fiber.get_group_index(mode)
|
|
39
|
+
except ConvergenceError:
|
|
40
|
+
# Higher-order modes can be unguided below cutoff. Use NaN so the
|
|
41
|
+
# plot shows a gap without obscuring other guided solutions.
|
|
42
|
+
effective_index = numpy.nan
|
|
38
43
|
neff.append(effective_index)
|
|
39
44
|
|
|
40
45
|
ax.plot(core_indexes, neff, label=str(mode))
|