PyFiberModes 0.17.7__tar.gz → 1.0.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.17.7 → pyfibermodes-1.0.1}/.zenodo.json +2 -2
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/CHANGELOG.md +9 -1
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PKG-INFO +34 -16
- pyfibermodes-0.17.7/PyFiberModes/fiber.py → pyfibermodes-1.0.1/PyFiberModes/_fiber.py +2 -2
- pyfibermodes-0.17.7/PyFiberModes/field.py → pyfibermodes-1.0.1/PyFiberModes/_field.py +2 -2
- pyfibermodes-1.0.1/PyFiberModes/_version.py +5 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/analysis.py +45 -19
- pyfibermodes-1.0.1/PyFiberModes/coordinates.py +153 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/factory.py +14 -13
- pyfibermodes-1.0.1/PyFiberModes/fiber.py +447 -0
- pyfibermodes-1.0.1/PyFiberModes/field.py +181 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fundamentals.py +1 -3
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/loader.py +2 -1
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/materials.py +43 -22
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/models.py +9 -6
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/optimization.py +39 -11
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/plotting.py +1 -1
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/propagation.py +36 -10
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/services.py +1 -1
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/base_solver.py +4 -2
- pyfibermodes-1.0.1/PyFiberModes/source.py +100 -0
- pyfibermodes-1.0.1/PyFiberModes/units.py +67 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes.egg-info/PKG-INFO +34 -16
- pyfibermodes-1.0.1/PyFiberModes.egg-info/SOURCES.txt +83 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes.egg-info/requires.txt +7 -1
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/README.rst +27 -14
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/pyproject.toml +15 -8
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_advanced_features.py +11 -10
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_api.py +7 -5
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_architecture_enhancements.py +9 -8
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_coordinates.py +28 -27
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_fiber.py +7 -5
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_field.py +2 -2
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_file_loading.py +3 -2
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_physics_regression.py +6 -5
- pyfibermodes-1.0.1/tests/test_release_tools.py +32 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_three_layer_solver.py +4 -2
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_two_layer_solver.py +3 -1
- pyfibermodes-1.0.1/tests/test_units.py +247 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_validation.py +7 -5
- pyfibermodes-0.17.7/.coveragerc +0 -22
- pyfibermodes-0.17.7/.github/dependabot.yml +0 -10
- pyfibermodes-0.17.7/.github/workflows/deploy_coverage.yml +0 -21
- pyfibermodes-0.17.7/.github/workflows/deploy_documentation.yml +0 -20
- pyfibermodes-0.17.7/.github/workflows/deploy_release.yml +0 -35
- pyfibermodes-0.17.7/.github/workflows/quality.yml +0 -21
- pyfibermodes-0.17.7/.github/workflows/tests.yml +0 -19
- pyfibermodes-0.17.7/.gitignore +0 -44
- pyfibermodes-0.17.7/CONTRIBUTING.md +0 -9
- pyfibermodes-0.17.7/Makefile +0 -61
- pyfibermodes-0.17.7/PyFiberModes/_version.py +0 -34
- pyfibermodes-0.17.7/PyFiberModes/source.py +0 -81
- pyfibermodes-0.17.7/PyFiberModes.egg-info/SOURCES.txt +0 -168
- pyfibermodes-0.17.7/benchmarks/README.md +0 -11
- pyfibermodes-0.17.7/benchmarks/test_field_performance.py +0 -32
- pyfibermodes-0.17.7/conda.recipe/meta.yaml +0 -64
- pyfibermodes-0.17.7/docs/Makefile +0 -19
- pyfibermodes-0.17.7/docs/examples/README.rst +0 -8
- pyfibermodes-0.17.7/docs/examples/SMF28/README.rst +0 -6
- pyfibermodes-0.17.7/docs/examples/SMF28/plot_smf28.py +0 -26
- pyfibermodes-0.17.7/docs/examples/SMF28/plot_smf28_dispersion_vs_wavelength.py +0 -39
- pyfibermodes-0.17.7/docs/examples/SMF28/plot_smf28_group_index_vs_wavelength.py +0 -39
- pyfibermodes-0.17.7/docs/examples/analysis/README.rst +0 -6
- pyfibermodes-0.17.7/docs/examples/analysis/plot_coupled_mode_exchange.py +0 -22
- pyfibermodes-0.17.7/docs/examples/analysis/plot_guided_mode_discovery.py +0 -22
- pyfibermodes-0.17.7/docs/examples/analysis/plot_structured_wavelength_sweep.py +0 -27
- pyfibermodes-0.17.7/docs/examples/basic/README.rst +0 -6
- pyfibermodes-0.17.7/docs/examples/basic/plot_U_vs_V.py +0 -48
- pyfibermodes-0.17.7/docs/examples/basic/plot_comparison_solvers.py +0 -54
- pyfibermodes-0.17.7/docs/examples/basic/plot_dispersion.py +0 -50
- pyfibermodes-0.17.7/docs/examples/basic/plot_effective_index.py +0 -45
- pyfibermodes-0.17.7/docs/examples/basic/plot_fiber_LP_modes.py +0 -51
- pyfibermodes-0.17.7/docs/examples/basic/plot_group_index.py +0 -50
- pyfibermodes-0.17.7/docs/examples/basic/plot_mode_field.py +0 -47
- pyfibermodes-0.17.7/docs/examples/basic/plot_mode_field_1.py +0 -37
- pyfibermodes-0.17.7/docs/examples/basic/plot_mode_field_2.py +0 -49
- pyfibermodes-0.17.7/docs/examples/basic/plot_neff_tapered_fiber.py +0 -67
- pyfibermodes-0.17.7/docs/examples/benchmarks/README.rst +0 -7
- pyfibermodes-0.17.7/docs/examples/benchmarks/plot_component_batching_speedup.py +0 -33
- pyfibermodes-0.17.7/docs/examples/benchmarks/plot_field_grid_scaling.py +0 -28
- pyfibermodes-0.17.7/docs/examples/benchmarks/plot_modal_cache_speedup.py +0 -28
- pyfibermodes-0.17.7/docs/examples/fields/README.rst +0 -7
- pyfibermodes-0.17.7/docs/examples/fields/plot_confinement_by_radius.py +0 -28
- pyfibermodes-0.17.7/docs/examples/fields/plot_polarization_rotation.py +0 -27
- pyfibermodes-0.17.7/docs/examples/fields/plot_vector_components.py +0 -24
- pyfibermodes-0.17.7/docs/examples/specialty_fibers/README.rst +0 -7
- pyfibermodes-0.17.7/docs/examples/specialty_fibers/plot_refractive_index_profile.py +0 -26
- pyfibermodes-0.17.7/docs/examples/specialty_fibers/plot_specialty_fiber_catalog.py +0 -33
- pyfibermodes-0.17.7/docs/examples/specialty_fibers/plot_specialty_mode_indices.py +0 -25
- pyfibermodes-0.17.7/docs/examples/validation/README.rst +0 -7
- pyfibermodes-0.17.7/docs/examples/validation/plot_effective_index_bounds.py +0 -25
- pyfibermodes-0.17.7/docs/examples/validation/plot_field_area_convergence.py +0 -26
- pyfibermodes-0.17.7/docs/examples/validation/plot_normalized_effective_index.py +0 -31
- pyfibermodes-0.17.7/docs/make.bat +0 -35
- pyfibermodes-0.17.7/docs/redirect.html +0 -12
- pyfibermodes-0.17.7/docs/source/_static/default.css +0 -43
- pyfibermodes-0.17.7/docs/source/_static/favicon.png +0 -0
- pyfibermodes-0.17.7/docs/source/_static/logo.png +0 -0
- pyfibermodes-0.17.7/docs/source/_static/thumbnail.png +0 -0
- pyfibermodes-0.17.7/docs/source/api_policy.rst +0 -64
- pyfibermodes-0.17.7/docs/source/architecture.rst +0 -42
- pyfibermodes-0.17.7/docs/source/code/analysis.rst +0 -38
- pyfibermodes-0.17.7/docs/source/code/fibers.rst +0 -15
- pyfibermodes-0.17.7/docs/source/code/fields.rst +0 -11
- pyfibermodes-0.17.7/docs/source/code/fundamentals.rst +0 -22
- pyfibermodes-0.17.7/docs/source/code.rst +0 -45
- pyfibermodes-0.17.7/docs/source/conf.py +0 -41
- pyfibermodes-0.17.7/docs/source/examples.rst +0 -73
- pyfibermodes-0.17.7/docs/source/getting_started.rst +0 -69
- pyfibermodes-0.17.7/docs/source/guide.rst +0 -37
- pyfibermodes-0.17.7/docs/source/index.rst +0 -50
- pyfibermodes-0.17.7/docs/source/migration_guide.rst +0 -84
- pyfibermodes-0.17.7/docs/source/performance.rst +0 -20
- pyfibermodes-0.17.7/docs/source/public_api_contract.rst +0 -164
- pyfibermodes-0.17.7/docs/source/references.rst +0 -12
- pyfibermodes-0.17.7/docs/source/resources.rst +0 -62
- pyfibermodes-0.17.7/docs/source/theory.rst +0 -64
- pyfibermodes-0.17.7/docs/source/troubleshooting.rst +0 -33
- pyfibermodes-0.17.7/docs/source/user_guide/fibers.rst +0 -78
- pyfibermodes-0.17.7/docs/source/user_guide/fields.rst +0 -71
- pyfibermodes-0.17.7/docs/source/user_guide/index.rst +0 -24
- pyfibermodes-0.17.7/docs/source/user_guide/modes.rst +0 -70
- pyfibermodes-0.17.7/docs/source/user_guide/reproducibility.rst +0 -53
- pyfibermodes-0.17.7/docs/source/user_guide/sweeps.rst +0 -101
- pyfibermodes-0.17.7/docs/source/user_guide/units.rst +0 -59
- pyfibermodes-0.17.7/docs/source/workflows.rst +0 -35
- pyfibermodes-0.17.7/pytest.ini +0 -21
- pyfibermodes-0.17.7/tests/__init__.py +0 -1
- pyfibermodes-0.17.7/tests/api_snapshot.json +0 -72
- pyfibermodes-0.17.7/tests/helpers.py +0 -13
- pyfibermodes-0.17.7/tests/test_release_tools.py +0 -66
- pyfibermodes-0.17.7/tools/check_release.py +0 -88
- pyfibermodes-0.17.7/tools/next_release_version.py +0 -55
- pyfibermodes-0.17.7/tools/release_tag.py +0 -136
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/CITATION.cff +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/LICENSE +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/MANIFEST.in +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/__init__.py +0 -0
- /pyfibermodes-0.17.7/PyFiberModes/coordinates.py → /pyfibermodes-1.0.1/PyFiberModes/_coordinates.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/directories.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/exceptions.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/1550BHP.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/DCF13.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/DCF1300S_20.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/DCF1300S_26.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/DCF1300S_33.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/DCF1300S_42.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/F2028M12.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/F2028M21.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/F2028M24.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/F2058G1.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/F2058L1.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/HI1060.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/HP630.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/SM1950.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/SMF28.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/fluorine_doped_1%_capillary.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/fluorine_doped_2%_capillary.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/test_fiber.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/fiber_files/test_multimode_fiber.yaml +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/mode.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/mode_instances.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/__init__.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/multilayer/__init__.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/multilayer/effective_index.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/protocols.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/results.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/three_layer/__init__.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/three_layer/cutoff.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/two_layer/__init__.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/two_layer/cutoff.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/solver/two_layer/effective_index.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes/stepindex.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes.egg-info/dependency_links.txt +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/PyFiberModes.egg-info/top_level.txt +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/setup.cfg +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_architecture.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_docstrings.py +0 -0
- {pyfibermodes-0.17.7 → pyfibermodes-1.0.1}/tests/test_public_api.py +0 -0
|
@@ -6,6 +6,12 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.0.1] - 2026-10-27
|
|
10
|
+
|
|
11
|
+
## [1.0.0] - 2026-10-23
|
|
12
|
+
|
|
13
|
+
- Require TypedUnit/Pint quantities for physical inputs and return unit-bearing fiber, field, sweep, material, design and propagation results. Numerical solvers continue to operate in SI internally.
|
|
14
|
+
|
|
9
15
|
## [0.17.7] - 2026-10-23
|
|
10
16
|
|
|
11
17
|
## [0.17.6] - 2026-10-22
|
|
@@ -175,7 +181,9 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
175
181
|
|
|
176
182
|
- Established the current tagged baseline for subsequent documented releases.
|
|
177
183
|
|
|
178
|
-
[Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/
|
|
184
|
+
[Unreleased]: https://github.com/MartinPdeS/PyFiberModes/compare/v1.0.1...HEAD
|
|
185
|
+
[1.0.1]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v1.0.1
|
|
186
|
+
[1.0.0]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v1.0.0
|
|
179
187
|
[0.17.7]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.17.7
|
|
180
188
|
[0.17.6]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.17.6
|
|
181
189
|
[0.17.5]: https://github.com/MartinPdeS/PyFiberModes/releases/tag/v0.17.5
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyFiberModes
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.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
|
|
@@ -699,10 +699,15 @@ Requires-Python: >=3.11
|
|
|
699
699
|
Description-Content-Type: text/x-rst
|
|
700
700
|
License-File: LICENSE
|
|
701
701
|
Requires-Dist: PyFinitDiff
|
|
702
|
+
Requires-Dist: TypedUnit>=0.2.9
|
|
703
|
+
Requires-Dist: pint<0.26,>=0.24
|
|
702
704
|
Requires-Dist: pyyaml
|
|
703
705
|
Requires-Dist: numpy
|
|
704
706
|
Requires-Dist: scipy
|
|
707
|
+
Provides-Extra: release
|
|
708
|
+
Requires-Dist: martinpdes-maintenance==0.2.2; extra == "release"
|
|
705
709
|
Provides-Extra: testing
|
|
710
|
+
Requires-Dist: martinpdes-maintenance==0.2.2; extra == "testing"
|
|
706
711
|
Requires-Dist: pytest<10.0,>=7.4; extra == "testing"
|
|
707
712
|
Requires-Dist: pytest-cov<8,>=2; extra == "testing"
|
|
708
713
|
Requires-Dist: pytest-json-report~=1.5; extra == "testing"
|
|
@@ -715,7 +720,7 @@ Requires-Dist: matplotlib>=3.8; extra == "plotting"
|
|
|
715
720
|
Provides-Extra: benchmarking
|
|
716
721
|
Requires-Dist: pytest-benchmark<6,>=5; extra == "benchmarking"
|
|
717
722
|
Provides-Extra: documentation
|
|
718
|
-
Requires-Dist: MartinPdeS-docs<0.
|
|
723
|
+
Requires-Dist: MartinPdeS-docs<0.5,>=0.4.0; extra == "documentation"
|
|
719
724
|
Requires-Dist: matplotlib>=3.8; extra == "documentation"
|
|
720
725
|
Provides-Extra: dev
|
|
721
726
|
Requires-Dist: ruff<1,>=0.8; extra == "dev"
|
|
@@ -818,22 +823,25 @@ First mode calculation
|
|
|
818
823
|
----------------------
|
|
819
824
|
|
|
820
825
|
Load the bundled SMF-28 definition at 1550 nm and solve its fundamental LP
|
|
821
|
-
mode.
|
|
826
|
+
mode. Physical inputs require Pint quantities; lengths may use any compatible unit.
|
|
827
|
+
Results also carry units, using the shared TypedUnit registry as in PyMieSim.
|
|
822
828
|
|
|
823
829
|
.. code-block:: python
|
|
824
830
|
|
|
831
|
+
from PyFiberModes.units import ureg
|
|
832
|
+
|
|
825
833
|
from PyFiberModes import LP01
|
|
826
834
|
from PyFiberModes.fiber import load_fiber
|
|
827
835
|
|
|
828
|
-
fiber = load_fiber("SMF28", wavelength=1550e-9)
|
|
836
|
+
fiber = load_fiber("SMF28", wavelength=1550e-9 * ureg.meter)
|
|
829
837
|
|
|
830
838
|
effective_index = fiber.get_effective_index(LP01)
|
|
831
839
|
propagation_constant = fiber.get_propagation_constant(LP01)
|
|
832
840
|
dispersion = fiber.get_dispersion(LP01)
|
|
833
841
|
|
|
834
842
|
print(f"n_eff = {effective_index:.9f}")
|
|
835
|
-
print(f"beta = {propagation_constant:.6e}
|
|
836
|
-
print(f"D = {dispersion:.3f}
|
|
843
|
+
print(f"beta = {propagation_constant:.6e}")
|
|
844
|
+
print(f"D = {dispersion:.3f}")
|
|
837
845
|
|
|
838
846
|
``load_fiber`` accepts the stem of any YAML definition in
|
|
839
847
|
``PyFiberModes/fiber_files``. A fiber can also be assembled programmatically
|
|
@@ -848,6 +856,8 @@ fiber index:
|
|
|
848
856
|
|
|
849
857
|
.. code-block:: python
|
|
850
858
|
|
|
859
|
+
from PyFiberModes.units import ureg
|
|
860
|
+
|
|
851
861
|
modes = fiber.find_modes(
|
|
852
862
|
families=("LP",),
|
|
853
863
|
max_nu=4,
|
|
@@ -869,9 +879,11 @@ values and whose columns correspond to modes.
|
|
|
869
879
|
|
|
870
880
|
.. code-block:: python
|
|
871
881
|
|
|
882
|
+
from PyFiberModes.units import ureg
|
|
883
|
+
|
|
872
884
|
import numpy as np
|
|
873
885
|
|
|
874
|
-
wavelengths = np.linspace(1260e-9, 1650e-9, 101)
|
|
886
|
+
wavelengths = np.linspace(1260e-9, 1650e-9, 101) * ureg.meter
|
|
875
887
|
result = fiber.sweep(
|
|
876
888
|
wavelengths,
|
|
877
889
|
modes=modes,
|
|
@@ -892,16 +904,18 @@ Create a two-dimensional field grid from a solved mode:
|
|
|
892
904
|
|
|
893
905
|
.. code-block:: python
|
|
894
906
|
|
|
907
|
+
from PyFiberModes.units import ureg
|
|
908
|
+
|
|
895
909
|
field = fiber.get_mode_field(
|
|
896
910
|
mode=LP01,
|
|
897
|
-
limit=20e-6,
|
|
911
|
+
limit=20e-6 * ureg.meter,
|
|
898
912
|
n_point=201,
|
|
899
913
|
)
|
|
900
914
|
|
|
901
915
|
electric_x = field.Ex()
|
|
902
916
|
intensity = field.Emod() ** 2
|
|
903
917
|
effective_area = field.get_effective_area()
|
|
904
|
-
confinement = field.get_confinement_factor(radius=4.1e-6)
|
|
918
|
+
confinement = field.get_confinement_factor(radius=4.1e-6 * ureg.meter)
|
|
905
919
|
power = field.get_power()
|
|
906
920
|
sx, sy, sz = field.get_poynting_vector()
|
|
907
921
|
|
|
@@ -921,17 +935,19 @@ scalar value to minimize.
|
|
|
921
935
|
|
|
922
936
|
.. code-block:: python
|
|
923
937
|
|
|
938
|
+
from PyFiberModes.units import ureg
|
|
939
|
+
|
|
924
940
|
from PyFiberModes import DesignParameter, optimize_fiber
|
|
925
941
|
|
|
926
942
|
core_radius = DesignParameter.layer_radius(
|
|
927
943
|
layer=0,
|
|
928
|
-
bounds=(3.0e-6, 6.0e-6),
|
|
944
|
+
bounds=(3.0e-6 * ureg.meter, 6.0e-6 * ureg.meter),
|
|
929
945
|
)
|
|
930
946
|
|
|
931
947
|
design = optimize_fiber(
|
|
932
948
|
fiber,
|
|
933
949
|
parameters=[core_radius],
|
|
934
|
-
objective=lambda candidate: abs(candidate.get_dispersion(LP01)),
|
|
950
|
+
objective=lambda candidate: abs(candidate.get_dispersion(LP01).to("ps / nm / km").magnitude),
|
|
935
951
|
constraints=(
|
|
936
952
|
lambda candidate: candidate.get_effective_index(LP01)
|
|
937
953
|
- candidate.last_layer.refractive_index,
|
|
@@ -956,10 +972,12 @@ electric field. Modal amplitudes then evolve according to
|
|
|
956
972
|
|
|
957
973
|
.. code-block:: python
|
|
958
974
|
|
|
975
|
+
from PyFiberModes.units import ureg
|
|
976
|
+
|
|
959
977
|
import numpy as np
|
|
960
978
|
from PyFiberModes import CoupledModeSystem
|
|
961
979
|
|
|
962
|
-
multimode_fiber = load_fiber("test_multimode_fiber", wavelength=1550e-9)
|
|
980
|
+
multimode_fiber = load_fiber("test_multimode_fiber", wavelength=1550e-9 * ureg.meter)
|
|
963
981
|
multimode_modes = multimode_fiber.find_modes(
|
|
964
982
|
families=("LP",),
|
|
965
983
|
max_nu=3,
|
|
@@ -968,16 +986,16 @@ electric field. Modal amplitudes then evolve according to
|
|
|
968
986
|
selected_modes = multimode_modes[:2]
|
|
969
987
|
fields = [multimode_fiber.get_mode_field(mode, n_point=151) for mode in selected_modes]
|
|
970
988
|
betas = [multimode_fiber.get_propagation_constant(mode) for mode in selected_modes]
|
|
971
|
-
relative_betas =
|
|
989
|
+
relative_betas = ureg.Quantity.from_list(betas) - betas[0]
|
|
972
990
|
mode_overlap = fields[0].overlap(fields[1])
|
|
973
991
|
|
|
974
992
|
coupling = np.array([
|
|
975
993
|
[0.0, 0.25],
|
|
976
994
|
[0.25, 0.0],
|
|
977
|
-
])
|
|
995
|
+
]) / ureg.meter
|
|
978
996
|
system = CoupledModeSystem(betas=relative_betas, coupling=coupling)
|
|
979
997
|
|
|
980
|
-
z = np.linspace(0, 20, 500)
|
|
998
|
+
z = np.linspace(0, 20, 500) * ureg.meter
|
|
981
999
|
propagation = system.propagate(initial=[1.0, 0.0], z=z)
|
|
982
1000
|
modal_power = propagation.powers
|
|
983
1001
|
|
|
@@ -1054,7 +1072,7 @@ Releases and changelog
|
|
|
1054
1072
|
|
|
1055
1073
|
User-visible changes are recorded in
|
|
1056
1074
|
`CHANGELOG.md <https://github.com/MartinPdeS/PyFiberModes/blob/master/CHANGELOG.md>`_.
|
|
1057
|
-
Release helpers keep the Python package, Conda recipe,
|
|
1075
|
+
Release helpers keep the Python package, Conda recipe, checked-in version,
|
|
1058
1076
|
Zenodo metadata, changelog, and annotated Git tag synchronized.
|
|
1059
1077
|
|
|
1060
1078
|
.. code-block:: bash
|
|
@@ -12,7 +12,7 @@ from scipy.constants import c
|
|
|
12
12
|
from PyFiberModes.stepindex import StepIndex
|
|
13
13
|
from PyFiberModes import Mode
|
|
14
14
|
from PyFinitDiff.finite_difference_1D import get_function_derivative
|
|
15
|
-
from PyFiberModes.
|
|
15
|
+
from PyFiberModes._field import Field
|
|
16
16
|
|
|
17
17
|
from PyFiberModes.fundamentals import (
|
|
18
18
|
get_radial_field,
|
|
@@ -20,7 +20,7 @@ from PyFiberModes.fundamentals import (
|
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
from PyFiberModes import loader
|
|
23
|
-
from PyFiberModes.
|
|
23
|
+
from PyFiberModes._coordinates import CylindricalCoordinates
|
|
24
24
|
from PyFiberModes.exceptions import ConvergenceError, ValidationError
|
|
25
25
|
from PyFiberModes.materials import DEFAULT_MATERIALS, MaterialRegistry
|
|
26
26
|
from PyFiberModes.services import FieldAnalysis, ModalAnalysis
|
|
@@ -7,8 +7,8 @@ import numpy as np
|
|
|
7
7
|
from PyFiberModes.mode_instances import HE11
|
|
8
8
|
from PyFiberModes.mode import Mode
|
|
9
9
|
from dataclasses import dataclass
|
|
10
|
-
from PyFiberModes.
|
|
11
|
-
from PyFiberModes.
|
|
10
|
+
from PyFiberModes._coordinates import CartesianCoordinates
|
|
11
|
+
from PyFiberModes._coordinates import CylindricalCoordinates as CylindricalCoordinates # noqa: F401
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
@dataclass
|
|
@@ -8,6 +8,7 @@ import numpy as np
|
|
|
8
8
|
|
|
9
9
|
from PyFiberModes.exceptions import ConvergenceError, ValidationError
|
|
10
10
|
from PyFiberModes.mode import Mode
|
|
11
|
+
from PyFiberModes.units import MODAL_UNITS, Quantity, magnitude, quantity
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
@dataclass(frozen=True)
|
|
@@ -30,9 +31,9 @@ class ModeSweepResult:
|
|
|
30
31
|
"""
|
|
31
32
|
|
|
32
33
|
parameter_name: str
|
|
33
|
-
parameters: np.ndarray
|
|
34
|
+
parameters: np.ndarray | Quantity
|
|
34
35
|
modes: tuple[Mode, ...]
|
|
35
|
-
values: dict[str, np.ndarray]
|
|
36
|
+
values: dict[str, np.ndarray | Quantity]
|
|
36
37
|
|
|
37
38
|
def __getitem__(self, metric: str) -> np.ndarray:
|
|
38
39
|
"""Return the array associated with a metric name.
|
|
@@ -74,9 +75,11 @@ class ModeSweepResult:
|
|
|
74
75
|
One record for every parameter and mode combination.
|
|
75
76
|
"""
|
|
76
77
|
return [
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
{
|
|
79
|
+
self.parameter_name: parameter,
|
|
80
|
+
"mode": mode,
|
|
81
|
+
**{name: array[i, j] for name, array in self.values.items()},
|
|
82
|
+
}
|
|
80
83
|
for i, parameter in enumerate(self.parameters)
|
|
81
84
|
for j, mode in enumerate(self.modes)
|
|
82
85
|
]
|
|
@@ -137,11 +140,7 @@ def find_modes(fiber, families=("LP",), max_nu=6, max_m=6) -> tuple[Mode, ...]:
|
|
|
137
140
|
for mode in candidate_modes(families, max_nu, max_m):
|
|
138
141
|
try:
|
|
139
142
|
effective_index = fiber.get_effective_index(mode)
|
|
140
|
-
guided =
|
|
141
|
-
fiber.last_layer.refractive_index
|
|
142
|
-
< effective_index
|
|
143
|
-
<= fiber.maximum_index
|
|
144
|
-
)
|
|
143
|
+
guided = fiber.last_layer.refractive_index < effective_index <= fiber.maximum_index
|
|
145
144
|
if np.isfinite(effective_index) and guided:
|
|
146
145
|
found.append(mode)
|
|
147
146
|
except ConvergenceError:
|
|
@@ -167,8 +166,8 @@ def sweep_modes(
|
|
|
167
166
|
----------
|
|
168
167
|
fiber : Fiber
|
|
169
168
|
Fiber used as the immutable sweep template.
|
|
170
|
-
parameters : iterable of
|
|
171
|
-
Ordered parameter values.
|
|
169
|
+
parameters : pint.Quantity or iterable of pint.Quantity
|
|
170
|
+
Ordered parameter values with explicit units for public fibers.
|
|
172
171
|
modes : sequence of Mode, optional
|
|
173
172
|
Modes to evaluate. When omitted, modes are discovered automatically.
|
|
174
173
|
parameter_name : str, optional
|
|
@@ -195,7 +194,26 @@ def sweep_modes(
|
|
|
195
194
|
If ``parameters`` is empty or not one-dimensional, or when a custom
|
|
196
195
|
parameter is requested without a setter.
|
|
197
196
|
"""
|
|
198
|
-
|
|
197
|
+
unit_aware = hasattr(fiber, "_si")
|
|
198
|
+
parameter_unit = None
|
|
199
|
+
if unit_aware:
|
|
200
|
+
if isinstance(parameters, Quantity):
|
|
201
|
+
parameter_unit = parameters.units
|
|
202
|
+
if setter is None:
|
|
203
|
+
magnitude(parameters, "meter", "parameters")
|
|
204
|
+
parameters = np.asarray(parameters.magnitude, dtype=float)
|
|
205
|
+
else:
|
|
206
|
+
items = tuple(parameters)
|
|
207
|
+
if not items:
|
|
208
|
+
raise ValueError("parameters must be a non-empty one-dimensional sequence")
|
|
209
|
+
parameter_unit = items[0].units if isinstance(items[0], Quantity) else "meter"
|
|
210
|
+
parameters = np.asarray(
|
|
211
|
+
[magnitude(item, parameter_unit, "parameters") for item in items], dtype=float
|
|
212
|
+
)
|
|
213
|
+
if setter is None:
|
|
214
|
+
quantity(parameters, parameter_unit).to("meter")
|
|
215
|
+
else:
|
|
216
|
+
parameters = np.asarray(tuple(parameters), dtype=float)
|
|
199
217
|
if parameters.ndim != 1 or not len(parameters):
|
|
200
218
|
raise ValueError("parameters must be a non-empty one-dimensional sequence")
|
|
201
219
|
if setter is None:
|
|
@@ -205,11 +223,14 @@ def sweep_modes(
|
|
|
205
223
|
def setter(current_fiber, value):
|
|
206
224
|
"""Update wavelength for the default sweep behavior."""
|
|
207
225
|
current_fiber.update_wavelength(value)
|
|
226
|
+
|
|
208
227
|
if modes is None:
|
|
209
228
|
discovered = []
|
|
210
229
|
for parameter in parameters:
|
|
211
230
|
parameter_fiber = deepcopy(fiber)
|
|
212
|
-
setter(
|
|
231
|
+
setter(
|
|
232
|
+
parameter_fiber, quantity(parameter, parameter_unit) if unit_aware else parameter
|
|
233
|
+
)
|
|
213
234
|
for mode in find_modes(parameter_fiber, families, max_nu, max_m):
|
|
214
235
|
if mode not in discovered:
|
|
215
236
|
discovered.append(mode)
|
|
@@ -218,17 +239,22 @@ def sweep_modes(
|
|
|
218
239
|
values = {metric: np.full((len(parameters), len(modes)), np.nan) for metric in metrics}
|
|
219
240
|
parameter_fibers = tuple(deepcopy(fiber) for _ in parameters)
|
|
220
241
|
for parameter_fiber, parameter in zip(parameter_fibers, parameters, strict=True):
|
|
221
|
-
setter(parameter_fiber,
|
|
242
|
+
setter(parameter_fiber, quantity(parameter, parameter_unit) if unit_aware else parameter)
|
|
222
243
|
|
|
223
244
|
for i, parameter_fiber in enumerate(parameter_fibers):
|
|
224
|
-
metric_functions = {
|
|
225
|
-
metric: getattr(parameter_fiber, f"get_{metric}") for metric in metrics
|
|
226
|
-
}
|
|
245
|
+
metric_functions = {metric: getattr(parameter_fiber, f"get_{metric}") for metric in metrics}
|
|
227
246
|
for metric, metric_function in metric_functions.items():
|
|
228
247
|
for j, mode in enumerate(modes):
|
|
229
248
|
try:
|
|
230
249
|
value = metric_function(mode)
|
|
231
|
-
values[metric][i, j] =
|
|
250
|
+
values[metric][i, j] = (
|
|
251
|
+
(value.to(MODAL_UNITS[metric]).magnitude if unit_aware else value)
|
|
252
|
+
if np.isfinite(value)
|
|
253
|
+
else np.nan
|
|
254
|
+
)
|
|
232
255
|
except ConvergenceError:
|
|
233
256
|
pass
|
|
257
|
+
if unit_aware:
|
|
258
|
+
parameters = quantity(parameters, parameter_unit)
|
|
259
|
+
values = {metric: quantity(array, MODAL_UNITS[metric]) for metric, array in values.items()}
|
|
234
260
|
return ModeSweepResult(parameter_name, parameters, modes, values)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Length-valued Cartesian and cylindrical coordinate grids."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from PyFiberModes import _coordinates
|
|
7
|
+
from PyFiberModes.units import Angle, Length, magnitude, quantity
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class CylindricalCoordinates:
|
|
12
|
+
"""Cylindrical positions with length-valued rho/z and angle-valued phi."""
|
|
13
|
+
|
|
14
|
+
rho: Length
|
|
15
|
+
phi: Angle
|
|
16
|
+
z: Length
|
|
17
|
+
|
|
18
|
+
def __post_init__(self):
|
|
19
|
+
"""Validate and normalize coordinate quantities."""
|
|
20
|
+
self.rho = quantity(magnitude(self.rho, "meter", "rho"), "meter")
|
|
21
|
+
self.phi = quantity(magnitude(self.phi, "radian", "phi"), "radian")
|
|
22
|
+
self.z = quantity(magnitude(self.z, "meter", "z"), "meter")
|
|
23
|
+
|
|
24
|
+
def to_cartesian(self):
|
|
25
|
+
"""Convert cylindrical positions to Cartesian positions."""
|
|
26
|
+
return CartesianCoordinates(
|
|
27
|
+
x=self.rho * np.cos(self.phi),
|
|
28
|
+
y=self.rho * np.sin(self.phi),
|
|
29
|
+
z=self.z,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def to_cylindrical(self):
|
|
33
|
+
"""Return these cylindrical positions."""
|
|
34
|
+
return self
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class CartesianCoordinates:
|
|
39
|
+
"""Cartesian positions with explicit length units on every axis."""
|
|
40
|
+
|
|
41
|
+
x: Length
|
|
42
|
+
y: Length
|
|
43
|
+
z: Length
|
|
44
|
+
is_structured: bool = False
|
|
45
|
+
is_3D: bool = False
|
|
46
|
+
|
|
47
|
+
def __post_init__(self):
|
|
48
|
+
"""Validate lengths and normalize numerical coordinate arrays to meters."""
|
|
49
|
+
for name in ("x", "y", "z"):
|
|
50
|
+
setattr(
|
|
51
|
+
self,
|
|
52
|
+
name,
|
|
53
|
+
quantity(
|
|
54
|
+
np.asarray(magnitude(getattr(self, name), "meter", name), dtype=float), "meter"
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def _from_si(cls, coordinates):
|
|
60
|
+
"""Attach length units to a numerical coordinate grid."""
|
|
61
|
+
return cls(
|
|
62
|
+
x=quantity(coordinates.x, "meter"),
|
|
63
|
+
y=quantity(coordinates.y, "meter"),
|
|
64
|
+
z=quantity(coordinates.z, "meter"),
|
|
65
|
+
is_structured=coordinates.is_structured,
|
|
66
|
+
is_3D=coordinates.is_3D,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def x_boundaries(self):
|
|
71
|
+
"""Minimum and maximum x positions."""
|
|
72
|
+
return self.x.min(), self.x.max()
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def y_boundaries(self):
|
|
76
|
+
"""Minimum and maximum y positions."""
|
|
77
|
+
return self.y.min(), self.y.max()
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def dx(self):
|
|
81
|
+
"""Structured grid spacing along x."""
|
|
82
|
+
if not self.is_structured:
|
|
83
|
+
raise ValueError("dx value cannot be inferred from an unstructured mesh")
|
|
84
|
+
return quantity(np.diff(np.unique(self.x.magnitude))[0], self.x.units)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def dy(self):
|
|
88
|
+
"""Structured grid spacing along y."""
|
|
89
|
+
if not self.is_structured:
|
|
90
|
+
raise ValueError("dy value cannot be inferred from an unstructured mesh")
|
|
91
|
+
return quantity(np.diff(np.unique(self.y.magnitude))[0], self.y.units)
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def generate_from_square(cls, length: Length, center=None, n_points: int = 100):
|
|
95
|
+
"""Generate a square grid with a length-valued side and center."""
|
|
96
|
+
center_si = (
|
|
97
|
+
(0.0, 0.0)
|
|
98
|
+
if center is None
|
|
99
|
+
else tuple(magnitude(item, "meter", "center") for item in center)
|
|
100
|
+
)
|
|
101
|
+
return cls._from_si(
|
|
102
|
+
_coordinates.CartesianCoordinates.generate_from_square(
|
|
103
|
+
length=magnitude(length, "meter", "length"),
|
|
104
|
+
center=center_si,
|
|
105
|
+
n_points=n_points,
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def generate_from_boundaries(cls, x_limits, y_limits, z_limits, x_points, y_points, z_points):
|
|
111
|
+
"""Generate a structured grid from length-valued axis limits."""
|
|
112
|
+
limits = [
|
|
113
|
+
tuple(magnitude(item, "meter", "limits") for item in axis)
|
|
114
|
+
for axis in (x_limits, y_limits, z_limits)
|
|
115
|
+
]
|
|
116
|
+
return cls._from_si(
|
|
117
|
+
_coordinates.CartesianCoordinates.generate_from_boundaries(
|
|
118
|
+
x_limits=limits[0],
|
|
119
|
+
y_limits=limits[1],
|
|
120
|
+
z_limits=limits[2],
|
|
121
|
+
x_points=x_points,
|
|
122
|
+
y_points=y_points,
|
|
123
|
+
z_points=z_points,
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def to_cylindrical(self):
|
|
128
|
+
"""Convert positions to cylindrical coordinates."""
|
|
129
|
+
return CylindricalCoordinates(
|
|
130
|
+
rho=np.sqrt(self.x**2 + self.y**2),
|
|
131
|
+
phi=np.arctan2(self.y, self.x),
|
|
132
|
+
z=self.z,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def centering(self):
|
|
136
|
+
"""Center each axis in place."""
|
|
137
|
+
self.x -= self.x.mean()
|
|
138
|
+
self.y -= self.y.mean()
|
|
139
|
+
self.z -= self.z.mean()
|
|
140
|
+
|
|
141
|
+
def shift_coordinates(self, shift):
|
|
142
|
+
"""Shift the grid by three length-valued displacements."""
|
|
143
|
+
# Validate all inputs before mutating the grid.
|
|
144
|
+
values = [quantity(magnitude(item, "meter", "shift"), "meter") for item in shift]
|
|
145
|
+
self.x += values[0]
|
|
146
|
+
self.y += values[1]
|
|
147
|
+
self.z += values[2]
|
|
148
|
+
|
|
149
|
+
def scale_coordinates(self, scale):
|
|
150
|
+
"""Scale axes by dimensionless factors."""
|
|
151
|
+
self.x *= float(scale[0])
|
|
152
|
+
self.y *= float(scale[1])
|
|
153
|
+
self.z *= float(scale[2])
|
|
@@ -4,6 +4,7 @@ from itertools import product
|
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
5
|
import numpy as np
|
|
6
6
|
from PyFiberModes.fiber import Fiber
|
|
7
|
+
from PyFiberModes.units import Length, RefractiveIndex, magnitude, quantity, ureg
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
@dataclass
|
|
@@ -15,9 +16,9 @@ class ProxyLayer:
|
|
|
15
16
|
----------
|
|
16
17
|
name : str
|
|
17
18
|
Name of the layer.
|
|
18
|
-
radius :
|
|
19
|
+
radius : pint.Quantity
|
|
19
20
|
Radius values for the layer (in meters).
|
|
20
|
-
index :
|
|
21
|
+
index : pint.Quantity
|
|
21
22
|
Refractive index values for the layer.
|
|
22
23
|
"""
|
|
23
24
|
name: str
|
|
@@ -27,8 +28,8 @@ class ProxyLayer:
|
|
|
27
28
|
def __post_init__(self):
|
|
28
29
|
"""Normalize scalar layer parameters into one-dimensional arrays."""
|
|
29
30
|
self.name = [self.name]
|
|
30
|
-
self.radius = np.atleast_1d(self.radius)
|
|
31
|
-
self.index = np.atleast_1d(self.index)
|
|
31
|
+
self.radius = quantity(np.atleast_1d(magnitude(self.radius, "meter", "radius")), "meter")
|
|
32
|
+
self.index = quantity(np.atleast_1d(magnitude(self.index, "dimensionless", "index")), "dimensionless")
|
|
32
33
|
|
|
33
34
|
def get_generator(self):
|
|
34
35
|
"""
|
|
@@ -48,40 +49,40 @@ class FiberFactory:
|
|
|
48
49
|
|
|
49
50
|
Parameters
|
|
50
51
|
----------
|
|
51
|
-
wavelength :
|
|
52
|
+
wavelength : TypedUnit.Length
|
|
52
53
|
Wavelength (in meters) used for fiber simulations.
|
|
53
54
|
|
|
54
55
|
Attributes
|
|
55
56
|
----------
|
|
56
57
|
layers_list : list[ProxyLayer]
|
|
57
58
|
List of ProxyLayer objects representing the layers of the fiber.
|
|
58
|
-
wavelength :
|
|
59
|
+
wavelength : TypedUnit.Length
|
|
59
60
|
Wavelength used in simulations.
|
|
60
61
|
"""
|
|
61
62
|
|
|
62
|
-
def __init__(self, wavelength:
|
|
63
|
+
def __init__(self, wavelength: Length):
|
|
63
64
|
"""Initialize an empty fiber-configuration factory.
|
|
64
65
|
|
|
65
66
|
Parameters
|
|
66
67
|
----------
|
|
67
|
-
wavelength :
|
|
68
|
+
wavelength : TypedUnit.Length
|
|
68
69
|
Vacuum wavelength in meters for generated fibers.
|
|
69
70
|
"""
|
|
70
71
|
self.layers_list = []
|
|
71
|
-
self.wavelength = wavelength
|
|
72
|
+
self.wavelength = quantity(magnitude(wavelength, "meter", "wavelength"), "meter")
|
|
72
73
|
|
|
73
|
-
def add_layer(self, index:
|
|
74
|
+
def add_layer(self, index: RefractiveIndex, name: str = "", radius: Length = np.inf * ureg.meter):
|
|
74
75
|
"""
|
|
75
76
|
Add a new layer to the fiber factory.
|
|
76
77
|
|
|
77
78
|
Parameters
|
|
78
79
|
----------
|
|
79
|
-
index :
|
|
80
|
+
index : TypedUnit.RefractiveIndex
|
|
80
81
|
Refractive index of the layer.
|
|
81
82
|
name : str, optional
|
|
82
83
|
Name of the layer (default is an empty string).
|
|
83
|
-
radius :
|
|
84
|
-
Radius of the layer (
|
|
84
|
+
radius : TypedUnit.Length, optional
|
|
85
|
+
Radius of the layer (defaults to an unbounded outer layer).
|
|
85
86
|
"""
|
|
86
87
|
layer = ProxyLayer(name=name, radius=radius, index=index)
|
|
87
88
|
self.layers_list.append(layer)
|