├── docs ├── requirements.txt ├── readme_link.rst ├── _build │ ├── html │ │ ├── objects.inv │ │ ├── _static │ │ │ ├── file.png │ │ │ ├── plus.png │ │ │ ├── minus.png │ │ │ ├── css │ │ │ │ ├── fonts │ │ │ │ │ ├── lato-bold.woff │ │ │ │ │ ├── lato-bold.woff2 │ │ │ │ │ ├── lato-normal.woff │ │ │ │ │ ├── lato-normal.woff2 │ │ │ │ │ ├── Roboto-Slab-Bold.woff │ │ │ │ │ ├── Roboto-Slab-Bold.woff2 │ │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ │ ├── lato-bold-italic.woff │ │ │ │ │ ├── lato-bold-italic.woff2 │ │ │ │ │ ├── lato-normal-italic.woff │ │ │ │ │ ├── Roboto-Slab-Regular.woff │ │ │ │ │ ├── Roboto-Slab-Regular.woff2 │ │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ │ └── lato-normal-italic.woff2 │ │ │ │ └── badge_only.css │ │ │ ├── documentation_options.js │ │ │ ├── js │ │ │ │ ├── badge_only.js │ │ │ │ ├── html5shiv.min.js │ │ │ │ ├── html5shiv-printshiv.min.js │ │ │ │ └── theme.js │ │ │ ├── pygments.css │ │ │ ├── doctools.js │ │ │ ├── underscore.js │ │ │ ├── language_data.js │ │ │ ├── basic.css │ │ │ └── searchtools.js │ │ ├── _sources │ │ │ ├── modules.rst.txt │ │ │ ├── index.rst.txt │ │ │ └── pychi.rst.txt │ │ ├── _modules │ │ │ └── index.html │ │ ├── searchindex.js │ │ ├── search.html │ │ ├── py-modindex.html │ │ ├── modules.html │ │ ├── index.html │ │ └── genindex.html │ └── doctrees │ │ ├── index.doctree │ │ ├── pychi.doctree │ │ ├── modules.doctree │ │ └── environment.pickle ├── modules.rst ├── index.rst ├── Makefile ├── pychi.rst ├── make.bat └── conf.py ├── .gitattributes ├── examples ├── SiN │ ├── exp_SiN.mat │ ├── n_eff_data_SiN.npy │ ├── Experimental_vs_simulation_SiN.png │ └── pychi_SiN_exp_vs_sim.py ├── LiNb │ ├── exp_LiNb.mat │ ├── n_eff_data_LiNb.npy │ ├── Experimental_vs_simulation_LiNb.png │ └── pychi_LiNb_exp_vs_sim.py ├── effective_index.npy ├── QPM │ ├── effective_index.npy │ └── pychi_QPM.py ├── SPM │ ├── time_propagation.png │ ├── frequency_propagation.png │ └── pychi_spm_validation.py ├── Cascaded Nonlinearities │ ├── cascaded.png │ ├── effective_index.npy │ └── pychi_cascaded.py └── pychi_example.py ├── requirements.txt ├── src └── pychi │ ├── __init__.py │ ├── utils.py │ ├── solvers.py │ └── materials.py ├── .readthedocs.yaml ├── .github └── workflows │ ├── build_test.yml │ ├── pypi_publish.yml │ └── pypi_test.yml ├── pyproject.toml ├── LICENSE └── README.md /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | myst-parser 2 | sphinx_rtd_theme 3 | -------------------------------------------------------------------------------- /docs/readme_link.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.md 2 | :parser: myst_parser.sphinx_ -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /examples/SiN/exp_SiN.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/SiN/exp_SiN.mat -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /examples/LiNb/exp_LiNb.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/LiNb/exp_LiNb.mat -------------------------------------------------------------------------------- /examples/effective_index.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/effective_index.npy -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | pychi package 2 | === 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | pychi 8 | -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /examples/LiNb/n_eff_data_LiNb.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/LiNb/n_eff_data_LiNb.npy -------------------------------------------------------------------------------- /examples/QPM/effective_index.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/QPM/effective_index.npy -------------------------------------------------------------------------------- /examples/SPM/time_propagation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/SPM/time_propagation.png -------------------------------------------------------------------------------- /examples/SiN/n_eff_data_SiN.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/SiN/n_eff_data_SiN.npy -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib>=3.1.3 2 | numpy>=1.21.6 3 | scipy>=1.4.1 4 | numba>=0.56.0 5 | pyFFTW>=0.12.0 6 | -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/pychi.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/doctrees/pychi.doctree -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_build/doctrees/modules.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/doctrees/modules.doctree -------------------------------------------------------------------------------- /examples/SPM/frequency_propagation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/SPM/frequency_propagation.png -------------------------------------------------------------------------------- /docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_build/html/_sources/modules.rst.txt: -------------------------------------------------------------------------------- 1 | pychi package 2 | === 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | pychi 8 | -------------------------------------------------------------------------------- /examples/Cascaded Nonlinearities/cascaded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/Cascaded Nonlinearities/cascaded.png -------------------------------------------------------------------------------- /examples/SiN/Experimental_vs_simulation_SiN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/SiN/Experimental_vs_simulation_SiN.png -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-bold.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-bold.woff2 -------------------------------------------------------------------------------- /examples/LiNb/Experimental_vs_simulation_LiNb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/LiNb/Experimental_vs_simulation_LiNb.png -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-normal.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-normal.woff2 -------------------------------------------------------------------------------- /examples/Cascaded Nonlinearities/effective_index.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/examples/Cascaded Nonlinearities/effective_index.npy -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-bold-italic.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-bold-italic.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-normal-italic.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pychi-code/pychi/HEAD/docs/_build/html/_static/css/fonts/lato-normal-italic.woff2 -------------------------------------------------------------------------------- /src/pychi/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Thu Feb 17 12:32:49 2022 4 | 5 | @author: voumardt 6 | """ 7 | __version__ = '0.0.17' 8 | 9 | from . import light 10 | from . import materials 11 | from . import models 12 | from . import solvers 13 | from . import utils 14 | -------------------------------------------------------------------------------- /docs/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '0.0.1', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | BUILDER: 'html', 7 | FILE_SUFFIX: '.html', 8 | HAS_SOURCE: true, 9 | SOURCELINK_SUFFIX: '.txt', 10 | NAVIGATION_WITH_KEYS: false 11 | }; -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. pychi documentation master file, created by 2 | sphinx-quickstart on Fri Mar 3 10:39:56 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to pychi's documentation! 7 | ================================= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | readme_link 14 | pychi 15 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | .. pychi documentation master file, created by 2 | sphinx-quickstart on Fri Mar 3 10:39:56 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to pychi's documentation! 7 | ================================= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | modules 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the docs/ directory with Sphinx 19 | sphinx: 20 | configuration: docs/conf.py 21 | 22 | # If using Sphinx, optionally build your docs in additional formats such as PDF 23 | # formats: 24 | # - pdf 25 | 26 | # Optionally declare the Python requirements required to build your docs 27 | python: 28 | install: 29 | - requirements: docs/requirements.txt 30 | 31 | 32 | submodules: 33 | include: all 34 | -------------------------------------------------------------------------------- /docs/pychi.rst: -------------------------------------------------------------------------------- 1 | pychi package 2 | ============= 3 | 4 | pychi.light module 5 | ------------------ 6 | 7 | .. automodule:: pychi.light 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | pychi.materials module 13 | ---------------------- 14 | 15 | .. automodule:: pychi.materials 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | pychi.models module 21 | ------------------- 22 | 23 | .. automodule:: pychi.models 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | pychi.solvers module 29 | -------------------- 30 | 31 | .. automodule:: pychi.solvers 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | pychi.utils module 37 | -------------------- 38 | 39 | .. automodule:: pychi.utils 40 | :members: 41 | :undoc-members: 42 | :show-inheritance: 43 | -------------------------------------------------------------------------------- /.github/workflows/build_test.yml: -------------------------------------------------------------------------------- 1 | # This workflow is manually triggered and makes a build test of the package. 2 | 3 | name: Build Python Package 4 | 5 | on: workflow_dispatch 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | deploy: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Set up Python 18 | uses: actions/setup-python@v3 19 | with: 20 | python-version: '3.x' 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | python -m pip install --upgrade build 25 | python -m pip install --upgrade twine 26 | - name: Edit Toml 27 | uses: sandstromviktor/toml-editor@2.0.0 28 | with: 29 | file: "pyproject.toml" 30 | key: "project.version" 31 | value: 0.0.0 32 | - name: Build package 33 | run: python -m build 34 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/pychi.rst.txt: -------------------------------------------------------------------------------- 1 | pychi package 2 | ============= 3 | 4 | pychi.light module 5 | ------------------ 6 | 7 | .. automodule:: pychi.light 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | pychi.materials module 13 | ---------------------- 14 | 15 | .. automodule:: pychi.materials 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | pychi.models module 21 | ------------------- 22 | 23 | .. automodule:: pychi.models 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | pychi.solvers module 29 | -------------------- 30 | 31 | .. automodule:: pychi.solvers 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | 37 | Module contents 38 | --------------- 39 | 40 | .. automodule:: pychi 41 | :members: 42 | :undoc-members: 43 | :show-inheritance: 44 | -------------------------------------------------------------------------------- /docs/_build/html/_static/js/badge_only.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.setuptools] 6 | package-dir = {"" = "src"} 7 | 8 | [project] 9 | name = "pychi" 10 | version = "" 11 | authors = [ 12 | { name="Ultrafast Microphotonics Group - DESY", email="pychi@desy.de" }, 13 | ] 14 | description = "Simulation package for the propagation of optical pulses in nonlinear media" 15 | readme = "README.md" 16 | requires-python = ">=3.7" 17 | classifiers = [ 18 | "Programming Language :: Python :: 3", 19 | "License :: OSI Approved :: MIT License", 20 | "Operating System :: OS Independent", 21 | ] 22 | 23 | dependencies = [ 24 | "matplotlib>=3.1.3", 25 | "numpy>=1.21.6", 26 | "scipy>=1.4.1", 27 | "numba>=0.56.0", 28 | "pyFFTW>=0.12.0", 29 | ] 30 | 31 | 32 | [project.urls] 33 | "Homepage" = "https://github.com/pychi-code/pychi" 34 | "Documentation" = "https://pychi.readthedocs.io/en/latest/index.html" 35 | "PyPI" = "https://pypi.org/project/pychi/" 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ultrafast Microphotonics Group, DESY 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /.github/workflows/pypi_publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | #on: workflow_dispatch 7 | on: 8 | release: 9 | types: [published] 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | deploy: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Set up Python 22 | uses: actions/setup-python@v3 23 | with: 24 | python-version: '3.x' 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | python -m pip install --upgrade build 29 | python -m pip install --upgrade twine 30 | - name: Get version 31 | id: get_version 32 | run: echo "VERSION=$(echo $GITHUB_REF | cut -d / -f 3)" >> $GITHUB_OUTPUT 33 | - name: Edit Toml 34 | uses: sandstromviktor/toml-editor@2.0.0 35 | with: 36 | file: "pyproject.toml" 37 | key: "project.version" 38 | value: ${{ steps.get_version.outputs.VERSION }} 39 | - name: Build package 40 | run: python -m build 41 | - name: Publish package 42 | run: python -m twine upload dist/* --u __token__ --p ${{ secrets.PYPI_API_TOKEN }} 43 | -------------------------------------------------------------------------------- /.github/workflows/pypi_test.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package when triggered. Test file for the automatic release action. 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: workflow_dispatch 7 | #on: 8 | # release: 9 | # types: [published] 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | deploy: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Set up Python 22 | uses: actions/setup-python@v3 23 | with: 24 | python-version: '3.x' 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | python -m pip install --upgrade build 29 | python -m pip install --upgrade twine 30 | - name: Get version 31 | id: get_version 32 | run: echo "VERSION=$(echo $GITHUB_REF | cut -d / -f 3)" >> $GITHUB_OUTPUT 33 | - name: Edit Toml 34 | uses: sandstromviktor/toml-editor@2.0.0 35 | with: 36 | file: "pyproject.toml" 37 | key: "project.version" 38 | #value: ${{ steps.get_version.outputs.VERSION }} 39 | value: 0.0.13 40 | - name: Build package 41 | run: python -m build 42 | - name: Publish package 43 | run: python -m twine upload dist/* --u __token__ --p ${{ secrets.PYPI_API_TOKEN }} 44 | -------------------------------------------------------------------------------- /examples/Cascaded Nonlinearities/pychi_cascaded.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Feb 28 15:31:47 2022 4 | 5 | The waveguide/fiber parameters are first provided, and a Waveguide instance 6 | is created. Then, the pulse parameters are used to create a Light object. 7 | A physical model is then chosen, taking into account different nonlinear 8 | interactions based on the user choice. Finally, a solver is instantiated 9 | and computes the propagation of the pulse in the waveguide with the chosen 10 | nonlinear interactions. 11 | 12 | @author: voumardt 13 | """ 14 | import matplotlib.pyplot as plt 15 | import numpy as np 16 | import os 17 | from scipy.constants import c 18 | 19 | import sys 20 | sys.path.append(os.getcwd() + '../../../') 21 | 22 | from src import * 23 | 24 | 25 | """ 26 | User parameters 27 | """ 28 | ### Simulation 29 | t_pts = 2**17 30 | 31 | ### Light 32 | pulse_duration = 100e-15 33 | pulse_wavelength = 1.56e-06 34 | pulse_energy = 1.6e-9 35 | 36 | ### Waveguide 37 | wg_length = 0.001 38 | wg_chi_2 = 1.1e-12 39 | wg_chi_3 = 3.4e-21 40 | wg_a_eff = 1e-12 41 | wg_freq, wg_n_eff = np.load('effective_index.npy') 42 | 43 | 44 | """ 45 | Nonlinear propagation 46 | """ 47 | ### Prepare waveguide 48 | waveguide = materials.Waveguide(wg_freq, wg_n_eff, wg_chi_2, wg_chi_3, 49 | wg_a_eff, wg_length, t_pts=t_pts) 50 | 51 | ### Prepare input pulse 52 | pulse = light.Sech(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 53 | 54 | ### Prepare model 55 | model = models.SpmChi2Chi3(waveguide, pulse) 56 | 57 | ### Prepare solver, solve 58 | solver = solvers.Solver(model) 59 | solver.solve() 60 | 61 | 62 | """ 63 | Plots 64 | """ 65 | pulse.plot_propagation('cascaded.png') 66 | 67 | -------------------------------------------------------------------------------- /examples/SiN/pychi_SiN_exp_vs_sim.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Feb 28 15:31:47 2022 4 | 5 | @author: voumardt 6 | """ 7 | import matplotlib.pyplot as plt 8 | import numpy as np 9 | import os 10 | import pandas 11 | from scipy.constants import c 12 | from scipy.io import loadmat 13 | 14 | import sys 15 | sys.path.append(os.getcwd() + '../../../') 16 | 17 | from src import * 18 | 19 | 20 | """ 21 | User parameters 22 | """ 23 | ### Simulation 24 | t_pts = 2**17 25 | 26 | ### Light 27 | pulse_duration = 80e-15 28 | pulse_wavelength = 1.56e-6 29 | pulse_energy = 1e-10 30 | 31 | ### Waveguide 32 | wg_length = 0.0058 33 | wg_chi_2 = 0 34 | wg_chi_3 = 2.8e-21 35 | wg_a_eff = 3e-13 36 | wg_freq, wg_n_eff = np.load('n_eff_data_SiN.npy') 37 | 38 | 39 | """ 40 | Nonlinear propagation 41 | """ 42 | waveguide = materials.Waveguide(wg_freq, wg_n_eff, wg_chi_2, wg_chi_3, 43 | wg_a_eff, wg_length, t_pts=t_pts) 44 | pulse = light.Sech(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 45 | model = models.SpmChi3(waveguide, pulse) 46 | solver = solvers.Solver(model) 47 | solver.solve() 48 | 49 | 50 | """ 51 | Plots 52 | """ 53 | pulse.plot_propagation() 54 | 55 | # Load experimental results 56 | exp_data = loadmat('exp_SiN.mat') 57 | exp_wl = exp_data['wavelength'][0] 58 | exp_int = exp_data['intensity'][0] 59 | 60 | # Compare experimental results and simulation 61 | plt.figure() 62 | plt.plot(pulse.wl, 10*np.log10(pulse.spectrum_wl[-1]/np.amax(pulse.spectrum_wl[-1]))-15) 63 | plt.plot(exp_wl, exp_int - np.amax(exp_int)) 64 | plt.xlim(3.5e-7, 1.75e-6) 65 | plt.ylim(-75, 5) 66 | plt.title('Experimental vs simulation - SiN') 67 | plt.xlabel('Wavelength [m]') 68 | plt.ylabel('Intensity [dB]') 69 | plt.legend(('Simulation', 'Experiment')) 70 | plt.savefig('Experimental_vs_simulation_SiN.png') 71 | -------------------------------------------------------------------------------- /examples/LiNb/pychi_LiNb_exp_vs_sim.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Feb 28 15:31:47 2022 4 | 5 | @author: voumardt 6 | """ 7 | import matplotlib.pyplot as plt 8 | import numpy as np 9 | import os 10 | import pandas 11 | from scipy.constants import c 12 | from scipy.io import loadmat 13 | 14 | import sys 15 | sys.path.append(os.getcwd() + '../../../') 16 | 17 | from src import * 18 | 19 | 20 | """ 21 | User parameters 22 | """ 23 | ### Simulation 24 | t_pts = 2**16 25 | 26 | ### Light 27 | pulse_duration = 80e-15 28 | pulse_wavelength = 1.58e-06 29 | pulse_energy = 1.056e-11 30 | 31 | ### Waveguide 32 | wg_length = 0.006 33 | wg_chi_2 = 20e-12 34 | wg_chi_3 = 2.5e-21 # Raman lasing and soliton mode-locking in lithium niobate microresonators 35 | wg_a_eff = 1e-12 36 | wg_freq, wg_n_eff = np.load('n_eff_data_LiNb.npy') 37 | 38 | 39 | """ 40 | Nonlinear propagation 41 | """ 42 | waveguide = materials.Waveguide(wg_freq, wg_n_eff, wg_chi_2, wg_chi_3, 43 | wg_a_eff, wg_length, t_pts=t_pts) 44 | pulse = light.Sech(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 45 | model = models.SpmChi2(waveguide, pulse) 46 | solver = solvers.Solver(model) 47 | solver.solve() 48 | 49 | 50 | """ 51 | Plots 52 | """ 53 | pulse.plot_propagation() 54 | 55 | # Load experimental results 56 | exp_data = loadmat('exp_LiNb.mat') 57 | exp_wl = exp_data['wavelength'][0] 58 | exp_int = exp_data['intensity'][0] 59 | 60 | # Compare experimental results and simulation 61 | plt.figure() 62 | plt.plot(pulse.wl, 10*np.log10(pulse.spectrum_wl[-1]/np.amax(pulse.spectrum_wl[-1]))-3) 63 | plt.plot(exp_wl, exp_int - np.amax(exp_int)) 64 | plt.xlim(3.5e-7, 1.75e-6) 65 | plt.ylim(-75, 5) 66 | plt.title('Experimental vs simulation - LiNb') 67 | plt.xlabel('Wavelength [m]') 68 | plt.ylabel('Intensity [dB]') 69 | plt.legend(('Simulation', 'Experiment')) 70 | plt.savefig('Experimental_vs_simulation_LiNb.png') 71 | -------------------------------------------------------------------------------- /examples/QPM/pychi_QPM.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Feb 28 15:31:47 2022 4 | 5 | The waveguide/fiber parameters are first provided, and a Waveguide instance 6 | is created. Then, the pulse parameters are used to create a Light object. 7 | A physical model is then chosen, taking into account different nonlinear 8 | interactions based on the user choice. Finally, a solver is instantiated 9 | and computes the propagation of the pulse in the waveguide with the chosen 10 | nonlinear interactions. This particular examples shows how to define a poling 11 | and breakpoints forcing computation at some desired distances. 12 | 13 | @author: voumardt 14 | """ 15 | import matplotlib.pyplot as plt 16 | import numpy as np 17 | import os 18 | 19 | import sys 20 | sys.path.append(os.getcwd() + '../../../') 21 | 22 | from src import * 23 | 24 | 25 | """ 26 | User parameters 27 | """ 28 | ### Simulation 29 | t_pts = 2**15 30 | 31 | ### Light 32 | pulse_duration = 100e-15 33 | pulse_wavelength = 1.56e-06 34 | pulse_energy = 1e-9 35 | 36 | ### Waveguide 37 | wg_length = 0.001 38 | const_wg_chi_2 = 1.1e-12 39 | 40 | # poling period 41 | qpm_length = 3.3e-5/2 42 | 43 | wg_chi_3 = 3.4e-21 44 | wg_a_eff = 1e-12 45 | wg_freq, wg_n_eff = np.load('effective_index.npy') 46 | 47 | # Define the nonlinearity as a function of z 48 | def wg_chi_2(z): 49 | return (-1)**(np.floor(z/qpm_length)%2)*const_wg_chi_2 50 | 51 | # Define breakpoints to force computation whenever the poling changes sign 52 | breakpoints = np.arange(wg_length//qpm_length)*qpm_length + 1e-10 53 | 54 | """ 55 | Nonlinear propagation 56 | """ 57 | waveguide = materials.Waveguide(wg_freq, wg_n_eff, wg_chi_2, wg_chi_3, 58 | wg_a_eff, wg_length, t_pts=t_pts) 59 | pulse = light.Sech(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 60 | model = models.Chi2(waveguide, pulse) 61 | solver = solvers.Solver(model, method='ERK4IP', breakpoints=breakpoints) 62 | solver.solve() 63 | 64 | 65 | """ 66 | Plots 67 | """ 68 | pulse.plot_propagation() 69 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | 16 | sys.path.insert(0, os.path.abspath('../src')) 17 | 18 | 19 | # -- Project information ----------------------------------------------------- 20 | 21 | project = 'pychi' 22 | copyright = '2023, Thibault Voumard' 23 | author = 'Thibault Voumard' 24 | 25 | # The full version, including alpha/beta/rc tags 26 | release = '0.0.12' 27 | 28 | 29 | # -- General configuration --------------------------------------------------- 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [ 35 | 'sphinx.ext.autodoc', 36 | 'sphinx.ext.viewcode', 37 | 'sphinx.ext.napoleon', 38 | 'sphinx_rtd_theme', 39 | 'myst_parser' 40 | ] 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # List of patterns, relative to source directory, that match files and 46 | # directories to ignore when looking for source files. 47 | # This pattern also affects html_static_path and html_extra_path. 48 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 49 | 50 | 51 | # -- Options for HTML output ------------------------------------------------- 52 | 53 | # Tell Sphinx to document private methods 54 | #autodoc_default_options = { 55 | # "members": True, 56 | # "undoc-members": True, 57 | # "private-members": True 58 | #} 59 | 60 | autodoc_mock_imports = ["matplotlib", "scipy", "numpy", "pyfftw", "numba"] 61 | 62 | # The theme to use for HTML and HTML Help pages. See the documentation for 63 | # a list of builtin themes. 64 | # 65 | html_theme = 'sphinx_rtd_theme' 66 | 67 | # Add any paths that contain custom static files (such as style sheets) here, 68 | # relative to this directory. They are copied after the builtin static files, 69 | # so a file named "default.css" will overwrite the builtin "default.css". 70 | html_static_path = [] 71 | -------------------------------------------------------------------------------- /docs/_build/html/_static/js/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /examples/pychi_example.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Feb 28 15:31:47 2022 4 | 5 | The waveguide/fiber parameters are first provided, and a Waveguide instance 6 | is created. Then, the pulse parameters are used to create a Light object. 7 | A physical model is then chosen, taking into account different nonlinear 8 | interactions based on the user choice. Finally, a solver is instantiated 9 | and computes the propagation of the pulse in the waveguide with the chosen 10 | nonlinear interactions. 11 | 12 | @author: voumardt 13 | """ 14 | import matplotlib.pyplot as plt 15 | import numpy as np 16 | from scipy.constants import c 17 | 18 | from src import * 19 | 20 | 21 | """ 22 | User parameters 23 | """ 24 | ### Simulation 25 | t_pts = 2**15 26 | 27 | ### Light 28 | pulse_duration = 100e-15 29 | pulse_wavelength = 1.56e-06 30 | pulse_energy = 1e-9 31 | 32 | ### Waveguide 33 | wg_length = 0.001 34 | wg_chi_2 = 1.1e-12 35 | wg_chi_3 = 3.4e-21 36 | wg_a_eff = 1e-12 37 | wg_freq, wg_n_eff = np.load('effective_index.npy') 38 | 39 | 40 | """ 41 | Nonlinear propagation 42 | """ 43 | ### Prepare waveguide 44 | waveguide = materials.Waveguide(wg_freq, wg_n_eff, wg_chi_2, wg_chi_3, 45 | wg_a_eff, wg_length, t_pts=t_pts) 46 | # Additional options: 47 | # One can provide beta coefficients (strongly discouraged) overwriting the refractive 48 | # index using waveguide.set_betas(betas, wavelength) 49 | # 50 | # wg_n_eff can be a 2 dimensional array, with first dimension the wavelength dependence 51 | # and second dimension the z dependence. 52 | # 53 | # chi2 and chi3 can be callables, returning a z dependent value. Alternatively, they 54 | # can be defined as one dimensional arrays describing their z dependence, or 55 | # two dimensional arrays describing their z and frequency dependence. 56 | # 57 | # One can use waveguide.set_gamma(gamma) or waveguide.set_n2(n2) to provide 58 | # nonlinear coefficient or nonlinear refractive index and overwrite chi3. 59 | # 60 | # Check documentation for more options and details. 61 | 62 | 63 | ### Prepare input pulse 64 | pulse = light.Sech(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 65 | # Other available pulse shapes: 66 | # pulse = light.Gaussian(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 67 | # pulse = light.Cw(waveguide, pulse_average_power, pulse_wavelength) 68 | # pulse = light.Arbitrary(waveguide, pulse_frequency_axis, pulse_electric_field, pulse_energy) 69 | 70 | 71 | ### Prepare model 72 | model = models.SpmChi2Chi3(waveguide, pulse) 73 | # Other models available: 74 | # model = models.Spm(waveguide, pulse) 75 | # model = models.Chi2(waveguide, pulse) 76 | # model = models.Chi3(waveguide, pulse) 77 | # model = models.SpmChi2(waveguide, pulse) 78 | # model = models.SpmChi3(waveguide, pulse) 79 | # model = models.Chi2Chi3(waveguide, pulse) 80 | 81 | 82 | ### Prepare solver, solve 83 | solver = solvers.Solver(model) 84 | solver.solve() 85 | 86 | 87 | """ 88 | Plots 89 | """ 90 | pulse.plot_propagation() 91 | # Results can also be accessed via pulse.z_save, pulse.freq, pulse.spectrum, pulse.waveform 92 | # The refractive index and GVD can be seen with waveguide.plot_refractive_index() 93 | -------------------------------------------------------------------------------- /docs/_build/html/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} -------------------------------------------------------------------------------- /examples/SPM/pychi_spm_validation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Feb 28 15:31:47 2022 4 | 5 | @author: voumardt 6 | """ 7 | import matplotlib.pyplot as plt 8 | import numpy as np 9 | from scipy.constants import c 10 | eps_0 = 8.8541878128e-12 11 | import math 12 | import os 13 | 14 | import sys 15 | sys.path.append(os.getcwd() + '../../../') 16 | 17 | from src import * 18 | 19 | 20 | """ 21 | User parameters 22 | 23 | Parameters taken from 'Supercontinuum generation in photonic crystal fiber', 24 | John M. Dudley, Goëry Genty, and Stéphane Coen, DOI: https://doi.org/10.1103/RevModPhys.78.1135 25 | to reproduce figure 3 therein. 26 | """ 27 | ### Simulation 28 | t_pts = 2**14 29 | 30 | ### Light 31 | pulse_duration = 50e-15 32 | pulse_wavelength = 0.835e-06 33 | pulse_peak_power = 1e4 34 | pulse_energy = pulse_peak_power*pulse_duration/np.log(1+2**0.5) 35 | 36 | ### Waveguide 37 | wg_length = 0.15 38 | wg_chi_2 = 0 39 | wg_a_eff = 1e-12 40 | wg_n = 1.45 41 | gamma = 0.11 42 | wg_chi_3 = 4*wg_n**2*c*eps_0*gamma*pulse_wavelength*wg_a_eff/6/np.pi 43 | wg_omega = np.linspace(c/1670e-9*2*np.pi, c/417.5e-9*2*np.pi, t_pts) 44 | betas = [wg_n*2*np.pi/pulse_wavelength, wg_n/c, -1.183e-26, 8.1038e-41, 45 | -9.5205e-56, 2.0737e-70, -5.3943e-85, 1.3486e-99, -2.5495e-114, 46 | 3.0524e-129, -1.7140e-144] 47 | 48 | ### Compute refractive index 49 | wg_freq = wg_omega/2/np.pi 50 | def compute_n_eff(wg_omega, pulse_wavelength, betas): 51 | k = np.zeros(t_pts, dtype='float64') 52 | for i, beta in enumerate(betas): 53 | k += beta*(wg_omega - 2*np.pi*c/pulse_wavelength)**i/math.factorial(i) 54 | n_eff = k*c/wg_omega 55 | return n_eff 56 | wg_n_eff = compute_n_eff(wg_omega, pulse_wavelength, betas) 57 | 58 | 59 | """ 60 | Nonlinear propagation 61 | """ 62 | ### Prepare waveguide 63 | waveguide = materials.Waveguide(wg_freq, wg_n_eff, wg_chi_2, wg_chi_3, 64 | wg_a_eff, wg_length, t_pts=t_pts) 65 | 66 | ### Prepare input pulse 67 | pulse = light.Sech(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 68 | 69 | ### Prepare model 70 | model = models.Spm(waveguide, pulse) 71 | 72 | ### Prepare solver 73 | solver = solvers.Solver(model) 74 | 75 | ### Solve 76 | solver.solve() 77 | 78 | 79 | """ 80 | Plots 81 | """ 82 | z_pos = pulse.z_save 83 | wl = pulse.wl 84 | spec_wl = pulse.spectrum_wl[:, (wl>450e-9)&(wl<1300e-9)] 85 | wl = wl[(wl>450e-9)&(wl<1300e-9)] 86 | spec_wl_db = 20*np.log10(np.abs(spec_wl) + 1e-20) 87 | 88 | 89 | plt.figure() 90 | plt.subplot(121) 91 | plt.imshow(spec_wl_db[::-1], cmap='jet', aspect='auto', vmin=np.amax(spec_wl_db) - 40, 92 | extent=(np.amin(wl)*1e9, np.amax(wl)*1e9, 0, np.amax(z_pos))) 93 | plt.xlabel('Wavelength [nm]') 94 | plt.ylabel('Distance [m]') 95 | 96 | waveform = 10*np.log10(np.abs(pulse.waveform)**2 + 1e-20) - np.amax(10*np.log10(np.abs(pulse.waveform)**2 + 1e-20)) 97 | time = waveguide.time 98 | waveform = waveform[:, (time<5e-12)&(time>-2e-12)] 99 | time = time[(time<5e-12)&(time>-2e-12)] 100 | 101 | plt.subplot(122) 102 | plt.imshow(waveform[::-1], cmap='jet', aspect='auto', vmin = np.amax(waveform) - 40, 103 | extent=(np.amin(time)*1e12, np.amax(time)*1e12, 0, np.amax(z_pos))) 104 | plt.xlabel('Time [ps]') 105 | plt.ylabel('Distance [m]') 106 | plt.colorbar(label='Intensity [dB]') 107 | plt.tight_layout() 108 | plt.savefig('propagation.png') 109 | -------------------------------------------------------------------------------- /src/pychi/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Jul 15 09:42:48 2025 4 | 5 | @author: Thibault Voumard 6 | 7 | This module contains utility functions that either make sense to keep out of 8 | other modules or are annoying to implement otherwise, although could be at a 9 | later stage. 10 | """ 11 | import math 12 | import numpy as np 13 | from scipy.constants import c 14 | 15 | def betas_from_dispersion(wavelength, n, disp=0, disp_slope=0): 16 | """ 17 | Compute the corresponding set of betas from typical dispersion values 18 | provided by fiber manufacturers. Should eventually belong to waveguide 19 | module. 20 | 21 | Parameters 22 | ---------- 23 | wavelength : float 24 | Wavelength at which the dispersion is specified. 25 | n : float 26 | Refractive index at the specified wavelength. 27 | disp : float, optional 28 | Dispersion at the specified wavelength. Default is 0. 29 | disp_slope : float, optional 30 | Dispersion slope at the specified wavelength. Default is 0. 31 | 32 | Returns 33 | ------- 34 | list 35 | Beta coefficients corresponding to the given dispersion. 36 | 37 | """ 38 | beta_0 = n*2*np.pi/wavelength 39 | beta_1 = n/c 40 | beta_2 = -disp*wavelength**2/2/np.pi/c 41 | beta_3 = -wavelength**3/(2*np.pi*c)**2*(2*disp-wavelength*disp_slope) 42 | return [beta_0, beta_1, beta_2, beta_3] 43 | 44 | def betas_from_dispersion_non_SI(wavelength, n, disp=0, disp_slope=0): 45 | """ 46 | Compute the corresponding set of betas from typical dispersion values 47 | provided by fiber manufacturers in their non SI but more common units, 48 | i.e. ps/(nm km) and ps/(nm**2 km). Should eventually belong to waveguide 49 | module. 50 | 51 | Parameters 52 | ---------- 53 | wavelength : float 54 | Wavelength at which the dispersion is specified. 55 | n : float 56 | Refractive index at the specified wavelength. 57 | disp : float, optional 58 | Dispersion at the specified wavelength, in ps/(nm km). Default is 0. 59 | disp_slope : float, optional 60 | Dispersion slope at the specified wavelength, in ps/(nm**2 km). Default 61 | is 0. 62 | 63 | Returns 64 | ------- 65 | list 66 | Beta coefficients corresponding to the given dispersion. 67 | 68 | """ 69 | disp = 1e6*disp 70 | disp_slope = 1e-3*disp_slope 71 | beta_0 = n*2*np.pi/wavelength 72 | beta_1 = n/c 73 | beta_2 = -disp*wavelength**2/2/np.pi/c 74 | beta_3 = -wavelength**3/(2*np.pi*c)**2*(2*disp-wavelength*disp_slope) 75 | return [beta_0, beta_1, beta_2, beta_3] 76 | 77 | def n_eff_from_betas(freq, wavelength, betas): 78 | """ 79 | Compute the effective refractive index from a set of beta coefficients. 80 | Should eventually belong to waveguide module. 81 | 82 | Parameters 83 | ---------- 84 | freq : array of float 85 | Frequency axis over which the refractive index will be defined. 86 | wavelength : float 87 | Wavelength at which the beta coefficients are defined. 88 | betas : list of float 89 | List of the beta coefficients. 90 | 91 | Returns 92 | ------- 93 | n_eff : array of float 94 | Effective refractive indices computed from the beta coefficients. 95 | 96 | """ 97 | omega = 2*np.pi*freq 98 | k = np.zeros(len(freq), dtype='float64') 99 | for i, beta in enumerate(betas): 100 | k += beta*(omega - 2*np.pi*c/wavelength)**i/math.factorial(i) 101 | n_eff = k*c/omega 102 | return n_eff 103 | -------------------------------------------------------------------------------- /docs/_build/html/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview: module code — pychi 0.0.1 documentation 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 44 | 45 |
49 | 50 |
51 |
52 |
53 |
    54 |
  • »
  • 55 |
  • Overview: module code
  • 56 |
  • 57 |
  • 58 |
59 |
60 |
61 |
62 |
63 | 64 |

All modules for which code is available

65 | 70 | 71 |
72 |
73 | 87 |
88 |
89 |
90 |
91 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["index","modules","pychi"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.index":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst","modules.rst","pychi.rst"],objects:{"":{pychi:[2,0,0,"-"]},"pychi.light":{Arbitrary:[2,1,1,""],Cw:[2,1,1,""],Gaussian:[2,1,1,""],Light:[2,1,1,""],Sech:[2,1,1,""]},"pychi.light.Light":{add_shot_noise:[2,2,1,""],plot_propagation:[2,2,1,""],set_result_as_start:[2,2,1,""]},"pychi.materials":{Waveguide:[2,1,1,""]},"pychi.materials.Waveguide":{chi_2:[2,2,1,""],chi_3:[2,2,1,""],compute_betas:[2,2,1,""],k:[2,2,1,""],n_eff:[2,2,1,""],plot_refractive_index:[2,2,1,""],rhs_prefactor:[2,2,1,""],set_betas:[2,2,1,""],set_gamma:[2,2,1,""],set_n2:[2,2,1,""]},"pychi.models":{Chi2:[2,1,1,""],Chi2Chi3:[2,1,1,""],Chi3:[2,1,1,""],Model:[2,1,1,""],Spm:[2,1,1,""],SpmChi2:[2,1,1,""],SpmChi2Chi3:[2,1,1,""],SpmChi3:[2,1,1,""],numbaconj:[2,3,1,""],numbacopy:[2,3,1,""],numbaexp:[2,3,1,""]},"pychi.models.Chi2":{nonlinear_term:[2,2,1,""]},"pychi.models.Chi2Chi3":{nonlinear_term:[2,2,1,""]},"pychi.models.Chi3":{nonlinear_term:[2,2,1,""]},"pychi.models.Model":{dispersion_step:[2,2,1,""],nonlinear_term:[2,2,1,""]},"pychi.models.Spm":{nonlinear_term:[2,2,1,""]},"pychi.models.SpmChi2":{nonlinear_term:[2,2,1,""]},"pychi.models.SpmChi2Chi3":{nonlinear_term:[2,2,1,""]},"pychi.models.SpmChi3":{nonlinear_term:[2,2,1,""]},"pychi.solvers":{Solver:[2,1,1,""],numbaexp:[2,3,1,""],numbanorm:[2,3,1,""]},"pychi.solvers.Solver":{solve:[2,2,1,""]},pychi:{light:[2,0,0,"-"],materials:[2,0,0,"-"],models:[2,0,0,"-"],solvers:[2,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:attribute"},terms:{"22e":2,"class":2,"default":2,"final":2,"float":2,"function":2,"int":2,"new":2,"return":2,"schr\u00f6dinger":2,Not:2,The:2,accomod:2,accordingli:2,adapt:2,adaptive_factor:2,add:2,add_shot_nois:2,adding:2,affect:2,all:2,allow:2,analyt:2,arbitrari:2,area:2,arrai:2,aug:2,author:2,avail:2,average_pow:2,avoid:2,axes:2,axi:2,base:2,beta:2,built:2,center:2,chi2:2,chi2chi3:2,chi3:2,chi:2,chi_2:2,chi_3:2,child:2,coeffici:2,coher:2,complex:2,comput:2,compute_beta:2,conjug:2,contain:2,content:[0,1],conveni:2,copi:2,creat:2,curv:2,data:2,dedic:2,delai:2,deriv:2,differ:2,dispers:2,dispersion_step:2,domain:2,effect:2,effective_area:2,electr:2,envelop:2,equat:2,evolut:2,exponenti:2,feb:2,field:2,field_f:2,field_t_in:2,first:2,frequenc:2,fri:2,from:2,gamma:2,gaussian:2,gener:2,give:2,given:2,happen:2,harmon:2,here:2,highest:2,implement:2,index:[0,2],inform:2,initi:2,input:2,instanti:2,instead:2,integr:2,interact:2,length:2,light:[0,1],local_error:2,materi:[0,1],max_dz:2,method:2,model:[0,1],modul:[0,1],n_eff:2,nois:2,none:2,nonlinear:2,nonlinear_term:2,note:2,numba:2,numbaconj:2,numbacopi:2,numbaexp:2,numbanorm:2,number:2,object:2,onli:2,optim:2,option:2,order:2,output:2,over:2,overwrit:2,packag:[0,1],page:0,paramet:2,parent:2,phase:2,physic:2,plot:2,plot_propag:2,plot_refractive_index:2,propag:2,properti:2,provid:2,puls:2,pulse_dur:2,pulse_electric_field:2,pulse_energi:2,pulse_frequency_axi:2,pulse_wavelength:2,pychi:1,quantiti:2,raman:2,raman_fract:2,raman_tau_1:2,raman_tau_2:2,random:2,refract:2,relat:2,reproduc:2,result:2,rhs_prefactor:2,save:2,savenam:2,search:0,sech:2,seed:2,self:2,set:2,set_beta:2,set_gamma:2,set_n2:2,set_result_as_start:2,setup:2,shape:2,shot:2,should:2,simul:2,size:2,solv:2,solver:[0,1],sourc:2,specifi:2,spectral:2,spm:2,spmchi2:2,spmchi2chi3:2,spmchi3:2,src:[],standard:2,step:2,store:2,studi:2,submodul:[0,1],suitabl:2,sum:2,support:2,t_pt:2,term:2,thi:2,thibault:2,thu:2,time:2,tripl:2,type:2,use:2,used:2,useful:2,user:2,util:2,valu:2,vector:2,versu:2,voumardt:2,waveform:2,waveguid:2,wavelength:2,which:2,z_pt:2},titles:["Welcome to pychi\u2019s documentation!","<no title>","pychi package"],titleterms:{content:2,document:0,indic:0,light:2,materi:2,model:2,modul:2,packag:2,pychi:[0,2],solver:2,src:[],submodul:2,tabl:0,welcom:0}}) -------------------------------------------------------------------------------- /docs/_build/html/_static/js/html5shiv-printshiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Search — pychi 0.0.1 documentation 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 47 | 48 |
52 | 53 |
54 |
55 |
56 |
    57 |
  • »
  • 58 |
  • Search
  • 59 |
  • 60 |
  • 61 |
62 |
63 |
64 |
65 |
66 | 67 | 74 | 75 | 76 |
77 | 78 |
79 | 80 |
81 |
82 | 96 |
97 |
98 |
99 |
100 | 105 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /docs/_build/html/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | !function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t 2 | 3 | 4 | 5 | 6 | Python Module Index — pychi 0.0.1 documentation 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 47 | 48 |
52 | 53 |
54 |
55 |
56 |
    57 |
  • »
  • 58 |
  • Python Module Index
  • 59 |
  • 60 |
  • 61 |
62 |
63 |
64 |
65 |
66 | 67 | 68 |

Python Module Index

69 | 70 |
71 | p 72 |
73 | 74 | 75 | 76 | 78 | 79 | 81 | 84 | 85 | 86 | 89 | 90 | 91 | 94 | 95 | 96 | 99 | 100 | 101 | 104 |
 
77 | p
82 | pychi 83 |
    87 | pychi.light 88 |
    92 | pychi.materials 93 |
    97 | pychi.models 98 |
    102 | pychi.solvers 103 |
105 | 106 | 107 |
108 |
109 |
110 | 111 |
112 | 113 |
114 |

© Copyright 2023, Thibault Voumard.

115 |
116 | 117 | Built with Sphinx using a 118 | theme 119 | provided by Read the Docs. 120 | 121 | 122 |
123 |
124 |
125 |
126 |
127 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /docs/_build/html/modules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <no title> — pychi 0.0.1 documentation 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 46 | 47 |
51 | 52 |
53 |
54 |
55 | 62 |
63 |
64 |
65 |
66 | 67 |

pychi package 68 | ===

69 | 82 | 83 | 84 |
85 |
86 |
90 | 91 |
92 | 93 |
94 |

© Copyright 2023, Thibault Voumard.

95 |
96 | 97 | Built with Sphinx using a 98 | theme 99 | provided by Read the Docs. 100 | 101 | 102 |
103 |
104 |
105 |
106 |
107 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /docs/_build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Welcome to pychi’s documentation! — pychi 0.0.1 documentation 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 45 | 46 |
50 | 51 |
52 |
53 |
54 |
    55 |
  • »
  • 56 |
  • Welcome to pychi’s documentation!
  • 57 |
  • 58 | View page source 59 |
  • 60 |
61 |
62 |
63 |
64 |
65 | 66 |
67 |

Welcome to pychi’s documentation!

68 |
69 |

Contents:

70 | 81 |
82 |
83 |
84 |

Indices and tables

85 | 90 |
91 | 92 | 93 |
94 |
95 |
98 | 99 |
100 | 101 |
102 |

© Copyright 2023, Thibault Voumard.

103 |
104 | 105 | Built with Sphinx using a 106 | theme 107 | provided by Read the Docs. 108 | 109 | 110 |
111 |
112 |
113 |
114 |
115 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pychi 2 | 3 | A Python package for simulating the propagation of optical pulses in nonlinear materials. 4 | 5 | ## Capabilities 6 | 7 | *pychi* is aimed at simulating the propagation of short pulses in nonlinear media and capturing as much physics as possible. It is based on a unidirectional propagation model, which stays valid even for sub-cycle optical pulses. In particular, this propagation model accounts for 8 | - Full frequency dependence of the effective refractive index 9 | - Quadratic nonlinear interactions (sum- and difference-frequency generation) 10 | - Cubic nonlinear interactions (triple sum-frequency generation, self-phase modulation, conjugated Kerr term) 11 | - Raman scattering 12 | - Self-steepening 13 | - Frequency-dependence of the nonlinear coefficients and effective area 14 | - z-dependence of the effective refractive index, nonlinear coefficients and effective area (permitting poling to be simulated) 15 | 16 | The package is built to be as user-friendly as possible, providing a relatively high-level interface for the user while still allowing for physically intricate simulation cases. It leverages a custom-made order 5 solver, although more classical solvers (such as the RK4IP) have also been implemented for completeness and versatility. 17 | 18 | ## Installation 19 | 20 | First, make sure pip is up-to-date using 21 | ``` 22 | pip install --upgrade pip 23 | ``` 24 | 25 | On Windows, install the package using 26 | ``` 27 | pip install pychi 28 | ``` 29 | 30 | On Mac, one might have to first run 31 | ``` 32 | conda install -c conda-forge pyfftw 33 | ``` 34 | due to some OS specificities in pyFFTW installation. 35 | 36 | Then, one should be able to install pychi normally using 37 | ``` 38 | pip install pychi 39 | ``` 40 | 41 | 42 | ## Documentation 43 | 44 | The documentation is available and best viewed under 45 | https://pychi.readthedocs.io/en/latest/ 46 | This documentation has been automatically generated using SPHINX, and is still a work in progress. Do not hesitate to contact us for any needed clarifications and examples. 47 | 48 | ## Implementation 49 | 50 | pychi has been developped at DESY by the Ultrafast Microphotonics group. Details about the implementation have been published at https://doi.org/10.1063/5.0135252 - if you use *pychi* for scientific publications, please cite this paper. 51 | 52 | 53 | ## Theory 54 | 55 | The full theoretical derivation leading to the master equation used in *pychi* is described in Appendix C of the following thesis: https://ediss.sub.uni-hamburg.de/handle/ediss/10785. 56 | 57 | ## Example 58 | 59 | Here is a typical example of the use of pychi to simulate the propagation of a short optical pulse in a nonlinear waveguide exhibiting both cubic and quadratic nonlinearities. 60 | 61 | ```python 62 | # -*- coding: utf-8 -*- 63 | """ 64 | Created on Mon Feb 28 15:31:47 2022 65 | The waveguide/fiber parameters are first provided, and a Waveguide instance 66 | is created. Then, the pulse parameters are used to create a Light object. 67 | A physical model is then chosen, taking into account different nonlinear 68 | interactions based on the user choice. Finally, a solver is instantiated 69 | and computes the propagation of the pulse in the waveguide with the chosen 70 | nonlinear interactions. 71 | @author: voumardt 72 | """ 73 | import matplotlib.pyplot as plt 74 | import numpy as np 75 | from scipy.constants import c 76 | 77 | import pychi 78 | 79 | 80 | """ 81 | User parameters 82 | """ 83 | ### Simulation 84 | t_pts = 2**15 85 | 86 | ### Light 87 | pulse_duration = 100e-15 88 | pulse_wavelength = 1.56e-06 89 | pulse_energy = 1e-9 90 | 91 | ### Waveguide 92 | wg_length = 0.001 93 | wg_chi_2 = 1.1e-12 94 | wg_chi_3 = 3.4e-21 95 | wg_a_eff = 1e-12 96 | wg_freq, wg_n_eff = np.load('effective_index.npy') 97 | # wg_n_eff is the effective dispersion of the waveguide considered, sampled on the grid wg_freq 98 | 99 | 100 | """ 101 | Nonlinear propagation 102 | """ 103 | ### Prepare waveguide 104 | waveguide = pychi.materials.Waveguide(wg_freq, wg_n_eff, wg_chi_2, wg_chi_3, 105 | wg_a_eff, wg_length, t_pts=t_pts) 106 | # Additional options: 107 | # wg_n_eff can be a 2 dimensional array, with first dimension the wavelength dependence 108 | # and second dimension the z dependence. 109 | # 110 | # chi2 and chi3 can be callables, returning a z dependent value. Alternatively, they 111 | # can be defined as one dimensional arrays describing their z dependence, or 112 | # two dimensional arrays describing their z and frequency dependence. They 113 | # can also be callables of (z, freq). 114 | # 115 | # One can use waveguide.set_gamma(gamma) or waveguide.set_n2(n2) to provide a 116 | # nonlinear coefficient or nonlinear refractive index and overwrite chi3. 117 | # 118 | # Check documentation for more options and details. 119 | 120 | 121 | ### Prepare input pulse 122 | pulse = pychi.light.Sech(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 123 | # Other available pulse shapes: 124 | # pulse = pychi.light.Gaussian(waveguide, pulse_duration, pulse_energy, pulse_wavelength) 125 | # pulse = pychi.light.Cw(waveguide, pulse_average_power, pulse_wavelength) 126 | # pulse = pychi.light.Arbitrary(waveguide, pulse_frequency_axis, pulse_electric_field, pulse_energy) 127 | 128 | 129 | ### Prepare model 130 | model = pychi.models.SpmChi2Chi3(waveguide, pulse) 131 | # Other models available: 132 | # model = pychi.models.Spm(waveguide, pulse) 133 | # model = pychi.models.Chi2(waveguide, pulse) 134 | # model = pychi.models.Chi3(waveguide, pulse) 135 | # model = pychi.models.SpmChi2(waveguide, pulse) 136 | # model = pychi.models.SpmChi3(waveguide, pulse) 137 | # model = pychi.models.Chi2Chi3(waveguide, pulse) 138 | 139 | 140 | ### Prepare solver, solve 141 | solver = pychi.solvers.Solver(model) 142 | solver.solve() 143 | 144 | 145 | """ 146 | Plots 147 | """ 148 | pulse.plot_propagation() 149 | # Results can also be accessed via pulse.z_save, pulse.freq, pulse.spectrum, pulse.waveform 150 | # The refractive index and GVD can be seen with waveguide.plot_refractive_index() 151 | 152 | 153 | ``` 154 | 155 | Typical propagation results using the above script would look as follows: 156 | ![grafik](https://user-images.githubusercontent.com/97957751/222731448-ff856390-4325-4f39-8817-f508898e2308.png) 157 | 158 | Check the examples folder for some specific cases and validation against experimental data. 159 | 160 | ## Contacts 161 | 162 | If you have any questions, remarks, contributions, do not hesitate to contact us at: 163 | pychi@desy.de 164 | or here on GitHub. 165 | -------------------------------------------------------------------------------- /docs/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s === 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node, addItems) { 70 | if (node.nodeType === 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && 74 | !jQuery(node.parentNode).hasClass(className) && 75 | !jQuery(node.parentNode).hasClass("nohighlight")) { 76 | var span; 77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 78 | if (isInSVG) { 79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 80 | } else { 81 | span = document.createElement("span"); 82 | span.className = className; 83 | } 84 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 86 | document.createTextNode(val.substr(pos + text.length)), 87 | node.nextSibling)); 88 | node.nodeValue = val.substr(0, pos); 89 | if (isInSVG) { 90 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 91 | var bbox = node.parentElement.getBBox(); 92 | rect.x.baseVal.value = bbox.x; 93 | rect.y.baseVal.value = bbox.y; 94 | rect.width.baseVal.value = bbox.width; 95 | rect.height.baseVal.value = bbox.height; 96 | rect.setAttribute('class', className); 97 | addItems.push({ 98 | "parent": node.parentNode, 99 | "target": rect}); 100 | } 101 | } 102 | } 103 | else if (!jQuery(node).is("button, select, textarea")) { 104 | jQuery.each(node.childNodes, function() { 105 | highlight(this, addItems); 106 | }); 107 | } 108 | } 109 | var addItems = []; 110 | var result = this.each(function() { 111 | highlight(this, addItems); 112 | }); 113 | for (var i = 0; i < addItems.length; ++i) { 114 | jQuery(addItems[i].parent).before(addItems[i].target); 115 | } 116 | return result; 117 | }; 118 | 119 | /* 120 | * backward compatibility for jQuery.browser 121 | * This will be supported until firefox bug is fixed. 122 | */ 123 | if (!jQuery.browser) { 124 | jQuery.uaMatch = function(ua) { 125 | ua = ua.toLowerCase(); 126 | 127 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 128 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 129 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 130 | /(msie) ([\w.]+)/.exec(ua) || 131 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 132 | []; 133 | 134 | return { 135 | browser: match[ 1 ] || "", 136 | version: match[ 2 ] || "0" 137 | }; 138 | }; 139 | jQuery.browser = {}; 140 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 141 | } 142 | 143 | /** 144 | * Small JavaScript module for the documentation. 145 | */ 146 | var Documentation = { 147 | 148 | init : function() { 149 | this.fixFirefoxAnchorBug(); 150 | this.highlightSearchWords(); 151 | this.initIndexTable(); 152 | if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { 153 | this.initOnKeyListeners(); 154 | } 155 | }, 156 | 157 | /** 158 | * i18n support 159 | */ 160 | TRANSLATIONS : {}, 161 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 162 | LOCALE : 'unknown', 163 | 164 | // gettext and ngettext don't access this so that the functions 165 | // can safely bound to a different name (_ = Documentation.gettext) 166 | gettext : function(string) { 167 | var translated = Documentation.TRANSLATIONS[string]; 168 | if (typeof translated === 'undefined') 169 | return string; 170 | return (typeof translated === 'string') ? translated : translated[0]; 171 | }, 172 | 173 | ngettext : function(singular, plural, n) { 174 | var translated = Documentation.TRANSLATIONS[singular]; 175 | if (typeof translated === 'undefined') 176 | return (n == 1) ? singular : plural; 177 | return translated[Documentation.PLURALEXPR(n)]; 178 | }, 179 | 180 | addTranslations : function(catalog) { 181 | for (var key in catalog.messages) 182 | this.TRANSLATIONS[key] = catalog.messages[key]; 183 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 184 | this.LOCALE = catalog.locale; 185 | }, 186 | 187 | /** 188 | * add context elements like header anchor links 189 | */ 190 | addContextElements : function() { 191 | $('div[id] > :header:first').each(function() { 192 | $('\u00B6'). 193 | attr('href', '#' + this.id). 194 | attr('title', _('Permalink to this headline')). 195 | appendTo(this); 196 | }); 197 | $('dt[id]').each(function() { 198 | $('\u00B6'). 199 | attr('href', '#' + this.id). 200 | attr('title', _('Permalink to this definition')). 201 | appendTo(this); 202 | }); 203 | }, 204 | 205 | /** 206 | * workaround a firefox stupidity 207 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 208 | */ 209 | fixFirefoxAnchorBug : function() { 210 | if (document.location.hash && $.browser.mozilla) 211 | window.setTimeout(function() { 212 | document.location.href += ''; 213 | }, 10); 214 | }, 215 | 216 | /** 217 | * highlight the search words provided in the url in the text 218 | */ 219 | highlightSearchWords : function() { 220 | var params = $.getQueryParameters(); 221 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 222 | if (terms.length) { 223 | var body = $('div.body'); 224 | if (!body.length) { 225 | body = $('body'); 226 | } 227 | window.setTimeout(function() { 228 | $.each(terms, function() { 229 | body.highlightText(this.toLowerCase(), 'highlighted'); 230 | }); 231 | }, 10); 232 | $('') 234 | .appendTo($('#searchbox')); 235 | } 236 | }, 237 | 238 | /** 239 | * init the domain index toggle buttons 240 | */ 241 | initIndexTable : function() { 242 | var togglers = $('img.toggler').click(function() { 243 | var src = $(this).attr('src'); 244 | var idnum = $(this).attr('id').substr(7); 245 | $('tr.cg-' + idnum).toggle(); 246 | if (src.substr(-9) === 'minus.png') 247 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 248 | else 249 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 250 | }).css('display', ''); 251 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 252 | togglers.click(); 253 | } 254 | }, 255 | 256 | /** 257 | * helper function to hide the search marks again 258 | */ 259 | hideSearchWords : function() { 260 | $('#searchbox .highlight-link').fadeOut(300); 261 | $('span.highlighted').removeClass('highlighted'); 262 | }, 263 | 264 | /** 265 | * make the url absolute 266 | */ 267 | makeURL : function(relativeURL) { 268 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 269 | }, 270 | 271 | /** 272 | * get the current relative url 273 | */ 274 | getCurrentURL : function() { 275 | var path = document.location.pathname; 276 | var parts = path.split(/\//); 277 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 278 | if (this === '..') 279 | parts.pop(); 280 | }); 281 | var url = parts.join('/'); 282 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 283 | }, 284 | 285 | initOnKeyListeners: function() { 286 | $(document).keydown(function(event) { 287 | var activeElementType = document.activeElement.tagName; 288 | // don't navigate when in search box or textarea 289 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' 290 | && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) { 291 | switch (event.keyCode) { 292 | case 37: // left 293 | var prevHref = $('link[rel="prev"]').prop('href'); 294 | if (prevHref) { 295 | window.location.href = prevHref; 296 | return false; 297 | } 298 | case 39: // right 299 | var nextHref = $('link[rel="next"]').prop('href'); 300 | if (nextHref) { 301 | window.location.href = nextHref; 302 | return false; 303 | } 304 | } 305 | } 306 | }); 307 | } 308 | }; 309 | 310 | // quick alias for translations 311 | _ = Documentation.gettext; 312 | 313 | $(document).ready(function() { 314 | Documentation.init(); 315 | }); 316 | -------------------------------------------------------------------------------- /docs/_build/html/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/_build/html/_static/language_data.js: -------------------------------------------------------------------------------- 1 | /* 2 | * language_data.js 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * This script contains the language-specific data used by searchtools.js, 6 | * namely the list of stopwords, stemmer, scorer and splitter. 7 | * 8 | * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. 9 | * :license: BSD, see LICENSE for details. 10 | * 11 | */ 12 | 13 | var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; 14 | 15 | 16 | /* Non-minified version JS is _stemmer.js if file is provided */ 17 | /** 18 | * Porter Stemmer 19 | */ 20 | var Stemmer = function() { 21 | 22 | var step2list = { 23 | ational: 'ate', 24 | tional: 'tion', 25 | enci: 'ence', 26 | anci: 'ance', 27 | izer: 'ize', 28 | bli: 'ble', 29 | alli: 'al', 30 | entli: 'ent', 31 | eli: 'e', 32 | ousli: 'ous', 33 | ization: 'ize', 34 | ation: 'ate', 35 | ator: 'ate', 36 | alism: 'al', 37 | iveness: 'ive', 38 | fulness: 'ful', 39 | ousness: 'ous', 40 | aliti: 'al', 41 | iviti: 'ive', 42 | biliti: 'ble', 43 | logi: 'log' 44 | }; 45 | 46 | var step3list = { 47 | icate: 'ic', 48 | ative: '', 49 | alize: 'al', 50 | iciti: 'ic', 51 | ical: 'ic', 52 | ful: '', 53 | ness: '' 54 | }; 55 | 56 | var c = "[^aeiou]"; // consonant 57 | var v = "[aeiouy]"; // vowel 58 | var C = c + "[^aeiouy]*"; // consonant sequence 59 | var V = v + "[aeiou]*"; // vowel sequence 60 | 61 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 62 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 63 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 64 | var s_v = "^(" + C + ")?" + v; // vowel in stem 65 | 66 | this.stemWord = function (w) { 67 | var stem; 68 | var suffix; 69 | var firstch; 70 | var origword = w; 71 | 72 | if (w.length < 3) 73 | return w; 74 | 75 | var re; 76 | var re2; 77 | var re3; 78 | var re4; 79 | 80 | firstch = w.substr(0,1); 81 | if (firstch == "y") 82 | w = firstch.toUpperCase() + w.substr(1); 83 | 84 | // Step 1a 85 | re = /^(.+?)(ss|i)es$/; 86 | re2 = /^(.+?)([^s])s$/; 87 | 88 | if (re.test(w)) 89 | w = w.replace(re,"$1$2"); 90 | else if (re2.test(w)) 91 | w = w.replace(re2,"$1$2"); 92 | 93 | // Step 1b 94 | re = /^(.+?)eed$/; 95 | re2 = /^(.+?)(ed|ing)$/; 96 | if (re.test(w)) { 97 | var fp = re.exec(w); 98 | re = new RegExp(mgr0); 99 | if (re.test(fp[1])) { 100 | re = /.$/; 101 | w = w.replace(re,""); 102 | } 103 | } 104 | else if (re2.test(w)) { 105 | var fp = re2.exec(w); 106 | stem = fp[1]; 107 | re2 = new RegExp(s_v); 108 | if (re2.test(stem)) { 109 | w = stem; 110 | re2 = /(at|bl|iz)$/; 111 | re3 = new RegExp("([^aeiouylsz])\\1$"); 112 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 113 | if (re2.test(w)) 114 | w = w + "e"; 115 | else if (re3.test(w)) { 116 | re = /.$/; 117 | w = w.replace(re,""); 118 | } 119 | else if (re4.test(w)) 120 | w = w + "e"; 121 | } 122 | } 123 | 124 | // Step 1c 125 | re = /^(.+?)y$/; 126 | if (re.test(w)) { 127 | var fp = re.exec(w); 128 | stem = fp[1]; 129 | re = new RegExp(s_v); 130 | if (re.test(stem)) 131 | w = stem + "i"; 132 | } 133 | 134 | // Step 2 135 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 136 | if (re.test(w)) { 137 | var fp = re.exec(w); 138 | stem = fp[1]; 139 | suffix = fp[2]; 140 | re = new RegExp(mgr0); 141 | if (re.test(stem)) 142 | w = stem + step2list[suffix]; 143 | } 144 | 145 | // Step 3 146 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 147 | if (re.test(w)) { 148 | var fp = re.exec(w); 149 | stem = fp[1]; 150 | suffix = fp[2]; 151 | re = new RegExp(mgr0); 152 | if (re.test(stem)) 153 | w = stem + step3list[suffix]; 154 | } 155 | 156 | // Step 4 157 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 158 | re2 = /^(.+?)(s|t)(ion)$/; 159 | if (re.test(w)) { 160 | var fp = re.exec(w); 161 | stem = fp[1]; 162 | re = new RegExp(mgr1); 163 | if (re.test(stem)) 164 | w = stem; 165 | } 166 | else if (re2.test(w)) { 167 | var fp = re2.exec(w); 168 | stem = fp[1] + fp[2]; 169 | re2 = new RegExp(mgr1); 170 | if (re2.test(stem)) 171 | w = stem; 172 | } 173 | 174 | // Step 5 175 | re = /^(.+?)e$/; 176 | if (re.test(w)) { 177 | var fp = re.exec(w); 178 | stem = fp[1]; 179 | re = new RegExp(mgr1); 180 | re2 = new RegExp(meq1); 181 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 182 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 183 | w = stem; 184 | } 185 | re = /ll$/; 186 | re2 = new RegExp(mgr1); 187 | if (re.test(w) && re2.test(w)) { 188 | re = /.$/; 189 | w = w.replace(re,""); 190 | } 191 | 192 | // and turn initial Y back to y 193 | if (firstch == "y") 194 | w = firstch.toLowerCase() + w.substr(1); 195 | return w; 196 | } 197 | } 198 | 199 | 200 | 201 | 202 | 203 | var splitChars = (function() { 204 | var result = {}; 205 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, 206 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, 207 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, 208 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, 209 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, 210 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, 211 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, 212 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, 213 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, 214 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; 215 | var i, j, start, end; 216 | for (i = 0; i < singles.length; i++) { 217 | result[singles[i]] = true; 218 | } 219 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], 220 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], 221 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], 222 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], 223 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], 224 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], 225 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], 226 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], 227 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], 228 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], 229 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], 230 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], 231 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], 232 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], 233 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], 234 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], 235 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], 236 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], 237 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], 238 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], 239 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], 240 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], 241 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], 242 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], 243 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], 244 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], 245 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], 246 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], 247 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], 248 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], 249 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], 250 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], 251 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], 252 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], 253 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], 254 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], 255 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], 256 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], 257 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], 258 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], 259 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], 260 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], 261 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], 262 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], 263 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], 264 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], 265 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], 266 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], 267 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; 268 | for (i = 0; i < ranges.length; i++) { 269 | start = ranges[i][0]; 270 | end = ranges[i][1]; 271 | for (j = start; j <= end; j++) { 272 | result[j] = true; 273 | } 274 | } 275 | return result; 276 | })(); 277 | 278 | function splitQuery(query) { 279 | var result = []; 280 | var start = -1; 281 | for (var i = 0; i < query.length; i++) { 282 | if (splitChars[query.charCodeAt(i)]) { 283 | if (start !== -1) { 284 | result.push(query.slice(start, i)); 285 | start = -1; 286 | } 287 | } else if (start === -1) { 288 | start = i; 289 | } 290 | } 291 | if (start !== -1) { 292 | result.push(query.slice(start)); 293 | } 294 | return result; 295 | } 296 | 297 | 298 | -------------------------------------------------------------------------------- /docs/_build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Index — pychi 0.0.1 documentation 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 45 | 46 |
50 | 51 |
52 |
53 |
54 |
    55 |
  • »
  • 56 |
  • Index
  • 57 |
  • 58 |
  • 59 |
60 |
61 |
62 |
63 |
64 | 65 | 66 |

Index

67 | 68 |
69 | A 70 | | C 71 | | D 72 | | G 73 | | K 74 | | L 75 | | M 76 | | N 77 | | P 78 | | R 79 | | S 80 | | W 81 | 82 |
83 |

A

84 | 85 | 89 | 93 |
94 | 95 |

C

96 | 97 | 105 | 115 |
116 | 117 |

D

118 | 119 | 123 |
124 | 125 |

G

126 | 127 | 131 |
132 | 133 |

K

134 | 135 | 139 |
140 | 141 |

L

142 | 143 | 147 |
148 | 149 |

M

150 | 151 | 155 |
156 | 157 |

N

158 | 159 | 181 | 195 |
196 | 197 |

P

198 | 199 | 207 | 217 |
218 | 219 |

R

220 | 221 | 225 |
226 | 227 |

S

228 | 229 | 241 | 255 |
256 | 257 |

W

258 | 259 | 263 |
264 | 265 | 266 | 267 |
268 |
269 |
270 | 271 |
272 | 273 |
274 |

© Copyright 2023, Thibault Voumard.

275 |
276 | 277 | Built with Sphinx using a 278 | theme 279 | provided by Read the Docs. 280 | 281 | 282 |
283 |
284 |
285 |
286 |
287 | 292 | 293 | 294 | -------------------------------------------------------------------------------- /src/pychi/solvers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Feb 18 17:54:20 2022 4 | 5 | @author: voumardt 6 | """ 7 | import matplotlib.pyplot as plt 8 | import numba 9 | import numpy as np 10 | from scipy.constants import c 11 | import time as timing 12 | eps_0 = 8.8541878128e-12 13 | 14 | 15 | class Solver(): 16 | def __init__(self, model, z_pts=500, local_error=0.00001, adaptive_factor=1.1, 17 | max_dz=None, method=None, breakpoints=[]): 18 | """ 19 | Solver class. Provides a stepper which performs integration of the PDE 20 | as well as error control and results saving. 21 | 22 | Parameters 23 | ---------- 24 | model : Model object 25 | Physical model of the problem to be integrated. 26 | z_pts : int, optional 27 | Number of results to keep along the propagation axis. The default is 500. 28 | local_error : float, optional 29 | Tolerated local error. The default is 0.00001. 30 | adaptive_factor : float, optional 31 | Adaptive factor for the step size control. Bigger values lead to 32 | more aggressive step size control. The default is 1.1. 33 | max_dz : float, optional 34 | Maximum step size allowed. Particularly useful when simulating 35 | quasi-phase matched structures. The default is None. 36 | method: string 37 | Method used for integration. Can be RK4IP, ERK4IP or DP5IP. 38 | Default is DP5IP. 39 | breakpoints: array 40 | This array contains z coordinates where the solver will be forced 41 | to compute a result. Useful for poled structures, to avoid having 42 | a step larger than the poling. The default is an empty array. 43 | """ 44 | self.model = model 45 | self.z_pts = z_pts 46 | self.local_error = local_error 47 | self.adaptive_factor = adaptive_factor 48 | self.max_dz = max_dz 49 | self.z_save = np.linspace(0, self.model.waveguide.length, self.z_pts) 50 | self.method_name = self._set_method_name(method) 51 | self.breakpoints = breakpoints 52 | self.stepsize_save = [] 53 | self.power_prefactor = eps_0*c/2/self.model.waveguide.t_pts*self.model.waveguide.delta_t 54 | 55 | def _set_method_name(self, method): 56 | """ 57 | Helper function to choose an appropriate solver. If a method is not 58 | provided by the user, it will look into the model used to see if 59 | there is a recommended solver. Otherwise, defaults to the model that 60 | should be mostly used, i.e. DP5IP. 61 | 62 | Parameters 63 | ---------- 64 | method : string 65 | Name of the solver. 66 | 67 | Returns 68 | ------- 69 | string 70 | Name of the solver. 71 | """ 72 | if method is None: 73 | if hasattr(self.model, '_recommended_solver'): 74 | return self.model._recommended_solver 75 | else: 76 | return 'DP5IP' 77 | else: 78 | return method 79 | 80 | def _compute_error(self, field_1, field_2): 81 | """ 82 | Error estimation for adaptive step size 83 | 84 | Parameters 85 | ---------- 86 | field_1 : array 87 | Reference field. 88 | field_2 : array 89 | Test field. 90 | 91 | Returns 92 | ------- 93 | float 94 | Error estimate between the two fields. 95 | """ 96 | return numbanorm(field_1 - field_2)/numbanorm(field_1) 97 | 98 | def _dormand_prince_step(self, field, dz): 99 | """ 100 | Dormand Prince order 5(4) adaptive scheme in the interaction picture. This 101 | new stepper uses the interaction picture in an embedded scheme of order 5. 102 | Tests have shown it to be up to four times faster than RK4IP. 103 | 104 | Parameters 105 | ---------- 106 | field : array 107 | Current field. 108 | dz : float 109 | Current step size. 110 | 111 | Returns 112 | ------- 113 | array 114 | New field estimate. 115 | 116 | float 117 | Error estimate. 118 | """ 119 | if self._k_7 is None: 120 | k_1 = dz*self.model.dispersion_step(self.model.nonlinear_term(field), dz) 121 | else: 122 | k_1 = self.model.dispersion_step(self._k_7, dz) 123 | a_int = self.model.dispersion_step(field, dz) 124 | k_2 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(a_int + k_1/5, -4*dz/5)), 4*dz/5) 125 | k_3 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(a_int + 3*k_1/40 + 9*k_2/40, -7*dz/10)), 7*dz/10) 126 | k_4 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(a_int + 44*k_1/45 - 56*k_2/15 + 32*k_3/9, -dz/5)), dz/5) 127 | k_5 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(a_int + 19372*k_1/6561 - 25360*k_2/2187 + 64448*k_3/6561 - 212*k_4/729, -dz/9)), dz/9) 128 | k_6 = dz*self.model.nonlinear_term(a_int + 9017*k_1/3168 - 355*k_2/33 + 46732*k_3/5247 + 49*k_4/176 - 5103*k_5/18656) 129 | sol_5 = a_int + 35*k_1/384 + 500*k_3/1113 + 125*k_4/192 - 2187*k_5/6784 + 11*k_6/84 130 | self._k_7 = dz*self.model.nonlinear_term(sol_5) 131 | sol_4 = a_int + 5179*k_1/57600 + 7571*k_3/16695 + 393*k_4/640 - 92097*k_5/339200 + 187*k_6/2100 + self._k_7/40 132 | error = self._compute_error(sol_5, sol_4) 133 | return sol_5, error 134 | 135 | def _rk546m(self, field, dz): 136 | """ 137 | Some other Dormand-Prince method that has one less step but does not 138 | leverage the interaction picture and does not have the FSAL property. 139 | Usually worse than the other dormand-prince method. 140 | References: 141 | DOI: 10.1016/0771-050X(80)90013-3 142 | 143 | Parameters 144 | ---------- 145 | field : array 146 | Current field. 147 | dz : float 148 | Current step size. 149 | 150 | Returns 151 | ------- 152 | array 153 | New field estimate. 154 | 155 | float 156 | Error estimate. 157 | """ 158 | k_1 = dz*self.model.nonlinear_term(field) 159 | k_2 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(field + k_1/5, dz/5)), -dz/5) 160 | k_3 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(field + 3*k_1/40 + 9*k_2/40, 3*dz/10)), -3*dz/10) 161 | k_4 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(field + 3*k_1/10 - 9*k_2/10 + 6*k_3/5, 3*dz/5)), -3*dz/5) 162 | k_5 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(field + 226*k_1/729 - 25*k_2/27 + 880*k_3/729 + 55*k_4/729, 2*dz/3)), -2*dz/3) 163 | k_6 = dz*self.model.dispersion_step(self.model.nonlinear_term(self.model.dispersion_step(field - 181*k_1/270 + 5*k_2/2 - 266*k_3/297 - 91*k_4/27 + 189*k_5/55, dz)), -dz) 164 | sol_5 = self.model.dispersion_step(field + 19*k_1/216 + 1000*k_3/2079 - 125*k_4/216 + 81*k_5/88 + 5*k_6/56, dz) 165 | sol_4 = self.model.dispersion_step(field + 31*k_1/540 + 190*k_3/297 - 145*k_4/108 + 351*k_5/220 + k_6/20, dz) 166 | error = self._compute_error(sol_5, sol_4) 167 | return sol_5, error 168 | 169 | def _adams_bashforth54_step(self, field, dz): 170 | """To be implemented""" 171 | pass 172 | 173 | def _rk4ip_single_step(self, field, dz): 174 | """ 175 | Runge-Kutta order 4 step in the interaction picture (RK4IP) 176 | 177 | Parameters 178 | ---------- 179 | field : array 180 | Current field. 181 | dz : float 182 | Current step size. 183 | 184 | Returns 185 | ------- 186 | array 187 | New field estimate. 188 | """ 189 | dispersion_op = numbaexp(-1j*self.model.waveguide.k*dz/2) 190 | a_int = dispersion_op*field 191 | k_1 = dz*dispersion_op*self.model.nonlinear_term(field) 192 | k_2 = dz*self.model.nonlinear_term(a_int + k_1/2) 193 | k_3 = dz*self.model.nonlinear_term(a_int + k_2/2) 194 | k_4 = dz*self.model.nonlinear_term(dispersion_op*(a_int + k_3)) 195 | return dispersion_op*(a_int + k_1/6 + k_2/3 + k_3/3) + k_4/6 196 | 197 | def _rk4ip_step(self, field, dz): 198 | """ 199 | Runge-Kutta order 4 adaptive scheme in the interaction picture (RK4IP) 200 | with step doubling and combining. Provided for comparison but slower 201 | than the dormand-prince method. 202 | References: 203 | DOI: 10.1109/JLT.2007.909373 204 | DOI: 10.1109/JLT.2009.2021538 205 | 206 | Parameters 207 | ---------- 208 | field : array 209 | Current field. 210 | dz : float 211 | Current step size. 212 | 213 | Returns 214 | ------- 215 | array 216 | New field estimate. 217 | 218 | float 219 | Error estimate. 220 | """ 221 | sol_single = self._rk4ip_single_step(field, dz) 222 | sol_double = self._rk4ip_single_step(field, dz/2) 223 | sol_double = self._rk4ip_single_step(sol_double, dz/2) 224 | error = self._compute_error(sol_double, sol_single) 225 | sol_5 = (sol_double*16 - sol_single)/15 226 | return sol_5, error 227 | 228 | def _erk4ip_step(self, field, dz): 229 | """ 230 | Embedded Runge-Kutta order 4(3) adaptive scheme in the interaction 231 | picture (ERK4IP). Can be faster than DP5IP if accuracy is irrelevant, 232 | for example in SPM only cases. Otherwise, DP5IP performs better. 233 | References: 234 | DOI: 10.1016/j.cpc.2012.12.020 235 | 236 | Parameters 237 | ---------- 238 | field : array 239 | Current field. 240 | dz : float 241 | Current step size. 242 | 243 | Returns 244 | ------- 245 | array 246 | New field estimate. 247 | 248 | float 249 | Error estimate. 250 | """ 251 | dispersion_op = numbaexp(-1j*self.model.waveguide.k*dz/2) 252 | a_int = dispersion_op*field 253 | if self._k_5 is None: 254 | k_1 = dz*dispersion_op*self.model.nonlinear_term(field) 255 | else: 256 | k_1 = dispersion_op*self._k_5 257 | k_2 = dz*self.model.nonlinear_term(a_int + k_1/2) 258 | k_3 = dz*self.model.nonlinear_term(a_int + k_2/2) 259 | k_4 = dz*self.model.nonlinear_term(dispersion_op*(a_int + k_3)) 260 | beta = dispersion_op*(a_int + k_1/6 + k_2/3 + k_3/3) 261 | sol_4 = beta + k_4/6 262 | self._k_5 = dz*self.model.nonlinear_term(sol_4) 263 | sol_3 = beta + k_4/15 + self._k_5/10 264 | error = self._compute_error(sol_4, sol_3) 265 | return sol_4, error 266 | 267 | def _integrate_to_z(self, z): 268 | """ 269 | Integrate to z with adaptive step size. 270 | 271 | Parameters 272 | ------- 273 | z : float 274 | Target propagation length. 275 | """ 276 | while self.stock_z < z: 277 | # Actuate position inside the waveguide 278 | self.model.waveguide.z = self.stock_z 279 | 280 | # Check for forcing breakpoints 281 | if (len(self.breakpoints) != 0 and (self.stock_z + self.dz > self.breakpoints[0])): 282 | 283 | # Step to breakpoint 284 | dz = self.breakpoints[0] - self.stock_z + 1e-20 285 | vec_eval, _ = self.step(self.stock_vec, dz) 286 | 287 | # Remove breakpoint 288 | self.breakpoints = self.breakpoints[1:] 289 | 290 | # Update z pos and field 291 | self.stock_z += dz 292 | self.stock_vec = vec_eval 293 | self.stepsize_save = np.append(self.stepsize_save, dz) 294 | 295 | else: 296 | 297 | # Step of dz 298 | vec_eval, error = self.step(self.stock_vec, self.dz) 299 | 300 | # Error control 301 | if error >= 2*self.local_error: 302 | self.dz /= 2 303 | print('Discarded') 304 | if self.method_name == 'DP5IP': 305 | self._k_7 = None 306 | if self.method_name == 'ERK4IP': 307 | self._k_5 = None 308 | continue 309 | elif self.local_error <= error < 2*self.local_error: 310 | self.stock_z += self.dz 311 | self.stepsize_save = np.append(self.stepsize_save, self.dz) 312 | self.dz /= self.adaptive_factor 313 | elif 0.5*self.local_error <= error < self.local_error: 314 | self.stock_z += self.dz 315 | self.stepsize_save = np.append(self.stepsize_save, self.dz) 316 | else: 317 | self.stock_z += self.dz 318 | self.stepsize_save = np.append(self.stepsize_save, self.dz) 319 | if self.max_dz is None or self.dz*self.adaptive_factor < self.max_dz: 320 | self.dz *= self.adaptive_factor 321 | self.stock_vec = vec_eval 322 | 323 | def solve(self): 324 | """ 325 | Integrate over waveguide length with adaptive step size 326 | """ 327 | # Initialization 328 | self.spectrum = np.zeros((self.z_pts, self.model.waveguide.t_pts), dtype='complex128') 329 | self.dz = np.mean(np.diff(self.z_save))*np.sqrt(np.sqrt(self.local_error)) 330 | self.stock_z = 0 331 | self.stock_vec = np.fft.fft(self.model.light.field_t_in) 332 | if self.method_name == 'DP5IP': 333 | self._k_7 = None 334 | self.step = self._dormand_prince_step 335 | elif self.method_name == 'ERK4IP': 336 | self._k_5 = None 337 | self.step = self._erk4ip_step 338 | elif self.method_name == 'RK4IP': 339 | self.step = self._rk4ip_step 340 | elif self.method_name == 'RK546M': 341 | self.step = self._rk546m 342 | timer = timing.perf_counter() 343 | 344 | # Total integration 345 | for i, z in enumerate(self.z_save): 346 | print('z: {}/{}'.format(i+1, self.z_pts)) 347 | 348 | # Integrate over dz 349 | self._integrate_to_z(z) 350 | 351 | # Save spectrum 352 | self.spectrum[i, :] = np.fft.fftshift(self.stock_vec)\ 353 | *numbaexp(1j*(self.model.waveguide.betas[0] + self.model.waveguide.betas[1]*self.model.waveguide.rel_omega)*self.stock_z)\ 354 | *np.sqrt(self.model.waveguide.eff_area*self.model.waveguide.n_eff*self.power_prefactor) 355 | 356 | # Save waveform 357 | print(f"{timing.perf_counter() - timer} seconds for integration.") 358 | self.waveform = np.fft.ifft(np.fft.ifftshift(self.spectrum, axes=1), axis=1) 359 | self.model.light._set_propagation(self.z_save, self.model.waveguide.freq, self.spectrum, self.waveform) 360 | 361 | def plot_stepsize(self): 362 | """ 363 | Plot the evolution of the stepsize against the position in the waveguide 364 | """ 365 | plt.figure() 366 | plt.plot(np.cumsum(self.stepsize_save), self.stepsize_save) 367 | plt.xlabel('Distance [m]') 368 | plt.ylabel('Step size [m]') 369 | 370 | 371 | """ 372 | Optimized functions 373 | """ 374 | ### Numba exponential 375 | @numba.njit([numba.complex128[:](numba.complex128[:]),numba.complex64[:](numba.complex64[:])]) 376 | def numbaexp(x): 377 | return np.exp(x) 378 | 379 | ### Numba norm 380 | @numba.njit([numba.float64(numba.complex128[:])]) 381 | def numbanorm(field): 382 | return np.linalg.norm(field) 383 | -------------------------------------------------------------------------------- /src/pychi/materials.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from inspect import signature 3 | from math import factorial 4 | import matplotlib.pyplot as plt 5 | import numpy as np 6 | from scipy.interpolate import interp1d 7 | from scipy.constants import c 8 | eps_0 = 8.8541878128e-12 9 | 10 | class Waveguide(): 11 | """ 12 | Waveguide class. Contains all material related information, i.e. the 13 | refractive index curve versus frequency, the Raman parameters, the 14 | nonlinear coefficients, the effective area and length. This object 15 | should be the first object instantiated, as the time/frequency axes of 16 | the simulation are derived here from the available refractive 17 | index data. 18 | 19 | Parameters 20 | ---------- 21 | frequency : array 22 | Frequency axis on which the effective refractive index is given. 23 | n_eff : float, vector, array or callable 24 | Effective refractive index of the material. 25 | chi_2 : float, vector, array or callable 26 | Order 2 material nonlinearity. 27 | chi_3 : float, vector, array or callable 28 | Order 3 material nonlinearity. 29 | effective_area : float 30 | Effective area at the pump wavelength. 31 | length : float 32 | Length of the material. 33 | raman_fraction : float 34 | Fractional contribution of the Raman effect to the Kerr effect. 35 | The default is 0.18. 36 | raman_tau_1 : float 37 | Raman effect primary time scale. The default is 0.0122e-12. 38 | raman_tau_2 : float 39 | Raman effect secondary time scale. The default is 0.032e-12. 40 | t_pts : float, optional 41 | Number of points in the time and frequency axes, will be rounded 42 | to nearest higher power of 2. The default is 2**14. 43 | """ 44 | def __init__(self, frequency, n_eff, chi_2, chi_3, 45 | effective_area, length, raman_fraction=0.18, 46 | raman_tau_1=0.0122e-12, raman_tau_2=0.032e-12, 47 | t_pts=2**14): 48 | self.z = 0 49 | self.t_pts = int(2**np.ceil(np.log2(t_pts))) 50 | self.length = length 51 | self.data_freq = frequency 52 | self.center_freq, self.freq = self._compute_frequency_axis() 53 | self.center_omega, self.omega, self.rel_omega = self._compute_omega_axis() 54 | self.time, self.delta_t = self._compute_time_axis() 55 | 56 | self.n_eff = n_eff 57 | 58 | self.chi_2 = chi_2 59 | self.chi_3 = chi_3 60 | self.eff_area = effective_area 61 | 62 | # Standard Raman response for fibers 63 | self.raman_fraction = raman_fraction 64 | self.raman_tau_1 = raman_tau_1 65 | self.raman_tau_2 = raman_tau_2 66 | self.raman_effect = self._compute_raman_effect() 67 | 68 | @property 69 | def n_eff(self): 70 | """Get the effective refractive index at position z.""" 71 | return self._n_eff(self.z) 72 | 73 | @n_eff.setter 74 | def n_eff(self, n_eff): 75 | """ 76 | Set the effective refractive index. Change any float, vector or 77 | array provided by the user into a z-callable function. A version 78 | interpolated in frequency is also kept for other operations. 79 | Beta coefficients are computed at this stage - they are 80 | solely used for plotting purpose. 81 | """ 82 | self._n_eff = self._make_callable(n_eff) 83 | self.n_eff_inter = self._interpolate_n_eff() 84 | self.betas = self.compute_betas() 85 | 86 | @property 87 | def chi_2(self): 88 | """Get the quadratic nonlinear coefficient at position z.""" 89 | return self._chi_2(self.z)*np.sqrt(self._eff_area(0)/self._eff_area(self.z)) 90 | 91 | @chi_2.setter 92 | def chi_2(self, chi_2): 93 | """ 94 | Set the quadractic nonlinear coefficient. Change any float, 95 | vector or array provided by the user into a z-callable 96 | function. 97 | """ 98 | self._chi_2 = self._make_callable(chi_2) 99 | 100 | @property 101 | def chi_3(self): 102 | """Get the cubic nonlinear coefficient at position z.""" 103 | return self._chi_3(self.z)*self._eff_area(0)/self._eff_area(self.z) 104 | 105 | @chi_3.setter 106 | def chi_3(self, chi_3): 107 | """ 108 | Set the quadractic nonlinear coefficient. Change any float, 109 | vector or array provided by the user into a z-callable 110 | function. 111 | """ 112 | self._chi_3 = self._make_callable(chi_3) 113 | 114 | @property 115 | def eff_area(self): 116 | """Get the effective area at position z.""" 117 | return self._eff_area(self.z) 118 | 119 | @eff_area.setter 120 | def eff_area(self, eff_area): 121 | """ 122 | Set the effective area. Change any float, 123 | vector or array provided by the user into a z-callable 124 | function. 125 | """ 126 | self._eff_area = self._make_callable(eff_area) 127 | 128 | @property 129 | def k(self): 130 | """Get the wavevectors at position z.""" 131 | return np.fft.fftshift(self.n_eff*self.omega/c) 132 | 133 | @property 134 | def rhs_prefactor(self): 135 | """Get the GNLSE right-hand-side prefactor at position z.""" 136 | return -1j*np.fft.fftshift(self.omega/(2*self.n_eff*c)) 137 | 138 | def _make_callable(self, var): 139 | """ 140 | Transform an input vector, array, float or callable into a z-callable, 141 | allowing the user to provide z-dependant quantities. 142 | 143 | Note that a provided callable should have as arguments exactly at most 144 | 'z' and 'freq', e.g. var(z, freq), var(freq, z), var(z) or var(freq). 145 | A bit wonky, but couldn't figure out a better way to do that. Another 146 | alternative would be to implement derived classes with overwritten 147 | properties, which is not very elegant either. Actually found out that 148 | singledispatch from functools is probably the way to go here. 149 | 150 | Note that a provided array should have first dimension coinciding with 151 | the frequency axis given along the refractive index data. The second 152 | dimension is assumed to be evenly distributed along the whole length 153 | of the waveguide. 154 | 155 | Note that if a vector is provided it will be assumed that it describes 156 | a z dependent quantity, unless it has the same dimension as the 157 | frequency axis. Wavelength dependent only quantities can also be 158 | provided through callables. 159 | 160 | Parameters 161 | ---------- 162 | var : float, vector, array or callable 163 | Some simulation parameter. 164 | 165 | Returns 166 | ------- 167 | function 168 | A z-callable version of the provided variable. 169 | """ 170 | # Case when the argument is callable 171 | if callable(var): 172 | return self._parse_callable(var) 173 | # Case when the argument is an array or a vector 174 | elif hasattr(var, '__len__'): 175 | return self._parse_array(var) 176 | # Otherwise (float) 177 | else: 178 | return lambda _: var 179 | 180 | def _parse_array(self, var): 181 | """ 182 | Parse the correct arguments for a callable parameter. 183 | 184 | Parameters 185 | ---------- 186 | var : array 187 | A one or two dimensional array representing z and/or frequency 188 | dependence of a parameter. 189 | 190 | Returns 191 | ------- 192 | function 193 | A z-callable function. 194 | """ 195 | # Case of an array 196 | if len(np.shape(var)) == 2: 197 | arr_inter = interp1d(self.data_freq, var.T, kind='cubic', 198 | bounds_error=False, fill_value='extrapolate') 199 | arr = arr_inter(self.freq).T 200 | z = np.linspace(0, self.length, np.shape(arr)[-1]) 201 | arr_inter = interp1d(z, arr, kind='cubic', bounds_error=False, 202 | fill_value='extrapolate') 203 | return arr_inter 204 | # Case of a vector 205 | elif len(np.shape(var)) == 1: 206 | if len(var) == len(self.data_freq): 207 | arr_inter = interp1d(self.data_freq, var, kind='cubic', 208 | bounds_error=False, fill_value='extrapolate') 209 | arr = arr_inter(self.freq) 210 | return lambda _: arr 211 | else: 212 | z = np.linspace(0, self.length, len(var)) 213 | var_inter = interp1d(z, var, kind='cubic', bounds_error=False, 214 | fill_value='extrapolate') 215 | return var_inter 216 | else: 217 | raise ValueError 218 | 219 | def _parse_callable(self, var): 220 | """ 221 | Parse the correct arguments for a callable parameter. 222 | 223 | Parameters 224 | ---------- 225 | var : callable 226 | A z or frequency (or both) dependent callable. 227 | 228 | Returns 229 | ------- 230 | function 231 | A z-callable function. 232 | """ 233 | # Get funtion signature 234 | z_flag = False 235 | freq_flag = False 236 | order_flag = False 237 | args = signature(var).parameters 238 | for arg in args: 239 | if arg == 'z': 240 | z_flag = True 241 | if arg == 'freq': 242 | freq_flag = True 243 | if z_flag: 244 | order_flag = True 245 | 246 | # Reorder arguments and evaluate the frequency axis 247 | if z_flag: 248 | if freq_flag: 249 | if order_flag: 250 | return lambda _: var(_, self.freq) 251 | else: 252 | return lambda _: var(self.freq, _) 253 | else: 254 | return var 255 | else: 256 | if freq_flag: 257 | return lambda _: var(self.freq) 258 | else: 259 | return lambda _: var 260 | 261 | def _compute_frequency_axis(self): 262 | """ 263 | Define a frequency axis covering exactly the data range available. 264 | """ 265 | min_freq = np.amin(self.data_freq) 266 | max_freq = np.amax(self.data_freq) 267 | center_freq = min_freq/2 + max_freq/2 268 | freq = np.linspace(min_freq, max_freq, self.t_pts) 269 | return center_freq, freq 270 | 271 | def _compute_omega_axis(self): 272 | """ 273 | Compute the angular frequency axis associated to the frequency axis 274 | """ 275 | center_omega = 2*np.pi*self.center_freq 276 | omega = 2*np.pi*self.freq 277 | rel_omega = omega - center_omega 278 | return center_omega, omega, rel_omega 279 | 280 | def _compute_time_axis(self): 281 | """ 282 | Compute the time axis associated to the frequency axis 283 | """ 284 | time = np.fft.fftshift(np.fft.fftfreq(self.t_pts, np.mean(np.diff(self.freq)))) 285 | delta_t = np.mean(np.diff(time)) 286 | return time, delta_t 287 | 288 | def _interpolate_n_eff(self): 289 | """ 290 | Interpolate the refractive index data on the simulation frequency axis 291 | """ 292 | n_eff_inter = interp1d(self.freq, self.n_eff, kind='cubic', 293 | bounds_error=False, fill_value='extrapolate') 294 | return n_eff_inter 295 | 296 | def _compute_raman_effect(self): 297 | """ 298 | Compute the Raman term for the simulation frequency axis 299 | """ 300 | raman_time = (self.raman_tau_1**2 + self.raman_tau_2**2) 301 | raman_time = raman_time/self.raman_tau_1/self.raman_tau_2**2 302 | raman_time *= np.exp(-np.abs(self.time)/self.raman_tau_2)*np.sin(self.time/self.raman_tau_1) 303 | raman_time[self.time < 0] = 0 304 | raman_effect = np.conjugate(self.t_pts*np.fft.ifft(np.fft.fftshift(raman_time))) 305 | raman_effect *= self.delta_t*self.raman_fraction 306 | return raman_effect 307 | 308 | def compute_betas(self, wavelength=None, order=6): 309 | """ 310 | Compute beta coefficients at a given wavelength and order. 311 | 312 | Parameters 313 | ---------- 314 | wavelength : float, optional 315 | Wavelength at which the beta coefficients are computed. The default is 316 | the center of the simulation axis. 317 | order : int, optional 318 | Highest order of the beta coefficients to be computed. The default is 6. 319 | 320 | Returns 321 | ------- 322 | beta : array 323 | Beta coefficients of the material at the given wavelength. 324 | """ 325 | if wavelength is None: 326 | center_omega = self.center_omega 327 | else: 328 | center_omega = 2*np.pi*c/wavelength 329 | 330 | om = 2*np.pi*self.freq 331 | dk = np.real(self.n_eff)*om/c 332 | b_inter = interp1d(om, dk, kind='cubic') 333 | beta = np.zeros(order+1) 334 | beta[0] = b_inter(center_omega) 335 | for i in np.arange(order): 336 | dk = np.diff(dk) 337 | dom = np.diff(om) 338 | om = om[:-1] + dom/2 339 | der = dk/dom 340 | der_inter = interp1d(om, der, kind='cubic') 341 | beta[i+1] = der_inter(center_omega) 342 | dk = der 343 | return beta 344 | 345 | def set_betas(self, betas, wavelength): 346 | """ 347 | Convenience only. Allow the use to provide the beta coefficients 348 | instead of n_eff. Should be avoided. 349 | """ 350 | rel_om = self.omega - 2*np.pi*c/wavelength 351 | n = np.ones(self.t_pts)*betas[0] 352 | factorial = 1 353 | for i, b in enumerate(betas[1:]): 354 | factorial *= (i+1) 355 | n += b*rel_om**(i+1)/factorial 356 | n *= c/self.omega 357 | self.n_eff = n 358 | 359 | def set_n2(self, n2, wavelength=None): 360 | """ 361 | Convenience only. Allow the user to give the nonlinear index instead 362 | of chi3. Overwrite the initialized chi3 value accordingly. 363 | 364 | Parameters 365 | ---------- 366 | n2 : float 367 | Nonlinear index. 368 | """ 369 | if wavelength is None: 370 | freq = self.center_freq 371 | else: 372 | freq = c/wavelength 373 | self.chi_3 = 4*n2*eps_0*c*self.n_eff_inter(freq)**2/3 374 | 375 | def set_gamma(self, gamma, wavelength=None): 376 | """ 377 | Convenience only. Allow the user to give the nonlinear coefficient instead 378 | of chi3. Overwrite the initialized chi3 value accordingly. 379 | 380 | Parameters 381 | ---------- 382 | gamma : float 383 | Nonlinear coefficient. 384 | """ 385 | if wavelength is None: 386 | freq = self.center_freq 387 | else: 388 | freq = c/wavelength 389 | self.chi_3 = 2*self.n_eff_inter(freq)**2*c**2*eps_0*gamma*self.eff_area/3/np.pi/freq 390 | 391 | def plot_refractive_index(self, savename=None): 392 | """ 393 | Plot refractive index 394 | """ 395 | k = self.n_eff*2*np.pi*self.freq/c 396 | inverse_group_velocity = np.gradient(k, 2*np.pi*self.freq) 397 | group_velocity_dispersion = np.gradient(inverse_group_velocity, 2*np.pi*self.freq) 398 | 399 | fig, axs = plt.subplots(3) 400 | axs[0].plot(self.freq, self.n_eff) 401 | axs[0].set_ylabel('Refractive index') 402 | axs[1].plot(self.freq, inverse_group_velocity) 403 | axs[1].set_ylabel('IGV [s/m]') 404 | axs[2].plot(self.freq, group_velocity_dispersion) 405 | axs[2].set_ylabel('GVD [s^2/m]') 406 | axs[2].set_xlabel('Frequency [Hz]') 407 | fig.tight_layout() 408 | -------------------------------------------------------------------------------- /docs/_build/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | word-wrap: break-word; 56 | overflow-wrap : break-word; 57 | } 58 | 59 | div.sphinxsidebar ul { 60 | list-style: none; 61 | } 62 | 63 | div.sphinxsidebar ul ul, 64 | div.sphinxsidebar ul.want-points { 65 | margin-left: 20px; 66 | list-style: square; 67 | } 68 | 69 | div.sphinxsidebar ul ul { 70 | margin-top: 0; 71 | margin-bottom: 0; 72 | } 73 | 74 | div.sphinxsidebar form { 75 | margin-top: 10px; 76 | } 77 | 78 | div.sphinxsidebar input { 79 | border: 1px solid #98dbcc; 80 | font-family: sans-serif; 81 | font-size: 1em; 82 | } 83 | 84 | div.sphinxsidebar #searchbox form.search { 85 | overflow: hidden; 86 | } 87 | 88 | div.sphinxsidebar #searchbox input[type="text"] { 89 | float: left; 90 | width: 80%; 91 | padding: 0.25em; 92 | box-sizing: border-box; 93 | } 94 | 95 | div.sphinxsidebar #searchbox input[type="submit"] { 96 | float: left; 97 | width: 20%; 98 | border-left: none; 99 | padding: 0.25em; 100 | box-sizing: border-box; 101 | } 102 | 103 | 104 | img { 105 | border: 0; 106 | max-width: 100%; 107 | } 108 | 109 | /* -- search page ----------------------------------------------------------- */ 110 | 111 | ul.search { 112 | margin: 10px 0 0 20px; 113 | padding: 0; 114 | } 115 | 116 | ul.search li { 117 | padding: 5px 0 5px 20px; 118 | background-image: url(file.png); 119 | background-repeat: no-repeat; 120 | background-position: 0 7px; 121 | } 122 | 123 | ul.search li a { 124 | font-weight: bold; 125 | } 126 | 127 | ul.search li div.context { 128 | color: #888; 129 | margin: 2px 0 0 30px; 130 | text-align: left; 131 | } 132 | 133 | ul.keywordmatches li.goodmatch a { 134 | font-weight: bold; 135 | } 136 | 137 | /* -- index page ------------------------------------------------------------ */ 138 | 139 | table.contentstable { 140 | width: 90%; 141 | margin-left: auto; 142 | margin-right: auto; 143 | } 144 | 145 | table.contentstable p.biglink { 146 | line-height: 150%; 147 | } 148 | 149 | a.biglink { 150 | font-size: 1.3em; 151 | } 152 | 153 | span.linkdescr { 154 | font-style: italic; 155 | padding-top: 5px; 156 | font-size: 90%; 157 | } 158 | 159 | /* -- general index --------------------------------------------------------- */ 160 | 161 | table.indextable { 162 | width: 100%; 163 | } 164 | 165 | table.indextable td { 166 | text-align: left; 167 | vertical-align: top; 168 | } 169 | 170 | table.indextable ul { 171 | margin-top: 0; 172 | margin-bottom: 0; 173 | list-style-type: none; 174 | } 175 | 176 | table.indextable > tbody > tr > td > ul { 177 | padding-left: 0em; 178 | } 179 | 180 | table.indextable tr.pcap { 181 | height: 10px; 182 | } 183 | 184 | table.indextable tr.cap { 185 | margin-top: 10px; 186 | background-color: #f2f2f2; 187 | } 188 | 189 | img.toggler { 190 | margin-right: 3px; 191 | margin-top: 3px; 192 | cursor: pointer; 193 | } 194 | 195 | div.modindex-jumpbox { 196 | border-top: 1px solid #ddd; 197 | border-bottom: 1px solid #ddd; 198 | margin: 1em 0 1em 0; 199 | padding: 0.4em; 200 | } 201 | 202 | div.genindex-jumpbox { 203 | border-top: 1px solid #ddd; 204 | border-bottom: 1px solid #ddd; 205 | margin: 1em 0 1em 0; 206 | padding: 0.4em; 207 | } 208 | 209 | /* -- domain module index --------------------------------------------------- */ 210 | 211 | table.modindextable td { 212 | padding: 2px; 213 | border-collapse: collapse; 214 | } 215 | 216 | /* -- general body styles --------------------------------------------------- */ 217 | 218 | div.body { 219 | min-width: 450px; 220 | max-width: 800px; 221 | } 222 | 223 | div.body p, div.body dd, div.body li, div.body blockquote { 224 | -moz-hyphens: auto; 225 | -ms-hyphens: auto; 226 | -webkit-hyphens: auto; 227 | hyphens: auto; 228 | } 229 | 230 | a.headerlink { 231 | visibility: hidden; 232 | } 233 | 234 | a.brackets:before, 235 | span.brackets > a:before{ 236 | content: "["; 237 | } 238 | 239 | a.brackets:after, 240 | span.brackets > a:after { 241 | content: "]"; 242 | } 243 | 244 | h1:hover > a.headerlink, 245 | h2:hover > a.headerlink, 246 | h3:hover > a.headerlink, 247 | h4:hover > a.headerlink, 248 | h5:hover > a.headerlink, 249 | h6:hover > a.headerlink, 250 | dt:hover > a.headerlink, 251 | caption:hover > a.headerlink, 252 | p.caption:hover > a.headerlink, 253 | div.code-block-caption:hover > a.headerlink { 254 | visibility: visible; 255 | } 256 | 257 | div.body p.caption { 258 | text-align: inherit; 259 | } 260 | 261 | div.body td { 262 | text-align: left; 263 | } 264 | 265 | .first { 266 | margin-top: 0 !important; 267 | } 268 | 269 | p.rubric { 270 | margin-top: 30px; 271 | font-weight: bold; 272 | } 273 | 274 | img.align-left, .figure.align-left, object.align-left { 275 | clear: left; 276 | float: left; 277 | margin-right: 1em; 278 | } 279 | 280 | img.align-right, .figure.align-right, object.align-right { 281 | clear: right; 282 | float: right; 283 | margin-left: 1em; 284 | } 285 | 286 | img.align-center, .figure.align-center, object.align-center { 287 | display: block; 288 | margin-left: auto; 289 | margin-right: auto; 290 | } 291 | 292 | img.align-default, .figure.align-default { 293 | display: block; 294 | margin-left: auto; 295 | margin-right: auto; 296 | } 297 | 298 | .align-left { 299 | text-align: left; 300 | } 301 | 302 | .align-center { 303 | text-align: center; 304 | } 305 | 306 | .align-default { 307 | text-align: center; 308 | } 309 | 310 | .align-right { 311 | text-align: right; 312 | } 313 | 314 | /* -- sidebars -------------------------------------------------------------- */ 315 | 316 | div.sidebar { 317 | margin: 0 0 0.5em 1em; 318 | border: 1px solid #ddb; 319 | padding: 7px 7px 0 7px; 320 | background-color: #ffe; 321 | width: 40%; 322 | float: right; 323 | } 324 | 325 | p.sidebar-title { 326 | font-weight: bold; 327 | } 328 | 329 | /* -- topics ---------------------------------------------------------------- */ 330 | 331 | div.topic { 332 | border: 1px solid #ccc; 333 | padding: 7px 7px 0 7px; 334 | margin: 10px 0 10px 0; 335 | } 336 | 337 | p.topic-title { 338 | font-size: 1.1em; 339 | font-weight: bold; 340 | margin-top: 10px; 341 | } 342 | 343 | /* -- admonitions ----------------------------------------------------------- */ 344 | 345 | div.admonition { 346 | margin-top: 10px; 347 | margin-bottom: 10px; 348 | padding: 7px; 349 | } 350 | 351 | div.admonition dt { 352 | font-weight: bold; 353 | } 354 | 355 | div.admonition dl { 356 | margin-bottom: 0; 357 | } 358 | 359 | p.admonition-title { 360 | margin: 0px 10px 5px 0px; 361 | font-weight: bold; 362 | } 363 | 364 | div.body p.centered { 365 | text-align: center; 366 | margin-top: 25px; 367 | } 368 | 369 | /* -- tables ---------------------------------------------------------------- */ 370 | 371 | table.docutils { 372 | border: 0; 373 | border-collapse: collapse; 374 | } 375 | 376 | table.align-center { 377 | margin-left: auto; 378 | margin-right: auto; 379 | } 380 | 381 | table.align-default { 382 | margin-left: auto; 383 | margin-right: auto; 384 | } 385 | 386 | table caption span.caption-number { 387 | font-style: italic; 388 | } 389 | 390 | table caption span.caption-text { 391 | } 392 | 393 | table.docutils td, table.docutils th { 394 | padding: 1px 8px 1px 5px; 395 | border-top: 0; 396 | border-left: 0; 397 | border-right: 0; 398 | border-bottom: 1px solid #aaa; 399 | } 400 | 401 | table.footnote td, table.footnote th { 402 | border: 0 !important; 403 | } 404 | 405 | th { 406 | text-align: left; 407 | padding-right: 5px; 408 | } 409 | 410 | table.citation { 411 | border-left: solid 1px gray; 412 | margin-left: 1px; 413 | } 414 | 415 | table.citation td { 416 | border-bottom: none; 417 | } 418 | 419 | th > p:first-child, 420 | td > p:first-child { 421 | margin-top: 0px; 422 | } 423 | 424 | th > p:last-child, 425 | td > p:last-child { 426 | margin-bottom: 0px; 427 | } 428 | 429 | /* -- figures --------------------------------------------------------------- */ 430 | 431 | div.figure { 432 | margin: 0.5em; 433 | padding: 0.5em; 434 | } 435 | 436 | div.figure p.caption { 437 | padding: 0.3em; 438 | } 439 | 440 | div.figure p.caption span.caption-number { 441 | font-style: italic; 442 | } 443 | 444 | div.figure p.caption span.caption-text { 445 | } 446 | 447 | /* -- field list styles ----------------------------------------------------- */ 448 | 449 | table.field-list td, table.field-list th { 450 | border: 0 !important; 451 | } 452 | 453 | .field-list ul { 454 | margin: 0; 455 | padding-left: 1em; 456 | } 457 | 458 | .field-list p { 459 | margin: 0; 460 | } 461 | 462 | .field-name { 463 | -moz-hyphens: manual; 464 | -ms-hyphens: manual; 465 | -webkit-hyphens: manual; 466 | hyphens: manual; 467 | } 468 | 469 | /* -- hlist styles ---------------------------------------------------------- */ 470 | 471 | table.hlist td { 472 | vertical-align: top; 473 | } 474 | 475 | 476 | /* -- other body styles ----------------------------------------------------- */ 477 | 478 | ol.arabic { 479 | list-style: decimal; 480 | } 481 | 482 | ol.loweralpha { 483 | list-style: lower-alpha; 484 | } 485 | 486 | ol.upperalpha { 487 | list-style: upper-alpha; 488 | } 489 | 490 | ol.lowerroman { 491 | list-style: lower-roman; 492 | } 493 | 494 | ol.upperroman { 495 | list-style: upper-roman; 496 | } 497 | 498 | li > p:first-child { 499 | margin-top: 0px; 500 | } 501 | 502 | li > p:last-child { 503 | margin-bottom: 0px; 504 | } 505 | 506 | dl.footnote > dt, 507 | dl.citation > dt { 508 | float: left; 509 | } 510 | 511 | dl.footnote > dd, 512 | dl.citation > dd { 513 | margin-bottom: 0em; 514 | } 515 | 516 | dl.footnote > dd:after, 517 | dl.citation > dd:after { 518 | content: ""; 519 | clear: both; 520 | } 521 | 522 | dl.field-list { 523 | display: grid; 524 | grid-template-columns: fit-content(30%) auto; 525 | } 526 | 527 | dl.field-list > dt { 528 | font-weight: bold; 529 | word-break: break-word; 530 | padding-left: 0.5em; 531 | padding-right: 5px; 532 | } 533 | 534 | dl.field-list > dt:after { 535 | content: ":"; 536 | } 537 | 538 | dl.field-list > dd { 539 | padding-left: 0.5em; 540 | margin-top: 0em; 541 | margin-left: 0em; 542 | margin-bottom: 0em; 543 | } 544 | 545 | dl { 546 | margin-bottom: 15px; 547 | } 548 | 549 | dd > p:first-child { 550 | margin-top: 0px; 551 | } 552 | 553 | dd ul, dd table { 554 | margin-bottom: 10px; 555 | } 556 | 557 | dd { 558 | margin-top: 3px; 559 | margin-bottom: 10px; 560 | margin-left: 30px; 561 | } 562 | 563 | dt:target, span.highlighted { 564 | background-color: #fbe54e; 565 | } 566 | 567 | rect.highlighted { 568 | fill: #fbe54e; 569 | } 570 | 571 | dl.glossary dt { 572 | font-weight: bold; 573 | font-size: 1.1em; 574 | } 575 | 576 | .optional { 577 | font-size: 1.3em; 578 | } 579 | 580 | .sig-paren { 581 | font-size: larger; 582 | } 583 | 584 | .versionmodified { 585 | font-style: italic; 586 | } 587 | 588 | .system-message { 589 | background-color: #fda; 590 | padding: 5px; 591 | border: 3px solid red; 592 | } 593 | 594 | .footnote:target { 595 | background-color: #ffa; 596 | } 597 | 598 | .line-block { 599 | display: block; 600 | margin-top: 1em; 601 | margin-bottom: 1em; 602 | } 603 | 604 | .line-block .line-block { 605 | margin-top: 0; 606 | margin-bottom: 0; 607 | margin-left: 1.5em; 608 | } 609 | 610 | .guilabel, .menuselection { 611 | font-family: sans-serif; 612 | } 613 | 614 | .accelerator { 615 | text-decoration: underline; 616 | } 617 | 618 | .classifier { 619 | font-style: oblique; 620 | } 621 | 622 | .classifier:before { 623 | font-style: normal; 624 | margin: 0.5em; 625 | content: ":"; 626 | } 627 | 628 | abbr, acronym { 629 | border-bottom: dotted 1px; 630 | cursor: help; 631 | } 632 | 633 | /* -- code displays --------------------------------------------------------- */ 634 | 635 | pre { 636 | overflow: auto; 637 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 638 | } 639 | 640 | span.pre { 641 | -moz-hyphens: none; 642 | -ms-hyphens: none; 643 | -webkit-hyphens: none; 644 | hyphens: none; 645 | } 646 | 647 | td.linenos pre { 648 | padding: 5px 0px; 649 | border: 0; 650 | background-color: transparent; 651 | color: #aaa; 652 | } 653 | 654 | table.highlighttable { 655 | margin-left: 0.5em; 656 | } 657 | 658 | table.highlighttable td { 659 | padding: 0 0.5em 0 0.5em; 660 | } 661 | 662 | div.code-block-caption { 663 | padding: 2px 5px; 664 | font-size: small; 665 | } 666 | 667 | div.code-block-caption code { 668 | background-color: transparent; 669 | } 670 | 671 | div.code-block-caption + div > div.highlight > pre { 672 | margin-top: 0; 673 | } 674 | 675 | div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */ 676 | user-select: none; 677 | } 678 | 679 | div.code-block-caption span.caption-number { 680 | padding: 0.1em 0.3em; 681 | font-style: italic; 682 | } 683 | 684 | div.code-block-caption span.caption-text { 685 | } 686 | 687 | div.literal-block-wrapper { 688 | padding: 1em 1em 0; 689 | } 690 | 691 | div.literal-block-wrapper div.highlight { 692 | margin: 0; 693 | } 694 | 695 | code.descname { 696 | background-color: transparent; 697 | font-weight: bold; 698 | font-size: 1.2em; 699 | } 700 | 701 | code.descclassname { 702 | background-color: transparent; 703 | } 704 | 705 | code.xref, a code { 706 | background-color: transparent; 707 | font-weight: bold; 708 | } 709 | 710 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 711 | background-color: transparent; 712 | } 713 | 714 | .viewcode-link { 715 | float: right; 716 | } 717 | 718 | .viewcode-back { 719 | float: right; 720 | font-family: sans-serif; 721 | } 722 | 723 | div.viewcode-block:target { 724 | margin: -1px -10px; 725 | padding: 0 10px; 726 | } 727 | 728 | /* -- math display ---------------------------------------------------------- */ 729 | 730 | img.math { 731 | vertical-align: middle; 732 | } 733 | 734 | div.body div.math p { 735 | text-align: center; 736 | } 737 | 738 | span.eqno { 739 | float: right; 740 | } 741 | 742 | span.eqno a.headerlink { 743 | position: relative; 744 | left: 0px; 745 | z-index: 1; 746 | } 747 | 748 | div.math:hover a.headerlink { 749 | visibility: visible; 750 | } 751 | 752 | /* -- printout stylesheet --------------------------------------------------- */ 753 | 754 | @media print { 755 | div.document, 756 | div.documentwrapper, 757 | div.bodywrapper { 758 | margin: 0 !important; 759 | width: 100%; 760 | } 761 | 762 | div.sphinxsidebar, 763 | div.related, 764 | div.footer, 765 | #top-link { 766 | display: none; 767 | } 768 | } -------------------------------------------------------------------------------- /docs/_build/html/_static/searchtools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * searchtools.js 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for the full-text search. 6 | * 7 | * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | if (!Scorer) { 13 | /** 14 | * Simple result scoring code. 15 | */ 16 | var Scorer = { 17 | // Implement the following function to further tweak the score for each result 18 | // The function takes a result array [filename, title, anchor, descr, score] 19 | // and returns the new score. 20 | /* 21 | score: function(result) { 22 | return result[4]; 23 | }, 24 | */ 25 | 26 | // query matches the full name of an object 27 | objNameMatch: 11, 28 | // or matches in the last dotted part of the object name 29 | objPartialMatch: 6, 30 | // Additive scores depending on the priority of the object 31 | objPrio: {0: 15, // used to be importantResults 32 | 1: 5, // used to be objectResults 33 | 2: -5}, // used to be unimportantResults 34 | // Used when the priority is not in the mapping. 35 | objPrioDefault: 0, 36 | 37 | // query found in title 38 | title: 15, 39 | partialTitle: 7, 40 | // query found in terms 41 | term: 5, 42 | partialTerm: 2 43 | }; 44 | } 45 | 46 | if (!splitQuery) { 47 | function splitQuery(query) { 48 | return query.split(/\s+/); 49 | } 50 | } 51 | 52 | /** 53 | * Search Module 54 | */ 55 | var Search = { 56 | 57 | _index : null, 58 | _queued_query : null, 59 | _pulse_status : -1, 60 | 61 | htmlToText : function(htmlString) { 62 | var htmlElement = document.createElement('span'); 63 | htmlElement.innerHTML = htmlString; 64 | $(htmlElement).find('.headerlink').remove(); 65 | docContent = $(htmlElement).find('[role=main]')[0]; 66 | return docContent.textContent || docContent.innerText; 67 | }, 68 | 69 | init : function() { 70 | var params = $.getQueryParameters(); 71 | if (params.q) { 72 | var query = params.q[0]; 73 | $('input[name="q"]')[0].value = query; 74 | this.performSearch(query); 75 | } 76 | }, 77 | 78 | loadIndex : function(url) { 79 | $.ajax({type: "GET", url: url, data: null, 80 | dataType: "script", cache: true, 81 | complete: function(jqxhr, textstatus) { 82 | if (textstatus != "success") { 83 | document.getElementById("searchindexloader").src = url; 84 | } 85 | }}); 86 | }, 87 | 88 | setIndex : function(index) { 89 | var q; 90 | this._index = index; 91 | if ((q = this._queued_query) !== null) { 92 | this._queued_query = null; 93 | Search.query(q); 94 | } 95 | }, 96 | 97 | hasIndex : function() { 98 | return this._index !== null; 99 | }, 100 | 101 | deferQuery : function(query) { 102 | this._queued_query = query; 103 | }, 104 | 105 | stopPulse : function() { 106 | this._pulse_status = 0; 107 | }, 108 | 109 | startPulse : function() { 110 | if (this._pulse_status >= 0) 111 | return; 112 | function pulse() { 113 | var i; 114 | Search._pulse_status = (Search._pulse_status + 1) % 4; 115 | var dotString = ''; 116 | for (i = 0; i < Search._pulse_status; i++) 117 | dotString += '.'; 118 | Search.dots.text(dotString); 119 | if (Search._pulse_status > -1) 120 | window.setTimeout(pulse, 500); 121 | } 122 | pulse(); 123 | }, 124 | 125 | /** 126 | * perform a search for something (or wait until index is loaded) 127 | */ 128 | performSearch : function(query) { 129 | // create the required interface elements 130 | this.out = $('#search-results'); 131 | this.title = $('

' + _('Searching') + '

').appendTo(this.out); 132 | this.dots = $('').appendTo(this.title); 133 | this.status = $('

 

').appendTo(this.out); 134 | this.output = $('