mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-11-01 10:38:10 +00:00
Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b104af296 | ||
|
|
f170574abf | ||
|
|
a68e8ff8d2 | ||
|
|
d5a52d1b2b | ||
|
|
7ac6e058ec | ||
|
|
74ab3c1bcd | ||
|
|
1a2ff2d215 | ||
|
|
aaf0480e9c | ||
|
|
5e50ffbbf6 | ||
|
|
243b701391 | ||
|
|
bdbfe76aed | ||
|
|
541ec04444 | ||
|
|
bf1522b047 | ||
|
|
3f4188a0fd | ||
|
|
8b387ef722 | ||
|
|
cad9a0f18e | ||
|
|
ab84c77363 | ||
|
|
62fa9ab0b0 | ||
|
|
14591c7a11 | ||
|
|
587932290d | ||
|
|
82b148eb87 | ||
|
|
8393daf67d | ||
|
|
be61dfd094 | ||
|
|
77925b218e | ||
|
|
4621ac12bf | ||
|
|
09920c0af2 | ||
|
|
e6a3d9ce5b | ||
|
|
b9645702c8 | ||
|
|
9c2095b138 | ||
|
|
cb42115230 | ||
|
|
5909da4bbf | ||
|
|
2ba1e86b28 | ||
|
|
3358c5eeb5 | ||
|
|
13e4c29bc1 | ||
|
|
4becc9060c | ||
|
|
32d8b2a4d8 | ||
|
|
399eb9700f | ||
|
|
82f83e1462 | ||
|
|
171450fa54 | ||
|
|
9f9f4c78fc | ||
|
|
c469a8d9ba | ||
|
|
99b2a554dc | ||
|
|
57e98d7173 | ||
|
|
78b45a3958 | ||
|
|
64b6b486a9 | ||
|
|
65cb46f479 | ||
|
|
f94d06f124 | ||
|
|
e1f2c55942 | ||
|
|
d28c67143e | ||
|
|
6bb9ae8336 | ||
|
|
0dc7d853ef | ||
|
|
dec9388416 | ||
|
|
017b35fa33 | ||
|
|
cb0a410418 | ||
|
|
f250990a49 | ||
|
|
280443f17f | ||
|
|
6f62251cb4 | ||
|
|
5ad54879b1 | ||
|
|
825d37c05c | ||
|
|
3ac9f90914 | ||
|
|
dbfbf115ff | ||
|
|
ad2590962b | ||
|
|
a9d530c776 | ||
|
|
f255c31f1f | ||
|
|
80ec05f84c | ||
|
|
22541d65e4 | ||
|
|
26fcf0ff6e | ||
|
|
1c32e437a2 | ||
|
|
718007b3de | ||
|
|
4d6c06340f | ||
|
|
bad893bf86 | ||
|
|
75e7fca8e4 | ||
|
|
4e38ba98ab | ||
|
|
fdcdfca589 | ||
|
|
299ca10a47 | ||
|
|
c0b7bf714e | ||
|
|
7f7c568160 | ||
|
|
9bf6ed953a | ||
|
|
e68dc39ddd | ||
|
|
f8007b41d1 | ||
|
|
228125029e | ||
|
|
d185e0c241 | ||
|
|
357bbec257 | ||
|
|
d25e98c567 | ||
|
|
397411690e | ||
|
|
4ab6f8cb1b | ||
|
|
44aff147db | ||
|
|
a36b139065 | ||
|
|
141fc66d47 | ||
|
|
53f29957fd | ||
|
|
9f3995ee20 | ||
|
|
0cf45bd102 | ||
|
|
55932ee3e9 | ||
|
|
797a0856ec | ||
|
|
3fa53adc4d | ||
|
|
bcb5e6bb60 | ||
|
|
6380f8f37a | ||
|
|
93869d6cb5 | ||
|
|
ce51a4d160 | ||
|
|
601e228bb6 | ||
|
|
3f58cbd559 | ||
|
|
2e3274ac78 | ||
|
|
e33144f8cc | ||
|
|
fd1e3f0f61 | ||
|
|
80c41264cf | ||
|
|
a051a5723b | ||
|
|
72f300ab94 | ||
|
|
2c3b0d8c82 | ||
|
|
11dab614a9 | ||
|
|
11d88bf09a | ||
|
|
af3cc4736e | ||
|
|
50cb82ee18 | ||
|
|
c80aca6696 | ||
|
|
dfca35d4ae | ||
|
|
1fbdaef58a | ||
|
|
bd025f3af4 | ||
|
|
c3e546abe3 | ||
|
|
9427d0b139 | ||
|
|
89f5b12f7e | ||
|
|
9d2c10e267 | ||
|
|
305620e5dd | ||
|
|
c91c5d622f | ||
|
|
24e7f4a5a1 | ||
|
|
08c922a5e5 | ||
|
|
efd7468d42 | ||
|
|
902cfa11a7 | ||
|
|
24c6acc027 |
112
.github/workflows/main.yml
vendored
Normal file
112
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Tox test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: fedora-python/tox-github-action@v0.4
|
||||||
|
with:
|
||||||
|
tox_env: ${{ matrix.tox_env }}
|
||||||
|
dnf_install: ${{ matrix.dnf_install }}
|
||||||
|
- uses: codecov/codecov-action@29386c70ef20e286228c72b668a06fd0e8399192
|
||||||
|
if: ${{ endswith(matrix.tox_env, '-cover') }}
|
||||||
|
with:
|
||||||
|
files: ${{ github.workspace }}/cover/coverage.xml
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
tox_env:
|
||||||
|
- py38
|
||||||
|
- py39
|
||||||
|
- py310-cover
|
||||||
|
include:
|
||||||
|
- tox_env: docs
|
||||||
|
dnf_install: graphviz
|
||||||
|
|
||||||
|
pypi:
|
||||||
|
needs: build
|
||||||
|
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.repository_owner == 'Telecominfraproject' }}
|
||||||
|
name: PyPI packaging
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: actions/setup-python@v2
|
||||||
|
name: Install Python
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
- uses: casperdcl/deploy-pypi@bb869aafd89f657ceaafe9561d3b5584766c0f95
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||||
|
pip: wheel -w dist/ --no-deps .
|
||||||
|
upload: true
|
||||||
|
|
||||||
|
docker:
|
||||||
|
needs: build
|
||||||
|
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) && github.repository_owner == 'Telecominfraproject' }}
|
||||||
|
name: Docker image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: jktjkt
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Extract tag name
|
||||||
|
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||||
|
id: extract_pretty_git
|
||||||
|
run: echo ::set-output name=GIT_DESC::$(git describe --tags)
|
||||||
|
- name: Build and push a container
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
telecominfraproject/oopt-gnpy:${{ steps.extract_pretty_git.outputs.GIT_DESC }}
|
||||||
|
telecominfraproject/oopt-gnpy:master
|
||||||
|
- name: Extract tag name
|
||||||
|
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
id: extract_tag_name
|
||||||
|
run: echo ::set-output name=GIT_DESC::${GITHUB_REF/refs\/tags\//}
|
||||||
|
- name: Build and push a container
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
telecominfraproject/oopt-gnpy:${{ steps.extract_tag_name.outputs.GIT_DESC }}
|
||||||
|
telecominfraproject/oopt-gnpy:latest
|
||||||
|
|
||||||
|
windows:
|
||||||
|
name: Tests on Windows
|
||||||
|
runs-on: windows-2019
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python_version }}
|
||||||
|
- run: |
|
||||||
|
pip install --editable .
|
||||||
|
pip install 'pytest>=6.2.5,<7'
|
||||||
|
pytest -vv
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python_version:
|
||||||
|
- "3.10"
|
||||||
3
.lgtm.yml
Normal file
3
.lgtm.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
queries:
|
||||||
|
- exclude: py/clear-text-logging-sensitive-data
|
||||||
|
- exclude: py/clear-text-storage-sensitive-data
|
||||||
@@ -3,8 +3,6 @@ os: linux
|
|||||||
language: python
|
language: python
|
||||||
services: docker
|
services: docker
|
||||||
python:
|
python:
|
||||||
- "3.6"
|
|
||||||
- "3.7"
|
|
||||||
- "3.8"
|
- "3.8"
|
||||||
- "3.9"
|
- "3.9"
|
||||||
before_install:
|
before_install:
|
||||||
|
|||||||
21
.zuul.yaml
21
.zuul.yaml
@@ -2,24 +2,21 @@
|
|||||||
- project:
|
- project:
|
||||||
check:
|
check:
|
||||||
jobs:
|
jobs:
|
||||||
- tox-py38-cover
|
- tox-py38
|
||||||
|
- tox-py39
|
||||||
|
- tox-py310-cover
|
||||||
|
- tox-docs-f35
|
||||||
- coverage-diff:
|
- coverage-diff:
|
||||||
voting: false
|
voting: false
|
||||||
dependencies:
|
dependencies:
|
||||||
- tox-py38-cover-previous
|
- tox-py310-cover-previous
|
||||||
- tox-py38-cover
|
- tox-py310-cover
|
||||||
vars:
|
vars:
|
||||||
coverage_job_name_previous: tox-py38-cover-previous
|
coverage_job_name_previous: tox-py310-cover-previous
|
||||||
coverage_job_name_current: tox-py38-cover
|
coverage_job_name_current: tox-py310-cover
|
||||||
- tox-linters-diff-n-report:
|
- tox-linters-diff-n-report:
|
||||||
voting: false
|
voting: false
|
||||||
- tox-py36-el8
|
- tox-py310-cover-previous
|
||||||
- tox-docs-f32
|
|
||||||
- tox-py38-cover-previous
|
|
||||||
gate:
|
|
||||||
jobs:
|
|
||||||
- tox-py38-f32
|
|
||||||
- tox-docs-f32
|
|
||||||
tag:
|
tag:
|
||||||
jobs:
|
jobs:
|
||||||
- oopt-release-python:
|
- oopt-release-python:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[](https://pypi.org/project/gnpy/)
|
[](https://pypi.org/project/gnpy/)
|
||||||
[](https://pypi.org/project/gnpy/)
|
[](https://pypi.org/project/gnpy/)
|
||||||
[](http://gnpy.readthedocs.io/en/master/?badge=master)
|
[](http://gnpy.readthedocs.io/en/master/?badge=master)
|
||||||
[](https://travis-ci.com/Telecominfraproject/oopt-gnpy)
|
[](https://github.com/Telecominfraproject/oopt-gnpy/actions/workflows/main.yml)
|
||||||
[](https://review.gerrithub.io/q/project:Telecominfraproject/oopt-gnpy+is:open)
|
[](https://review.gerrithub.io/q/project:Telecominfraproject/oopt-gnpy+is:open)
|
||||||
[](https://github.com/Telecominfraproject/oopt-gnpy/graphs/contributors)
|
[](https://github.com/Telecominfraproject/oopt-gnpy/graphs/contributors)
|
||||||
[](https://lgtm.com/projects/g/Telecominfraproject/oopt-gnpy/)
|
[](https://lgtm.com/projects/g/Telecominfraproject/oopt-gnpy/)
|
||||||
@@ -18,12 +18,12 @@ Together, we are building this tool for rapid development of production-grade ro
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
Install either via [Docker](docs/install.rst#install-docker), or as a [Python package](docs/install.rst#install-pip).
|
Install either via [Docker](https://gnpy.readthedocs.io/en/master/install.html#using-prebuilt-docker-images), or as a [Python package](https://gnpy.readthedocs.io/en/master/install.html#using-python-on-your-computer).
|
||||||
Read our [documentation](https://gnpy.readthedocs.io/), learn from the demos, and [get in touch with us](https://github.com/Telecominfraproject/oopt-gnpy/discussions).
|
Read our [documentation](https://gnpy.readthedocs.io/), learn from the demos, and [get in touch with us](https://github.com/Telecominfraproject/oopt-gnpy/discussions).
|
||||||
|
|
||||||
This example demonstrates how GNPy can be used to check the expected SNR at the end of the line by varying the channel input power:
|
This example demonstrates how GNPy can be used to check the expected SNR at the end of the line by varying the channel input power:
|
||||||
|
|
||||||
[](https://asciinema.org/a/252295)
|

|
||||||
|
|
||||||
GNPy can do much more, including acting as a Path Computation Engine, tracking bandwidth requests, or advising the SDN controller about a best possible path through a large DWDM network.
|
GNPy can do much more, including acting as a Path Computation Engine, tracking bandwidth requests, or advising the SDN controller about a best possible path through a large DWDM network.
|
||||||
Learn more about this [in the documentation](https://gnpy.readthedocs.io/).
|
Learn more about this [in the documentation](https://gnpy.readthedocs.io/).
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ There are weekly calls about our progress.
|
|||||||
Newcomers, users and telecom operators are especially welcome there.
|
Newcomers, users and telecom operators are especially welcome there.
|
||||||
We encourage all interested people outside the TIP to [join the project](https://telecominfraproject.com/apply-for-membership/) and especially to [get in touch with us](https://github.com/Telecominfraproject/oopt-gnpy/discussions).
|
We encourage all interested people outside the TIP to [join the project](https://telecominfraproject.com/apply-for-membership/) and especially to [get in touch with us](https://github.com/Telecominfraproject/oopt-gnpy/discussions).
|
||||||
|
|
||||||
|
(contributing)=
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
`gnpy` is looking for additional contributors, especially those with experience planning and maintaining large-scale, real-world mesh optical networks.
|
`gnpy` is looking for additional contributors, especially those with experience planning and maintaining large-scale, real-world mesh optical networks.
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ This path is directional, and all "GNPy elements" along the path match the unidi
|
|||||||
|
|
||||||
The network topology contains not just the physical topology of the network, but also references to the :ref:`equipment library<concepts-equipment>` and a set of *operating parameters* for each entity.
|
The network topology contains not just the physical topology of the network, but also references to the :ref:`equipment library<concepts-equipment>` and a set of *operating parameters* for each entity.
|
||||||
These parameters include the **fiber length** of each fiber, the connector **attenutation losses**, or an amplifier's specific **gain setting**.
|
These parameters include the **fiber length** of each fiber, the connector **attenutation losses**, or an amplifier's specific **gain setting**.
|
||||||
|
The topology is specified via :ref:`XLS files<excel>` or via :ref:`JSON<json>`.
|
||||||
|
|
||||||
.. _complete-vs-incomplete:
|
.. _complete-vs-incomplete:
|
||||||
|
|
||||||
|
|||||||
@@ -190,3 +190,5 @@ autodoc_default_options = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
graphviz_output_format = 'svg'
|
graphviz_output_format = 'svg'
|
||||||
|
|
||||||
|
bibtex_bibfiles = ['biblio.bib']
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
.. _excel:
|
||||||
|
|
||||||
Excel (XLS, XLSX) input files
|
Excel (XLS, XLSX) input files
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Extending GNPy with vendor-specific data
|
|||||||
========================================
|
========================================
|
||||||
|
|
||||||
GNPy ships with an :ref:`equipment library<concepts-equipment>` containing machine-readable datasheets of networking equipment.
|
GNPy ships with an :ref:`equipment library<concepts-equipment>` containing machine-readable datasheets of networking equipment.
|
||||||
Vendors who are willing to contribute descriptions of their supported products are encouraged to `submit a patch <https://review.gerrithub.io/Documentation/intro-gerrit-walkthrough-github.html>`__.
|
Vendors who are willing to contribute descriptions of their supported products are encouraged to `submit a patch <https://review.gerrithub.io/Documentation/intro-gerrit-walkthrough-github.html>`__ -- or just :ref:`get in touch with us directly<contributing>`.
|
||||||
|
|
||||||
This chapter discusses option for modeling performance of :ref:`EDFA amplifiers<extending-edfa>`, :ref:`Raman amplifiers<extending-raman>`, :ref:`transponders<extending-transponder>` and :ref:`ROADMs<extending-roadm>`.
|
This chapter discusses option for modeling performance of :ref:`EDFA amplifiers<extending-edfa>`, :ref:`Raman amplifiers<extending-raman>`, :ref:`transponders<extending-transponder>` and :ref:`ROADMs<extending-roadm>`.
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ The NF is expressed as a third-degree polynomial:
|
|||||||
|
|
||||||
f(x) &= \text{a}x^3 + \text{b}x^2 + \text{c}x + \text{d}
|
f(x) &= \text{a}x^3 + \text{b}x^2 + \text{c}x + \text{d}
|
||||||
|
|
||||||
\text{NF} &= f(G_\text{max} - G)
|
\text{NF} &= f(G - G_\text{max})
|
||||||
|
|
||||||
This model can be also used for fixed-gain fixed-NF amplifiers.
|
This model can be also used for fixed-gain fixed-NF amplifiers.
|
||||||
In that case, use:
|
In that case, use:
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Using Python on your computer
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
**Note**: `gnpy` supports Python 3 only. Python 2 is not supported.
|
**Note**: `gnpy` supports Python 3 only. Python 2 is not supported.
|
||||||
`gnpy` requires Python ≥3.6
|
`gnpy` requires Python ≥3.8
|
||||||
|
|
||||||
**Note**: the `gnpy` maintainers strongly recommend the use of Anaconda for
|
**Note**: the `gnpy` maintainers strongly recommend the use of Anaconda for
|
||||||
managing dependencies.
|
managing dependencies.
|
||||||
@@ -84,7 +84,7 @@ exact version of Python you are using.
|
|||||||
$ which python # check which Python executable is used
|
$ which python # check which Python executable is used
|
||||||
/path/to/anaconda/bin/python
|
/path/to/anaconda/bin/python
|
||||||
$ python -V # check your Python version
|
$ python -V # check your Python version
|
||||||
Python 3.6.5 :: Anaconda, Inc.
|
Python 3.8.0 :: Anaconda, Inc.
|
||||||
|
|
||||||
.. _install-pip:
|
.. _install-pip:
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ This example demonstrates how GNPy can be used to check the expected SNR at the
|
|||||||
:width: 100%
|
:width: 100%
|
||||||
:align: left
|
:align: left
|
||||||
:alt: Running a simple simulation example
|
:alt: Running a simple simulation example
|
||||||
:target: https://asciinema.org/a/252295
|
|
||||||
|
|
||||||
By default, this script operates on a single span network defined in
|
By default, this script operates on a single span network defined in
|
||||||
`gnpy/example-data/edfa_example_network.json <gnpy/example-data/edfa_example_network.json>`_
|
`gnpy/example-data/edfa_example_network.json <gnpy/example-data/edfa_example_network.json>`_
|
||||||
@@ -92,4 +91,4 @@ As a result transponder type is not part of the network info. it is related to t
|
|||||||
|
|
||||||
The current version includes a spectrum assigment features that enables to compute a candidate spectrum assignment for each service based on a first fit policy. Spectrum is assigned based on service specified spacing value, path_bandwidth value and selected mode for the transceiver. This spectrum assignment includes a basic capacity planning capability so that the spectrum resource is limited by the frequency min and max values defined for the links. If the requested services reach the link spectrum capacity, additional services feasibility are computed but marked as blocked due to spectrum reason.
|
The current version includes a spectrum assigment features that enables to compute a candidate spectrum assignment for each service based on a first fit policy. Spectrum is assigned based on service specified spacing value, path_bandwidth value and selected mode for the transceiver. This spectrum assignment includes a basic capacity planning capability so that the spectrum resource is limited by the frequency min and max values defined for the links. If the requested services reach the link spectrum capacity, additional services feasibility are computed but marked as blocked due to spectrum reason.
|
||||||
|
|
||||||
OpenROADM networks can be simulated via ``gnpy/example-data/eqpt_config_openroadm.json`` -- see ``gnpy/example-data/Sweden_OpenROADM_example_network.json`` as an example.
|
OpenROADM networks can be simulated via ``gnpy/example-data/eqpt_config_openroadm_*.json`` -- see ``gnpy/example-data/Sweden_OpenROADM*_example_network.json`` as an example.
|
||||||
|
|||||||
105
docs/json.rst
105
docs/json.rst
@@ -1,3 +1,5 @@
|
|||||||
|
.. _json:
|
||||||
|
|
||||||
JSON Input Files
|
JSON Input Files
|
||||||
================
|
================
|
||||||
|
|
||||||
@@ -71,13 +73,57 @@ The fiber library currently describes SSMF and NZDF but additional fiber types c
|
|||||||
| ``dispersion_slope`` | (number) | In :math:`s \times m^{-1} \times m^{-1} |
|
| ``dispersion_slope`` | (number) | In :math:`s \times m^{-1} \times m^{-1} |
|
||||||
| | | \times m^{-1}` |
|
| | | \times m^{-1}` |
|
||||||
+----------------------+-----------+------------------------------------------+
|
+----------------------+-----------+------------------------------------------+
|
||||||
| ``gamma`` | (number) | :math:`2\pi\times n^2/(\lambda*A_{eff})`,|
|
| ``effective_area`` | (number) | Effective area of the fiber (not just |
|
||||||
| | | in :math:`w^{-1} \times m^{-1}`. |
|
| | | the MFD circle). This is the |
|
||||||
|
| | | :math:`A_{eff}`, see e.g., the |
|
||||||
|
| | | `Corning whitepaper on MFD/EA`_. |
|
||||||
|
| | | Specified in :math:`m^{2}`. |
|
||||||
|
+----------------------+-----------+------------------------------------------+
|
||||||
|
| ``gamma`` | (number) | Coefficient :math:`\gamma = 2\pi\times |
|
||||||
|
| | | n^2/(\lambda*A_{eff})`. |
|
||||||
|
| | | If not provided, this will be derived |
|
||||||
|
| | | from the ``effective_area`` |
|
||||||
|
| | | :math:`A_{eff}`. |
|
||||||
|
| | | In :math:`w^{-1} \times m^{-1}`. |
|
||||||
+----------------------+-----------+------------------------------------------+
|
+----------------------+-----------+------------------------------------------+
|
||||||
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) |
|
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) |
|
||||||
| | | coefficient. In |
|
| | | coefficient. In |
|
||||||
| | | :math:`s\times\sqrt{m}^{-1}`. |
|
| | | :math:`s\times\sqrt{m}^{-1}`. |
|
||||||
+----------------------+-----------+------------------------------------------+
|
+----------------------+-----------+------------------------------------------+
|
||||||
|
| ``lumped_losses`` | (array) | Places along the fiber length with extra |
|
||||||
|
| | | losses. Specified as a loss in dB at |
|
||||||
|
| | | each relevant position (in km): |
|
||||||
|
| | | ``{"position": 10, "loss": 1.5}``) |
|
||||||
|
+----------------------+-----------+------------------------------------------+
|
||||||
|
|
||||||
|
.. _Corning whitepaper on MFD/EA: https://www.corning.com/microsites/coc/oem/documents/specialty-fiber/WP7071-Mode-Field-Diam-and-Eff-Area.pdf
|
||||||
|
|
||||||
|
RamanFiber
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
The RamanFiber can be used to simulate Raman amplification through dedicated Raman pumps. The Raman pumps must be listed
|
||||||
|
in the key ``raman_pumps`` within the RamanFiber ``operational`` dictionary. The description of each Raman pump must
|
||||||
|
contain the following:
|
||||||
|
|
||||||
|
+---------------------------+-----------+------------------------------------------------------------+
|
||||||
|
| field | type | description |
|
||||||
|
+===========================+===========+============================================================+
|
||||||
|
| ``power`` | (number) | Total pump power in :math:`W` |
|
||||||
|
| | | considering a depolarized pump |
|
||||||
|
+---------------------------+-----------+------------------------------------------------------------+
|
||||||
|
| ``frequency`` | (number) | Pump central frequency in :math:`Hz` |
|
||||||
|
+---------------------------+-----------+------------------------------------------------------------+
|
||||||
|
| ``propagation_direction`` | (number) | The pumps can propagate in the same or opposite direction |
|
||||||
|
| | | with respect the signal. Valid choices are ``coprop`` and |
|
||||||
|
| | | ``counterprop``, respectively |
|
||||||
|
+---------------------------+-----------+------------------------------------------------------------+
|
||||||
|
|
||||||
|
Beside the list of Raman pumps, the RamanFiber ``operational`` dictionary must include the ``temperature`` that affects
|
||||||
|
the amplified spontaneous emission noise generated by the Raman amplification.
|
||||||
|
As the loss coefficient significantly varies outside the C-band, where the Raman pumps are usually placed,
|
||||||
|
it is suggested to include an estimation of the loss coefficient for the Raman pump central frequencies within
|
||||||
|
a dictionary-like definition of the ``RamanFiber.params.loss_coef``
|
||||||
|
(e.g. ``loss_coef = {"value": [0.18, 0.18, 0.20, 0.20], "frequency": [191e12, 196e12, 200e12, 210e12]}``).
|
||||||
|
|
||||||
Transceiver
|
Transceiver
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
@@ -174,6 +220,61 @@ Only the EDFA that are marked ``'allowed_for_design': true`` are considered.
|
|||||||
|
|
||||||
For amplifiers defined in the topology JSON input but whose ``gain = 0`` (placeholder), auto-design will set its gain automatically: see ``power_mode`` in the ``Spans`` library to find out how the gain is calculated.
|
For amplifiers defined in the topology JSON input but whose ``gain = 0`` (placeholder), auto-design will set its gain automatically: see ``power_mode`` in the ``Spans`` library to find out how the gain is calculated.
|
||||||
|
|
||||||
|
The file ``sim_params.json`` contains the tuning parameters used within both the ``gnpy.science_utils.RamanSolver`` and
|
||||||
|
the ``gnpy.science_utils.NliSolver`` for the evaluation of the Raman profile and the NLI generation, respectively.
|
||||||
|
|
||||||
|
+---------------------------------------------+-----------+---------------------------------------------+
|
||||||
|
| field | type | description |
|
||||||
|
+=============================================+===========+=============================================+
|
||||||
|
| ``raman_params.flag`` | (boolean) | Enable/Disable the Raman effect that |
|
||||||
|
| | | produces a power transfer from higher to |
|
||||||
|
| | | lower frequencies. |
|
||||||
|
| | | In general, considering the Raman effect |
|
||||||
|
| | | provides more accurate results. It is |
|
||||||
|
| | | mandatory when Raman amplification is |
|
||||||
|
| | | included in the simulation |
|
||||||
|
+---------------------------------------------+-----------+---------------------------------------------+
|
||||||
|
| ``raman_params.result_spatial_resolution`` | (number) | Spatial resolution of the output |
|
||||||
|
| | | Raman profile along the entire fiber span. |
|
||||||
|
| | | This affects the accuracy and the |
|
||||||
|
| | | computational time of the NLI |
|
||||||
|
| | | calculation when the GGN method is used: |
|
||||||
|
| | | smaller the spatial resolution higher both |
|
||||||
|
| | | the accuracy and the computational time. |
|
||||||
|
| | | In C-band simulations, with input power per |
|
||||||
|
| | | channel around 0 dBm, a suggested value of |
|
||||||
|
| | | spatial resolution is 10e3 m |
|
||||||
|
+---------------------------------------------+-----------+---------------------------------------------+
|
||||||
|
| ``raman_params.solver_spatial_resolution`` | (number) | Spatial step for the iterative solution |
|
||||||
|
| | | of the first order differential equation |
|
||||||
|
| | | used to calculate the Raman profile |
|
||||||
|
| | | along the entire fiber span. |
|
||||||
|
| | | This affects the accuracy and the |
|
||||||
|
| | | computational time of the evaluated |
|
||||||
|
| | | Raman profile: |
|
||||||
|
| | | smaller the spatial resolution higher both |
|
||||||
|
| | | the accuracy and the computational time. |
|
||||||
|
| | | In C-band simulations, with input power per |
|
||||||
|
| | | channel around 0 dBm, a suggested value of |
|
||||||
|
| | | spatial resolution is 100 m |
|
||||||
|
+---------------------------------------------+-----------+---------------------------------------------+
|
||||||
|
| ``nli_params.method`` | (string) | Model used for the NLI evaluation. Valid |
|
||||||
|
| | | choices are ``gn_model_analytic`` (see |
|
||||||
|
| | | eq. 120 from `arXiv:1209.0394 |
|
||||||
|
| | | <https://arxiv.org/abs/1209.0394>`_) and |
|
||||||
|
| | | ``ggn_spectrally_separated`` (see eq. 21 |
|
||||||
|
| | | from `arXiv:1710.02225 |
|
||||||
|
| | | <https://arxiv.org/abs/1710.02225>`_). |
|
||||||
|
+---------------------------------------------+-----------+---------------------------------------------+
|
||||||
|
| ``nli_params.computed_channels`` | (number) | The channels on which the NLI is |
|
||||||
|
| | | explicitly evaluated. |
|
||||||
|
| | | The NLI of the other channels is |
|
||||||
|
| | | interpolated using ``numpy.interp``. |
|
||||||
|
| | | In a C-band simulation with 96 channels in |
|
||||||
|
| | | a 50 GHz spacing fix-grid we recommend at |
|
||||||
|
| | | one computed channel every 20 channels. |
|
||||||
|
+---------------------------------------------+-----------+---------------------------------------------+
|
||||||
|
|
||||||
Span
|
Span
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -145,4 +145,4 @@ Raman Scattering in order to give a proper estimation for all channels
|
|||||||
:cite:`cantono2018modeling`. This will be the main upgrade required within the
|
:cite:`cantono2018modeling`. This will be the main upgrade required within the
|
||||||
PSE framework.
|
PSE framework.
|
||||||
|
|
||||||
.. bibliography:: biblio.bib
|
.. bibliography::
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
alabaster>=0.7.12,<1
|
alabaster>=0.7.12,<1
|
||||||
docutils>=0.15.2,<1
|
docutils>=0.17.1,<1
|
||||||
myst-parser>=0.14.0,<1
|
myst-parser>=0.16.1,<1
|
||||||
Pygments>=2.7.4,<3
|
Pygments>=2.11.2,<3
|
||||||
rstcheck
|
rstcheck
|
||||||
Sphinx>=3.5.0,<4
|
Sphinx>=4.4.0,<5
|
||||||
sphinxcontrib-bibtex>=0.4.2,<1
|
sphinxcontrib-bibtex>=2.4.1,<3
|
||||||
|
|||||||
@@ -20,13 +20,17 @@ unique identifier and a printable name, and provide the :py:meth:`__call__` meth
|
|||||||
instance as a result.
|
instance as a result.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from numpy import abs, arange, array, divide, errstate, ones, interp, mean, pi, polyfit, polyval, sum, sqrt
|
from numpy import abs, array, errstate, ones, interp, mean, pi, polyfit, polyval, sum, sqrt, log10, exp, asarray, full,\
|
||||||
|
squeeze, zeros, append, flip, outer
|
||||||
from scipy.constants import h, c
|
from scipy.constants import h, c
|
||||||
|
from scipy.interpolate import interp1d
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
|
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
|
||||||
from gnpy.core.parameters import FiberParams, PumpParams
|
from gnpy.core.parameters import RoadmParams, FusedParams, FiberParams, PumpParams, EdfaParams, EdfaOperational
|
||||||
from gnpy.core.science_utils import NliSolver, RamanSolver, propagate_raman_fiber, _psi
|
from gnpy.core.science_utils import NliSolver, RamanSolver
|
||||||
|
from gnpy.core.info import SpectralInformation
|
||||||
|
from gnpy.core.exceptions import NetworkTopologyError, SpectrumError
|
||||||
|
|
||||||
|
|
||||||
class Location(namedtuple('Location', 'latitude longitude city region')):
|
class Location(namedtuple('Location', 'latitude longitude city region')):
|
||||||
@@ -79,32 +83,47 @@ class Transceiver(_Node):
|
|||||||
self.baud_rate = None
|
self.baud_rate = None
|
||||||
self.chromatic_dispersion = None
|
self.chromatic_dispersion = None
|
||||||
self.pmd = None
|
self.pmd = None
|
||||||
|
self.pdl = None
|
||||||
|
self.penalties = {}
|
||||||
|
self.total_penalty = 0
|
||||||
|
|
||||||
def _calc_cd(self, spectral_info):
|
def _calc_cd(self, spectral_info):
|
||||||
""" Updates the Transceiver property with the CD of the received channels. CD in ps/nm.
|
""" Updates the Transceiver property with the CD of the received channels. CD in ps/nm.
|
||||||
"""
|
"""
|
||||||
self.chromatic_dispersion = [carrier.chromatic_dispersion * 1e3 for carrier in spectral_info.carriers]
|
self.chromatic_dispersion = spectral_info.chromatic_dispersion * 1e3
|
||||||
|
|
||||||
def _calc_pmd(self, spectral_info):
|
def _calc_pmd(self, spectral_info):
|
||||||
"""Updates the Transceiver property with the PMD of the received channels. PMD in ps.
|
"""Updates the Transceiver property with the PMD of the received channels. PMD in ps.
|
||||||
"""
|
"""
|
||||||
self.pmd = [carrier.pmd*1e12 for carrier in spectral_info.carriers]
|
self.pmd = spectral_info.pmd * 1e12
|
||||||
|
|
||||||
|
def _calc_pdl(self, spectral_info):
|
||||||
|
"""Updates the Transceiver property with the PDL of the received channels. PDL in dB.
|
||||||
|
"""
|
||||||
|
self.pdl = spectral_info.pdl
|
||||||
|
|
||||||
|
def _calc_penalty(self, impairment_value, boundary_list):
|
||||||
|
return interp(impairment_value, boundary_list['up_to_boundary'], boundary_list['penalty_value'],
|
||||||
|
left=float('inf'), right=float('inf'))
|
||||||
|
|
||||||
|
def calc_penalties(self, penalties):
|
||||||
|
"""Updates the Transceiver property with penalties (CD, PMD, etc.) of the received channels in dB.
|
||||||
|
Penalties are linearly interpolated between given points and set to 'inf' outside interval.
|
||||||
|
"""
|
||||||
|
self.penalties = {impairment: self._calc_penalty(getattr(self, impairment), boundary_list)
|
||||||
|
for impairment, boundary_list in penalties.items()}
|
||||||
|
self.total_penalty = sum(list(self.penalties.values()), axis=0)
|
||||||
|
|
||||||
def _calc_snr(self, spectral_info):
|
def _calc_snr(self, spectral_info):
|
||||||
with errstate(divide='ignore'):
|
with errstate(divide='ignore'):
|
||||||
self.baud_rate = [c.baud_rate for c in spectral_info.carriers]
|
self.baud_rate = spectral_info.baud_rate
|
||||||
ratio_01nm = [lin2db(12.5e9 / b_rate) for b_rate in self.baud_rate]
|
ratio_01nm = lin2db(12.5e9 / self.baud_rate)
|
||||||
# set raw values to record original calculation, before update_snr()
|
# set raw values to record original calculation, before update_snr()
|
||||||
self.raw_osnr_ase = [lin2db(divide(c.power.signal, c.power.ase))
|
self.raw_osnr_ase = lin2db(spectral_info.signal / spectral_info.ase)
|
||||||
for c in spectral_info.carriers]
|
self.raw_osnr_ase_01nm = self.raw_osnr_ase - ratio_01nm
|
||||||
self.raw_osnr_ase_01nm = [ase - ratio for ase, ratio
|
self.raw_osnr_nli = lin2db(spectral_info.signal / spectral_info.nli)
|
||||||
in zip(self.raw_osnr_ase, ratio_01nm)]
|
self.raw_snr = lin2db(spectral_info.signal / (spectral_info.ase + spectral_info.nli))
|
||||||
self.raw_osnr_nli = [lin2db(divide(c.power.signal, c.power.nli))
|
self.raw_snr_01nm = self.raw_snr - ratio_01nm
|
||||||
for c in spectral_info.carriers]
|
|
||||||
self.raw_snr = [lin2db(divide(c.power.signal, c.power.nli + c.power.ase))
|
|
||||||
for c in spectral_info.carriers]
|
|
||||||
self.raw_snr_01nm = [snr - ratio for snr, ratio
|
|
||||||
in zip(self.raw_snr, ratio_01nm)]
|
|
||||||
|
|
||||||
self.osnr_ase = self.raw_osnr_ase
|
self.osnr_ase = self.raw_osnr_ase
|
||||||
self.osnr_ase_01nm = self.raw_osnr_ase_01nm
|
self.osnr_ase_01nm = self.raw_osnr_ase_01nm
|
||||||
@@ -124,14 +143,10 @@ class Transceiver(_Node):
|
|||||||
for s in args:
|
for s in args:
|
||||||
snr_added += db2lin(-s)
|
snr_added += db2lin(-s)
|
||||||
snr_added = -lin2db(snr_added)
|
snr_added = -lin2db(snr_added)
|
||||||
self.osnr_ase = list(map(lambda x, y: snr_sum(x, y, snr_added),
|
self.osnr_ase = snr_sum(self.raw_osnr_ase, self.baud_rate, snr_added)
|
||||||
self.raw_osnr_ase, self.baud_rate))
|
self.snr = snr_sum(self.raw_snr, self.baud_rate, snr_added)
|
||||||
self.snr = list(map(lambda x, y: snr_sum(x, y, snr_added),
|
self.osnr_ase_01nm = snr_sum(self.raw_osnr_ase_01nm, 12.5e9, snr_added)
|
||||||
self.raw_snr, self.baud_rate))
|
self.snr_01nm = snr_sum(self.raw_snr_01nm, 12.5e9, snr_added)
|
||||||
self.osnr_ase_01nm = list(map(lambda x: snr_sum(x, 12.5e9, snr_added),
|
|
||||||
self.raw_osnr_ase_01nm))
|
|
||||||
self.snr_01nm = list(map(lambda x: snr_sum(x, 12.5e9, snr_added),
|
|
||||||
self.raw_snr_01nm))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
@@ -150,7 +165,9 @@ class Transceiver(_Node):
|
|||||||
f'osnr_nli={self.osnr_nli!r}, '
|
f'osnr_nli={self.osnr_nli!r}, '
|
||||||
f'snr={self.snr!r}, '
|
f'snr={self.snr!r}, '
|
||||||
f'chromatic_dispersion={self.chromatic_dispersion!r}, '
|
f'chromatic_dispersion={self.chromatic_dispersion!r}, '
|
||||||
f'pmd={self.pmd!r})')
|
f'pmd={self.pmd!r}, '
|
||||||
|
f'pdl={self.pdl!r}, '
|
||||||
|
f'penalties={self.penalties!r})')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.snr is None or self.osnr_ase is None:
|
if self.snr is None or self.osnr_ase is None:
|
||||||
@@ -162,34 +179,46 @@ class Transceiver(_Node):
|
|||||||
snr_01nm = round(mean(self.snr_01nm), 2)
|
snr_01nm = round(mean(self.snr_01nm), 2)
|
||||||
cd = mean(self.chromatic_dispersion)
|
cd = mean(self.chromatic_dispersion)
|
||||||
pmd = mean(self.pmd)
|
pmd = mean(self.pmd)
|
||||||
|
pdl = mean(self.pdl)
|
||||||
|
|
||||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
result = '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||||
|
|
||||||
f' GSNR (0.1nm, dB): {snr_01nm:.2f}',
|
f' GSNR (0.1nm, dB): {snr_01nm:.2f}',
|
||||||
f' GSNR (signal bw, dB): {snr:.2f}',
|
f' GSNR (signal bw, dB): {snr:.2f}',
|
||||||
f' OSNR ASE (0.1nm, dB): {osnr_ase_01nm:.2f}',
|
f' OSNR ASE (0.1nm, dB): {osnr_ase_01nm:.2f}',
|
||||||
f' OSNR ASE (signal bw, dB): {osnr_ase:.2f}',
|
f' OSNR ASE (signal bw, dB): {osnr_ase:.2f}',
|
||||||
f' CD (ps/nm): {cd:.2f}',
|
f' CD (ps/nm): {cd:.2f}',
|
||||||
f' PMD (ps): {pmd:.2f}'])
|
f' PMD (ps): {pmd:.2f}',
|
||||||
|
f' PDL (dB): {pdl:.2f}'])
|
||||||
|
|
||||||
|
cd_penalty = self.penalties.get('chromatic_dispersion')
|
||||||
|
if cd_penalty is not None:
|
||||||
|
result += f'\n CD penalty (dB): {mean(cd_penalty):.2f}'
|
||||||
|
pmd_penalty = self.penalties.get('pmd')
|
||||||
|
if pmd_penalty is not None:
|
||||||
|
result += f'\n PMD penalty (dB): {mean(pmd_penalty):.2f}'
|
||||||
|
pdl_penalty = self.penalties.get('pdl')
|
||||||
|
if pdl_penalty is not None:
|
||||||
|
result += f'\n PDL penalty (dB): {mean(pdl_penalty):.2f}'
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def __call__(self, spectral_info):
|
def __call__(self, spectral_info):
|
||||||
self._calc_snr(spectral_info)
|
self._calc_snr(spectral_info)
|
||||||
self._calc_cd(spectral_info)
|
self._calc_cd(spectral_info)
|
||||||
self._calc_pmd(spectral_info)
|
self._calc_pmd(spectral_info)
|
||||||
|
self._calc_pdl(spectral_info)
|
||||||
return spectral_info
|
return spectral_info
|
||||||
|
|
||||||
|
|
||||||
RoadmParams = namedtuple('RoadmParams', 'target_pch_out_db add_drop_osnr pmd restrictions per_degree_pch_out_db')
|
|
||||||
|
|
||||||
|
|
||||||
class Roadm(_Node):
|
class Roadm(_Node):
|
||||||
def __init__(self, *args, params, **kwargs):
|
def __init__(self, *args, params=None, **kwargs):
|
||||||
if 'per_degree_pch_out_db' not in params.keys():
|
if not params:
|
||||||
params['per_degree_pch_out_db'] = {}
|
params = {}
|
||||||
super().__init__(*args, params=RoadmParams(**params), **kwargs)
|
super().__init__(*args, params=RoadmParams(**params), **kwargs)
|
||||||
|
self.pch_out_db = self.params.target_pch_out_db
|
||||||
self.loss = 0 # auto-design interest
|
self.loss = 0 # auto-design interest
|
||||||
self.effective_loss = None
|
self.effective_loss = None
|
||||||
self.effective_pch_out_db = self.params.target_pch_out_db
|
|
||||||
self.passive = True
|
self.passive = True
|
||||||
self.restrictions = self.params.restrictions
|
self.restrictions = self.params.restrictions
|
||||||
self.per_degree_pch_out_db = self.params.per_degree_pch_out_db
|
self.per_degree_pch_out_db = self.params.per_degree_pch_out_db
|
||||||
@@ -199,7 +228,7 @@ class Roadm(_Node):
|
|||||||
return {'uid': self.uid,
|
return {'uid': self.uid,
|
||||||
'type': type(self).__name__,
|
'type': type(self).__name__,
|
||||||
'params': {
|
'params': {
|
||||||
'target_pch_out_db': self.effective_pch_out_db,
|
'target_pch_out_db': self.pch_out_db,
|
||||||
'restrictions': self.restrictions,
|
'restrictions': self.restrictions,
|
||||||
'per_degree_pch_out_db': self.per_degree_pch_out_db
|
'per_degree_pch_out_db': self.per_degree_pch_out_db
|
||||||
},
|
},
|
||||||
@@ -217,9 +246,9 @@ class Roadm(_Node):
|
|||||||
|
|
||||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||||
f' effective loss (dB): {self.effective_loss:.2f}',
|
f' effective loss (dB): {self.effective_loss:.2f}',
|
||||||
f' pch out (dBm): {self.effective_pch_out_db:.2f}'])
|
f' pch out (dBm): {self.pch_out_db:.2f}'])
|
||||||
|
|
||||||
def propagate(self, pref, *carriers, degree):
|
def propagate(self, spectral_info, degree):
|
||||||
# pin_target and loss are read from eqpt_config.json['Roadm']
|
# pin_target and loss are read from eqpt_config.json['Roadm']
|
||||||
# all ingress channels in xpress are set to this power level
|
# all ingress channels in xpress are set to this power level
|
||||||
# but add channels are not, so we define an effective loss
|
# but add channels are not, so we define an effective loss
|
||||||
@@ -229,38 +258,31 @@ class Roadm(_Node):
|
|||||||
# if the input power is lower than the target one, use the input power instead because
|
# if the input power is lower than the target one, use the input power instead because
|
||||||
# a ROADM doesn't amplify, it can only attenuate
|
# a ROADM doesn't amplify, it can only attenuate
|
||||||
# TODO maybe add a minimum loss for the ROADM
|
# TODO maybe add a minimum loss for the ROADM
|
||||||
per_degree_pch = self.per_degree_pch_out_db[degree] if degree in self.per_degree_pch_out_db.keys() else self.params.target_pch_out_db
|
per_degree_pch = self.per_degree_pch_out_db[degree] \
|
||||||
self.effective_pch_out_db = min(pref.p_spani, per_degree_pch)
|
if degree in self.per_degree_pch_out_db else self.pch_out_db
|
||||||
self.effective_loss = pref.p_spani - self.effective_pch_out_db
|
self.pch_out_db = min(spectral_info.pref.p_spani, per_degree_pch)
|
||||||
carriers_power = array([c.power.signal + c.power.nli + c.power.ase for c in carriers])
|
self.effective_loss = spectral_info.pref.p_spani - self.pch_out_db
|
||||||
carriers_att = list(map(lambda x: lin2db(x * 1e3) - per_degree_pch, carriers_power))
|
input_power = spectral_info.signal + spectral_info.nli + spectral_info.ase
|
||||||
exceeding_att = -min(list(filter(lambda x: x < 0, carriers_att)), default=0)
|
min_power = min(lin2db(input_power * 1e3))
|
||||||
carriers_att = list(map(lambda x: db2lin(x + exceeding_att), carriers_att))
|
per_degree_pch = per_degree_pch if per_degree_pch < min_power else min_power
|
||||||
for carrier_att, carrier in zip(carriers_att, carriers):
|
delta_power = lin2db(input_power * 1e3) - per_degree_pch
|
||||||
pwr = carrier.power
|
spectral_info.apply_attenuation_db(delta_power)
|
||||||
pwr = pwr._replace(signal=pwr.signal / carrier_att,
|
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2)
|
||||||
nli=pwr.nli / carrier_att,
|
spectral_info.pdl = sqrt(spectral_info.pdl ** 2 + self.params.pdl ** 2)
|
||||||
ase=pwr.ase / carrier_att)
|
|
||||||
pmd = sqrt(carrier.pmd**2 + self.params.pmd**2)
|
|
||||||
yield carrier._replace(power=pwr, pmd=pmd)
|
|
||||||
|
|
||||||
def update_pref(self, pref):
|
def update_pref(self, spectral_info):
|
||||||
return pref._replace(p_span0=pref.p_span0, p_spani=self.effective_pch_out_db)
|
spectral_info.pref = spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0, p_spani=self.pch_out_db)
|
||||||
|
|
||||||
def __call__(self, spectral_info, degree):
|
def __call__(self, spectral_info, degree):
|
||||||
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers, degree=degree))
|
self.propagate(spectral_info, degree=degree)
|
||||||
pref = self.update_pref(spectral_info.pref)
|
self.update_pref(spectral_info)
|
||||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
return spectral_info
|
||||||
|
|
||||||
|
|
||||||
FusedParams = namedtuple('FusedParams', 'loss')
|
|
||||||
|
|
||||||
|
|
||||||
class Fused(_Node):
|
class Fused(_Node):
|
||||||
def __init__(self, *args, params=None, **kwargs):
|
def __init__(self, *args, params=None, **kwargs):
|
||||||
if params is None:
|
if not params:
|
||||||
# default loss value if not mentioned in loaded network json
|
params = {}
|
||||||
params = {'loss': 1}
|
|
||||||
super().__init__(*args, params=FusedParams(**params), **kwargs)
|
super().__init__(*args, params=FusedParams(**params), **kwargs)
|
||||||
self.loss = self.params.loss
|
self.loss = self.params.loss
|
||||||
self.passive = True
|
self.passive = True
|
||||||
@@ -284,23 +306,17 @@ class Fused(_Node):
|
|||||||
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
return '\n'.join([f'{type(self).__name__} {self.uid}',
|
||||||
f' loss (dB): {self.loss:.2f}'])
|
f' loss (dB): {self.loss:.2f}'])
|
||||||
|
|
||||||
def propagate(self, *carriers):
|
def propagate(self, spectral_info):
|
||||||
attenuation = db2lin(self.loss)
|
spectral_info.apply_attenuation_db(self.loss)
|
||||||
|
|
||||||
for carrier in carriers:
|
def update_pref(self, spectral_info):
|
||||||
pwr = carrier.power
|
spectral_info.pref = spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0,
|
||||||
pwr = pwr._replace(signal=pwr.signal / attenuation,
|
p_spani=spectral_info.pref.p_spani - self.loss)
|
||||||
nli=pwr.nli / attenuation,
|
|
||||||
ase=pwr.ase / attenuation)
|
|
||||||
yield carrier._replace(power=pwr)
|
|
||||||
|
|
||||||
def update_pref(self, pref):
|
|
||||||
return pref._replace(p_span0=pref.p_span0, p_spani=pref.p_spani - self.loss)
|
|
||||||
|
|
||||||
def __call__(self, spectral_info):
|
def __call__(self, spectral_info):
|
||||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
self.propagate(spectral_info)
|
||||||
pref = self.update_pref(spectral_info.pref)
|
self.update_pref(spectral_info)
|
||||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
return spectral_info
|
||||||
|
|
||||||
|
|
||||||
class Fiber(_Node):
|
class Fiber(_Node):
|
||||||
@@ -309,7 +325,28 @@ class Fiber(_Node):
|
|||||||
params = {}
|
params = {}
|
||||||
super().__init__(*args, params=FiberParams(**params), **kwargs)
|
super().__init__(*args, params=FiberParams(**params), **kwargs)
|
||||||
self.pch_out_db = None
|
self.pch_out_db = None
|
||||||
self.nli_solver = NliSolver(self)
|
self.passive = True
|
||||||
|
|
||||||
|
# Raman efficiency matrix function of the delta frequency constructed such that each row is related to a
|
||||||
|
# fixed frequency: positive elements represent a gain (from higher frequency) and negative elements represent
|
||||||
|
# a loss (to lower frequency)
|
||||||
|
if self.params.raman_efficiency:
|
||||||
|
frequency_offset = self.params.raman_efficiency['frequency_offset']
|
||||||
|
frequency_offset = append(-flip(frequency_offset[1:]), frequency_offset)
|
||||||
|
cr = self.params.raman_efficiency['cr']
|
||||||
|
cr = append(- flip(cr[1:]), cr)
|
||||||
|
self._cr_function = lambda frequency: interp(frequency, frequency_offset, cr)
|
||||||
|
else:
|
||||||
|
self._cr_function = lambda frequency: zeros(squeeze(frequency).shape)
|
||||||
|
|
||||||
|
# Lumped losses
|
||||||
|
z_lumped_losses = array([lumped['position'] for lumped in self.params.lumped_losses]) # km
|
||||||
|
lumped_losses_power = array([lumped['loss'] for lumped in self.params.lumped_losses]) # dB
|
||||||
|
if not ((z_lumped_losses > 0) * (z_lumped_losses < 1e-3 * self.params.length)).all():
|
||||||
|
raise NetworkTopologyError("Lumped loss positions must be between 0 and the fiber length "
|
||||||
|
f"({1e-3 * self.params.length} km), boundaries excluded.")
|
||||||
|
self.lumped_losses = db2lin(- lumped_losses_power) # [linear units]
|
||||||
|
self.z_lumped_losses = array(z_lumped_losses) * 1e3 # [m]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
@@ -319,7 +356,7 @@ class Fiber(_Node):
|
|||||||
'params': {
|
'params': {
|
||||||
# have to specify each because namedtupple cannot be updated :(
|
# have to specify each because namedtupple cannot be updated :(
|
||||||
'length': round(self.params.length * 1e-3, 6),
|
'length': round(self.params.length * 1e-3, 6),
|
||||||
'loss_coef': self.params.loss_coef * 1e3,
|
'loss_coef': round(self.params.loss_coef * 1e3, 6),
|
||||||
'length_units': 'km',
|
'length_units': 'km',
|
||||||
'att_in': self.params.att_in,
|
'att_in': self.params.att_in,
|
||||||
'con_in': self.params.con_in,
|
'con_in': self.params.con_in,
|
||||||
@@ -348,43 +385,56 @@ class Fiber(_Node):
|
|||||||
f' (conn loss out includes EOL margin defined in eqpt_config.json)',
|
f' (conn loss out includes EOL margin defined in eqpt_config.json)',
|
||||||
f' pch out (dBm): {self.pch_out_db:.2f}'])
|
f' pch out (dBm): {self.pch_out_db:.2f}'])
|
||||||
|
|
||||||
|
def loss_coef_func(self, frequency):
|
||||||
|
frequency = asarray(frequency)
|
||||||
|
if self.params.loss_coef.size > 1:
|
||||||
|
try:
|
||||||
|
loss_coef = interp1d(self.params.f_loss_ref, self.params.loss_coef)(frequency)
|
||||||
|
except ValueError:
|
||||||
|
raise SpectrumError('The spectrum bandwidth exceeds the frequency interval used to define the fiber '
|
||||||
|
f'loss coefficient in "{type(self).__name__} {self.uid}".'
|
||||||
|
f'\nSpectrum f_min-f_max: {round(frequency[0]*1e-12,2)}-'
|
||||||
|
f'{round(frequency[-1]*1e-12,2)}'
|
||||||
|
f'\nLoss coefficient f_min-f_max: {round(self.params.f_loss_ref[0]*1e-12,2)}-'
|
||||||
|
f'{round(self.params.f_loss_ref[-1]*1e-12,2)}')
|
||||||
|
else:
|
||||||
|
loss_coef = full(frequency.size, self.params.loss_coef)
|
||||||
|
return squeeze(loss_coef)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def loss(self):
|
def loss(self):
|
||||||
"""total loss including padding att_in: useful for polymorphism with roadm loss"""
|
"""total loss including padding att_in: useful for polymorphism with roadm loss"""
|
||||||
return self.params.loss_coef * self.params.length + self.params.con_in + self.params.con_out + self.params.att_in
|
return self.loss_coef_func(self.params.ref_frequency) * self.params.length + \
|
||||||
|
self.params.con_in + self.params.con_out + self.params.att_in
|
||||||
|
|
||||||
@property
|
def alpha(self, frequency):
|
||||||
def passive(self):
|
"""Returns the linear exponent attenuation coefficient such that
|
||||||
return True
|
:math: `lin_attenuation = e^{- alpha length}`
|
||||||
|
|
||||||
def alpha(self, frequencies):
|
:param frequency: the frequency at which alpha is computed [Hz]
|
||||||
"""It returns the values of the series expansion of attenuation coefficient alpha(f) for all f in frequencies
|
:return: alpha: power attenuation coefficient for f in frequency [Neper/m]
|
||||||
|
|
||||||
:param frequencies: frequencies of series expansion [Hz]
|
|
||||||
:return: alpha: power attenuation coefficient for f in frequencies [Neper/m]
|
|
||||||
"""
|
"""
|
||||||
if type(self.params.loss_coef) == dict:
|
return self.loss_coef_func(frequency) / (10 * log10(exp(1)))
|
||||||
alpha = interp(frequencies, self.params.f_loss_ref, self.params.lin_loss_exp)
|
|
||||||
else:
|
|
||||||
alpha = self.params.lin_loss_exp * ones(frequencies.shape)
|
|
||||||
|
|
||||||
return alpha
|
def cr(self, frequency):
|
||||||
|
"""Returns the raman efficiency matrix including the vibrational loss
|
||||||
|
|
||||||
def alpha0(self, f_ref=193.5e12):
|
:param frequency: the frequency at which cr is computed [Hz]
|
||||||
"""It returns the zero element of the series expansion of attenuation coefficient alpha(f) in the
|
:return: cr: raman efficiency matrix [1 / (W m)]
|
||||||
reference frequency f_ref
|
|
||||||
|
|
||||||
:param f_ref: reference frequency of series expansion [Hz]
|
|
||||||
:return: alpha0: power attenuation coefficient in f_ref [Neper/m]
|
|
||||||
"""
|
"""
|
||||||
return self.alpha(f_ref * ones(1))[0]
|
df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape))
|
||||||
|
cr = self._cr_function(df)
|
||||||
|
vibrational_loss = outer(frequency, ones(frequency.shape)) / outer(ones(frequency.shape), frequency)
|
||||||
|
return cr * (cr >= 0) + cr * (cr < 0) * vibrational_loss # Raman efficiency [1/(W m)]
|
||||||
|
|
||||||
def chromatic_dispersion(self, freq=193.5e12):
|
def chromatic_dispersion(self, freq=None):
|
||||||
"""Returns accumulated chromatic dispersion (CD).
|
"""Returns accumulated chromatic dispersion (CD).
|
||||||
|
|
||||||
:param freq: the frequency at which the chromatic dispersion is computed
|
:param freq: the frequency at which the chromatic dispersion is computed
|
||||||
:return: chromatic dispersion: the accumulated dispersion [s/m]
|
:return: chromatic dispersion: the accumulated dispersion [s/m]
|
||||||
"""
|
"""
|
||||||
|
freq = self.params.ref_frequency if freq is None else freq
|
||||||
beta2 = self.params.beta2
|
beta2 = self.params.beta2
|
||||||
beta3 = self.params.beta3
|
beta3 = self.params.beta3
|
||||||
ref_f = self.params.ref_frequency
|
ref_f = self.params.ref_frequency
|
||||||
@@ -398,147 +448,103 @@ class Fiber(_Node):
|
|||||||
"""differential group delay (PMD) [s]"""
|
"""differential group delay (PMD) [s]"""
|
||||||
return self.params.pmd_coef * sqrt(self.params.length)
|
return self.params.pmd_coef * sqrt(self.params.length)
|
||||||
|
|
||||||
def _gn_analytic(self, carrier, *carriers):
|
def propagate(self, spectral_info: SpectralInformation):
|
||||||
r"""Computes the nonlinear interference power on a single carrier.
|
"""Modifies the spectral information computing the attenuation, the non-linear interference generation,
|
||||||
The method uses eq. 120 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__.
|
the CD and PMD accumulation.
|
||||||
|
|
||||||
:param carrier: the signal under analysis
|
|
||||||
:param \*carriers: the full WDM comb
|
|
||||||
:return: carrier_nli: the amount of nonlinear interference in W on the under analysis
|
|
||||||
"""
|
"""
|
||||||
|
# apply the attenuation due to the input connector loss
|
||||||
|
attenuation_in_db = self.params.con_in + self.params.att_in
|
||||||
|
spectral_info.apply_attenuation_db(attenuation_in_db)
|
||||||
|
|
||||||
g_nli = 0
|
# inter channels Raman effect
|
||||||
for interfering_carrier in carriers:
|
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(spectral_info, self)
|
||||||
psi = _psi(carrier, interfering_carrier, beta2=self.params.beta2,
|
|
||||||
asymptotic_length=self.params.asymptotic_length)
|
|
||||||
g_nli += (interfering_carrier.power.signal / interfering_carrier.baud_rate)**2 \
|
|
||||||
* (carrier.power.signal / carrier.baud_rate) * psi
|
|
||||||
|
|
||||||
g_nli *= (16 / 27) * (self.params.gamma * self.params.effective_length)**2 \
|
# NLI noise evaluated at the fiber input
|
||||||
/ (2 * pi * abs(self.params.beta2) * self.params.asymptotic_length)
|
spectral_info.nli += NliSolver.compute_nli(spectral_info, stimulated_raman_scattering, self)
|
||||||
|
|
||||||
carrier_nli = carrier.baud_rate * g_nli
|
# chromatic dispersion and pmd variations
|
||||||
return carrier_nli
|
spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency)
|
||||||
|
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2)
|
||||||
|
|
||||||
def propagate(self, *carriers):
|
# apply the attenuation due to the fiber losses
|
||||||
r"""Generator that computes the fiber propagation: attenuation, non-linear interference generation, CD
|
attenuation_fiber = stimulated_raman_scattering.loss_profile[:, -1]
|
||||||
accumulation and PMD accumulation.
|
spectral_info.apply_attenuation_lin(attenuation_fiber)
|
||||||
|
|
||||||
:param: \*carriers: the channels at the input of the fiber
|
# apply the attenuation due to the output connector loss
|
||||||
:yield: carrier: the next channel at the output of the fiber
|
attenuation_out_db = self.params.con_out
|
||||||
"""
|
spectral_info.apply_attenuation_db(attenuation_out_db)
|
||||||
|
|
||||||
# apply connector_att_in on all carriers before computing gn analytics premiere partie pas bonne
|
def update_pref(self, spectral_info):
|
||||||
attenuation = db2lin(self.params.con_in + self.params.att_in)
|
# in case of Raman, the resulting loss of the fiber is not equivalent to self.loss
|
||||||
|
# because of Raman gain. In order to correctly update pref, we need the resulting loss:
|
||||||
chan = []
|
# power_out - power_in. We use the total signal power (sum on all channels) to compute
|
||||||
for carrier in carriers:
|
# this loss, because pref is a noiseless reference.
|
||||||
pwr = carrier.power
|
loss = round(lin2db(self._psig_in / sum(spectral_info.signal)), 2)
|
||||||
pwr = pwr._replace(signal=pwr.signal / attenuation,
|
self.pch_out_db = spectral_info.pref.p_spani - loss
|
||||||
nli=pwr.nli / attenuation,
|
spectral_info.pref = spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0,
|
||||||
ase=pwr.ase / attenuation)
|
p_spani=self.pch_out_db)
|
||||||
carrier = carrier._replace(power=pwr)
|
|
||||||
chan.append(carrier)
|
|
||||||
|
|
||||||
carriers = tuple(f for f in chan)
|
|
||||||
|
|
||||||
# propagate in the fiber and apply attenuation out
|
|
||||||
attenuation = db2lin(self.params.con_out)
|
|
||||||
for carrier in carriers:
|
|
||||||
pwr = carrier.power
|
|
||||||
carrier_nli = self._gn_analytic(carrier, *carriers)
|
|
||||||
pwr = pwr._replace(signal=pwr.signal / self.params.lin_attenuation / attenuation,
|
|
||||||
nli=(pwr.nli + carrier_nli) / self.params.lin_attenuation / attenuation,
|
|
||||||
ase=pwr.ase / self.params.lin_attenuation / attenuation)
|
|
||||||
chromatic_dispersion = carrier.chromatic_dispersion + self.chromatic_dispersion(carrier.frequency)
|
|
||||||
pmd = sqrt(carrier.pmd**2 + self.pmd**2)
|
|
||||||
yield carrier._replace(power=pwr, chromatic_dispersion=chromatic_dispersion, pmd=pmd)
|
|
||||||
|
|
||||||
def update_pref(self, pref):
|
|
||||||
self.pch_out_db = round(pref.p_spani - self.loss, 2)
|
|
||||||
return pref._replace(p_span0=pref.p_span0, p_spani=self.pch_out_db)
|
|
||||||
|
|
||||||
def __call__(self, spectral_info):
|
def __call__(self, spectral_info):
|
||||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
# _psig_in records the total signal power of the spectral information before propagation.
|
||||||
pref = self.update_pref(spectral_info.pref)
|
self._psig_in = sum(spectral_info.signal)
|
||||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
self.propagate(spectral_info)
|
||||||
|
self.update_pref(spectral_info)
|
||||||
|
return spectral_info
|
||||||
|
|
||||||
|
|
||||||
class RamanFiber(Fiber):
|
class RamanFiber(Fiber):
|
||||||
def __init__(self, *args, params=None, **kwargs):
|
def __init__(self, *args, params=None, **kwargs):
|
||||||
super().__init__(*args, params=params, **kwargs)
|
super().__init__(*args, params=params, **kwargs)
|
||||||
if self.operational and 'raman_pumps' in self.operational:
|
if not self.operational:
|
||||||
self.raman_pumps = tuple(PumpParams(p['power'], p['frequency'], p['propagation_direction'])
|
raise NetworkTopologyError(f'Fiber element uid:{self.uid} '
|
||||||
|
'defined as RamanFiber without operational parameters')
|
||||||
|
|
||||||
|
if 'raman_pumps' not in self.operational:
|
||||||
|
raise NetworkTopologyError(f'Fiber element uid:{self.uid} '
|
||||||
|
'defined as RamanFiber without raman pumps description in operational')
|
||||||
|
|
||||||
|
if 'temperature' not in self.operational:
|
||||||
|
raise NetworkTopologyError(f'Fiber element uid:{self.uid} '
|
||||||
|
'defined as RamanFiber without temperature in operational')
|
||||||
|
|
||||||
|
pump_loss = db2lin(self.params.con_out)
|
||||||
|
self.raman_pumps = tuple(PumpParams(p['power'] / pump_loss, p['frequency'], p['propagation_direction'])
|
||||||
for p in self.operational['raman_pumps'])
|
for p in self.operational['raman_pumps'])
|
||||||
else:
|
self.temperature = self.operational['temperature']
|
||||||
self.raman_pumps = None
|
|
||||||
self.raman_solver = RamanSolver(self)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
return dict(super().to_json, operational=self.operational)
|
return dict(super().to_json, operational=self.operational)
|
||||||
|
|
||||||
def update_pref(self, pref, *carriers):
|
def propagate(self, spectral_info: SpectralInformation):
|
||||||
pch_out_db = lin2db(mean([carrier.power.signal for carrier in carriers])) + 30
|
"""Modifies the spectral information computing the attenuation, the non-linear interference generation,
|
||||||
self.pch_out_db = round(pch_out_db, 2)
|
the CD and PMD accumulation.
|
||||||
return pref._replace(p_span0=pref.p_span0, p_spani=self.pch_out_db)
|
"""
|
||||||
|
# apply the attenuation due to the input connector loss
|
||||||
|
attenuation_in_db = self.params.con_in + self.params.att_in
|
||||||
|
spectral_info.apply_attenuation_db(attenuation_in_db)
|
||||||
|
|
||||||
def __call__(self, spectral_info):
|
# Raman pumps and inter channel Raman effect
|
||||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(spectral_info, self)
|
||||||
pref = self.update_pref(spectral_info.pref, *carriers)
|
spontaneous_raman_scattering = \
|
||||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
RamanSolver.calculate_spontaneous_raman_scattering(spectral_info, stimulated_raman_scattering, self)
|
||||||
|
|
||||||
def propagate(self, *carriers):
|
# nli and ase noise evaluated at the fiber input
|
||||||
for propagated_carrier in propagate_raman_fiber(self, *carriers):
|
spectral_info.nli += NliSolver.compute_nli(spectral_info, stimulated_raman_scattering, self)
|
||||||
chromatic_dispersion = propagated_carrier.chromatic_dispersion + \
|
spectral_info.ase += spontaneous_raman_scattering
|
||||||
self.chromatic_dispersion(propagated_carrier.frequency)
|
|
||||||
pmd = sqrt(propagated_carrier.pmd**2 + self.pmd**2)
|
|
||||||
propagated_carrier = propagated_carrier._replace(chromatic_dispersion=chromatic_dispersion, pmd=pmd)
|
|
||||||
yield propagated_carrier
|
|
||||||
|
|
||||||
|
# chromatic dispersion and pmd variations
|
||||||
|
spectral_info.chromatic_dispersion += self.chromatic_dispersion(spectral_info.frequency)
|
||||||
|
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.pmd ** 2)
|
||||||
|
|
||||||
class EdfaParams:
|
# apply the attenuation due to the fiber losses
|
||||||
def __init__(self, **params):
|
attenuation_fiber = stimulated_raman_scattering.loss_profile[:spectral_info.number_of_channels, -1]
|
||||||
self.update_params(params)
|
|
||||||
if params == {}:
|
|
||||||
self.type_variety = ''
|
|
||||||
self.type_def = ''
|
|
||||||
# self.gain_flatmax = 0
|
|
||||||
# self.gain_min = 0
|
|
||||||
# self.p_max = 0
|
|
||||||
# self.nf_model = None
|
|
||||||
# self.nf_fit_coeff = None
|
|
||||||
# self.nf_ripple = None
|
|
||||||
# self.dgt = None
|
|
||||||
# self.gain_ripple = None
|
|
||||||
# self.out_voa_auto = False
|
|
||||||
# self.allowed_for_design = None
|
|
||||||
|
|
||||||
def update_params(self, kwargs):
|
spectral_info.apply_attenuation_lin(attenuation_fiber)
|
||||||
for k, v in kwargs.items():
|
|
||||||
setattr(self, k, self.update_params(**v) if isinstance(v, dict) else v)
|
|
||||||
|
|
||||||
|
# apply the attenuation due to the output connector loss
|
||||||
class EdfaOperational:
|
attenuation_out_db = self.params.con_out
|
||||||
default_values = {
|
spectral_info.apply_attenuation_db(attenuation_out_db)
|
||||||
'gain_target': None,
|
|
||||||
'delta_p': None,
|
|
||||||
'out_voa': None,
|
|
||||||
'tilt_target': 0
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, **operational):
|
|
||||||
self.update_attr(operational)
|
|
||||||
|
|
||||||
def update_attr(self, kwargs):
|
|
||||||
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
|
|
||||||
for k, v in self.default_values.items():
|
|
||||||
setattr(self, k, clean_kwargs.get(k, v))
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return (f'{type(self).__name__}('
|
|
||||||
f'gain_target={self.gain_target!r}, '
|
|
||||||
f'tilt_target={self.tilt_target!r})')
|
|
||||||
|
|
||||||
|
|
||||||
class Edfa(_Node):
|
class Edfa(_Node):
|
||||||
@@ -548,12 +554,7 @@ class Edfa(_Node):
|
|||||||
if operational is None:
|
if operational is None:
|
||||||
operational = {}
|
operational = {}
|
||||||
self.variety_list = kwargs.pop('variety_list', None)
|
self.variety_list = kwargs.pop('variety_list', None)
|
||||||
super().__init__(
|
super().__init__(*args, params=EdfaParams(**params), operational=EdfaOperational(**operational), **kwargs)
|
||||||
*args,
|
|
||||||
params=EdfaParams(**params),
|
|
||||||
operational=EdfaOperational(**operational),
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
self.interpol_dgt = None # interpolated dynamic gain tilt
|
self.interpol_dgt = None # interpolated dynamic gain tilt
|
||||||
self.interpol_gain_ripple = None # gain ripple
|
self.interpol_gain_ripple = None # gain ripple
|
||||||
self.interpol_nf_ripple = None # nf_ripple
|
self.interpol_nf_ripple = None # nf_ripple
|
||||||
@@ -579,7 +580,7 @@ class Edfa(_Node):
|
|||||||
'type': type(self).__name__,
|
'type': type(self).__name__,
|
||||||
'type_variety': self.params.type_variety,
|
'type_variety': self.params.type_variety,
|
||||||
'operational': {
|
'operational': {
|
||||||
'gain_target': self.effective_gain,
|
'gain_target': round(self.effective_gain, 6),
|
||||||
'delta_p': self.delta_p,
|
'delta_p': self.delta_p,
|
||||||
'tilt_target': self.tilt_target,
|
'tilt_target': self.tilt_target,
|
||||||
'out_voa': self.out_voa
|
'out_voa': self.out_voa
|
||||||
@@ -614,31 +615,38 @@ class Edfa(_Node):
|
|||||||
f' pad att_in (dB): {self.att_in:.2f}',
|
f' pad att_in (dB): {self.att_in:.2f}',
|
||||||
f' Power In (dBm): {self.pin_db:.2f}',
|
f' Power In (dBm): {self.pin_db:.2f}',
|
||||||
f' Power Out (dBm): {self.pout_db:.2f}',
|
f' Power Out (dBm): {self.pout_db:.2f}',
|
||||||
f' Delta_P (dB): ' + f'{self.delta_p:.2f}' if self.delta_p is not None else 'None',
|
f' Delta_P (dB): ' + (f'{self.delta_p:.2f}' if self.delta_p is not None else 'None'),
|
||||||
f' target pch (dBm): ' + f'{self.target_pch_out_db:.2f}' if self.target_pch_out_db is not None else 'None',
|
f' target pch (dBm): ' + (f'{self.target_pch_out_db:.2f}' if self.target_pch_out_db is not None else 'None'),
|
||||||
f' effective pch (dBm): {self.effective_pch_out_db:.2f}',
|
f' effective pch (dBm): {self.effective_pch_out_db:.2f}',
|
||||||
f' output VOA (dB): {self.out_voa:.2f}'])
|
f' output VOA (dB): {self.out_voa:.2f}'])
|
||||||
|
|
||||||
def interpol_params(self, frequencies, pin, baud_rates, pref):
|
def interpol_params(self, spectral_info):
|
||||||
"""interpolate SI channel frequencies with the edfa dgt and gain_ripple frquencies from JSON
|
"""interpolate SI channel frequencies with the edfa dgt and gain_ripple frquencies from JSON
|
||||||
|
:param spectral_info: instance of gnpy.core.info.SpectralInformation
|
||||||
|
:return: None
|
||||||
"""
|
"""
|
||||||
# TODO|jla: read amplifier actual frequencies from additional params in json
|
# TODO|jla: read amplifier actual frequencies from additional params in json
|
||||||
self.channel_freq = frequencies
|
|
||||||
|
|
||||||
|
self.channel_freq = spectral_info.frequency
|
||||||
amplifier_freq = arrange_frequencies(len(self.params.dgt), self.params.f_min, self.params.f_max) # Hz
|
amplifier_freq = arrange_frequencies(len(self.params.dgt), self.params.f_min, self.params.f_max) # Hz
|
||||||
self.interpol_dgt = interp(self.channel_freq, amplifier_freq, self.params.dgt)
|
self.interpol_dgt = interp(spectral_info.frequency, amplifier_freq, self.params.dgt)
|
||||||
|
|
||||||
amplifier_freq = arrange_frequencies(len(self.params.gain_ripple), self.params.f_min, self.params.f_max) # Hz
|
amplifier_freq = arrange_frequencies(len(self.params.gain_ripple), self.params.f_min, self.params.f_max) # Hz
|
||||||
self.interpol_gain_ripple = interp(self.channel_freq, amplifier_freq, self.params.gain_ripple)
|
self.interpol_gain_ripple = interp(spectral_info.frequency, amplifier_freq, self.params.gain_ripple)
|
||||||
|
|
||||||
amplifier_freq = arrange_frequencies(len(self.params.nf_ripple), self.params.f_min, self.params.f_max) # Hz
|
amplifier_freq = arrange_frequencies(len(self.params.nf_ripple), self.params.f_min, self.params.f_max) # Hz
|
||||||
self.interpol_nf_ripple = interp(self.channel_freq, amplifier_freq, self.params.nf_ripple)
|
self.interpol_nf_ripple = interp(spectral_info.frequency, amplifier_freq, self.params.nf_ripple)
|
||||||
|
|
||||||
self.nch = frequencies.size
|
self.nch = spectral_info.number_of_channels
|
||||||
|
pin = spectral_info.signal + spectral_info.ase + spectral_info.nli
|
||||||
self.pin_db = lin2db(sum(pin * 1e3))
|
self.pin_db = lin2db(sum(pin * 1e3))
|
||||||
|
# The following should be changed when we have the new spectral information including slot widths.
|
||||||
|
# For now, with homogeneous spectrum, we can calculate it as the difference between neighbouring channels.
|
||||||
|
self.slot_width = self.channel_freq[1] - self.channel_freq[0]
|
||||||
|
|
||||||
"""in power mode: delta_p is defined and can be used to calculate the power target
|
"""in power mode: delta_p is defined and can be used to calculate the power target
|
||||||
This power target is used calculate the amplifier gain"""
|
This power target is used calculate the amplifier gain"""
|
||||||
|
pref = spectral_info.pref
|
||||||
if self.delta_p is not None:
|
if self.delta_p is not None:
|
||||||
self.target_pch_out_db = round(self.delta_p + pref.p_span0, 2)
|
self.target_pch_out_db = round(self.delta_p + pref.p_span0, 2)
|
||||||
self.effective_gain = self.target_pch_out_db - pref.p_spani
|
self.effective_gain = self.target_pch_out_db - pref.p_spani
|
||||||
@@ -656,7 +664,7 @@ class Edfa(_Node):
|
|||||||
self.nf = self._calc_nf()
|
self.nf = self._calc_nf()
|
||||||
self.gprofile = self._gain_profile(pin)
|
self.gprofile = self._gain_profile(pin)
|
||||||
|
|
||||||
pout = (pin + self.noise_profile(baud_rates)) * db2lin(self.gprofile)
|
pout = (pin + self.noise_profile(spectral_info)) * db2lin(self.gprofile)
|
||||||
self.pout_db = lin2db(sum(pout * 1e3))
|
self.pout_db = lin2db(sum(pout * 1e3))
|
||||||
# ase & nli are only calculated in signal bandwidth
|
# ase & nli are only calculated in signal bandwidth
|
||||||
# pout_db is not the absolute full output power (negligible if sufficient channels)
|
# pout_db is not the absolute full output power (negligible if sufficient channels)
|
||||||
@@ -673,13 +681,17 @@ class Edfa(_Node):
|
|||||||
elif type_def == 'fixed_gain':
|
elif type_def == 'fixed_gain':
|
||||||
nf_avg = nf_model.nf0
|
nf_avg = nf_model.nf0
|
||||||
elif type_def == 'openroadm':
|
elif type_def == 'openroadm':
|
||||||
pin_ch = self.pin_db - lin2db(self.nch)
|
# OpenROADM specifies OSNR vs. input power per channel for 50 GHz slot width so we
|
||||||
# model OSNR = f(Pin)
|
# scale it to 50 GHz based on actual slot width.
|
||||||
nf_avg = pin_ch - polyval(nf_model.nf_coef, pin_ch) + 58
|
pin_ch_50GHz = self.pin_db - lin2db(self.nch) + lin2db(50e9 / self.slot_width)
|
||||||
|
# model OSNR = f(Pin per 50 GHz channel)
|
||||||
|
nf_avg = pin_ch_50GHz - polyval(nf_model.nf_coef, pin_ch_50GHz) + 58
|
||||||
elif type_def == 'openroadm_preamp':
|
elif type_def == 'openroadm_preamp':
|
||||||
pin_ch = self.pin_db - lin2db(self.nch)
|
# OpenROADM specifies OSNR vs. input power per channel for 50 GHz slot width so we
|
||||||
# model OSNR = f(Pin)
|
# scale it to 50 GHz based on actual slot width.
|
||||||
nf_avg = pin_ch - min((4 * pin_ch + 275) / 7, 33) + 58
|
pin_ch_50GHz = self.pin_db - lin2db(self.nch) + lin2db(50e9 / self.slot_width)
|
||||||
|
# model OSNR = f(Pin per 50 GHz channel)
|
||||||
|
nf_avg = pin_ch_50GHz - min((4 * pin_ch_50GHz + 275) / 7, 33) + 58
|
||||||
elif type_def == 'openroadm_booster':
|
elif type_def == 'openroadm_booster':
|
||||||
# model a zero-noise amp with "infinitely negative" (in dB) NF
|
# model a zero-noise amp with "infinitely negative" (in dB) NF
|
||||||
nf_avg = float('-inf')
|
nf_avg = float('-inf')
|
||||||
@@ -725,13 +737,8 @@ class Edfa(_Node):
|
|||||||
else:
|
else:
|
||||||
return self.interpol_nf_ripple + nf_avg # input VOA = 1 for 1 NF degradation
|
return self.interpol_nf_ripple + nf_avg # input VOA = 1 for 1 NF degradation
|
||||||
|
|
||||||
def noise_profile(self, df):
|
def noise_profile(self, spectral_info: SpectralInformation):
|
||||||
"""noise_profile(bw) computes amplifier ASE (W) in signal bandwidth (Hz)
|
"""Computes amplifier ASE noise integrated over the signal bandwidth. This is calculated at amplifier input.
|
||||||
|
|
||||||
Noise is calculated at amplifier input
|
|
||||||
|
|
||||||
:bw: signal bandwidth = baud rate in Hz
|
|
||||||
:type bw: float
|
|
||||||
|
|
||||||
:return: the asepower in W in the signal bandwidth bw for 96 channels
|
:return: the asepower in W in the signal bandwidth bw for 96 channels
|
||||||
:return type: numpy array of float
|
:return type: numpy array of float
|
||||||
@@ -767,7 +774,7 @@ class Edfa(_Node):
|
|||||||
quoting power spectral density in the same BW for both signal and ASE,
|
quoting power spectral density in the same BW for both signal and ASE,
|
||||||
e.g. 12.5GHz."""
|
e.g. 12.5GHz."""
|
||||||
|
|
||||||
ase = h * df * self.channel_freq * db2lin(self.nf) # W
|
ase = h * spectral_info.baud_rate * spectral_info.frequency * db2lin(self.nf) # W
|
||||||
return ase # in W at amplifier input
|
return ase # in W at amplifier input
|
||||||
|
|
||||||
def _gain_profile(self, pin, err_tolerance=1.0e-11, simple_opt=True):
|
def _gain_profile(self, pin, err_tolerance=1.0e-11, simple_opt=True):
|
||||||
@@ -873,30 +880,24 @@ class Edfa(_Node):
|
|||||||
|
|
||||||
return g1st - voa + array(self.interpol_dgt) * dgts3
|
return g1st - voa + array(self.interpol_dgt) * dgts3
|
||||||
|
|
||||||
def propagate(self, pref, *carriers):
|
def propagate(self, spectral_info):
|
||||||
"""add ASE noise to the propagating carriers of :class:`.info.SpectralInformation`"""
|
"""add ASE noise to the propagating carriers of :class:`.info.SpectralInformation`"""
|
||||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in carriers]) # pin in W
|
|
||||||
freq = array([c.frequency for c in carriers])
|
|
||||||
brate = array([c.baud_rate for c in carriers])
|
|
||||||
# interpolate the amplifier vectors with the carriers freq, calculate nf & gain profile
|
# interpolate the amplifier vectors with the carriers freq, calculate nf & gain profile
|
||||||
self.interpol_params(freq, pin, brate, pref)
|
self.interpol_params(spectral_info)
|
||||||
|
|
||||||
gains = db2lin(self.gprofile)
|
ase = self.noise_profile(spectral_info)
|
||||||
carrier_ases = self.noise_profile(brate)
|
spectral_info.ase += ase
|
||||||
att = db2lin(self.out_voa)
|
|
||||||
|
|
||||||
for gain, carrier_ase, carrier in zip(gains, carrier_ases, carriers):
|
spectral_info.apply_gain_db(self.gprofile - self.out_voa)
|
||||||
pwr = carrier.power
|
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2)
|
||||||
pwr = pwr._replace(signal=pwr.signal * gain / att,
|
spectral_info.pdl = sqrt(spectral_info.pdl ** 2 + self.params.pdl ** 2)
|
||||||
nli=pwr.nli * gain / att,
|
|
||||||
ase=(pwr.ase + carrier_ase) * gain / att)
|
|
||||||
yield carrier._replace(power=pwr)
|
|
||||||
|
|
||||||
def update_pref(self, pref):
|
def update_pref(self, spectral_info):
|
||||||
return pref._replace(p_span0=pref.p_span0,
|
spectral_info.pref = \
|
||||||
p_spani=pref.p_spani + self.effective_gain - self.out_voa)
|
spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0,
|
||||||
|
p_spani=spectral_info.pref.p_spani + self.effective_gain - self.out_voa)
|
||||||
|
|
||||||
def __call__(self, spectral_info):
|
def __call__(self, spectral_info):
|
||||||
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers))
|
self.propagate(spectral_info)
|
||||||
pref = self.update_pref(spectral_info.pref)
|
self.update_pref(spectral_info)
|
||||||
return spectral_info._replace(carriers=carriers, pref=pref)
|
return spectral_info
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F
|
|||||||
mode_params = {"format": "undetermined",
|
mode_params = {"format": "undetermined",
|
||||||
"baud_rate": None,
|
"baud_rate": None,
|
||||||
"OSNR": None,
|
"OSNR": None,
|
||||||
|
"penalties": None,
|
||||||
"bit_rate": None,
|
"bit_rate": None,
|
||||||
"roll_off": None,
|
"roll_off": None,
|
||||||
"tx_osnr": None,
|
"tx_osnr": None,
|
||||||
@@ -59,6 +60,7 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F
|
|||||||
trx_params['baud_rate'] = default_si_data.baud_rate
|
trx_params['baud_rate'] = default_si_data.baud_rate
|
||||||
trx_params['spacing'] = default_si_data.spacing
|
trx_params['spacing'] = default_si_data.spacing
|
||||||
trx_params['OSNR'] = None
|
trx_params['OSNR'] = None
|
||||||
|
trx_params['penalties'] = {}
|
||||||
trx_params['bit_rate'] = None
|
trx_params['bit_rate'] = None
|
||||||
trx_params['cost'] = None
|
trx_params['cost'] = None
|
||||||
trx_params['roll_off'] = default_si_data.roll_off
|
trx_params['roll_off'] = default_si_data.roll_off
|
||||||
|
|||||||
@@ -8,24 +8,36 @@ gnpy.core.info
|
|||||||
This module contains classes for modelling :class:`SpectralInformation`.
|
This module contains classes for modelling :class:`SpectralInformation`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from gnpy.core.utils import automatic_nch, lin2db
|
from collections.abc import Iterable
|
||||||
|
from typing import Union
|
||||||
|
from numpy import argsort, mean, array, append, ones, ceil, any, zeros, outer, full, ndarray, asarray
|
||||||
|
|
||||||
|
from gnpy.core.utils import automatic_nch, lin2db, db2lin
|
||||||
|
from gnpy.core.exceptions import SpectrumError
|
||||||
|
|
||||||
|
DEFAULT_SLOT_WIDTH_STEP = 12.5e9 # Hz
|
||||||
|
"""Channels with unspecified slot width will have their slot width evaluated as the baud rate rounded up to the minimum
|
||||||
|
multiple of the DEFAULT_SLOT_WIDTH_STEP (the baud rate is extended including the roll off in this evaluation)"""
|
||||||
|
|
||||||
|
|
||||||
class Power(namedtuple('Power', 'signal nli ase')):
|
class Power(namedtuple('Power', 'signal nli ase')):
|
||||||
"""carriers power in W"""
|
"""carriers power in W"""
|
||||||
|
|
||||||
|
|
||||||
class Channel(namedtuple('Channel', 'channel_number frequency baud_rate roll_off power chromatic_dispersion pmd')):
|
class Channel(namedtuple('Channel',
|
||||||
|
'channel_number frequency baud_rate slot_width roll_off power chromatic_dispersion pmd pdl')):
|
||||||
""" Class containing the parameters of a WDM signal.
|
""" Class containing the parameters of a WDM signal.
|
||||||
|
|
||||||
:param channel_number: channel number in the WDM grid
|
:param channel_number: channel number in the WDM grid
|
||||||
:param frequency: central frequency of the signal (Hz)
|
:param frequency: central frequency of the signal (Hz)
|
||||||
:param baud_rate: the symbol rate of the signal (Baud)
|
:param baud_rate: the symbol rate of the signal (Baud)
|
||||||
|
:param slot_width: the slot width (Hz)
|
||||||
:param roll_off: the roll off of the signal. It is a pure number between 0 and 1
|
:param roll_off: the roll off of the signal. It is a pure number between 0 and 1
|
||||||
:param power (gnpy.core.info.Power): power of signal, ASE noise and NLI (W)
|
:param power (gnpy.core.info.Power): power of signal, ASE noise and NLI (W)
|
||||||
:param chromatic_dispersion: chromatic dispersion (s/m)
|
:param chromatic_dispersion: chromatic dispersion (s/m)
|
||||||
:param pmd: polarization mode dispersion (s)
|
:param pmd: polarization mode dispersion (s)
|
||||||
|
:param pdl: polarization dependent loss (dB)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@@ -36,21 +48,217 @@ class Pref(namedtuple('Pref', 'p_span0, p_spani, neq_ch ')):
|
|||||||
neq_ch: equivalent channel count in dB"""
|
neq_ch: equivalent channel count in dB"""
|
||||||
|
|
||||||
|
|
||||||
class SpectralInformation(namedtuple('SpectralInformation', 'pref carriers')):
|
class SpectralInformation(object):
|
||||||
|
""" Class containing the parameters of the entire WDM comb."""
|
||||||
|
|
||||||
def __new__(cls, pref, carriers):
|
def __init__(self, frequency: array, baud_rate: array, slot_width: array, signal: array, nli: array, ase: array,
|
||||||
return super().__new__(cls, pref, carriers)
|
roll_off: array, chromatic_dispersion: array, pmd: array, pdl: array):
|
||||||
|
indices = argsort(frequency)
|
||||||
|
self._frequency = frequency[indices]
|
||||||
|
self._df = outer(ones(frequency.shape), frequency) - outer(frequency, ones(frequency.shape))
|
||||||
|
self._number_of_channels = len(self._frequency)
|
||||||
|
self._channel_number = [*range(1, self._number_of_channels + 1)]
|
||||||
|
self._slot_width = slot_width[indices]
|
||||||
|
self._baud_rate = baud_rate[indices]
|
||||||
|
overlap = self._frequency[:-1] + self._slot_width[:-1] / 2 > self._frequency[1:] - self._slot_width[1:] / 2
|
||||||
|
if any(overlap):
|
||||||
|
overlap = [pair for pair in zip(overlap * self._channel_number[:-1], overlap * self._channel_number[1:])
|
||||||
|
if pair != (0, 0)]
|
||||||
|
raise SpectrumError(f'Spectrum required slot widths larger than the frequency spectral distances '
|
||||||
|
f'between channels: {overlap}.')
|
||||||
|
exceed = self._baud_rate > self._slot_width
|
||||||
|
if any(exceed):
|
||||||
|
raise SpectrumError(f'Spectrum baud rate, including the roll off, larger than the slot width for channels: '
|
||||||
|
f'{[ch for ch in exceed * self._channel_number if ch]}.')
|
||||||
|
self._signal = signal[indices]
|
||||||
|
self._nli = nli[indices]
|
||||||
|
self._ase = ase[indices]
|
||||||
|
self._roll_off = roll_off[indices]
|
||||||
|
self._chromatic_dispersion = chromatic_dispersion[indices]
|
||||||
|
self._pmd = pmd[indices]
|
||||||
|
self._pdl = pdl[indices]
|
||||||
|
pref = lin2db(mean(signal) * 1e3)
|
||||||
|
self._pref = Pref(pref, pref, lin2db(self._number_of_channels))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pref(self):
|
||||||
|
"""Instance of gnpy.info.Pref"""
|
||||||
|
return self._pref
|
||||||
|
|
||||||
|
@pref.setter
|
||||||
|
def pref(self, pref: Pref):
|
||||||
|
self._pref = pref
|
||||||
|
|
||||||
|
@property
|
||||||
|
def frequency(self):
|
||||||
|
return self._frequency
|
||||||
|
|
||||||
|
@property
|
||||||
|
def df(self):
|
||||||
|
"""Matrix of relative frequency distances between all channels. Positive elements in the upper right side."""
|
||||||
|
return self._df
|
||||||
|
|
||||||
|
@property
|
||||||
|
def slot_width(self):
|
||||||
|
return self._slot_width
|
||||||
|
|
||||||
|
@property
|
||||||
|
def baud_rate(self):
|
||||||
|
return self._baud_rate
|
||||||
|
|
||||||
|
@property
|
||||||
|
def number_of_channels(self):
|
||||||
|
return self._number_of_channels
|
||||||
|
|
||||||
|
@property
|
||||||
|
def powers(self):
|
||||||
|
powers = zip(self.signal, self.nli, self.ase)
|
||||||
|
return [Power(*p) for p in powers]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signal(self):
|
||||||
|
return self._signal
|
||||||
|
|
||||||
|
@signal.setter
|
||||||
|
def signal(self, signal):
|
||||||
|
self._signal = signal
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nli(self):
|
||||||
|
return self._nli
|
||||||
|
|
||||||
|
@nli.setter
|
||||||
|
def nli(self, nli):
|
||||||
|
self._nli = nli
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ase(self):
|
||||||
|
return self._ase
|
||||||
|
|
||||||
|
@ase.setter
|
||||||
|
def ase(self, ase):
|
||||||
|
self._ase = ase
|
||||||
|
|
||||||
|
@property
|
||||||
|
def roll_off(self):
|
||||||
|
return self._roll_off
|
||||||
|
|
||||||
|
@property
|
||||||
|
def chromatic_dispersion(self):
|
||||||
|
return self._chromatic_dispersion
|
||||||
|
|
||||||
|
@chromatic_dispersion.setter
|
||||||
|
def chromatic_dispersion(self, chromatic_dispersion):
|
||||||
|
self._chromatic_dispersion = chromatic_dispersion
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pmd(self):
|
||||||
|
return self._pmd
|
||||||
|
|
||||||
|
@pmd.setter
|
||||||
|
def pmd(self, pmd):
|
||||||
|
self._pmd = pmd
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pdl(self):
|
||||||
|
return self._pdl
|
||||||
|
|
||||||
|
@pdl.setter
|
||||||
|
def pdl(self, pdl):
|
||||||
|
self._pdl = pdl
|
||||||
|
|
||||||
|
@property
|
||||||
|
def channel_number(self):
|
||||||
|
return self._channel_number
|
||||||
|
|
||||||
|
@property
|
||||||
|
def carriers(self):
|
||||||
|
entries = zip(self.channel_number, self.frequency, self.baud_rate, self.slot_width,
|
||||||
|
self.roll_off, self.powers, self.chromatic_dispersion, self.pmd, self.pdl)
|
||||||
|
return [Channel(*entry) for entry in entries]
|
||||||
|
|
||||||
|
def apply_attenuation_lin(self, attenuation_lin):
|
||||||
|
self.signal *= attenuation_lin
|
||||||
|
self.nli *= attenuation_lin
|
||||||
|
self.ase *= attenuation_lin
|
||||||
|
|
||||||
|
def apply_attenuation_db(self, attenuation_db):
|
||||||
|
attenuation_lin = 1 / db2lin(attenuation_db)
|
||||||
|
self.apply_attenuation_lin(attenuation_lin)
|
||||||
|
|
||||||
|
def apply_gain_lin(self, gain_lin):
|
||||||
|
self.signal *= gain_lin
|
||||||
|
self.nli *= gain_lin
|
||||||
|
self.ase *= gain_lin
|
||||||
|
|
||||||
|
def apply_gain_db(self, gain_db):
|
||||||
|
gain_lin = db2lin(gain_db)
|
||||||
|
self.apply_gain_lin(gain_lin)
|
||||||
|
|
||||||
|
def __add__(self, other: SpectralInformation):
|
||||||
|
try:
|
||||||
|
return SpectralInformation(frequency=append(self.frequency, other.frequency),
|
||||||
|
slot_width=append(self.slot_width, other.slot_width),
|
||||||
|
signal=append(self.signal, other.signal), nli=append(self.nli, other.nli),
|
||||||
|
ase=append(self.ase, other.ase),
|
||||||
|
baud_rate=append(self.baud_rate, other.baud_rate),
|
||||||
|
roll_off=append(self.roll_off, other.roll_off),
|
||||||
|
chromatic_dispersion=append(self.chromatic_dispersion,
|
||||||
|
other.chromatic_dispersion),
|
||||||
|
pmd=append(self.pmd, other.pmd),
|
||||||
|
pdl=append(self.pdl, other.pdl))
|
||||||
|
except SpectrumError:
|
||||||
|
raise SpectrumError('Spectra cannot be summed: channels overlapping.')
|
||||||
|
|
||||||
|
def _replace(self, carriers, pref):
|
||||||
|
self.chromatic_dispersion = array([c.chromatic_dispersion for c in carriers])
|
||||||
|
self.pmd = array([c.pmd for c in carriers])
|
||||||
|
self.pdl = array([c.pdl for c in carriers])
|
||||||
|
self.signal = array([c.power.signal for c in carriers])
|
||||||
|
self.nli = array([c.power.nli for c in carriers])
|
||||||
|
self.ase = array([c.power.ase for c in carriers])
|
||||||
|
self.pref = pref
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
def create_arbitrary_spectral_information(frequency: Union[ndarray, Iterable, int, float],
|
||||||
|
signal: Union[int, float, ndarray, Iterable],
|
||||||
|
baud_rate: Union[int, float, ndarray, Iterable],
|
||||||
|
slot_width: Union[int, float, ndarray, Iterable] = None,
|
||||||
|
roll_off: Union[int, float, ndarray, Iterable] = 0.,
|
||||||
|
chromatic_dispersion: Union[int, float, ndarray, Iterable] = 0.,
|
||||||
|
pmd: Union[int, float, ndarray, Iterable] = 0.,
|
||||||
|
pdl: Union[int, float, ndarray, Iterable] = 0.):
|
||||||
|
"""This is just a wrapper around the SpectralInformation.__init__() that simplifies the creation of
|
||||||
|
a non-uniform spectral information with NLI and ASE powers set to zero."""
|
||||||
|
frequency = asarray(frequency)
|
||||||
|
number_of_channels = frequency.size
|
||||||
|
try:
|
||||||
|
signal = full(number_of_channels, signal)
|
||||||
|
baud_rate = full(number_of_channels, baud_rate)
|
||||||
|
roll_off = full(number_of_channels, roll_off)
|
||||||
|
slot_width = full(number_of_channels, slot_width) if slot_width is not None else \
|
||||||
|
ceil((1 + roll_off) * baud_rate / DEFAULT_SLOT_WIDTH_STEP) * DEFAULT_SLOT_WIDTH_STEP
|
||||||
|
chromatic_dispersion = full(number_of_channels, chromatic_dispersion)
|
||||||
|
pmd = full(number_of_channels, pmd)
|
||||||
|
pdl = full(number_of_channels, pdl)
|
||||||
|
nli = zeros(number_of_channels)
|
||||||
|
ase = zeros(number_of_channels)
|
||||||
|
return SpectralInformation(frequency=frequency, slot_width=slot_width,
|
||||||
|
signal=signal, nli=nli, ase=ase,
|
||||||
|
baud_rate=baud_rate, roll_off=roll_off,
|
||||||
|
chromatic_dispersion=chromatic_dispersion,
|
||||||
|
pmd=pmd, pdl=pdl)
|
||||||
|
except ValueError as e:
|
||||||
|
if 'could not broadcast' in str(e):
|
||||||
|
raise SpectrumError('Dimension mismatch in input fields.')
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing):
|
def create_input_spectral_information(f_min, f_max, roll_off, baud_rate, power, spacing):
|
||||||
# pref in dB : convert power lin into power in dB
|
""" Creates a fixed slot width spectral information with flat power """
|
||||||
pref = lin2db(power * 1e3)
|
|
||||||
nb_channel = automatic_nch(f_min, f_max, spacing)
|
nb_channel = automatic_nch(f_min, f_max, spacing)
|
||||||
si = SpectralInformation(
|
frequency = [(f_min + spacing * i) for i in range(1, nb_channel + 1)]
|
||||||
pref=Pref(pref, pref, lin2db(nb_channel)),
|
return create_arbitrary_spectral_information(frequency, slot_width=spacing, signal=power, baud_rate=baud_rate,
|
||||||
carriers=[
|
roll_off=roll_off)
|
||||||
Channel(f, (f_min + spacing * f),
|
|
||||||
baud_rate, roll_off, Power(power, 0, 0), 0, 0) for f in range(1, nb_channel + 1)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
return si
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ def edfa_nf(gain_target, variety_type, equipment):
|
|||||||
)
|
)
|
||||||
amp.pin_db = 0
|
amp.pin_db = 0
|
||||||
amp.nch = 88
|
amp.nch = 88
|
||||||
|
amp.slot_width = 50e9
|
||||||
return amp._calc_nf(True)
|
return amp._calc_nf(True)
|
||||||
|
|
||||||
|
|
||||||
@@ -269,7 +270,7 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
|
|||||||
node_loss = span_loss(network, prev_node)
|
node_loss = span_loss(network, prev_node)
|
||||||
voa = node.out_voa if node.out_voa else 0
|
voa = node.out_voa if node.out_voa else 0
|
||||||
if node.delta_p is None:
|
if node.delta_p is None:
|
||||||
dp = target_power(network, next_node, equipment)
|
dp = target_power(network, next_node, equipment) + voa
|
||||||
else:
|
else:
|
||||||
dp = node.delta_p
|
dp = node.delta_p
|
||||||
if node.effective_gain is None or power_mode:
|
if node.effective_gain is None or power_mode:
|
||||||
@@ -282,7 +283,7 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
|
|||||||
|
|
||||||
if isinstance(prev_node, elements.Fiber):
|
if isinstance(prev_node, elements.Fiber):
|
||||||
max_fiber_lineic_loss_for_raman = \
|
max_fiber_lineic_loss_for_raman = \
|
||||||
equipment['Span']['default'].max_fiber_lineic_loss_for_raman
|
equipment['Span']['default'].max_fiber_lineic_loss_for_raman * 1e-3 # dB/m
|
||||||
raman_allowed = prev_node.params.loss_coef < max_fiber_lineic_loss_for_raman
|
raman_allowed = prev_node.params.loss_coef < max_fiber_lineic_loss_for_raman
|
||||||
else:
|
else:
|
||||||
raman_allowed = False
|
raman_allowed = False
|
||||||
@@ -303,9 +304,14 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
|
|||||||
node.params.update_params(extra_params.__dict__)
|
node.params.update_params(extra_params.__dict__)
|
||||||
dp += power_reduction
|
dp += power_reduction
|
||||||
gain_target += power_reduction
|
gain_target += power_reduction
|
||||||
elif node.params.raman and not raman_allowed:
|
|
||||||
print(f'{ansi_escapes.red}WARNING{ansi_escapes.reset}: raman is used in node {node.uid}\n but fiber lineic loss is above threshold\n')
|
|
||||||
else:
|
else:
|
||||||
|
if node.params.raman and not raman_allowed:
|
||||||
|
if isinstance(prev_node, elements.Fiber):
|
||||||
|
print(f'{ansi_escapes.red}WARNING{ansi_escapes.reset}: raman is used in node {node.uid}\n '
|
||||||
|
'but fiber lineic loss is above threshold\n')
|
||||||
|
else:
|
||||||
|
print(f'{ansi_escapes.red}WARNING{ansi_escapes.reset}: raman is used in node {node.uid}\n '
|
||||||
|
'but previous node is not a fiber\n')
|
||||||
# if variety is imposed by user, and if the gain_target (computed or imposed) is also above
|
# if variety is imposed by user, and if the gain_target (computed or imposed) is also above
|
||||||
# variety max gain + extended range, then warn that gain > max_gain + extended range
|
# variety max gain + extended range, then warn that gain > max_gain + extended range
|
||||||
if gain_target - equipment['Edfa'][node.params.type_variety].gain_flatmax - \
|
if gain_target - equipment['Edfa'][node.params.type_variety].gain_flatmax - \
|
||||||
@@ -511,23 +517,25 @@ def add_fiber_padding(network, fibers, padding):
|
|||||||
first_fiber.params.att_in = first_fiber.params.att_in + padding - this_span_loss
|
first_fiber.params.att_in = first_fiber.params.att_in + padding - this_span_loss
|
||||||
|
|
||||||
|
|
||||||
def build_network(network, equipment, pref_ch_db, pref_total_db):
|
def build_network(network, equipment, pref_ch_db, pref_total_db, no_insert_edfas=False):
|
||||||
default_span_data = equipment['Span']['default']
|
default_span_data = equipment['Span']['default']
|
||||||
max_length = int(convert_length(default_span_data.max_length, default_span_data.length_units))
|
max_length = int(convert_length(default_span_data.max_length, default_span_data.length_units))
|
||||||
min_length = max(int(default_span_data.padding / 0.2 * 1e3), 50_000)
|
min_length = max(int(default_span_data.padding / 0.2 * 1e3), 50_000)
|
||||||
bounds = range(min_length, max_length)
|
bounds = range(min_length, max_length)
|
||||||
target_length = max(min_length, 90_000)
|
target_length = max(min_length, min(max_length, 90_000))
|
||||||
|
|
||||||
# set roadm loss for gain_mode before to build network
|
# set roadm loss for gain_mode before to build network
|
||||||
fibers = [f for f in network.nodes() if isinstance(f, elements.Fiber)]
|
fibers = [f for f in network.nodes() if isinstance(f, elements.Fiber)]
|
||||||
add_connector_loss(network, fibers, default_span_data.con_in, default_span_data.con_out, default_span_data.EOL)
|
add_connector_loss(network, fibers, default_span_data.con_in, default_span_data.con_out, default_span_data.EOL)
|
||||||
add_fiber_padding(network, fibers, default_span_data.padding)
|
|
||||||
# don't group split fiber and add amp in the same loop
|
# don't group split fiber and add amp in the same loop
|
||||||
# =>for code clarity (at the expense of speed):
|
# =>for code clarity (at the expense of speed):
|
||||||
|
|
||||||
|
roadms = [r for r in network.nodes() if isinstance(r, elements.Roadm)]
|
||||||
|
|
||||||
|
if not no_insert_edfas:
|
||||||
for fiber in fibers:
|
for fiber in fibers:
|
||||||
split_fiber(network, fiber, bounds, target_length, equipment)
|
split_fiber(network, fiber, bounds, target_length, equipment)
|
||||||
|
|
||||||
roadms = [r for r in network.nodes() if isinstance(r, elements.Roadm)]
|
|
||||||
for roadm in roadms:
|
for roadm in roadms:
|
||||||
add_roadm_preamp(network, roadm)
|
add_roadm_preamp(network, roadm)
|
||||||
add_roadm_booster(network, roadm)
|
add_roadm_booster(network, roadm)
|
||||||
@@ -536,6 +544,8 @@ def build_network(network, equipment, pref_ch_db, pref_total_db):
|
|||||||
for fiber in fibers:
|
for fiber in fibers:
|
||||||
add_inline_amplifier(network, fiber)
|
add_inline_amplifier(network, fiber)
|
||||||
|
|
||||||
|
add_fiber_padding(network, fibers, default_span_data.padding)
|
||||||
|
|
||||||
for roadm in roadms:
|
for roadm in roadms:
|
||||||
set_egress_amplifier(network, roadm, equipment, pref_ch_db, pref_total_db)
|
set_egress_amplifier(network, roadm, equipment, pref_ch_db, pref_total_db)
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ This module contains all parameters to configure standard network elements.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from scipy.constants import c, pi
|
from scipy.constants import c, pi
|
||||||
from numpy import squeeze, log10, exp
|
from numpy import asarray, array
|
||||||
|
|
||||||
from gnpy.core.utils import db2lin, convert_length
|
from gnpy.core.utils import convert_length
|
||||||
from gnpy.core.exceptions import ParametersError
|
from gnpy.core.exceptions import ParametersError
|
||||||
|
|
||||||
|
|
||||||
@@ -28,110 +28,102 @@ class Parameters:
|
|||||||
|
|
||||||
class PumpParams(Parameters):
|
class PumpParams(Parameters):
|
||||||
def __init__(self, power, frequency, propagation_direction):
|
def __init__(self, power, frequency, propagation_direction):
|
||||||
self._power = power
|
self.power = power
|
||||||
self._frequency = frequency
|
self.frequency = frequency
|
||||||
self._propagation_direction = propagation_direction
|
self.propagation_direction = propagation_direction.lower()
|
||||||
|
|
||||||
@property
|
|
||||||
def power(self):
|
|
||||||
return self._power
|
|
||||||
|
|
||||||
@property
|
|
||||||
def frequency(self):
|
|
||||||
return self._frequency
|
|
||||||
|
|
||||||
@property
|
|
||||||
def propagation_direction(self):
|
|
||||||
return self._propagation_direction
|
|
||||||
|
|
||||||
|
|
||||||
class RamanParams(Parameters):
|
class RamanParams(Parameters):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, flag=False, result_spatial_resolution=10e3, solver_spatial_resolution=50):
|
||||||
self._flag_raman = kwargs['flag_raman']
|
""" Simulation parameters used within the Raman Solver
|
||||||
self._space_resolution = kwargs['space_resolution'] if 'space_resolution' in kwargs else None
|
:params flag: boolean for enabling/disable the evaluation of the Raman power profile in frequency and position
|
||||||
self._tolerance = kwargs['tolerance'] if 'tolerance' in kwargs else None
|
:params result_spatial_resolution: spatial resolution of the evaluated Raman power profile
|
||||||
|
:params solver_spatial_resolution: spatial step for the iterative solution of the first order ode
|
||||||
@property
|
"""
|
||||||
def flag_raman(self):
|
self.flag = flag
|
||||||
return self._flag_raman
|
self.result_spatial_resolution = result_spatial_resolution # [m]
|
||||||
|
self.solver_spatial_resolution = solver_spatial_resolution # [m]
|
||||||
@property
|
|
||||||
def space_resolution(self):
|
|
||||||
return self._space_resolution
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tolerance(self):
|
|
||||||
return self._tolerance
|
|
||||||
|
|
||||||
|
|
||||||
class NLIParams(Parameters):
|
class NLIParams(Parameters):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, method='gn_model_analytic', dispersion_tolerance=1, phase_shift_tolerance=0.1,
|
||||||
self._nli_method_name = kwargs['nli_method_name']
|
computed_channels=None):
|
||||||
self._wdm_grid_size = kwargs['wdm_grid_size']
|
""" Simulation parameters used within the Nli Solver
|
||||||
self._dispersion_tolerance = kwargs['dispersion_tolerance']
|
:params method: formula for NLI calculation
|
||||||
self._phase_shift_tolerance = kwargs['phase_shift_tolerance']
|
:params dispersion_tolerance: tuning parameter for ggn model solution
|
||||||
self._f_cut_resolution = None
|
:params phase_shift_tolerance: tuning parameter for ggn model solution
|
||||||
self._f_pump_resolution = None
|
:params computed_channels: the NLI is evaluated for these channels and extrapolated for the others
|
||||||
self._computed_channels = kwargs['computed_channels'] if 'computed_channels' in kwargs else None
|
"""
|
||||||
|
self.method = method.lower()
|
||||||
@property
|
self.dispersion_tolerance = dispersion_tolerance
|
||||||
def nli_method_name(self):
|
self.phase_shift_tolerance = phase_shift_tolerance
|
||||||
return self._nli_method_name
|
self.computed_channels = computed_channels
|
||||||
|
|
||||||
@property
|
|
||||||
def wdm_grid_size(self):
|
|
||||||
return self._wdm_grid_size
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dispersion_tolerance(self):
|
|
||||||
return self._dispersion_tolerance
|
|
||||||
|
|
||||||
@property
|
|
||||||
def phase_shift_tolerance(self):
|
|
||||||
return self._phase_shift_tolerance
|
|
||||||
|
|
||||||
@property
|
|
||||||
def f_cut_resolution(self):
|
|
||||||
return self._f_cut_resolution
|
|
||||||
|
|
||||||
@f_cut_resolution.setter
|
|
||||||
def f_cut_resolution(self, f_cut_resolution):
|
|
||||||
self._f_cut_resolution = f_cut_resolution
|
|
||||||
|
|
||||||
@property
|
|
||||||
def f_pump_resolution(self):
|
|
||||||
return self._f_pump_resolution
|
|
||||||
|
|
||||||
@f_pump_resolution.setter
|
|
||||||
def f_pump_resolution(self, f_pump_resolution):
|
|
||||||
self._f_pump_resolution = f_pump_resolution
|
|
||||||
|
|
||||||
@property
|
|
||||||
def computed_channels(self):
|
|
||||||
return self._computed_channels
|
|
||||||
|
|
||||||
|
|
||||||
class SimParams(Parameters):
|
class SimParams(Parameters):
|
||||||
def __init__(self, **kwargs):
|
_shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
|
||||||
try:
|
|
||||||
if 'nli_parameters' in kwargs:
|
def __init__(self):
|
||||||
self._nli_params = NLIParams(**kwargs['nli_parameters'])
|
if type(self) == SimParams:
|
||||||
else:
|
raise NotImplementedError('Instances of SimParams cannot be generated')
|
||||||
self._nli_params = None
|
|
||||||
if 'raman_parameters' in kwargs:
|
@classmethod
|
||||||
self._raman_params = RamanParams(**kwargs['raman_parameters'])
|
def set_params(cls, sim_params):
|
||||||
else:
|
cls._shared_dict['nli_params'] = NLIParams(**sim_params.get('nli_params', {}))
|
||||||
self._raman_params = None
|
cls._shared_dict['raman_params'] = RamanParams(**sim_params.get('raman_params', {}))
|
||||||
except KeyError as e:
|
|
||||||
raise ParametersError(f'Simulation parameters must include {e}. Configuration: {kwargs}')
|
@classmethod
|
||||||
|
def get(cls):
|
||||||
|
self = cls.__new__(cls)
|
||||||
|
return self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def nli_params(self):
|
def nli_params(self):
|
||||||
return self._nli_params
|
return self._shared_dict['nli_params']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raman_params(self):
|
def raman_params(self):
|
||||||
return self._raman_params
|
return self._shared_dict['raman_params']
|
||||||
|
|
||||||
|
|
||||||
|
class RoadmParams(Parameters):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
try:
|
||||||
|
self.target_pch_out_db = kwargs['target_pch_out_db']
|
||||||
|
self.add_drop_osnr = kwargs['add_drop_osnr']
|
||||||
|
self.pmd = kwargs['pmd']
|
||||||
|
self.pdl = kwargs['pdl']
|
||||||
|
self.restrictions = kwargs['restrictions']
|
||||||
|
self.per_degree_pch_out_db = kwargs['per_degree_pch_out_db'] if 'per_degree_pch_out_db' in kwargs else {}
|
||||||
|
except KeyError as e:
|
||||||
|
raise ParametersError(f'ROADM configurations must include {e}. Configuration: {kwargs}')
|
||||||
|
|
||||||
|
|
||||||
|
class FusedParams(Parameters):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.loss = kwargs['loss'] if 'loss' in kwargs else 1
|
||||||
|
|
||||||
|
|
||||||
|
# SSMF Raman coefficient profile normalized with respect to the effective area (Cr * A_eff)
|
||||||
|
CR_NORM = array([
|
||||||
|
0., 7.802e-16, 2.4236e-15, 4.0504e-15, 5.6606e-15, 6.8973e-15, 7.802e-15, 8.4162e-15, 8.8727e-15, 9.2877e-15,
|
||||||
|
1.01011e-14, 1.05244e-14, 1.13295e-14, 1.2367e-14, 1.3695e-14, 1.5023e-14, 1.64091e-14, 1.81936e-14, 2.04927e-14,
|
||||||
|
2.28167e-14, 2.48917e-14, 2.66098e-14, 2.82615e-14, 2.98136e-14, 3.1042e-14, 3.17558e-14, 3.18803e-14, 3.17558e-14,
|
||||||
|
3.15566e-14, 3.11748e-14, 2.94567e-14, 3.14985e-14, 2.8552e-14, 2.43439e-14, 1.67992e-14, 9.6114e-15, 7.02180e-15,
|
||||||
|
5.9262e-15, 5.6938e-15, 7.055e-15, 7.4119e-15, 7.4783e-15, 6.7645e-15, 5.5361e-15, 3.6271e-15, 2.7224e-15,
|
||||||
|
2.4568e-15, 2.1995e-15, 2.1331e-15, 2.3323e-15, 2.5564e-15, 3.0461e-15, 4.8555e-15, 5.5029e-15, 5.2788e-15,
|
||||||
|
4.565e-15, 3.3698e-15, 2.2991e-15, 2.0086e-15, 1.5521e-15, 1.328e-15, 1.162e-15, 9.379e-16, 8.715e-16, 8.134e-16,
|
||||||
|
8.134e-16, 9.379e-16, 1.3612e-15, 1.6185e-15, 1.9754e-15, 1.8758e-15, 1.6849e-15, 1.2284e-15, 9.047e-16, 8.134e-16,
|
||||||
|
8.715e-16, 9.711e-16, 1.0375e-15, 1.0043e-15, 9.047e-16, 8.134e-16, 6.806e-16, 5.478e-16, 3.901e-16, 2.241e-16,
|
||||||
|
1.577e-16, 9.96e-17, 3.32e-17, 1.66e-17, 8.3e-18])
|
||||||
|
|
||||||
|
# Note the non-uniform spacing of this range; this is required for properly capturing the Raman peak shape.
|
||||||
|
FREQ_OFFSET = array([
|
||||||
|
0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8., 8.5, 9., 9.5, 10., 10.5, 11., 11.5, 12.,
|
||||||
|
12.5, 12.75, 13., 13.25, 13.5, 14., 14.5, 14.75, 15., 15.5, 16., 16.5, 17., 17.5, 18., 18.25, 18.5, 18.75, 19.,
|
||||||
|
19.5, 20., 20.5, 21., 21.5, 22., 22.5, 23., 23.5, 24., 24.5, 25., 25.5, 26., 26.5, 27., 27.5, 28., 28.5, 29., 29.5,
|
||||||
|
30., 30.5, 31., 31.5, 32., 32.5, 33., 33.5, 34., 34.5, 35., 35.5, 36., 36.5, 37., 37.5, 38., 38.5, 39., 39.5, 40.,
|
||||||
|
40.5, 41., 41.5, 42.]) * 1e12
|
||||||
|
|
||||||
|
|
||||||
class FiberParams(Parameters):
|
class FiberParams(Parameters):
|
||||||
@@ -139,45 +131,50 @@ class FiberParams(Parameters):
|
|||||||
try:
|
try:
|
||||||
self._length = convert_length(kwargs['length'], kwargs['length_units'])
|
self._length = convert_length(kwargs['length'], kwargs['length_units'])
|
||||||
# fixed attenuator for padding
|
# fixed attenuator for padding
|
||||||
self._att_in = kwargs['att_in'] if 'att_in' in kwargs else 0
|
self._att_in = kwargs.get('att_in', 0)
|
||||||
# if not defined in the network json connector loss in/out
|
# if not defined in the network json connector loss in/out
|
||||||
# the None value will be updated in network.py[build_network]
|
# the None value will be updated in network.py[build_network]
|
||||||
# with default values from eqpt_config.json[Spans]
|
# with default values from eqpt_config.json[Spans]
|
||||||
self._con_in = kwargs['con_in'] if 'con_in' in kwargs else None
|
self._con_in = kwargs.get('con_in')
|
||||||
self._con_out = kwargs['con_out'] if 'con_out' in kwargs else None
|
self._con_out = kwargs.get('con_out')
|
||||||
if 'ref_wavelength' in kwargs:
|
if 'ref_wavelength' in kwargs:
|
||||||
self._ref_wavelength = kwargs['ref_wavelength']
|
self._ref_wavelength = kwargs['ref_wavelength']
|
||||||
self._ref_frequency = c / self.ref_wavelength
|
self._ref_frequency = c / self._ref_wavelength
|
||||||
elif 'ref_frequency' in kwargs:
|
elif 'ref_frequency' in kwargs:
|
||||||
self._ref_frequency = kwargs['ref_frequency']
|
self._ref_frequency = kwargs['ref_frequency']
|
||||||
self._ref_wavelength = c / self.ref_frequency
|
self._ref_wavelength = c / self._ref_frequency
|
||||||
else:
|
else:
|
||||||
self._ref_wavelength = 1550e-9
|
self._ref_wavelength = 1550e-9 # conventional central C band wavelength [m]
|
||||||
self._ref_frequency = c / self.ref_wavelength
|
self._ref_frequency = c / self._ref_wavelength
|
||||||
self._dispersion = kwargs['dispersion'] # s/m/m
|
self._dispersion = kwargs['dispersion'] # s/m/m
|
||||||
self._dispersion_slope = kwargs['dispersion_slope'] if 'dispersion_slope' in kwargs else \
|
self._dispersion_slope = \
|
||||||
-2 * self._dispersion/self.ref_wavelength # s/m/m/m
|
kwargs.get('dispersion_slope', -2 * self._dispersion / self.ref_wavelength) # s/m/m/m
|
||||||
self._beta2 = -(self.ref_wavelength ** 2) * self.dispersion / (2 * pi * c) # 1/(m * Hz^2)
|
self._beta2 = -(self.ref_wavelength ** 2) * self.dispersion / (2 * pi * c) # 1/(m * Hz^2)
|
||||||
# Eq. (3.23) in Abramczyk, Halina. "Dispersion phenomena in optical fibers." Virtual European University
|
# Eq. (3.23) in Abramczyk, Halina. "Dispersion phenomena in optical fibers." Virtual European University
|
||||||
# on Lasers. Available online: http://mitr.p.lodz.pl/evu/lectures/Abramczyk3.pdf
|
# on Lasers. Available online: http://mitr.p.lodz.pl/evu/lectures/Abramczyk3.pdf
|
||||||
# (accessed on 25 March 2018) (2005).
|
# (accessed on 25 March 2018) (2005).
|
||||||
self._beta3 = ((self.dispersion_slope - (4*pi*c/self.ref_wavelength**3) * self.beta2) /
|
self._beta3 = ((self.dispersion_slope - (4*pi*c/self.ref_wavelength**3) * self.beta2) /
|
||||||
(2*pi*c/self.ref_wavelength**2)**2)
|
(2*pi*c/self.ref_wavelength**2)**2)
|
||||||
|
self._effective_area = kwargs.get('effective_area') # m^2
|
||||||
|
n2 = 2.6e-20 # m^2/W
|
||||||
|
if self._effective_area:
|
||||||
|
self._gamma = kwargs.get('gamma', 2 * pi * n2 / (self.ref_wavelength * self._effective_area)) # 1/W/m
|
||||||
|
elif 'gamma' in kwargs:
|
||||||
self._gamma = kwargs['gamma'] # 1/W/m
|
self._gamma = kwargs['gamma'] # 1/W/m
|
||||||
|
self._effective_area = 2 * pi * n2 / (self.ref_wavelength * self._gamma) # m^2
|
||||||
|
else:
|
||||||
|
self._gamma = 0 # 1/W/m
|
||||||
|
self._effective_area = 83e-12 # m^2
|
||||||
|
default_raman_efficiency = {'cr': CR_NORM / self._effective_area, 'frequency_offset': FREQ_OFFSET}
|
||||||
|
self._raman_efficiency = kwargs.get('raman_efficiency', default_raman_efficiency)
|
||||||
self._pmd_coef = kwargs['pmd_coef'] # s/sqrt(m)
|
self._pmd_coef = kwargs['pmd_coef'] # s/sqrt(m)
|
||||||
if type(kwargs['loss_coef']) == dict:
|
if type(kwargs['loss_coef']) == dict:
|
||||||
self._loss_coef = squeeze(kwargs['loss_coef']['loss_coef_power']) * 1e-3 # lineic loss dB/m
|
self._loss_coef = asarray(kwargs['loss_coef']['value']) * 1e-3 # lineic loss dB/m
|
||||||
self._f_loss_ref = squeeze(kwargs['loss_coef']['frequency']) # Hz
|
self._f_loss_ref = asarray(kwargs['loss_coef']['frequency']) # Hz
|
||||||
else:
|
else:
|
||||||
self._loss_coef = kwargs['loss_coef'] * 1e-3 # lineic loss dB/m
|
self._loss_coef = asarray(kwargs['loss_coef']) * 1e-3 # lineic loss dB/m
|
||||||
self._f_loss_ref = 193.5e12 # Hz
|
self._f_loss_ref = asarray(self._ref_frequency) # Hz
|
||||||
self._lin_attenuation = db2lin(self.length * self.loss_coef)
|
self._lumped_losses = kwargs['lumped_losses'] if 'lumped_losses' in kwargs else []
|
||||||
self._lin_loss_exp = self.loss_coef / (10 * log10(exp(1))) # linear power exponent loss Neper/m
|
|
||||||
self._effective_length = (1 - exp(- self.lin_loss_exp * self.length)) / self.lin_loss_exp
|
|
||||||
self._asymptotic_length = 1 / self.lin_loss_exp
|
|
||||||
# raman parameters (not compulsory)
|
|
||||||
self._raman_efficiency = kwargs['raman_efficiency'] if 'raman_efficiency' in kwargs else None
|
|
||||||
self._pumps_loss_coef = kwargs['pumps_loss_coef'] if 'pumps_loss_coef' in kwargs else None
|
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
raise ParametersError(f'Fiber configurations json must include {e}. Configuration: {kwargs}')
|
raise ParametersError(f'Fiber configurations json must include {e}. Configuration: {kwargs}')
|
||||||
|
|
||||||
@@ -210,6 +207,10 @@ class FiberParams(Parameters):
|
|||||||
def con_out(self):
|
def con_out(self):
|
||||||
return self._con_out
|
return self._con_out
|
||||||
|
|
||||||
|
@property
|
||||||
|
def lumped_losses(self):
|
||||||
|
return self._lumped_losses
|
||||||
|
|
||||||
@con_out.setter
|
@con_out.setter
|
||||||
def con_out(self, con_out):
|
def con_out(self, con_out):
|
||||||
self._con_out = con_out
|
self._con_out = con_out
|
||||||
@@ -254,32 +255,60 @@ class FiberParams(Parameters):
|
|||||||
def f_loss_ref(self):
|
def f_loss_ref(self):
|
||||||
return self._f_loss_ref
|
return self._f_loss_ref
|
||||||
|
|
||||||
@property
|
|
||||||
def lin_loss_exp(self):
|
|
||||||
return self._lin_loss_exp
|
|
||||||
|
|
||||||
@property
|
|
||||||
def lin_attenuation(self):
|
|
||||||
return self._lin_attenuation
|
|
||||||
|
|
||||||
@property
|
|
||||||
def effective_length(self):
|
|
||||||
return self._effective_length
|
|
||||||
|
|
||||||
@property
|
|
||||||
def asymptotic_length(self):
|
|
||||||
return self._asymptotic_length
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raman_efficiency(self):
|
def raman_efficiency(self):
|
||||||
return self._raman_efficiency
|
return self._raman_efficiency
|
||||||
|
|
||||||
@property
|
|
||||||
def pumps_loss_coef(self):
|
|
||||||
return self._pumps_loss_coef
|
|
||||||
|
|
||||||
def asdict(self):
|
def asdict(self):
|
||||||
dictionary = super().asdict()
|
dictionary = super().asdict()
|
||||||
dictionary['loss_coef'] = self.loss_coef * 1e3
|
dictionary['loss_coef'] = self.loss_coef * 1e3
|
||||||
dictionary['length_units'] = 'm'
|
dictionary['length_units'] = 'm'
|
||||||
|
if not self.lumped_losses:
|
||||||
|
dictionary.pop('lumped_losses')
|
||||||
|
if not self.raman_efficiency:
|
||||||
|
dictionary.pop('raman_efficiency')
|
||||||
return dictionary
|
return dictionary
|
||||||
|
|
||||||
|
|
||||||
|
class EdfaParams:
|
||||||
|
def __init__(self, **params):
|
||||||
|
self.update_params(params)
|
||||||
|
if params == {}:
|
||||||
|
self.type_variety = ''
|
||||||
|
self.type_def = ''
|
||||||
|
# self.gain_flatmax = 0
|
||||||
|
# self.gain_min = 0
|
||||||
|
# self.p_max = 0
|
||||||
|
# self.nf_model = None
|
||||||
|
# self.nf_fit_coeff = None
|
||||||
|
# self.nf_ripple = None
|
||||||
|
# self.dgt = None
|
||||||
|
# self.gain_ripple = None
|
||||||
|
# self.out_voa_auto = False
|
||||||
|
# self.allowed_for_design = None
|
||||||
|
|
||||||
|
def update_params(self, kwargs):
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
setattr(self, k, self.update_params(**v) if isinstance(v, dict) else v)
|
||||||
|
|
||||||
|
|
||||||
|
class EdfaOperational:
|
||||||
|
default_values = {
|
||||||
|
'gain_target': None,
|
||||||
|
'delta_p': None,
|
||||||
|
'out_voa': None,
|
||||||
|
'tilt_target': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, **operational):
|
||||||
|
self.update_attr(operational)
|
||||||
|
|
||||||
|
def update_attr(self, kwargs):
|
||||||
|
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
|
||||||
|
for k, v in self.default_values.items():
|
||||||
|
setattr(self, k, clean_kwargs.get(k, v))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return (f'{type(self).__name__}('
|
||||||
|
f'gain_target={self.gain_target!r}, '
|
||||||
|
f'tilt_target={self.tilt_target!r})')
|
||||||
|
|||||||
@@ -10,121 +10,26 @@ Solver definitions to calculate the Raman effect and the nonlinear interference
|
|||||||
The solvers take as input instances of the spectral information, the fiber and the simulation parameters
|
The solvers take as input instances of the spectral information, the fiber and the simulation parameters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from numpy import interp, pi, zeros, shape, where, cos, reshape, array, append, ones, argsort, nan, exp, arange, sqrt, \
|
from numpy import interp, pi, zeros, shape, where, cos, array, append, ones, exp, arange, sqrt, empty, trapz, arcsinh, \
|
||||||
empty, vstack, trapz, arcsinh, clip, abs, sum
|
clip, abs, sum, concatenate, flip, outer, inner, transpose, max, format_float_scientific, diag, prod, argwhere, \
|
||||||
from operator import attrgetter
|
unique, argsort, cumprod
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import scipy.constants as ph
|
from scipy.constants import k, h
|
||||||
from scipy.integrate import solve_bvp
|
|
||||||
from scipy.integrate import cumtrapz
|
|
||||||
from scipy.interpolate import interp1d
|
from scipy.interpolate import interp1d
|
||||||
from scipy.optimize import OptimizeResult
|
|
||||||
from math import isclose
|
from math import isclose
|
||||||
|
|
||||||
from gnpy.core.utils import db2lin, lin2db
|
from gnpy.core.utils import db2lin, lin2db
|
||||||
from gnpy.core.exceptions import EquipmentConfigError
|
from gnpy.core.exceptions import EquipmentConfigError
|
||||||
|
from gnpy.core.parameters import SimParams
|
||||||
|
from gnpy.core.info import SpectralInformation
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
sim_params = SimParams.get()
|
||||||
|
|
||||||
def propagate_raman_fiber(fiber, *carriers):
|
|
||||||
simulation = Simulation.get_simulation()
|
|
||||||
sim_params = simulation.sim_params
|
|
||||||
raman_params = sim_params.raman_params
|
|
||||||
nli_params = sim_params.nli_params
|
|
||||||
# apply input attenuation to carriers
|
|
||||||
attenuation_in = db2lin(fiber.params.con_in + fiber.params.att_in)
|
|
||||||
chan = []
|
|
||||||
for carrier in carriers:
|
|
||||||
pwr = carrier.power
|
|
||||||
pwr = pwr._replace(signal=pwr.signal / attenuation_in,
|
|
||||||
nli=pwr.nli / attenuation_in,
|
|
||||||
ase=pwr.ase / attenuation_in)
|
|
||||||
carrier = carrier._replace(power=pwr)
|
|
||||||
chan.append(carrier)
|
|
||||||
carriers = tuple(f for f in chan)
|
|
||||||
|
|
||||||
# evaluate fiber attenuation involving also SRS if required by sim_params
|
|
||||||
raman_solver = fiber.raman_solver
|
|
||||||
raman_solver.carriers = carriers
|
|
||||||
raman_solver.raman_pumps = fiber.raman_pumps
|
|
||||||
stimulated_raman_scattering = raman_solver.stimulated_raman_scattering
|
|
||||||
|
|
||||||
fiber_attenuation = (stimulated_raman_scattering.rho[:, -1])**-2
|
|
||||||
if not raman_params.flag_raman:
|
|
||||||
fiber_attenuation = tuple(fiber.params.lin_attenuation for _ in carriers)
|
|
||||||
|
|
||||||
# evaluate Raman ASE noise if required by sim_params and if raman pumps are present
|
|
||||||
if raman_params.flag_raman and fiber.raman_pumps:
|
|
||||||
raman_ase = raman_solver.spontaneous_raman_scattering.power[:, -1]
|
|
||||||
else:
|
|
||||||
raman_ase = tuple(0 for _ in carriers)
|
|
||||||
|
|
||||||
# evaluate nli and propagate in fiber
|
|
||||||
attenuation_out = db2lin(fiber.params.con_out)
|
|
||||||
nli_solver = fiber.nli_solver
|
|
||||||
nli_solver.stimulated_raman_scattering = stimulated_raman_scattering
|
|
||||||
|
|
||||||
nli_frequencies = []
|
|
||||||
computed_nli = []
|
|
||||||
for carrier in (c for c in carriers if c.channel_number in sim_params.nli_params.computed_channels):
|
|
||||||
resolution_param = frequency_resolution(carrier, carriers, sim_params, fiber)
|
|
||||||
f_cut_resolution, f_pump_resolution, _, _ = resolution_param
|
|
||||||
nli_params.f_cut_resolution = f_cut_resolution
|
|
||||||
nli_params.f_pump_resolution = f_pump_resolution
|
|
||||||
nli_frequencies.append(carrier.frequency)
|
|
||||||
computed_nli.append(nli_solver.compute_nli(carrier, *carriers))
|
|
||||||
|
|
||||||
new_carriers = []
|
|
||||||
for carrier, attenuation, rmn_ase in zip(carriers, fiber_attenuation, raman_ase):
|
|
||||||
carrier_nli = interp(carrier.frequency, nli_frequencies, computed_nli)
|
|
||||||
pwr = carrier.power
|
|
||||||
pwr = pwr._replace(signal=pwr.signal / attenuation / attenuation_out,
|
|
||||||
nli=(pwr.nli + carrier_nli) / attenuation / attenuation_out,
|
|
||||||
ase=((pwr.ase / attenuation) + rmn_ase) / attenuation_out)
|
|
||||||
new_carriers.append(carrier._replace(power=pwr))
|
|
||||||
return new_carriers
|
|
||||||
|
|
||||||
|
|
||||||
def frequency_resolution(carrier, carriers, sim_params, fiber):
|
|
||||||
def _get_freq_res_k_phi(delta_count, grid_size, alpha0, delta_z, beta2, k_tol, phi_tol):
|
|
||||||
res_phi = _get_freq_res_phase_rotation(delta_count, grid_size, delta_z, beta2, phi_tol)
|
|
||||||
res_k = _get_freq_res_dispersion_attenuation(delta_count, grid_size, alpha0, beta2, k_tol)
|
|
||||||
res_dict = {'res_phi': res_phi, 'res_k': res_k}
|
|
||||||
method = min(res_dict, key=res_dict.get)
|
|
||||||
return res_dict[method], method, res_dict
|
|
||||||
|
|
||||||
def _get_freq_res_dispersion_attenuation(delta_count, grid_size, alpha0, beta2, k_tol):
|
|
||||||
return k_tol * abs(alpha0) / abs(beta2) / (1 + delta_count) / (4 * pi ** 2 * grid_size)
|
|
||||||
|
|
||||||
def _get_freq_res_phase_rotation(delta_count, grid_size, delta_z, beta2, phi_tol):
|
|
||||||
return phi_tol / abs(beta2) / (1 + delta_count) / delta_z / (4 * pi ** 2 * grid_size)
|
|
||||||
|
|
||||||
grid_size = sim_params.nli_params.wdm_grid_size
|
|
||||||
delta_z = sim_params.raman_params.space_resolution
|
|
||||||
alpha0 = fiber.alpha0()
|
|
||||||
beta2 = fiber.params.beta2
|
|
||||||
k_tol = sim_params.nli_params.dispersion_tolerance
|
|
||||||
phi_tol = sim_params.nli_params.phase_shift_tolerance
|
|
||||||
f_pump_resolution, method_f_pump, res_dict_pump = \
|
|
||||||
_get_freq_res_k_phi(0, grid_size, alpha0, delta_z, beta2, k_tol, phi_tol)
|
|
||||||
f_cut_resolution = {}
|
|
||||||
method_f_cut = {}
|
|
||||||
res_dict_cut = {}
|
|
||||||
for cut_carrier in carriers:
|
|
||||||
delta_number = cut_carrier.channel_number - carrier.channel_number
|
|
||||||
delta_count = abs(delta_number)
|
|
||||||
f_res, method, res_dict = \
|
|
||||||
_get_freq_res_k_phi(delta_count, grid_size, alpha0, delta_z, beta2, k_tol, phi_tol)
|
|
||||||
f_cut_resolution[f'delta_{delta_number}'] = f_res
|
|
||||||
method_f_cut[delta_number] = method
|
|
||||||
res_dict_cut[delta_number] = res_dict
|
|
||||||
return [f_cut_resolution, f_pump_resolution, (method_f_cut, method_f_pump), (res_dict_cut, res_dict_pump)]
|
|
||||||
|
|
||||||
|
|
||||||
def raised_cosine_comb(f, *carriers):
|
def raised_cosine_comb(f, *carriers):
|
||||||
""" Returns an array storing the PSD of a WDM comb of raised cosine shaped
|
""" Returns an array storing the PSD of a WDM comb of raised cosine shaped
|
||||||
channels at the input frequencies defined in array f
|
channels at the input frequencies defined in array f
|
||||||
|
|
||||||
:param f: numpy array of frequencies in Hz
|
:param f: numpy array of frequencies in Hz
|
||||||
:param carriers: namedtuple describing the WDM comb
|
:param carriers: namedtuple describing the WDM comb
|
||||||
:return: PSD of the WDM comb evaluated over f
|
:return: PSD of the WDM comb evaluated over f
|
||||||
@@ -146,303 +51,223 @@ def raised_cosine_comb(f, *carriers):
|
|||||||
return psd
|
return psd
|
||||||
|
|
||||||
|
|
||||||
class Simulation:
|
|
||||||
_shared_dict = {}
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
if type(self) == Simulation:
|
|
||||||
raise NotImplementedError('Simulation cannot be instatiated')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_params(cls, sim_params):
|
|
||||||
cls._shared_dict['sim_params'] = sim_params
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_simulation(cls):
|
|
||||||
self = cls.__new__(cls)
|
|
||||||
return self
|
|
||||||
|
|
||||||
@property
|
|
||||||
def sim_params(self):
|
|
||||||
return self._shared_dict['sim_params']
|
|
||||||
|
|
||||||
|
|
||||||
class SpontaneousRamanScattering:
|
|
||||||
def __init__(self, frequency, z, power):
|
|
||||||
self.frequency = frequency
|
|
||||||
self.z = z
|
|
||||||
self.power = power
|
|
||||||
|
|
||||||
|
|
||||||
class StimulatedRamanScattering:
|
class StimulatedRamanScattering:
|
||||||
def __init__(self, frequency, z, rho, power):
|
def __init__(self, power_profile, loss_profile, frequency, z):
|
||||||
|
"""
|
||||||
|
:params power_profile: power profile matrix along frequency and z [W]
|
||||||
|
:params loss_profile: power profile matrix along frequency and z [linear units]
|
||||||
|
:params frequency: channels frequencies array [Hz]
|
||||||
|
:params z: positions array [m]
|
||||||
|
"""
|
||||||
|
self.power_profile = power_profile
|
||||||
|
self.loss_profile = loss_profile
|
||||||
|
# Field loss profile matrix along frequency and z
|
||||||
|
self.rho = sqrt(loss_profile)
|
||||||
self.frequency = frequency
|
self.frequency = frequency
|
||||||
self.z = z
|
self.z = z
|
||||||
self.rho = rho
|
|
||||||
self.power = power
|
|
||||||
|
|
||||||
|
|
||||||
class RamanSolver:
|
class RamanSolver:
|
||||||
def __init__(self, fiber=None):
|
"""This class contains the methods to calculate the Raman scattering effect."""
|
||||||
""" Initialize the Raman solver object.
|
|
||||||
:param fiber: instance of elements.py/Fiber.
|
|
||||||
:param carriers: tuple of carrier objects
|
|
||||||
:param raman_pumps: tuple containing pumps characteristics
|
|
||||||
"""
|
|
||||||
self._fiber = fiber
|
|
||||||
self._carriers = None
|
|
||||||
self._raman_pumps = None
|
|
||||||
self._stimulated_raman_scattering = None
|
|
||||||
self._spontaneous_raman_scattering = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fiber(self):
|
|
||||||
return self._fiber
|
|
||||||
|
|
||||||
@property
|
|
||||||
def carriers(self):
|
|
||||||
return self._carriers
|
|
||||||
|
|
||||||
@carriers.setter
|
|
||||||
def carriers(self, carriers):
|
|
||||||
self._carriers = carriers
|
|
||||||
self._spontaneous_raman_scattering = None
|
|
||||||
self._stimulated_raman_scattering = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def raman_pumps(self):
|
|
||||||
return self._raman_pumps
|
|
||||||
|
|
||||||
@raman_pumps.setter
|
|
||||||
def raman_pumps(self, raman_pumps):
|
|
||||||
self._raman_pumps = raman_pumps
|
|
||||||
self._stimulated_raman_scattering = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def stimulated_raman_scattering(self):
|
|
||||||
if self._stimulated_raman_scattering is None:
|
|
||||||
self.calculate_stimulated_raman_scattering(self.carriers, self.raman_pumps)
|
|
||||||
return self._stimulated_raman_scattering
|
|
||||||
|
|
||||||
@property
|
|
||||||
def spontaneous_raman_scattering(self):
|
|
||||||
if self._spontaneous_raman_scattering is None:
|
|
||||||
self.calculate_spontaneous_raman_scattering(self.carriers, self.raman_pumps)
|
|
||||||
return self._spontaneous_raman_scattering
|
|
||||||
|
|
||||||
def calculate_spontaneous_raman_scattering(self, carriers, raman_pumps):
|
|
||||||
raman_efficiency = self.fiber.params.raman_efficiency
|
|
||||||
temperature = self.fiber.operational['temperature']
|
|
||||||
|
|
||||||
logger.debug('Start computing fiber Spontaneous Raman Scattering')
|
|
||||||
power_spectrum, freq_array, prop_direct, bn_array = self._compute_power_spectrum(carriers, raman_pumps)
|
|
||||||
|
|
||||||
alphap_fiber = self.fiber.alpha(freq_array)
|
|
||||||
|
|
||||||
freq_diff = abs(freq_array - reshape(freq_array, (len(freq_array), 1)))
|
|
||||||
interp_cr = interp1d(raman_efficiency['frequency_offset'], raman_efficiency['cr'])
|
|
||||||
cr = interp_cr(freq_diff)
|
|
||||||
|
|
||||||
# z propagation axis
|
|
||||||
z_array = self.stimulated_raman_scattering.z
|
|
||||||
ase_bc = zeros(freq_array.shape)
|
|
||||||
|
|
||||||
# calculate ase power
|
|
||||||
int_spontaneous_raman = self._int_spontaneous_raman(z_array, self._stimulated_raman_scattering.power,
|
|
||||||
alphap_fiber, freq_array, cr, freq_diff, ase_bc,
|
|
||||||
bn_array, temperature)
|
|
||||||
|
|
||||||
spontaneous_raman_scattering = SpontaneousRamanScattering(freq_array, z_array, int_spontaneous_raman.x)
|
|
||||||
logger.debug("Spontaneous Raman Scattering evaluated successfully")
|
|
||||||
self._spontaneous_raman_scattering = spontaneous_raman_scattering
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _compute_power_spectrum(carriers, raman_pumps=None):
|
def _create_lumped_losses(z, lumped_losses, z_lumped_losses):
|
||||||
|
lumped_losses = concatenate((lumped_losses, ones(z.size)))
|
||||||
|
z, unique_indices = unique(concatenate((z_lumped_losses, z)), return_index=True)
|
||||||
|
order = argsort(z)
|
||||||
|
lumped_losses = (lumped_losses[unique_indices])[order]
|
||||||
|
z = z[order]
|
||||||
|
return z, lumped_losses
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def calculate_attenuation_profile(spectral_info: SpectralInformation, fiber):
|
||||||
|
"""Evaluates the attenuation profile along the z axis for all the frequency propagating in the
|
||||||
|
fiber without considering the stimulated Raman scattering.
|
||||||
"""
|
"""
|
||||||
Rearrangement of spectral and Raman pump information to make them compatible with Raman solver
|
# z array definition
|
||||||
:param carriers: a tuple of namedtuples describing the transmitted channels
|
z = array([0, fiber.params.length])
|
||||||
:param raman_pumps: a namedtuple describing the Raman pumps
|
|
||||||
:return:
|
# Lumped losses array definition
|
||||||
|
z, lumped_losses = RamanSolver._create_lumped_losses(z, fiber.lumped_losses, fiber.z_lumped_losses)
|
||||||
|
|
||||||
|
lumped_loss_acc = cumprod(lumped_losses)
|
||||||
|
frequency = spectral_info.frequency
|
||||||
|
alpha = fiber.alpha(frequency)
|
||||||
|
loss_profile = exp(- outer(alpha, z)) * lumped_loss_acc
|
||||||
|
power_profile = outer(spectral_info.signal, ones(z.size)) * loss_profile
|
||||||
|
return StimulatedRamanScattering(power_profile, loss_profile, spectral_info.frequency, z)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def calculate_stimulated_raman_scattering(spectral_info: SpectralInformation, fiber):
|
||||||
|
"""Evaluates the Raman profile along the z axis for all the frequency propagated in the fiber
|
||||||
|
including the Raman pumps co- and counter-propagating
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Signal power spectrum
|
|
||||||
pow_array = array([])
|
|
||||||
f_array = array([])
|
|
||||||
noise_bandwidth_array = array([])
|
|
||||||
for carrier in sorted(carriers, key=attrgetter('frequency')):
|
|
||||||
f_array = append(f_array, carrier.frequency)
|
|
||||||
pow_array = append(pow_array, carrier.power.signal)
|
|
||||||
ref_bw = carrier.baud_rate
|
|
||||||
noise_bandwidth_array = append(noise_bandwidth_array, ref_bw)
|
|
||||||
|
|
||||||
propagation_direction = ones(len(f_array))
|
|
||||||
|
|
||||||
# Raman pump power spectrum
|
|
||||||
if raman_pumps:
|
|
||||||
for pump in raman_pumps:
|
|
||||||
pow_array = append(pow_array, pump.power)
|
|
||||||
f_array = append(f_array, pump.frequency)
|
|
||||||
direction = +1 if pump.propagation_direction.lower() == 'coprop' else -1
|
|
||||||
propagation_direction = append(propagation_direction, direction)
|
|
||||||
noise_bandwidth_array = append(noise_bandwidth_array, ref_bw)
|
|
||||||
|
|
||||||
# Final sorting
|
|
||||||
ind = argsort(f_array)
|
|
||||||
f_array = f_array[ind]
|
|
||||||
pow_array = pow_array[ind]
|
|
||||||
propagation_direction = propagation_direction[ind]
|
|
||||||
|
|
||||||
return pow_array, f_array, propagation_direction, noise_bandwidth_array
|
|
||||||
|
|
||||||
def _int_spontaneous_raman(self, z_array, raman_matrix, alphap_fiber, freq_array,
|
|
||||||
cr_raman_matrix, freq_diff, ase_bc, bn_array, temperature):
|
|
||||||
spontaneous_raman_scattering = OptimizeResult()
|
|
||||||
|
|
||||||
simulation = Simulation.get_simulation()
|
|
||||||
sim_params = simulation.sim_params
|
|
||||||
|
|
||||||
dx = sim_params.raman_params.space_resolution
|
|
||||||
h = ph.value('Planck constant')
|
|
||||||
kb = ph.value('Boltzmann constant')
|
|
||||||
|
|
||||||
power_ase = nan * ones(raman_matrix.shape)
|
|
||||||
int_pump = cumtrapz(raman_matrix, z_array, dx=dx, axis=1, initial=0)
|
|
||||||
|
|
||||||
for f_ind, f_ase in enumerate(freq_array):
|
|
||||||
cr_raman = cr_raman_matrix[f_ind, :]
|
|
||||||
vibrational_loss = f_ase / freq_array[:f_ind]
|
|
||||||
eta = 1 / (exp((h * freq_diff[f_ind, f_ind + 1:]) / (kb * temperature)) - 1)
|
|
||||||
|
|
||||||
int_fiber_loss = -alphap_fiber[f_ind] * z_array
|
|
||||||
int_raman_loss = sum((cr_raman[:f_ind] * vibrational_loss * int_pump[:f_ind, :].transpose()).transpose(),
|
|
||||||
axis=0)
|
|
||||||
int_raman_gain = sum((cr_raman[f_ind + 1:] * int_pump[f_ind + 1:, :].transpose()).transpose(), axis=0)
|
|
||||||
|
|
||||||
int_gain_loss = int_fiber_loss + int_raman_gain + int_raman_loss
|
|
||||||
|
|
||||||
new_ase = sum((cr_raman[f_ind + 1:] * (1 + eta) * raman_matrix[f_ind + 1:, :].transpose()).transpose()
|
|
||||||
* h * f_ase * bn_array[f_ind], axis=0)
|
|
||||||
|
|
||||||
bc_evolution = ase_bc[f_ind] * exp(int_gain_loss)
|
|
||||||
ase_evolution = exp(int_gain_loss) * cumtrapz(new_ase * exp(-int_gain_loss), z_array, dx=dx, initial=0)
|
|
||||||
|
|
||||||
power_ase[f_ind, :] = bc_evolution + ase_evolution
|
|
||||||
|
|
||||||
spontaneous_raman_scattering.x = 2 * power_ase
|
|
||||||
return spontaneous_raman_scattering
|
|
||||||
|
|
||||||
def calculate_stimulated_raman_scattering(self, carriers, raman_pumps):
|
|
||||||
""" Returns stimulated Raman scattering solution including
|
|
||||||
fiber gain/loss profile.
|
|
||||||
:return: None
|
|
||||||
"""
|
|
||||||
# fiber parameters
|
|
||||||
fiber_length = self.fiber.params.length
|
|
||||||
raman_efficiency = self.fiber.params.raman_efficiency
|
|
||||||
simulation = Simulation.get_simulation()
|
|
||||||
sim_params = simulation.sim_params
|
|
||||||
|
|
||||||
if not sim_params.raman_params.flag_raman:
|
|
||||||
raman_efficiency['cr'] = zeros(len(raman_efficiency['cr']))
|
|
||||||
# raman solver parameters
|
|
||||||
z_resolution = sim_params.raman_params.space_resolution
|
|
||||||
tolerance = sim_params.raman_params.tolerance
|
|
||||||
|
|
||||||
logger.debug('Start computing fiber Stimulated Raman Scattering')
|
logger.debug('Start computing fiber Stimulated Raman Scattering')
|
||||||
|
|
||||||
power_spectrum, freq_array, prop_direct, _ = self._compute_power_spectrum(carriers, raman_pumps)
|
if sim_params.raman_params.flag:
|
||||||
|
# Raman parameters
|
||||||
|
z_resolution = sim_params.raman_params.result_spatial_resolution
|
||||||
|
z_step = sim_params.raman_params.solver_spatial_resolution
|
||||||
|
z = append(arange(0, fiber.params.length, z_step), fiber.params.length)
|
||||||
|
z_final = append(arange(0, fiber.params.length, z_resolution), fiber.params.length)
|
||||||
|
|
||||||
alphap_fiber = self.fiber.alpha(freq_array)
|
# Lumped losses array definition
|
||||||
|
z, lumped_losses = RamanSolver._create_lumped_losses(z, fiber.lumped_losses, fiber.z_lumped_losses)
|
||||||
|
|
||||||
freq_diff = abs(freq_array - reshape(freq_array, (len(freq_array), 1)))
|
if hasattr(fiber, 'raman_pumps'):
|
||||||
interp_cr = interp1d(raman_efficiency['frequency_offset'], raman_efficiency['cr'])
|
# TODO: verify co-propagating pumps computation and in general unsorted frequency
|
||||||
cr = interp_cr(freq_diff)
|
# Co-propagating spectrum definition
|
||||||
|
co_raman_pump_power = array([pump.power for pump in fiber.raman_pumps
|
||||||
|
if pump.propagation_direction == 'coprop'])
|
||||||
|
co_raman_pump_frequency = array([pump.frequency for pump in fiber.raman_pumps
|
||||||
|
if pump.propagation_direction == 'coprop'])
|
||||||
|
|
||||||
# z propagation axis
|
co_power = concatenate((spectral_info.signal, co_raman_pump_power))
|
||||||
z = append(arange(0, fiber_length, z_resolution), fiber_length)
|
co_frequency = concatenate((spectral_info.frequency, co_raman_pump_frequency))
|
||||||
|
|
||||||
def ode_function(z, p):
|
# Counter-propagating spectrum definition
|
||||||
return self._ode_stimulated_raman(z, p, alphap_fiber, freq_array, cr, prop_direct)
|
cnt_power = array([pump.power for pump in fiber.raman_pumps
|
||||||
|
if pump.propagation_direction == 'counterprop'])
|
||||||
def boundary_residual(ya, yb):
|
cnt_frequency = array([pump.frequency for pump in fiber.raman_pumps
|
||||||
return self._residuals_stimulated_raman(ya, yb, power_spectrum, prop_direct)
|
if pump.propagation_direction == 'counterprop'])
|
||||||
|
# Co-propagating profile initialization
|
||||||
initial_guess_conditions = self._initial_guess_stimulated_raman(z, power_spectrum, alphap_fiber, prop_direct)
|
co_power_profile = empty([co_frequency.size, z.size])
|
||||||
|
if co_frequency.size:
|
||||||
# ODE SOLVER
|
co_cr = fiber.cr(co_frequency)
|
||||||
bvp_solution = solve_bvp(ode_function, boundary_residual, z, initial_guess_conditions, tol=tolerance)
|
co_alpha = fiber.alpha(co_frequency)
|
||||||
|
co_power_profile = \
|
||||||
rho = (bvp_solution.y.transpose() / power_spectrum).transpose()
|
RamanSolver.first_order_derivative_solution(co_power, co_alpha, co_cr, z, lumped_losses)
|
||||||
rho = sqrt(rho) # From power attenuation to field attenuation
|
# Counter-propagating profile initialization
|
||||||
stimulated_raman_scattering = StimulatedRamanScattering(freq_array, bvp_solution.x, rho, bvp_solution.y)
|
cnt_power_profile = empty([co_frequency.size, z.size])
|
||||||
|
if cnt_frequency.size:
|
||||||
self._stimulated_raman_scattering = stimulated_raman_scattering
|
cnt_cr = fiber.cr(cnt_frequency)
|
||||||
|
cnt_alpha = fiber.alpha(cnt_frequency)
|
||||||
def _residuals_stimulated_raman(self, ya, yb, power_spectrum, prop_direct):
|
cnt_power_profile = \
|
||||||
|
flip(RamanSolver.first_order_derivative_solution(cnt_power, cnt_alpha, cnt_cr,
|
||||||
computed_boundary_value = zeros(ya.size)
|
z[-1] - flip(z), flip(lumped_losses)))
|
||||||
|
# Co-propagating and Counter-propagating Profile Computation
|
||||||
for index, direction in enumerate(prop_direct):
|
if co_frequency.size and cnt_frequency.size:
|
||||||
if direction == +1:
|
co_power_profile, cnt_power_profile = \
|
||||||
computed_boundary_value[index] = ya[index]
|
RamanSolver.iterative_algorithm(co_power_profile, cnt_power_profile,
|
||||||
|
co_frequency, cnt_frequency, z, fiber, lumped_losses)
|
||||||
|
# Complete Power Profile
|
||||||
|
power_profile = concatenate((co_power_profile, cnt_power_profile), axis=0)
|
||||||
|
# Complete Loss Profile
|
||||||
|
co_loss_profile = co_power_profile / outer(co_power, ones(z.size))
|
||||||
|
cnt_loss_profile = cnt_power_profile / outer(cnt_power, ones(z.size))
|
||||||
|
loss_profile = concatenate((co_loss_profile, cnt_loss_profile), axis=0)
|
||||||
|
# Complete frequency
|
||||||
|
frequency = concatenate((co_frequency, cnt_frequency))
|
||||||
else:
|
else:
|
||||||
computed_boundary_value[index] = yb[index]
|
# Without Raman pumps
|
||||||
|
alpha = fiber.alpha(spectral_info.frequency)
|
||||||
return power_spectrum - computed_boundary_value
|
cr = fiber.cr(spectral_info.frequency)
|
||||||
|
# Power profile
|
||||||
def _initial_guess_stimulated_raman(self, z, power_spectrum, alphap_fiber, prop_direct):
|
power_profile = \
|
||||||
""" Computes the initial guess knowing the boundary conditions
|
RamanSolver.first_order_derivative_solution(spectral_info.signal, alpha, cr, z, lumped_losses)
|
||||||
:param z: patial axis [m]. numpy array
|
# Loss profile
|
||||||
:param power_spectrum: power in each frequency slice [W].
|
loss_profile = power_profile / outer(spectral_info.signal, ones(z.size))
|
||||||
Frequency axis is defined by freq_array. numpy array
|
frequency = spectral_info.frequency
|
||||||
:param alphap_fiber: frequency dependent fiber attenuation of signal power [1/m].
|
power_profile = interp1d(z, power_profile, axis=1)(z_final)
|
||||||
Frequency defined by freq_array. numpy array
|
loss_profile = interp1d(z, loss_profile, axis=1)(z_final)
|
||||||
:param prop_direct: indicates the propagation direction of each power slice in power_spectrum:
|
stimulated_raman_scattering = StimulatedRamanScattering(power_profile, loss_profile, frequency, z_final)
|
||||||
+1 for forward propagation and -1 for backward propagation. Frequency defined by freq_array. numpy array
|
|
||||||
:return: power_guess: guess on the initial conditions [W].
|
|
||||||
The first ndarray index identifies the frequency slice,
|
|
||||||
the second ndarray index identifies the step in z. ndarray
|
|
||||||
"""
|
|
||||||
|
|
||||||
power_guess = empty((power_spectrum.size, z.size))
|
|
||||||
for f_index, power_slice in enumerate(power_spectrum):
|
|
||||||
if prop_direct[f_index] == +1:
|
|
||||||
power_guess[f_index, :] = exp(-alphap_fiber[f_index] * z) * power_slice
|
|
||||||
else:
|
else:
|
||||||
power_guess[f_index, :] = exp(-alphap_fiber[f_index] * z[::-1]) * power_slice
|
stimulated_raman_scattering = \
|
||||||
|
RamanSolver.calculate_attenuation_profile(spectral_info, fiber)
|
||||||
|
return stimulated_raman_scattering
|
||||||
|
|
||||||
return power_guess
|
@staticmethod
|
||||||
|
def calculate_spontaneous_raman_scattering(spectral_info: SpectralInformation, srs: StimulatedRamanScattering,
|
||||||
def _ode_stimulated_raman(self, z, power_spectrum, alphap_fiber, freq_array, cr_raman_matrix, prop_direct):
|
fiber):
|
||||||
""" Aim of ode_raman is to implement the set of ordinary differential equations (ODEs)
|
"""Evaluates the Raman profile along the z axis for all the frequency propagated in the fiber
|
||||||
describing the Raman effect.
|
including the Raman pumps co- and counter-propagating.
|
||||||
:param z: spatial axis (unused).
|
|
||||||
:param power_spectrum: power in each frequency slice [W].
|
|
||||||
Frequency axis is defined by freq_array. numpy array. Size n
|
|
||||||
:param alphap_fiber: frequency dependent fiber attenuation of signal power [1/m].
|
|
||||||
Frequency defined by freq_array. numpy array. Size n
|
|
||||||
:param freq_array: reference frequency axis [Hz]. numpy array. Size n
|
|
||||||
:param cr_raman: Cr(f) Raman gain efficiency variation in frequency [1/W/m].
|
|
||||||
Frequency defined by freq_array. numpy ndarray. Size nxn
|
|
||||||
:param prop_direct: indicates the propagation direction of each power slice in power_spectrum:
|
|
||||||
+1 for forward propagation and -1 for backward propagation.
|
|
||||||
Frequency defined by freq_array. numpy array. Size n
|
|
||||||
:return: dP/dz: the power variation in dz [W/m]. numpy array. Size n
|
|
||||||
"""
|
"""
|
||||||
|
logger.debug('Start computing fiber Spontaneous Raman Scattering')
|
||||||
|
z = srs.z
|
||||||
|
baud_rate = spectral_info.baud_rate
|
||||||
|
frequency = spectral_info.frequency
|
||||||
|
channels_loss = srs.loss_profile[:spectral_info.number_of_channels, :]
|
||||||
|
|
||||||
dpdz = nan * ones(power_spectrum.shape)
|
# calculate ase power
|
||||||
for f_ind, power in enumerate(power_spectrum):
|
ase = zeros(spectral_info.number_of_channels)
|
||||||
cr_raman = cr_raman_matrix[f_ind, :]
|
for i, pump in enumerate(fiber.raman_pumps):
|
||||||
vibrational_loss = freq_array[f_ind] / freq_array[:f_ind]
|
pump_power = srs.power_profile[spectral_info.number_of_channels + i, :]
|
||||||
|
df = pump.frequency - frequency
|
||||||
|
eta = - 1 / (1 - exp(h * df / (k * fiber.temperature)))
|
||||||
|
cr = fiber._cr_function(df)
|
||||||
|
integral = trapz(pump_power / channels_loss, z, axis=1)
|
||||||
|
ase += 2 * h * baud_rate * frequency * (1 + eta) * cr * (df > 0) * integral # 2 factor for double pol
|
||||||
|
return ase
|
||||||
|
|
||||||
for z_ind, power_sample in enumerate(power):
|
@staticmethod
|
||||||
raman_gain = sum(cr_raman[f_ind + 1:] * power_spectrum[f_ind + 1:, z_ind])
|
def first_order_derivative_solution(power_in, alpha, cr, z, lumped_losses):
|
||||||
raman_loss = sum(vibrational_loss * cr_raman[:f_ind] * power_spectrum[:f_ind, z_ind])
|
"""Solves the Raman first order derivative equation
|
||||||
|
|
||||||
dpdz_element = prop_direct[f_ind] * (-alphap_fiber[f_ind] + raman_gain - raman_loss) * power_sample
|
:param power_in: launch power array
|
||||||
dpdz[f_ind][z_ind] = dpdz_element
|
:param alpha: loss coefficient array
|
||||||
|
:param cr: Raman efficiency coefficients matrix
|
||||||
|
:param z: z position array
|
||||||
|
:param lumped_losses: concentrated losses array along the fiber span
|
||||||
|
:return: power profile matrix
|
||||||
|
"""
|
||||||
|
dz = z[1:] - z[:-1]
|
||||||
|
power = outer(power_in, ones(z.size))
|
||||||
|
for i in range(1, z.size):
|
||||||
|
power[:, i] = \
|
||||||
|
power[:, i - 1] * (1 + (- alpha + sum(cr * power[:, i - 1], 1)) * dz[i - 1]) * lumped_losses[i - 1]
|
||||||
|
return power
|
||||||
|
|
||||||
return vstack(dpdz)
|
@staticmethod
|
||||||
|
def iterative_algorithm(co_initial_guess_power, cnt_initial_guess_power, co_frequency, cnt_frequency, z, fiber,
|
||||||
|
lumped_losses):
|
||||||
|
"""Solves the Raman first order derivative equation in case of both co- and counter-propagating
|
||||||
|
frequencies
|
||||||
|
|
||||||
|
:param co_initial_guess_power: co-propagationg Raman first order derivative equation solution
|
||||||
|
:param cnt_initial_guess_power: counter-propagationg Raman first order derivative equation solution
|
||||||
|
:param co_frequency: co-propagationg frequencies
|
||||||
|
:param cnt_frequency: counter-propagationg frequencies
|
||||||
|
:param z: z position array
|
||||||
|
:param fiber: instance of gnpy.core.elements.Fiber or gnpy.core.elements.RamanFiber
|
||||||
|
:param lumped_losses: concentrated losses array along the fiber span
|
||||||
|
:return: co- and counter-propagatng power profile matrix
|
||||||
|
"""
|
||||||
|
logger.debug(' Start iterative algorithm')
|
||||||
|
residue = 1
|
||||||
|
residue_tol = 1e-6
|
||||||
|
accuracy = 1
|
||||||
|
accuracy_tol = 1e-3
|
||||||
|
iteration = 0
|
||||||
|
num_max_iter = 1000
|
||||||
|
prev_power = concatenate((co_initial_guess_power, cnt_initial_guess_power))
|
||||||
|
frequency = concatenate((co_frequency, cnt_frequency))
|
||||||
|
dz = z[1:] - z[:-1]
|
||||||
|
cr = fiber.cr(frequency)
|
||||||
|
alpha = fiber.alpha(frequency)
|
||||||
|
next_power = array(prev_power)
|
||||||
|
while residue > residue_tol and accuracy > accuracy_tol and iteration < num_max_iter:
|
||||||
|
iteration += 1
|
||||||
|
for i in range(1, z.size):
|
||||||
|
dpdz = - alpha + sum(cr * next_power[:, i - 1], 1)
|
||||||
|
next_power[:co_frequency.size, i] = \
|
||||||
|
next_power[:co_frequency.size, i - 1] * (1 + dpdz[:co_frequency.size] * dz[i - 1]) * \
|
||||||
|
lumped_losses[i - 1]
|
||||||
|
for i in range(1, z.size):
|
||||||
|
dpdz = - alpha + sum(cr * next_power[:, -i], 1)
|
||||||
|
next_power[co_frequency.size:, -i - 1] = \
|
||||||
|
next_power[co_frequency.size:, -i] * (1 + dpdz[co_frequency.size:] * dz[-i]) * \
|
||||||
|
lumped_losses[-i]
|
||||||
|
|
||||||
|
dpdz_num = (next_power[:co_frequency.size, 1:] - next_power[:co_frequency.size, :-1]) / dz
|
||||||
|
dpdz_exp = next_power[:co_frequency.size, :-1] * \
|
||||||
|
(- outer(alpha, ones(z.size)) + inner(cr, transpose(next_power)))[:co_frequency.size, :-1] * \
|
||||||
|
lumped_losses[:-1]
|
||||||
|
|
||||||
|
residue = max(abs((next_power - prev_power) / next_power))
|
||||||
|
accuracy = max(abs((dpdz_exp - dpdz_num) / dpdz_exp))
|
||||||
|
prev_power = array(next_power)
|
||||||
|
logger.debug(f' Iteration: {iteration} Accuracy: {format_float_scientific(accuracy, precision=3)}')
|
||||||
|
return next_power[:co_frequency.size, :], next_power[co_frequency.size:, :]
|
||||||
|
|
||||||
|
|
||||||
class NliSolver:
|
class NliSolver:
|
||||||
@@ -450,162 +275,141 @@ class NliSolver:
|
|||||||
Model and method can be specified in `sim_params.nli_params.method`.
|
Model and method can be specified in `sim_params.nli_params.method`.
|
||||||
List of implemented methods:
|
List of implemented methods:
|
||||||
'gn_model_analytic': eq. 120 from arXiv:1209.0394
|
'gn_model_analytic': eq. 120 from arXiv:1209.0394
|
||||||
'ggn_spectrally_separated_xpm_spm': XPM plus SPM
|
'ggn_spectrally_separated': eq. 21 from arXiv: 1710.02225 spectrally separated
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, fiber=None):
|
@staticmethod
|
||||||
""" Initialize the Nli solver object.
|
def effective_length(alpha, length):
|
||||||
:param fiber: instance of elements.py/Fiber.
|
"""The effective length identify the region in which the NLI has a significant contribution to
|
||||||
|
the signal degradation.
|
||||||
"""
|
"""
|
||||||
self._fiber = fiber
|
return (1 - exp(- alpha * length)) / alpha
|
||||||
self._stimulated_raman_scattering = None
|
|
||||||
|
|
||||||
@property
|
@staticmethod
|
||||||
def fiber(self):
|
def compute_nli(spectral_info: SpectralInformation, srs: StimulatedRamanScattering, fiber):
|
||||||
return self._fiber
|
|
||||||
|
|
||||||
@property
|
|
||||||
def stimulated_raman_scattering(self):
|
|
||||||
return self._stimulated_raman_scattering
|
|
||||||
|
|
||||||
@stimulated_raman_scattering.setter
|
|
||||||
def stimulated_raman_scattering(self, stimulated_raman_scattering):
|
|
||||||
self._stimulated_raman_scattering = stimulated_raman_scattering
|
|
||||||
|
|
||||||
def compute_nli(self, carrier, *carriers):
|
|
||||||
""" Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier`
|
""" Compute NLI power generated by the WDM comb `*carriers` on the channel under test `carrier`
|
||||||
at the end of the fiber span.
|
at the end of the fiber span.
|
||||||
"""
|
"""
|
||||||
simulation = Simulation.get_simulation()
|
logger.debug('Start computing fiber NLI noise')
|
||||||
sim_params = simulation.sim_params
|
# Physical fiber parameters
|
||||||
if 'gn_model_analytic' == sim_params.nli_params.nli_method_name.lower():
|
alpha = fiber.alpha(spectral_info.frequency)
|
||||||
carrier_nli = self._gn_analytic(carrier, *carriers)
|
beta2 = fiber.params.beta2
|
||||||
elif 'ggn_spectrally_separated' in sim_params.nli_params.nli_method_name.lower():
|
beta3 = fiber.params.beta3
|
||||||
eta_matrix = self._compute_eta_matrix(carrier, *carriers)
|
f_ref_beta = fiber.params.ref_frequency
|
||||||
carrier_nli = self._carrier_nli_from_eta_matrix(eta_matrix, carrier, *carriers)
|
gamma = fiber.params.gamma
|
||||||
|
length = fiber.params.length
|
||||||
|
|
||||||
|
if 'gn_model_analytic' == sim_params.nli_params.method:
|
||||||
|
nli = NliSolver._gn_analytic(spectral_info, alpha, beta2, gamma, length)
|
||||||
|
elif 'ggn_spectrally_separated' in sim_params.nli_params.method:
|
||||||
|
nli = NliSolver._ggn_spectrally_separated(spectral_info, srs, alpha, beta2, beta3, f_ref_beta, gamma)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'Method {sim_params.nli_params.nli_method_name} not implemented.')
|
raise ValueError(f'Method {sim_params.nli_params.method} not implemented.')
|
||||||
|
return nli
|
||||||
return carrier_nli
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _carrier_nli_from_eta_matrix(eta_matrix, carrier, *carriers):
|
|
||||||
carrier_nli = 0
|
|
||||||
for pump_carrier_1 in carriers:
|
|
||||||
for pump_carrier_2 in carriers:
|
|
||||||
carrier_nli += eta_matrix[pump_carrier_1.channel_number - 1, pump_carrier_2.channel_number - 1] * \
|
|
||||||
pump_carrier_1.power.signal * pump_carrier_2.power.signal
|
|
||||||
carrier_nli *= carrier.power.signal
|
|
||||||
|
|
||||||
return carrier_nli
|
|
||||||
|
|
||||||
def _compute_eta_matrix(self, cut_carrier, *carriers):
|
|
||||||
cut_index = cut_carrier.channel_number - 1
|
|
||||||
simulation = Simulation.get_simulation()
|
|
||||||
sim_params = simulation.sim_params
|
|
||||||
# Matrix initialization
|
|
||||||
matrix_size = max(carriers, key=lambda x: getattr(x, 'channel_number')).channel_number
|
|
||||||
eta_matrix = zeros(shape=(matrix_size, matrix_size))
|
|
||||||
|
|
||||||
# SPM
|
|
||||||
logger.debug(f'Start computing SPM on channel #{cut_carrier.channel_number}')
|
|
||||||
# SPM GGN
|
|
||||||
if 'ggn' in sim_params.nli_params.nli_method_name.lower():
|
|
||||||
partial_nli = self._generalized_spectrally_separated_spm(cut_carrier)
|
|
||||||
# SPM GN
|
|
||||||
elif 'gn' in sim_params.nli_params.nli_method_name.lower():
|
|
||||||
partial_nli = self._gn_analytic(cut_carrier, *[cut_carrier])
|
|
||||||
eta_matrix[cut_index, cut_index] = partial_nli / (cut_carrier.power.signal**3)
|
|
||||||
|
|
||||||
# XPM
|
|
||||||
for pump_carrier in carriers:
|
|
||||||
pump_index = pump_carrier.channel_number - 1
|
|
||||||
if not (cut_index == pump_index):
|
|
||||||
logger.debug(f'Start computing XPM on channel #{cut_carrier.channel_number} '
|
|
||||||
f'from channel #{pump_carrier.channel_number}')
|
|
||||||
# XPM GGN
|
|
||||||
if 'ggn' in sim_params.nli_params.nli_method_name.lower():
|
|
||||||
partial_nli = self._generalized_spectrally_separated_xpm(cut_carrier, pump_carrier)
|
|
||||||
# XPM GGN
|
|
||||||
elif 'gn' in sim_params.nli_params.nli_method_name.lower():
|
|
||||||
partial_nli = self._gn_analytic(cut_carrier, *[pump_carrier])
|
|
||||||
eta_matrix[pump_index, pump_index] = \
|
|
||||||
partial_nli / (cut_carrier.power.signal * pump_carrier.power.signal**2)
|
|
||||||
return eta_matrix
|
|
||||||
|
|
||||||
# Methods for computing GN-model
|
# Methods for computing GN-model
|
||||||
def _gn_analytic(self, carrier, *carriers):
|
@staticmethod
|
||||||
""" Computes the nonlinear interference power on a single carrier.
|
def _gn_analytic(spectral_info: SpectralInformation, alpha, beta2, gamma, length):
|
||||||
The method uses eq. 120 from arXiv:1209.0394.
|
""" Computes the nonlinear interference power evaluated at the fiber input.
|
||||||
:param carrier: the signal under analysis
|
The method uses eq. 120 from arXiv:1209.0394
|
||||||
:param carriers: the full WDM comb
|
|
||||||
:return: carrier_nli: the amount of nonlinear interference in W on the carrier under analysis
|
|
||||||
"""
|
"""
|
||||||
beta2 = self.fiber.params.beta2
|
spm_weight = (16.0 / 27.0) * gamma ** 2
|
||||||
gamma = self.fiber.params.gamma
|
xpm_weight = 2 * (16.0 / 27.0) * gamma ** 2
|
||||||
effective_length = self.fiber.params.effective_length
|
|
||||||
asymptotic_length = self.fiber.params.asymptotic_length
|
|
||||||
|
|
||||||
g_nli = 0
|
nch = spectral_info.number_of_channels
|
||||||
for interfering_carrier in carriers:
|
identity = diag(ones(nch))
|
||||||
g_interfering = interfering_carrier.power.signal / interfering_carrier.baud_rate
|
weight = spm_weight * identity + xpm_weight * (ones([nch, nch]) - identity)
|
||||||
g_signal = carrier.power.signal / carrier.baud_rate
|
|
||||||
g_nli += g_interfering**2 * g_signal \
|
effective_length = NliSolver.effective_length(alpha, length)
|
||||||
* _psi(carrier, interfering_carrier, beta2=beta2, asymptotic_length=asymptotic_length)
|
asymptotic_length = 1 / alpha
|
||||||
g_nli *= (16.0 / 27.0) * (gamma * effective_length) ** 2 /\
|
|
||||||
(2 * pi * abs(beta2) * asymptotic_length)
|
df = spectral_info.df
|
||||||
carrier_nli = carrier.baud_rate * g_nli
|
baud_rate = spectral_info.baud_rate
|
||||||
return carrier_nli
|
|
||||||
|
psd = spectral_info.signal / baud_rate
|
||||||
|
ggg = outer(psd, psd**2)
|
||||||
|
|
||||||
|
psi = NliSolver._psi(df, baud_rate, beta2, effective_length, asymptotic_length)
|
||||||
|
g_nli = sum(weight * ggg * psi, 1)
|
||||||
|
nli = spectral_info.baud_rate * g_nli # Local white noise
|
||||||
|
return nli
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _psi(df, baud_rate, beta2, effective_length, asymptotic_length):
|
||||||
|
"""Calculates eq. 123 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__"""
|
||||||
|
cut_baud_rate = outer(baud_rate, ones(baud_rate.size))
|
||||||
|
pump_baud_rate = baud_rate
|
||||||
|
right_extreme = df + pump_baud_rate / 2
|
||||||
|
left_extreme = df - pump_baud_rate / 2
|
||||||
|
psi = (arcsinh(pi ** 2 * asymptotic_length * abs(beta2) * cut_baud_rate * right_extreme) -
|
||||||
|
arcsinh(pi ** 2 * asymptotic_length * abs(beta2) * cut_baud_rate * left_extreme)) / 2
|
||||||
|
psi *= effective_length ** 2 / (2 * pi * abs(beta2) * asymptotic_length)
|
||||||
|
return psi
|
||||||
|
|
||||||
# Methods for computing the GGN-model
|
# Methods for computing the GGN-model
|
||||||
def _generalized_spectrally_separated_spm(self, carrier):
|
@staticmethod
|
||||||
gamma = self.fiber.params.gamma
|
def _ggn_spectrally_separated(spectral_info: SpectralInformation, srs: StimulatedRamanScattering,
|
||||||
simulation = Simulation.get_simulation()
|
alpha, beta2, beta3, f_ref_beta, gamma):
|
||||||
sim_params = simulation.sim_params
|
""" Computes the nonlinear interference power evaluated at the fiber input.
|
||||||
f_cut_resolution = sim_params.nli_params.f_cut_resolution['delta_0']
|
The method uses eq. 21 from arXiv: 1710.02225
|
||||||
f_eval = carrier.frequency
|
|
||||||
g_cut = (carrier.power.signal / carrier.baud_rate)
|
|
||||||
|
|
||||||
spm_nli = carrier.baud_rate * (16.0 / 27.0) * gamma ** 2 * g_cut ** 3 * \
|
|
||||||
self._generalized_psi(carrier, carrier, f_eval, f_cut_resolution, f_cut_resolution)
|
|
||||||
return spm_nli
|
|
||||||
|
|
||||||
def _generalized_spectrally_separated_xpm(self, cut_carrier, pump_carrier):
|
|
||||||
gamma = self.fiber.params.gamma
|
|
||||||
simulation = Simulation.get_simulation()
|
|
||||||
sim_params = simulation.sim_params
|
|
||||||
delta_index = pump_carrier.channel_number - cut_carrier.channel_number
|
|
||||||
f_cut_resolution = sim_params.nli_params.f_cut_resolution[f'delta_{delta_index}']
|
|
||||||
f_pump_resolution = sim_params.nli_params.f_pump_resolution
|
|
||||||
f_eval = cut_carrier.frequency
|
|
||||||
g_pump = (pump_carrier.power.signal / pump_carrier.baud_rate)
|
|
||||||
g_cut = (cut_carrier.power.signal / cut_carrier.baud_rate)
|
|
||||||
frequency_offset_threshold = self._frequency_offset_threshold(pump_carrier.baud_rate)
|
|
||||||
if abs(cut_carrier.frequency - pump_carrier.frequency) <= frequency_offset_threshold:
|
|
||||||
xpm_nli = cut_carrier.baud_rate * (16.0 / 27.0) * gamma ** 2 * g_pump**2 * g_cut * \
|
|
||||||
2 * self._generalized_psi(cut_carrier, pump_carrier, f_eval, f_cut_resolution, f_pump_resolution)
|
|
||||||
else:
|
|
||||||
xpm_nli = cut_carrier.baud_rate * (16.0 / 27.0) * gamma ** 2 * g_pump**2 * g_cut * \
|
|
||||||
2 * self._fast_generalized_psi(cut_carrier, pump_carrier, f_eval, f_cut_resolution)
|
|
||||||
return xpm_nli
|
|
||||||
|
|
||||||
def _fast_generalized_psi(self, cut_carrier, pump_carrier, f_eval, f_cut_resolution):
|
|
||||||
""" It computes the generalized psi function similarly to the one used in the GN model
|
|
||||||
:return: generalized_psi
|
|
||||||
"""
|
"""
|
||||||
# Fiber parameters
|
dispersion_tolerance = sim_params.nli_params.dispersion_tolerance
|
||||||
alpha0 = self.fiber.alpha0(f_eval)
|
phase_shift_tolerance = sim_params.nli_params.phase_shift_tolerance
|
||||||
beta2 = self.fiber.params.beta2
|
slot_width = max(spectral_info.slot_width)
|
||||||
beta3 = self.fiber.params.beta3
|
delta_z = sim_params.raman_params.result_spatial_resolution
|
||||||
f_ref_beta = self.fiber.params.ref_frequency
|
spm_weight = (16.0 / 27.0) * gamma ** 2
|
||||||
z = self.stimulated_raman_scattering.z
|
xpm_weight = 2 * (16.0 / 27.0) * gamma ** 2
|
||||||
frequency_rho = self.stimulated_raman_scattering.frequency
|
cuts = [carrier for carrier in spectral_info.carriers if carrier.channel_number
|
||||||
rho_norm = self.stimulated_raman_scattering.rho * exp(abs(alpha0) * z / 2)
|
in sim_params.nli_params.computed_channels] if sim_params.nli_params.computed_channels \
|
||||||
if len(frequency_rho) == 1:
|
else spectral_info.carriers
|
||||||
def rho_function(f): return rho_norm[0, :]
|
|
||||||
|
g_nli = array([])
|
||||||
|
f_nli = array([])
|
||||||
|
for cut_carrier in cuts:
|
||||||
|
logger.debug(f'Start computing fiber NLI noise of cut: {cut_carrier}')
|
||||||
|
f_eval = cut_carrier.frequency
|
||||||
|
g_nli_computed = 0
|
||||||
|
g_cut = (cut_carrier.power.signal / cut_carrier.baud_rate)
|
||||||
|
for j, pump_carrier in enumerate(spectral_info.carriers):
|
||||||
|
dn = abs(pump_carrier.channel_number - cut_carrier.channel_number)
|
||||||
|
delta_f = abs(cut_carrier.frequency - pump_carrier.frequency)
|
||||||
|
k_tol = dispersion_tolerance * abs(alpha[j])
|
||||||
|
phi_tol = phase_shift_tolerance / delta_z
|
||||||
|
f_cut_resolution = min(k_tol, phi_tol) / abs(beta2) / (4 * pi ** 2 * (1 + dn) * slot_width)
|
||||||
|
f_pump_resolution = min(k_tol, phi_tol) / abs(beta2) / (4 * pi ** 2 * slot_width)
|
||||||
|
if dn == 0: # SPM
|
||||||
|
ggg = g_cut ** 3
|
||||||
|
g_nli_computed += \
|
||||||
|
spm_weight * ggg * NliSolver._generalized_psi(f_eval, cut_carrier, pump_carrier,
|
||||||
|
f_cut_resolution, f_pump_resolution,
|
||||||
|
srs, alpha[j], beta2, beta3, f_ref_beta)
|
||||||
|
else: # XPM
|
||||||
|
g_pump = (pump_carrier.power.signal / pump_carrier.baud_rate)
|
||||||
|
ggg = g_cut * g_pump ** 2
|
||||||
|
frequency_offset_threshold = NliSolver._frequency_offset_threshold(beta2, pump_carrier.baud_rate)
|
||||||
|
if abs(delta_f) <= frequency_offset_threshold:
|
||||||
|
g_nli_computed += \
|
||||||
|
xpm_weight * ggg * NliSolver._generalized_psi(f_eval, cut_carrier, pump_carrier,
|
||||||
|
f_cut_resolution, f_pump_resolution,
|
||||||
|
srs, alpha[j], beta2, beta3, f_ref_beta)
|
||||||
else:
|
else:
|
||||||
rho_function = interp1d(frequency_rho, rho_norm, axis=0, fill_value='extrapolate')
|
g_nli_computed += \
|
||||||
rho_norm_pump = rho_function(pump_carrier.frequency)
|
xpm_weight * ggg * NliSolver._fast_generalized_psi(f_eval, cut_carrier, pump_carrier,
|
||||||
|
f_cut_resolution, srs, alpha[j], beta2,
|
||||||
|
beta3, f_ref_beta)
|
||||||
|
f_nli = append(f_nli, cut_carrier.frequency)
|
||||||
|
g_nli = append(g_nli, g_nli_computed)
|
||||||
|
g_nli = interp(spectral_info.frequency, f_nli, g_nli)
|
||||||
|
nli = spectral_info.baud_rate * g_nli # Local white noise
|
||||||
|
return nli
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _fast_generalized_psi(f_eval, cut_carrier, pump_carrier, f_cut_resolution, srs, alpha, beta2, beta3,
|
||||||
|
f_ref_beta):
|
||||||
|
"""Computes the generalized psi function similarly to the one used in the GN model."""
|
||||||
|
z = srs.z
|
||||||
|
rho_norm = srs.rho * exp(outer(alpha/2, z))
|
||||||
|
rho_pump = interp1d(srs.frequency, rho_norm, axis=0)(pump_carrier.frequency)
|
||||||
|
|
||||||
f1_array = array([pump_carrier.frequency - (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2),
|
f1_array = array([pump_carrier.frequency - (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2),
|
||||||
pump_carrier.frequency + (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2)])
|
pump_carrier.frequency + (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2)])
|
||||||
@@ -617,28 +421,18 @@ class NliSolver:
|
|||||||
for f1_index, f1 in enumerate(f1_array):
|
for f1_index, f1 in enumerate(f1_array):
|
||||||
delta_beta = 4 * pi ** 2 * (f1 - f_eval) * (f2_array - f_eval) * \
|
delta_beta = 4 * pi ** 2 * (f1 - f_eval) * (f2_array - f_eval) * \
|
||||||
(beta2 + pi * beta3 * (f1 + f2_array - 2 * f_ref_beta))
|
(beta2 + pi * beta3 * (f1 + f2_array - 2 * f_ref_beta))
|
||||||
integrand_f2 = self._generalized_rho_nli(delta_beta, rho_norm_pump, z, alpha0)
|
integrand_f2 = NliSolver._generalized_rho_nli(delta_beta, rho_pump, z, alpha)
|
||||||
integrand_f1[f1_index] = 2 * trapz(integrand_f2, f2_array) # 2x since integrand_f2 is symmetric in f2
|
integrand_f1[f1_index] = 2 * trapz(integrand_f2, f2_array) # 2x since integrand_f2 is symmetric in f2
|
||||||
generalized_psi = 0.5 * sum(integrand_f1) * pump_carrier.baud_rate
|
generalized_psi = 0.5 * sum(integrand_f1) * pump_carrier.baud_rate
|
||||||
return generalized_psi
|
return generalized_psi
|
||||||
|
|
||||||
def _generalized_psi(self, cut_carrier, pump_carrier, f_eval, f_cut_resolution, f_pump_resolution):
|
@staticmethod
|
||||||
""" It computes the generalized psi function similarly to the one used in the GN model
|
def _generalized_psi(f_eval, cut_carrier, pump_carrier, f_cut_resolution, f_pump_resolution, srs, alpha, beta2,
|
||||||
:return: generalized_psi
|
beta3, f_ref_beta):
|
||||||
"""
|
"""Computes the generalized psi function similarly to the one used in the GN model."""
|
||||||
# Fiber parameters
|
z = srs.z
|
||||||
alpha0 = self.fiber.alpha0(f_eval)
|
rho_norm = srs.rho * exp(outer(alpha / 2, z))
|
||||||
beta2 = self.fiber.params.beta2
|
rho_pump = interp1d(srs.frequency, rho_norm, axis=0)(pump_carrier.frequency)
|
||||||
beta3 = self.fiber.params.beta3
|
|
||||||
f_ref_beta = self.fiber.params.ref_frequency
|
|
||||||
z = self.stimulated_raman_scattering.z
|
|
||||||
frequency_rho = self.stimulated_raman_scattering.frequency
|
|
||||||
rho_norm = self.stimulated_raman_scattering.rho * exp(abs(alpha0) * z / 2)
|
|
||||||
if len(frequency_rho) == 1:
|
|
||||||
def rho_function(f): return rho_norm[0, :]
|
|
||||||
else:
|
|
||||||
rho_function = interp1d(frequency_rho, rho_norm, axis=0, fill_value='extrapolate')
|
|
||||||
rho_norm_pump = rho_function(pump_carrier.frequency)
|
|
||||||
|
|
||||||
f1_array = arange(pump_carrier.frequency - (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2),
|
f1_array = arange(pump_carrier.frequency - (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2),
|
||||||
pump_carrier.frequency + (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2),
|
pump_carrier.frequency + (pump_carrier.baud_rate * (1 + pump_carrier.roll_off) / 2),
|
||||||
@@ -654,48 +448,34 @@ class NliSolver:
|
|||||||
psd2 = raised_cosine_comb(f2_array, cut_carrier) * (cut_carrier.baud_rate / cut_carrier.power.signal)
|
psd2 = raised_cosine_comb(f2_array, cut_carrier) * (cut_carrier.baud_rate / cut_carrier.power.signal)
|
||||||
psd3 = raised_cosine_comb(f3_array, pump_carrier) * (pump_carrier.baud_rate / pump_carrier.power.signal)
|
psd3 = raised_cosine_comb(f3_array, pump_carrier) * (pump_carrier.baud_rate / pump_carrier.power.signal)
|
||||||
ggg = psd1_sample * psd2 * psd3
|
ggg = psd1_sample * psd2 * psd3
|
||||||
|
|
||||||
delta_beta = 4 * pi**2 * (f1 - f_eval) * (f2_array - f_eval) * \
|
delta_beta = 4 * pi**2 * (f1 - f_eval) * (f2_array - f_eval) * \
|
||||||
(beta2 + pi * beta3 * (f1 + f2_array - 2 * f_ref_beta))
|
(beta2 + pi * beta3 * (f1 + f2_array - 2 * f_ref_beta))
|
||||||
|
integrand_f2 = ggg * NliSolver._generalized_rho_nli(delta_beta, rho_pump, z, alpha)
|
||||||
integrand_f2 = ggg * self._generalized_rho_nli(delta_beta, rho_norm_pump, z, alpha0)
|
|
||||||
integrand_f1[f1_index] = trapz(integrand_f2, f2_array)
|
integrand_f1[f1_index] = trapz(integrand_f2, f2_array)
|
||||||
generalized_psi = trapz(integrand_f1, f1_array)
|
generalized_psi = trapz(integrand_f1, f1_array)
|
||||||
return generalized_psi
|
return generalized_psi
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _generalized_rho_nli(delta_beta, rho_norm_pump, z, alpha0):
|
def _generalized_rho_nli(delta_beta, rho_pump, z, alpha):
|
||||||
w = 1j * delta_beta - alpha0
|
w = 1j * delta_beta - alpha
|
||||||
generalized_rho_nli = (rho_norm_pump[-1]**2 * exp(w * z[-1]) - rho_norm_pump[0]**2 * exp(w * z[0])) / w
|
generalized_rho_nli = (rho_pump[-1]**2 * exp(w * z[-1]) - rho_pump[0]**2 * exp(w * z[0])) / w
|
||||||
for z_ind in range(0, len(z) - 1):
|
for z_ind in range(0, len(z) - 1):
|
||||||
derivative_rho = (rho_norm_pump[z_ind + 1]**2 - rho_norm_pump[z_ind]**2) / (z[z_ind + 1] - z[z_ind])
|
derivative_rho = (rho_pump[z_ind + 1]**2 - rho_pump[z_ind]**2) / (z[z_ind + 1] - z[z_ind])
|
||||||
generalized_rho_nli -= derivative_rho * (exp(w * z[z_ind + 1]) - exp(w * z[z_ind])) / (w**2)
|
generalized_rho_nli -= derivative_rho * (exp(w * z[z_ind + 1]) - exp(w * z[z_ind])) / (w**2)
|
||||||
generalized_rho_nli = abs(generalized_rho_nli)**2
|
generalized_rho_nli = abs(generalized_rho_nli)**2
|
||||||
return generalized_rho_nli
|
return generalized_rho_nli
|
||||||
|
|
||||||
def _frequency_offset_threshold(self, symbol_rate):
|
@staticmethod
|
||||||
|
def _frequency_offset_threshold(beta2, symbol_rate):
|
||||||
k_ref = 5
|
k_ref = 5
|
||||||
beta2_ref = 21.3e-27
|
beta2_ref = 21.3e-27
|
||||||
delta_f_ref = 50e9
|
delta_f_ref = 50e9
|
||||||
rs_ref = 32e9
|
rs_ref = 32e9
|
||||||
beta2 = abs(self.fiber.params.beta2)
|
beta2 = abs(beta2)
|
||||||
freq_offset_th = ((k_ref * delta_f_ref) * rs_ref * beta2_ref) / (beta2 * symbol_rate)
|
freq_offset_th = ((k_ref * delta_f_ref) * rs_ref * beta2_ref) / (beta2 * symbol_rate)
|
||||||
return freq_offset_th
|
return freq_offset_th
|
||||||
|
|
||||||
|
|
||||||
def _psi(carrier, interfering_carrier, beta2, asymptotic_length):
|
|
||||||
"""Calculates eq. 123 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__"""
|
|
||||||
if carrier.channel_number == interfering_carrier.channel_number: # SCI, SPM
|
|
||||||
psi = arcsinh(0.5 * pi**2 * asymptotic_length * abs(beta2) * carrier.baud_rate**2)
|
|
||||||
else: # XCI, XPM
|
|
||||||
delta_f = carrier.frequency - interfering_carrier.frequency
|
|
||||||
psi = arcsinh(pi**2 * asymptotic_length * abs(beta2) *
|
|
||||||
carrier.baud_rate * (delta_f + 0.5 * interfering_carrier.baud_rate))
|
|
||||||
psi -= arcsinh(pi**2 * asymptotic_length * abs(beta2) *
|
|
||||||
carrier.baud_rate * (delta_f - 0.5 * interfering_carrier.baud_rate))
|
|
||||||
return psi
|
|
||||||
|
|
||||||
|
|
||||||
def estimate_nf_model(type_variety, gain_min, gain_max, nf_min, nf_max):
|
def estimate_nf_model(type_variety, gain_min, gain_max, nf_min, nf_max):
|
||||||
if nf_min < -10:
|
if nf_min < -10:
|
||||||
raise EquipmentConfigError(f'Invalid nf_min value {nf_min!r} for amplifier {type_variety}')
|
raise EquipmentConfigError(f'Invalid nf_min value {nf_min!r} for amplifier {type_variety}')
|
||||||
|
|||||||
@@ -107,6 +107,35 @@ def db2lin(value):
|
|||||||
|
|
||||||
|
|
||||||
def round2float(number, step):
|
def round2float(number, step):
|
||||||
|
"""Round a floating point number so that its "resolution" is not bigger than 'step'
|
||||||
|
|
||||||
|
The finest step is fixed at 0.01; smaller values are silently changed to 0.01.
|
||||||
|
|
||||||
|
>>> round2float(123.456, 1000)
|
||||||
|
0.0
|
||||||
|
>>> round2float(123.456, 100)
|
||||||
|
100.0
|
||||||
|
>>> round2float(123.456, 10)
|
||||||
|
120.0
|
||||||
|
>>> round2float(123.456, 1)
|
||||||
|
123.0
|
||||||
|
>>> round2float(123.456, 0.1)
|
||||||
|
123.5
|
||||||
|
>>> round2float(123.456, 0.01)
|
||||||
|
123.46
|
||||||
|
>>> round2float(123.456, 0.001)
|
||||||
|
123.46
|
||||||
|
>>> round2float(123.249, 0.5)
|
||||||
|
123.0
|
||||||
|
>>> round2float(123.250, 0.5)
|
||||||
|
123.0
|
||||||
|
>>> round2float(123.251, 0.5)
|
||||||
|
123.5
|
||||||
|
>>> round2float(123.300, 0.2)
|
||||||
|
123.2
|
||||||
|
>>> round2float(123.301, 0.2)
|
||||||
|
123.4
|
||||||
|
"""
|
||||||
step = round(step, 1)
|
step = round(step, 1)
|
||||||
if step >= 0.01:
|
if step >= 0.01:
|
||||||
number = round(number / step, 0)
|
number = round(number / step, 0)
|
||||||
|
|||||||
6233
gnpy/example-data/Sweden_OpenROADMv5_example_network.json
Normal file
6233
gnpy/example-data/Sweden_OpenROADMv5_example_network.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,24 @@
|
|||||||
"allowed_for_design": false
|
"allowed_for_design": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"type_variety": "openroadm_mw_mw_preamp_typical_ver5",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-5.952e-4,-6.250e-2,-1.071,28.99],
|
||||||
|
"allowed_for_design": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_mw_mw_preamp_worstcase_ver5",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-5.952e-4,-6.250e-2,-1.071,27.99],
|
||||||
|
"allowed_for_design": false
|
||||||
|
},
|
||||||
|
{
|
||||||
"type_variety": "openroadm_mw_mw_booster",
|
"type_variety": "openroadm_mw_mw_booster",
|
||||||
"type_def": "openroadm_booster",
|
"type_def": "openroadm_booster",
|
||||||
"gain_flatmax": 32,
|
"gain_flatmax": 32,
|
||||||
@@ -162,51 +180,27 @@
|
|||||||
"Fiber":[{
|
"Fiber":[{
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"dispersion": 1.67e-05,
|
"dispersion": 1.67e-05,
|
||||||
"gamma": 0.00127,
|
"effective_area": 83e-12,
|
||||||
"pmd_coef": 1.265e-15
|
"pmd_coef": 1.265e-15
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type_variety": "NZDF",
|
"type_variety": "NZDF",
|
||||||
"dispersion": 0.5e-05,
|
"dispersion": 0.5e-05,
|
||||||
"gamma": 0.00146,
|
"effective_area": 72e-12,
|
||||||
"pmd_coef": 1.265e-15
|
"pmd_coef": 1.265e-15
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type_variety": "LOF",
|
"type_variety": "LOF",
|
||||||
"dispersion": 2.2e-05,
|
"dispersion": 2.2e-05,
|
||||||
"gamma": 0.000843,
|
"effective_area": 125e-12,
|
||||||
"pmd_coef": 1.265e-15
|
"pmd_coef": 1.265e-15
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"RamanFiber":[{
|
"RamanFiber":[{
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"dispersion": 1.67e-05,
|
"dispersion": 1.67e-05,
|
||||||
"gamma": 0.00127,
|
"effective_area": 83e-12,
|
||||||
"pmd_coef": 1.265e-15,
|
"pmd_coef": 1.265e-15
|
||||||
"raman_efficiency": {
|
|
||||||
"cr":[
|
|
||||||
0, 9.4E-06, 2.92E-05, 4.88E-05, 6.82E-05, 8.31E-05, 9.4E-05, 0.0001014, 0.0001069, 0.0001119,
|
|
||||||
0.0001217, 0.0001268, 0.0001365, 0.000149, 0.000165, 0.000181, 0.0001977, 0.0002192, 0.0002469,
|
|
||||||
0.0002749, 0.0002999, 0.0003206, 0.0003405, 0.0003592, 0.000374, 0.0003826, 0.0003841, 0.0003826,
|
|
||||||
0.0003802, 0.0003756, 0.0003549, 0.0003795, 0.000344, 0.0002933, 0.0002024, 0.0001158, 8.46E-05,
|
|
||||||
7.14E-05, 6.86E-05, 8.5E-05, 8.93E-05, 9.01E-05, 8.15E-05, 6.67E-05, 4.37E-05, 3.28E-05, 2.96E-05,
|
|
||||||
2.65E-05, 2.57E-05, 2.81E-05, 3.08E-05, 3.67E-05, 5.85E-05, 6.63E-05, 6.36E-05, 5.5E-05, 4.06E-05,
|
|
||||||
2.77E-05, 2.42E-05, 1.87E-05, 1.6E-05, 1.4E-05, 1.13E-05, 1.05E-05, 9.8E-06, 9.8E-06, 1.13E-05,
|
|
||||||
1.64E-05, 1.95E-05, 2.38E-05, 2.26E-05, 2.03E-05, 1.48E-05, 1.09E-05, 9.8E-06, 1.05E-05, 1.17E-05,
|
|
||||||
1.25E-05, 1.21E-05, 1.09E-05, 9.8E-06, 8.2E-06, 6.6E-06, 4.7E-06, 2.7E-06, 1.9E-06, 1.2E-06, 4E-07,
|
|
||||||
2E-07, 1E-07
|
|
||||||
],
|
|
||||||
"frequency_offset":[
|
|
||||||
0, 0.5e12, 1e12, 1.5e12, 2e12, 2.5e12, 3e12, 3.5e12, 4e12, 4.5e12, 5e12, 5.5e12, 6e12, 6.5e12, 7e12,
|
|
||||||
7.5e12, 8e12, 8.5e12, 9e12, 9.5e12, 10e12, 10.5e12, 11e12, 11.5e12, 12e12, 12.5e12, 12.75e12,
|
|
||||||
13e12, 13.25e12, 13.5e12, 14e12, 14.5e12, 14.75e12, 15e12, 15.5e12, 16e12, 16.5e12, 17e12,
|
|
||||||
17.5e12, 18e12, 18.25e12, 18.5e12, 18.75e12, 19e12, 19.5e12, 20e12, 20.5e12, 21e12, 21.5e12,
|
|
||||||
22e12, 22.5e12, 23e12, 23.5e12, 24e12, 24.5e12, 25e12, 25.5e12, 26e12, 26.5e12, 27e12, 27.5e12, 28e12,
|
|
||||||
28.5e12, 29e12, 29.5e12, 30e12, 30.5e12, 31e12, 31.5e12, 32e12, 32.5e12, 33e12, 33.5e12, 34e12, 34.5e12,
|
|
||||||
35e12, 35.5e12, 36e12, 36.5e12, 37e12, 37.5e12, 38e12, 38.5e12, 39e12, 39.5e12, 40e12, 40.5e12, 41e12,
|
|
||||||
41.5e12, 42e12
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Span":[{
|
"Span":[{
|
||||||
@@ -227,6 +221,7 @@
|
|||||||
"target_pch_out_db": -20,
|
"target_pch_out_db": -20,
|
||||||
"add_drop_osnr": 38,
|
"add_drop_osnr": 38,
|
||||||
"pmd": 0,
|
"pmd": 0,
|
||||||
|
"pdl": 0,
|
||||||
"restrictions": {
|
"restrictions": {
|
||||||
"preamp_variety_list":[],
|
"preamp_variety_list":[],
|
||||||
"booster_variety_list":[]
|
"booster_variety_list":[]
|
||||||
|
|||||||
@@ -1,190 +0,0 @@
|
|||||||
{ "Edfa":[
|
|
||||||
{
|
|
||||||
"type_variety": "openroadm_ila_low_noise",
|
|
||||||
"type_def": "openroadm",
|
|
||||||
"gain_flatmax": 27,
|
|
||||||
"gain_min": 0,
|
|
||||||
"p_max": 22,
|
|
||||||
"nf_coef": [-8.104e-4,-6.221e-2,-5.889e-1,37.62],
|
|
||||||
"allowed_for_design": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_variety": "openroadm_ila_standard",
|
|
||||||
"type_def": "openroadm",
|
|
||||||
"gain_flatmax": 27,
|
|
||||||
"gain_min": 0,
|
|
||||||
"p_max": 22,
|
|
||||||
"nf_coef": [-5.952e-4,-6.250e-2,-1.071,28.99],
|
|
||||||
"allowed_for_design": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_variety": "openroadm_mw_mw_preamp",
|
|
||||||
"type_def": "openroadm_preamp",
|
|
||||||
"gain_flatmax": 27,
|
|
||||||
"gain_min": 0,
|
|
||||||
"p_max": 22,
|
|
||||||
"allowed_for_design": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_variety": "openroadm_mw_mw_booster",
|
|
||||||
"type_def": "openroadm_booster",
|
|
||||||
"gain_flatmax": 32,
|
|
||||||
"gain_min": 0,
|
|
||||||
"p_max": 22,
|
|
||||||
"allowed_for_design": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Fiber":[
|
|
||||||
{
|
|
||||||
"type_variety": "SSMF",
|
|
||||||
"dispersion": 1.67e-05,
|
|
||||||
"gamma": 0.00127,
|
|
||||||
"pmd_coef": 1.265e-15
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_variety": "NZDF",
|
|
||||||
"dispersion": 0.5e-05,
|
|
||||||
"gamma": 0.00146,
|
|
||||||
"pmd_coef": 1.265e-15
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_variety": "LOF",
|
|
||||||
"dispersion": 2.2e-05,
|
|
||||||
"gamma": 0.000843,
|
|
||||||
"pmd_coef": 1.265e-15
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"RamanFiber":[
|
|
||||||
{
|
|
||||||
"type_variety": "SSMF",
|
|
||||||
"dispersion": 1.67e-05,
|
|
||||||
"gamma": 0.00127,
|
|
||||||
"pmd_coef": 1.265e-15,
|
|
||||||
"raman_efficiency": {
|
|
||||||
"cr":[
|
|
||||||
0, 9.4E-06, 2.92E-05, 4.88E-05, 6.82E-05, 8.31E-05, 9.4E-05, 0.0001014, 0.0001069, 0.0001119,
|
|
||||||
0.0001217, 0.0001268, 0.0001365, 0.000149, 0.000165, 0.000181, 0.0001977, 0.0002192, 0.0002469,
|
|
||||||
0.0002749, 0.0002999, 0.0003206, 0.0003405, 0.0003592, 0.000374, 0.0003826, 0.0003841, 0.0003826,
|
|
||||||
0.0003802, 0.0003756, 0.0003549, 0.0003795, 0.000344, 0.0002933, 0.0002024, 0.0001158, 8.46E-05,
|
|
||||||
7.14E-05, 6.86E-05, 8.5E-05, 8.93E-05, 9.01E-05, 8.15E-05, 6.67E-05, 4.37E-05, 3.28E-05, 2.96E-05,
|
|
||||||
2.65E-05, 2.57E-05, 2.81E-05, 3.08E-05, 3.67E-05, 5.85E-05, 6.63E-05, 6.36E-05, 5.5E-05, 4.06E-05,
|
|
||||||
2.77E-05, 2.42E-05, 1.87E-05, 1.6E-05, 1.4E-05, 1.13E-05, 1.05E-05, 9.8E-06, 9.8E-06, 1.13E-05,
|
|
||||||
1.64E-05, 1.95E-05, 2.38E-05, 2.26E-05, 2.03E-05, 1.48E-05, 1.09E-05, 9.8E-06, 1.05E-05, 1.17E-05,
|
|
||||||
1.25E-05, 1.21E-05, 1.09E-05, 9.8E-06, 8.2E-06, 6.6E-06, 4.7E-06, 2.7E-06, 1.9E-06, 1.2E-06, 4E-07,
|
|
||||||
2E-07, 1E-07
|
|
||||||
],
|
|
||||||
"frequency_offset":[
|
|
||||||
0, 0.5e12, 1e12, 1.5e12, 2e12, 2.5e12, 3e12, 3.5e12, 4e12, 4.5e12, 5e12, 5.5e12, 6e12, 6.5e12, 7e12,
|
|
||||||
7.5e12, 8e12, 8.5e12, 9e12, 9.5e12, 10e12, 10.5e12, 11e12, 11.5e12, 12e12, 12.5e12, 12.75e12,
|
|
||||||
13e12, 13.25e12, 13.5e12, 14e12, 14.5e12, 14.75e12, 15e12, 15.5e12, 16e12, 16.5e12, 17e12,
|
|
||||||
17.5e12, 18e12, 18.25e12, 18.5e12, 18.75e12, 19e12, 19.5e12, 20e12, 20.5e12, 21e12, 21.5e12,
|
|
||||||
22e12, 22.5e12, 23e12, 23.5e12, 24e12, 24.5e12, 25e12, 25.5e12, 26e12, 26.5e12, 27e12, 27.5e12, 28e12,
|
|
||||||
28.5e12, 29e12, 29.5e12, 30e12, 30.5e12, 31e12, 31.5e12, 32e12, 32.5e12, 33e12, 33.5e12, 34e12, 34.5e12,
|
|
||||||
35e12, 35.5e12, 36e12, 36.5e12, 37e12, 37.5e12, 38e12, 38.5e12, 39e12, 39.5e12, 40e12, 40.5e12, 41e12,
|
|
||||||
41.5e12, 42e12
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Span":[
|
|
||||||
{
|
|
||||||
"power_mode":true,
|
|
||||||
"delta_power_range_db": [0,0,0],
|
|
||||||
"max_fiber_lineic_loss_for_raman": 0.25,
|
|
||||||
"target_extended_gain": 0,
|
|
||||||
"max_length": 135,
|
|
||||||
"length_units": "km",
|
|
||||||
"max_loss": 28,
|
|
||||||
"padding": 11,
|
|
||||||
"EOL": 0,
|
|
||||||
"con_in": 0,
|
|
||||||
"con_out": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Roadm":[
|
|
||||||
{
|
|
||||||
"target_pch_out_db": -20,
|
|
||||||
"add_drop_osnr": 30,
|
|
||||||
"pmd": 0,
|
|
||||||
"restrictions": {
|
|
||||||
"preamp_variety_list":["openroadm_mw_mw_preamp"],
|
|
||||||
"booster_variety_list":["openroadm_mw_mw_booster"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"SI":[
|
|
||||||
{
|
|
||||||
"f_min": 191.3e12,
|
|
||||||
"baud_rate": 31.57e9,
|
|
||||||
"f_max":196.1e12,
|
|
||||||
"spacing": 50e9,
|
|
||||||
"power_dbm": 2,
|
|
||||||
"power_range_db": [0,0,1],
|
|
||||||
"roll_off": 0.15,
|
|
||||||
"tx_osnr": 35,
|
|
||||||
"sys_margins": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Transceiver":[
|
|
||||||
{
|
|
||||||
"type_variety": "OpenROADM MSA ver. 4.0",
|
|
||||||
"frequency":{
|
|
||||||
"min": 191.35e12,
|
|
||||||
"max": 196.1e12
|
|
||||||
},
|
|
||||||
"mode":[
|
|
||||||
{
|
|
||||||
"format": "100 Gbit/s, 27.95 Gbaud, DP-QPSK",
|
|
||||||
"baud_rate": 27.95e9,
|
|
||||||
"OSNR": 17,
|
|
||||||
"bit_rate": 100e9,
|
|
||||||
"roll_off": null,
|
|
||||||
"tx_osnr": 33,
|
|
||||||
"min_spacing": 50e9,
|
|
||||||
"cost":1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"format": "100 Gbit/s, 31.57 Gbaud, DP-QPSK",
|
|
||||||
"baud_rate": 31.57e9,
|
|
||||||
"OSNR": 12,
|
|
||||||
"bit_rate": 100e9,
|
|
||||||
"roll_off": 0.15,
|
|
||||||
"tx_osnr": 35,
|
|
||||||
"min_spacing": 50e9,
|
|
||||||
"cost":1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"format": "200 Gbit/s, DP-QPSK",
|
|
||||||
"baud_rate": 63.1e9,
|
|
||||||
"OSNR": 17,
|
|
||||||
"bit_rate": 200e9,
|
|
||||||
"roll_off": 0.15,
|
|
||||||
"tx_osnr": 36,
|
|
||||||
"min_spacing": 87.5e9,
|
|
||||||
"cost":1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"format": "300 Gbit/s, DP-8QAM",
|
|
||||||
"baud_rate": 63.1e9,
|
|
||||||
"OSNR": 21,
|
|
||||||
"bit_rate": 300e9,
|
|
||||||
"roll_off": 0.15,
|
|
||||||
"tx_osnr": 36,
|
|
||||||
"min_spacing": 87.5e9,
|
|
||||||
"cost":1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"format": "400 Gbit/s, DP-16QAM",
|
|
||||||
"baud_rate": 63.1e9,
|
|
||||||
"OSNR": 24,
|
|
||||||
"bit_rate": 400e9,
|
|
||||||
"roll_off": 0.15,
|
|
||||||
"tx_osnr": 36,
|
|
||||||
"min_spacing": 87.5e9,
|
|
||||||
"cost":1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
349
gnpy/example-data/eqpt_config_openroadm_ver4.json
Normal file
349
gnpy/example-data/eqpt_config_openroadm_ver4.json
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
{
|
||||||
|
"Edfa": [
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_ila_low_noise",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-8.104e-4, -6.221e-2, -5.889e-1, 37.62],
|
||||||
|
"pmd": 3e-12,
|
||||||
|
"pdl": 0.7,
|
||||||
|
"allowed_for_design": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_ila_standard",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-5.952e-4, -6.250e-2, -1.071, 28.99],
|
||||||
|
"pmd": 3e-12,
|
||||||
|
"pdl": 0.7,
|
||||||
|
"allowed_for_design": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_mw_mw_preamp",
|
||||||
|
"type_def": "openroadm_preamp",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"pmd": 0,
|
||||||
|
"pdl": 0,
|
||||||
|
"allowed_for_design": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_mw_mw_booster",
|
||||||
|
"type_def": "openroadm_booster",
|
||||||
|
"gain_flatmax": 32,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"pmd": 0,
|
||||||
|
"pdl": 0,
|
||||||
|
"allowed_for_design": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Fiber": [
|
||||||
|
{
|
||||||
|
"type_variety": "SSMF",
|
||||||
|
"dispersion": 1.67e-05,
|
||||||
|
"effective_area": 83e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "NZDF",
|
||||||
|
"dispersion": 0.5e-05,
|
||||||
|
"effective_area": 72e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "LOF",
|
||||||
|
"dispersion": 2.2e-05,
|
||||||
|
"effective_area": 125e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"RamanFiber": [
|
||||||
|
{
|
||||||
|
"type_variety": "SSMF",
|
||||||
|
"dispersion": 1.67e-05,
|
||||||
|
"effective_area": 83e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Span": [
|
||||||
|
{
|
||||||
|
"power_mode": true,
|
||||||
|
"delta_power_range_db": [0, 0, 0],
|
||||||
|
"max_fiber_lineic_loss_for_raman": 0.25,
|
||||||
|
"target_extended_gain": 0,
|
||||||
|
"max_length": 135,
|
||||||
|
"length_units": "km",
|
||||||
|
"max_loss": 28,
|
||||||
|
"padding": 11,
|
||||||
|
"EOL": 0,
|
||||||
|
"con_in": 0,
|
||||||
|
"con_out": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Roadm": [
|
||||||
|
{
|
||||||
|
"target_pch_out_db": -20,
|
||||||
|
"add_drop_osnr": 30,
|
||||||
|
"pmd": 3e-12,
|
||||||
|
"pdl": 1.5,
|
||||||
|
"restrictions": {
|
||||||
|
"preamp_variety_list": ["openroadm_mw_mw_preamp"],
|
||||||
|
"booster_variety_list": ["openroadm_mw_mw_booster"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SI": [
|
||||||
|
{
|
||||||
|
"f_min": 191.3e12,
|
||||||
|
"baud_rate": 31.57e9,
|
||||||
|
"f_max": 196.1e12,
|
||||||
|
"spacing": 50e9,
|
||||||
|
"power_dbm": 2,
|
||||||
|
"power_range_db": [0, 0, 1],
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 35,
|
||||||
|
"sys_margins": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Transceiver": [
|
||||||
|
{
|
||||||
|
"type_variety": "OpenROADM MSA ver. 4.0",
|
||||||
|
"frequency": {
|
||||||
|
"min": 191.35e12,
|
||||||
|
"max": 196.1e12
|
||||||
|
},
|
||||||
|
"mode": [
|
||||||
|
{
|
||||||
|
"format": "100 Gbit/s, 27.95 Gbaud, DP-QPSK",
|
||||||
|
"baud_rate": 27.95e9,
|
||||||
|
"OSNR": 17,
|
||||||
|
"bit_rate": 100e9,
|
||||||
|
"roll_off": null,
|
||||||
|
"tx_osnr": 33,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 18e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 30,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 6,
|
||||||
|
"penalty_value": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 50e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "100 Gbit/s, 31.57 Gbaud, DP-QPSK",
|
||||||
|
"baud_rate": 31.57e9,
|
||||||
|
"OSNR": 12,
|
||||||
|
"bit_rate": 100e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 35,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 40e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 30,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 6,
|
||||||
|
"penalty_value": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 50e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "200 Gbit/s, DP-QPSK",
|
||||||
|
"baud_rate": 63.1e9,
|
||||||
|
"OSNR": 17,
|
||||||
|
"bit_rate": 200e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 24e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 25,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 87.5e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "300 Gbit/s, DP-8QAM",
|
||||||
|
"baud_rate": 63.1e9,
|
||||||
|
"OSNR": 21,
|
||||||
|
"bit_rate": 300e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 18e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 25,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 87.5e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "400 Gbit/s, DP-16QAM",
|
||||||
|
"baud_rate": 63.1e9,
|
||||||
|
"OSNR": 24,
|
||||||
|
"bit_rate": 400e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 12e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 20,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 87.5e9,
|
||||||
|
"cost": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
409
gnpy/example-data/eqpt_config_openroadm_ver5.json
Normal file
409
gnpy/example-data/eqpt_config_openroadm_ver5.json
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
{
|
||||||
|
"Edfa": [
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_ila_low_noise",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-8.104e-4, -6.221e-2, -5.889e-1, 37.62],
|
||||||
|
"pmd": 3e-12,
|
||||||
|
"pdl": 0.7,
|
||||||
|
"allowed_for_design": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_ila_standard",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-5.952e-4, -6.250e-2, -1.071, 28.99],
|
||||||
|
"pmd": 3e-12,
|
||||||
|
"pdl": 0.7,
|
||||||
|
"allowed_for_design": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_mw_mw_preamp_typical_ver5",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-5.952e-4, -6.250e-2, -1.071, 28.99],
|
||||||
|
"pmd": 0,
|
||||||
|
"pdl": 0,
|
||||||
|
"allowed_for_design": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_mw_mw_preamp_worstcase_ver5",
|
||||||
|
"type_def": "openroadm",
|
||||||
|
"gain_flatmax": 27,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"nf_coef": [-5.952e-4, -6.250e-2, -1.071, 27.99],
|
||||||
|
"pmd": 0,
|
||||||
|
"pdl": 0,
|
||||||
|
"allowed_for_design": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "openroadm_mw_mw_booster",
|
||||||
|
"type_def": "openroadm_booster",
|
||||||
|
"gain_flatmax": 32,
|
||||||
|
"gain_min": 0,
|
||||||
|
"p_max": 22,
|
||||||
|
"pmd": 0,
|
||||||
|
"pdl": 0,
|
||||||
|
"allowed_for_design": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Fiber": [
|
||||||
|
{
|
||||||
|
"type_variety": "SSMF",
|
||||||
|
"dispersion": 1.67e-05,
|
||||||
|
"effective_area": 83e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "NZDF",
|
||||||
|
"dispersion": 0.5e-05,
|
||||||
|
"effective_area": 72e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "LOF",
|
||||||
|
"dispersion": 2.2e-05,
|
||||||
|
"effective_area": 125e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"RamanFiber": [
|
||||||
|
{
|
||||||
|
"type_variety": "SSMF",
|
||||||
|
"dispersion": 1.67e-05,
|
||||||
|
"effective_area": 83e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Span": [
|
||||||
|
{
|
||||||
|
"power_mode": true,
|
||||||
|
"delta_power_range_db": [0, 0, 0],
|
||||||
|
"max_fiber_lineic_loss_for_raman": 0.25,
|
||||||
|
"target_extended_gain": 0,
|
||||||
|
"max_length": 135,
|
||||||
|
"length_units": "km",
|
||||||
|
"max_loss": 28,
|
||||||
|
"padding": 11,
|
||||||
|
"EOL": 0,
|
||||||
|
"con_in": 0,
|
||||||
|
"con_out": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Roadm": [
|
||||||
|
{
|
||||||
|
"target_pch_out_db": -20,
|
||||||
|
"add_drop_osnr": 33,
|
||||||
|
"pmd": 3e-12,
|
||||||
|
"pdl": 1.5,
|
||||||
|
"restrictions": {
|
||||||
|
"preamp_variety_list": ["openroadm_mw_mw_preamp_worstcase_ver5"],
|
||||||
|
"booster_variety_list": ["openroadm_mw_mw_booster"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SI": [
|
||||||
|
{
|
||||||
|
"f_min": 191.3e12,
|
||||||
|
"baud_rate": 31.57e9,
|
||||||
|
"f_max": 196.1e12,
|
||||||
|
"spacing": 50e9,
|
||||||
|
"power_dbm": 2,
|
||||||
|
"power_range_db": [0, 0, 1],
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 35,
|
||||||
|
"sys_margins": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Transceiver": [
|
||||||
|
{
|
||||||
|
"type_variety": "OpenROADM MSA ver. 5.0",
|
||||||
|
"frequency": {
|
||||||
|
"min": 191.35e12,
|
||||||
|
"max": 196.1e12
|
||||||
|
},
|
||||||
|
"mode": [
|
||||||
|
{
|
||||||
|
"format": "100 Gbit/s, 27.95 Gbaud, DP-QPSK",
|
||||||
|
"baud_rate": 27.95e9,
|
||||||
|
"OSNR": 17,
|
||||||
|
"bit_rate": 100e9,
|
||||||
|
"roll_off": null,
|
||||||
|
"tx_osnr": 33,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 18e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 30,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 6,
|
||||||
|
"penalty_value": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 50e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "100 Gbit/s, 31.57 Gbaud, DP-QPSK",
|
||||||
|
"baud_rate": 31.57e9,
|
||||||
|
"OSNR": 12,
|
||||||
|
"bit_rate": 100e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 48e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 30,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 6,
|
||||||
|
"penalty_value": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 50e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "200 Gbit/s, 31.57 Gbaud, DP-16QAM",
|
||||||
|
"baud_rate": 31.57e9,
|
||||||
|
"OSNR": 20.5,
|
||||||
|
"bit_rate": 100e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 24e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 30,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 6,
|
||||||
|
"penalty_value": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 50e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "200 Gbit/s, DP-QPSK",
|
||||||
|
"baud_rate": 63.1e9,
|
||||||
|
"OSNR": 17,
|
||||||
|
"bit_rate": 200e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 24e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 25,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 87.5e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "300 Gbit/s, DP-8QAM",
|
||||||
|
"baud_rate": 63.1e9,
|
||||||
|
"OSNR": 21,
|
||||||
|
"bit_rate": 300e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 18e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 25,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 87.5e9,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"format": "400 Gbit/s, DP-16QAM",
|
||||||
|
"baud_rate": 63.1e9,
|
||||||
|
"OSNR": 24,
|
||||||
|
"bit_rate": 400e9,
|
||||||
|
"roll_off": 0.15,
|
||||||
|
"tx_osnr": 36,
|
||||||
|
"penalties": [
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": -1e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 4e3,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chromatic_dispersion": 12e3,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 10,
|
||||||
|
"penalty_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pmd": 20,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 1,
|
||||||
|
"penalty_value": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 2,
|
||||||
|
"penalty_value": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pdl": 4,
|
||||||
|
"penalty_value": 2.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"min_spacing": 87.5e9,
|
||||||
|
"cost": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -104,8 +104,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -129,8 +129,8 @@
|
|||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
@@ -154,8 +154,8 @@
|
|||||||
"trx_mode": "mode 2",
|
"trx_mode": "mode 2",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
@@ -179,8 +179,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -204,8 +204,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -229,8 +229,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
|
|||||||
@@ -20,12 +20,12 @@
|
|||||||
"temperature": 283,
|
"temperature": 283,
|
||||||
"raman_pumps": [
|
"raman_pumps": [
|
||||||
{
|
{
|
||||||
"power": 200e-3,
|
"power": 224.403e-3,
|
||||||
"frequency": 205e12,
|
"frequency": 205e12,
|
||||||
"propagation_direction": "counterprop"
|
"propagation_direction": "counterprop"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"power": 206e-3,
|
"power": 231.135e-3,
|
||||||
"frequency": 201e12,
|
"frequency": 201e12,
|
||||||
"propagation_direction": "counterprop"
|
"propagation_direction": "counterprop"
|
||||||
}
|
}
|
||||||
@@ -49,6 +49,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"uid": "Fused1",
|
||||||
|
"type": "Fused",
|
||||||
|
"params": {
|
||||||
|
"loss": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 1.5,
|
||||||
|
"longitude": 0,
|
||||||
|
"city": null,
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"uid": "Edfa1",
|
"uid": "Edfa1",
|
||||||
"type": "Edfa",
|
"type": "Edfa",
|
||||||
@@ -88,6 +103,10 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"from_node": "Span1",
|
"from_node": "Span1",
|
||||||
|
"to_node": "Fused1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_node": "Fused1",
|
||||||
"to_node": "Edfa1"
|
"to_node": "Edfa1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"raman_parameters": {
|
"raman_params": {
|
||||||
"flag_raman": true,
|
"flag": true,
|
||||||
"space_resolution": 10e3,
|
"result_spatial_resolution": 10e3,
|
||||||
"tolerance": 1e-8
|
"solver_spatial_resolution": 50
|
||||||
},
|
},
|
||||||
"nli_parameters": {
|
"nli_params": {
|
||||||
"nli_method_name": "ggn_spectrally_separated",
|
"method": "ggn_spectrally_separated",
|
||||||
"wdm_grid_size": 50e9,
|
|
||||||
"dispersion_tolerance": 1,
|
"dispersion_tolerance": 1,
|
||||||
"phase_shift_tolerance": 0.1,
|
"phase_shift_tolerance": 0.1,
|
||||||
"computed_channels": [1, 18, 37, 56, 75]
|
"computed_channels": [1, 18, 37, 56, 75]
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ from gnpy.tools.json_io import load_equipment
|
|||||||
from gnpy.topology.request import jsontocsv
|
from gnpy.topology.request import jsontocsv
|
||||||
|
|
||||||
|
|
||||||
parser = ArgumentParser(description='A function that writes json path results in an excel sheet.')
|
parser = ArgumentParser(description='Converting JSON path results into a CSV')
|
||||||
parser.add_argument('filename', nargs='?', type=Path)
|
parser.add_argument('filename', type=Path)
|
||||||
parser.add_argument('output_filename', nargs='?', type=Path)
|
parser.add_argument('output_filename', type=Path)
|
||||||
parser.add_argument('eqpt_filename', nargs='?', type=Path, default=Path(__file__).parent / 'eqpt_config.json')
|
parser.add_argument('eqpt_filename', nargs='?', type=Path, default=Path(__file__).parent / 'eqpt_config.json')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ Common code for CLI examples
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
|
||||||
import sys
|
import sys
|
||||||
from math import ceil
|
from math import ceil
|
||||||
from numpy import linspace, mean
|
from numpy import linspace, mean
|
||||||
@@ -21,7 +20,6 @@ from gnpy.core.equipment import trx_mode_params
|
|||||||
import gnpy.core.exceptions as exceptions
|
import gnpy.core.exceptions as exceptions
|
||||||
from gnpy.core.network import build_network
|
from gnpy.core.network import build_network
|
||||||
from gnpy.core.parameters import SimParams
|
from gnpy.core.parameters import SimParams
|
||||||
from gnpy.core.science_utils import Simulation
|
|
||||||
from gnpy.core.utils import db2lin, lin2db, automatic_nch
|
from gnpy.core.utils import db2lin, lin2db, automatic_nch
|
||||||
from gnpy.topology.request import (ResultElement, jsontocsv, compute_path_dsjctn, requests_aggregation,
|
from gnpy.topology.request import (ResultElement, jsontocsv, compute_path_dsjctn, requests_aggregation,
|
||||||
BLOCKING_NOPATH, correct_json_route_list,
|
BLOCKING_NOPATH, correct_json_route_list,
|
||||||
@@ -57,14 +55,15 @@ def load_common_data(equipment_filename, topology_filename, simulation_filename,
|
|||||||
if save_raw_network_filename is not None:
|
if save_raw_network_filename is not None:
|
||||||
save_network(network, save_raw_network_filename)
|
save_network(network, save_raw_network_filename)
|
||||||
print(f'{ansi_escapes.blue}Raw network (no optimizations) saved to {save_raw_network_filename}{ansi_escapes.reset}')
|
print(f'{ansi_escapes.blue}Raw network (no optimizations) saved to {save_raw_network_filename}{ansi_escapes.reset}')
|
||||||
sim_params = SimParams(**load_json(simulation_filename)) if simulation_filename is not None else None
|
if not simulation_filename:
|
||||||
if not sim_params:
|
sim_params = {}
|
||||||
if next((node for node in network if isinstance(node, RamanFiber)), None) is not None:
|
if next((node for node in network if isinstance(node, RamanFiber)), None) is not None:
|
||||||
print(f'{ansi_escapes.red}Invocation error:{ansi_escapes.reset} '
|
print(f'{ansi_escapes.red}Invocation error:{ansi_escapes.reset} '
|
||||||
f'RamanFiber requires passing simulation params via --sim-params')
|
f'RamanFiber requires passing simulation params via --sim-params')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
Simulation.set_params(sim_params)
|
sim_params = load_json(simulation_filename)
|
||||||
|
SimParams.set_params(sim_params)
|
||||||
except exceptions.EquipmentConfigError as e:
|
except exceptions.EquipmentConfigError as e:
|
||||||
print(f'{ansi_escapes.red}Configuration error in the equipment library:{ansi_escapes.reset} {e}')
|
print(f'{ansi_escapes.red}Configuration error in the equipment library:{ansi_escapes.reset} {e}')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -103,6 +102,9 @@ def _add_common_options(parser: argparse.ArgumentParser, network_default: Path):
|
|||||||
help='Save the final network as a JSON file')
|
help='Save the final network as a JSON file')
|
||||||
parser.add_argument('--save-network-before-autodesign', type=Path, metavar=_help_fname_json,
|
parser.add_argument('--save-network-before-autodesign', type=Path, metavar=_help_fname_json,
|
||||||
help='Dump the network into a JSON file prior to autodesign')
|
help='Dump the network into a JSON file prior to autodesign')
|
||||||
|
parser.add_argument('--no-insert-edfas', action='store_true',
|
||||||
|
help='Disable insertion of EDFAs after ROADMs and fibers '
|
||||||
|
'as well as splitting of fibers by auto-design.')
|
||||||
|
|
||||||
|
|
||||||
def transmission_main_example(args=None):
|
def transmission_main_example(args=None):
|
||||||
@@ -187,6 +189,7 @@ def transmission_main_example(args=None):
|
|||||||
params['loose_list'] = ['strict']
|
params['loose_list'] = ['strict']
|
||||||
params['format'] = ''
|
params['format'] = ''
|
||||||
params['path_bandwidth'] = 0
|
params['path_bandwidth'] = 0
|
||||||
|
params['effective_freq_slot'] = None
|
||||||
trx_params = trx_mode_params(equipment)
|
trx_params = trx_mode_params(equipment)
|
||||||
if args.power:
|
if args.power:
|
||||||
trx_params['power'] = db2lin(float(args.power)) * 1e-3
|
trx_params['power'] = db2lin(float(args.power)) * 1e-3
|
||||||
@@ -200,7 +203,7 @@ def transmission_main_example(args=None):
|
|||||||
pref_ch_db = lin2db(req.power * 1e3) # reference channel power / span (SL=20dB)
|
pref_ch_db = lin2db(req.power * 1e3) # reference channel power / span (SL=20dB)
|
||||||
pref_total_db = pref_ch_db + lin2db(req.nb_channel) # reference total power / span (SL=20dB)
|
pref_total_db = pref_ch_db + lin2db(req.nb_channel) # reference total power / span (SL=20dB)
|
||||||
try:
|
try:
|
||||||
build_network(network, equipment, pref_ch_db, pref_total_db)
|
build_network(network, equipment, pref_ch_db, pref_total_db, args.no_insert_edfas)
|
||||||
except exceptions.NetworkTopologyError as e:
|
except exceptions.NetworkTopologyError as e:
|
||||||
print(f'{ansi_escapes.red}Invalid network definition:{ansi_escapes.reset} {e}')
|
print(f'{ansi_escapes.red}Invalid network definition:{ansi_escapes.reset} {e}')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -214,17 +217,16 @@ def transmission_main_example(args=None):
|
|||||||
f'and {destination.uid}')
|
f'and {destination.uid}')
|
||||||
print(f'\nNow propagating between {source.uid} and {destination.uid}:')
|
print(f'\nNow propagating between {source.uid} and {destination.uid}:')
|
||||||
|
|
||||||
|
power_range = [0]
|
||||||
|
if power_mode:
|
||||||
|
# power cannot be changed in gain mode
|
||||||
try:
|
try:
|
||||||
p_start, p_stop, p_step = equipment['SI']['default'].power_range_db
|
p_start, p_stop, p_step = equipment['SI']['default'].power_range_db
|
||||||
p_num = abs(int(round((p_stop - p_start) / p_step))) + 1 if p_step != 0 else 1
|
p_num = abs(int(round((p_stop - p_start) / p_step))) + 1 if p_step != 0 else 1
|
||||||
power_range = list(linspace(p_start, p_stop, p_num))
|
power_range = list(linspace(p_start, p_stop, p_num))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
print('invalid power range definition in eqpt_config, should be power_range_db: [lower, upper, step]')
|
print('invalid power range definition in eqpt_config, should be power_range_db: [lower, upper, step]')
|
||||||
power_range = [0]
|
|
||||||
|
|
||||||
if not power_mode:
|
|
||||||
# power cannot be changed in gain mode
|
|
||||||
power_range = [0]
|
|
||||||
for dp_db in power_range:
|
for dp_db in power_range:
|
||||||
req.power = db2lin(pref_ch_db + dp_db) * 1e-3
|
req.power = db2lin(pref_ch_db + dp_db) * 1e-3
|
||||||
if power_mode:
|
if power_mode:
|
||||||
@@ -307,7 +309,6 @@ def path_requests_run(args=None):
|
|||||||
_setup_logging(args)
|
_setup_logging(args)
|
||||||
|
|
||||||
_logger.info(f'Computing path requests {args.service_filename} into JSON format')
|
_logger.info(f'Computing path requests {args.service_filename} into JSON format')
|
||||||
print(f'{ansi_escapes.blue}Computing path requests {os.path.relpath(args.service_filename)} into JSON format{ansi_escapes.reset}')
|
|
||||||
|
|
||||||
(equipment, network) = load_common_data(args.equipment, args.topology, args.sim_params, args.save_network_before_autodesign)
|
(equipment, network) = load_common_data(args.equipment, args.topology, args.sim_params, args.save_network_before_autodesign)
|
||||||
|
|
||||||
@@ -319,7 +320,7 @@ def path_requests_run(args=None):
|
|||||||
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,
|
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,
|
||||||
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
|
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
|
||||||
try:
|
try:
|
||||||
build_network(network, equipment, p_db, p_total_db)
|
build_network(network, equipment, p_db, p_total_db, args.no_insert_edfas)
|
||||||
except exceptions.NetworkTopologyError as e:
|
except exceptions.NetworkTopologyError as e:
|
||||||
print(f'{ansi_escapes.red}Invalid network definition:{ansi_escapes.reset} {e}')
|
print(f'{ansi_escapes.red}Invalid network definition:{ansi_escapes.reset} {e}')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from gnpy.core.equipment import trx_mode_params
|
|||||||
from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError, ServiceError
|
from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError, ServiceError
|
||||||
from gnpy.core.science_utils import estimate_nf_model
|
from gnpy.core.science_utils import estimate_nf_model
|
||||||
from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions
|
from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions
|
||||||
from gnpy.topology.request import PathRequest, Disjunction
|
from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth
|
||||||
from gnpy.tools.convert import xls_to_json_data
|
from gnpy.tools.convert import xls_to_json_data
|
||||||
from gnpy.tools.service_sheet import read_service_sheet
|
from gnpy.tools.service_sheet import read_service_sheet
|
||||||
|
|
||||||
@@ -33,6 +33,14 @@ Model_hybrid = namedtuple('Model_hybrid', 'nf_ram gain_ram edfa_variety')
|
|||||||
Model_dual_stage = namedtuple('Model_dual_stage', 'preamp_variety booster_variety')
|
Model_dual_stage = namedtuple('Model_dual_stage', 'preamp_variety booster_variety')
|
||||||
|
|
||||||
|
|
||||||
|
class Model_openroadm_preamp:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Model_openroadm_booster:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class _JsonThing:
|
class _JsonThing:
|
||||||
def update_attr(self, default_values, kwargs, name):
|
def update_attr(self, default_values, kwargs, name):
|
||||||
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
|
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
|
||||||
@@ -86,6 +94,7 @@ class Roadm(_JsonThing):
|
|||||||
'target_pch_out_db': -17,
|
'target_pch_out_db': -17,
|
||||||
'add_drop_osnr': 100,
|
'add_drop_osnr': 100,
|
||||||
'pmd': 0,
|
'pmd': 0,
|
||||||
|
'pdl': 0,
|
||||||
'restrictions': {
|
'restrictions': {
|
||||||
'preamp_variety_list': [],
|
'preamp_variety_list': [],
|
||||||
'booster_variety_list': []
|
'booster_variety_list': []
|
||||||
@@ -105,36 +114,45 @@ class Transceiver(_JsonThing):
|
|||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.update_attr(self.default_values, kwargs, 'Transceiver')
|
self.update_attr(self.default_values, kwargs, 'Transceiver')
|
||||||
|
for mode_params in self.mode:
|
||||||
|
penalties = mode_params.get('penalties')
|
||||||
|
mode_params['penalties'] = {}
|
||||||
|
if not penalties:
|
||||||
|
continue
|
||||||
|
for impairment in ('chromatic_dispersion', 'pmd', 'pdl'):
|
||||||
|
imp_penalties = [p for p in penalties if impairment in p]
|
||||||
|
if not imp_penalties:
|
||||||
|
continue
|
||||||
|
if all(p[impairment] > 0 for p in imp_penalties):
|
||||||
|
# make sure the list of penalty values include a proper lower boundary
|
||||||
|
# (we assume 0 penalty for 0 impairment)
|
||||||
|
imp_penalties.insert(0, {impairment: 0, 'penalty_value': 0})
|
||||||
|
# make sure the list of penalty values are sorted by impairment value
|
||||||
|
imp_penalties.sort(key=lambda i: i[impairment])
|
||||||
|
# rearrange as dict of lists instead of list of dicts
|
||||||
|
mode_params['penalties'][impairment] = {
|
||||||
|
'up_to_boundary': [p[impairment] for p in imp_penalties],
|
||||||
|
'penalty_value': [p['penalty_value'] for p in imp_penalties]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Fiber(_JsonThing):
|
class Fiber(_JsonThing):
|
||||||
default_values = {
|
default_values = {
|
||||||
'type_variety': '',
|
'type_variety': '',
|
||||||
'dispersion': None,
|
'dispersion': None,
|
||||||
'gamma': 0,
|
'effective_area': None,
|
||||||
'pmd_coef': 0
|
'pmd_coef': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.update_attr(self.default_values, kwargs, 'Fiber')
|
self.update_attr(self.default_values, kwargs, self.__class__.__name__)
|
||||||
|
for optional in ['gamma', 'raman_efficiency']:
|
||||||
|
if optional in kwargs:
|
||||||
|
setattr(self, optional, kwargs[optional])
|
||||||
|
|
||||||
|
|
||||||
class RamanFiber(_JsonThing):
|
class RamanFiber(Fiber):
|
||||||
default_values = {
|
pass
|
||||||
'type_variety': '',
|
|
||||||
'dispersion': None,
|
|
||||||
'gamma': 0,
|
|
||||||
'pmd_coef': 0,
|
|
||||||
'raman_efficiency': None
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.update_attr(self.default_values, kwargs, 'RamanFiber')
|
|
||||||
for param in ('cr', 'frequency_offset'):
|
|
||||||
if param not in self.raman_efficiency:
|
|
||||||
raise EquipmentConfigError(f'RamanFiber.raman_efficiency: missing "{param}" parameter')
|
|
||||||
if self.raman_efficiency['frequency_offset'] != sorted(self.raman_efficiency['frequency_offset']):
|
|
||||||
raise EquipmentConfigError(f'RamanFiber.raman_efficiency.frequency_offset is not sorted')
|
|
||||||
|
|
||||||
|
|
||||||
class Amp(_JsonThing):
|
class Amp(_JsonThing):
|
||||||
@@ -154,7 +172,9 @@ class Amp(_JsonThing):
|
|||||||
'gain_ripple': None,
|
'gain_ripple': None,
|
||||||
'out_voa_auto': False,
|
'out_voa_auto': False,
|
||||||
'allowed_for_design': False,
|
'allowed_for_design': False,
|
||||||
'raman': False
|
'raman': False,
|
||||||
|
'pmd': 0,
|
||||||
|
'pdl': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@@ -201,8 +221,10 @@ class Amp(_JsonThing):
|
|||||||
except KeyError: # nf_coef is expected for openroadm amp
|
except KeyError: # nf_coef is expected for openroadm amp
|
||||||
raise EquipmentConfigError(f'missing nf_coef input for amplifier: {type_variety} in equipment config')
|
raise EquipmentConfigError(f'missing nf_coef input for amplifier: {type_variety} in equipment config')
|
||||||
nf_def = Model_openroadm_ila(nf_coef)
|
nf_def = Model_openroadm_ila(nf_coef)
|
||||||
elif type_def in ('openroadm_preamp', 'openroadm_booster'):
|
elif type_def == 'openroadm_preamp':
|
||||||
pass # no extra parameters needed
|
nf_def = Model_openroadm_preamp()
|
||||||
|
elif type_def == 'openroadm_booster':
|
||||||
|
nf_def = Model_openroadm_booster()
|
||||||
elif type_def == 'dual_stage':
|
elif type_def == 'dual_stage':
|
||||||
try: # nf_ram and gain_ram are expected for a hybrid amp
|
try: # nf_ram and gain_ram are expected for a hybrid amp
|
||||||
preamp_variety = kwargs.pop('preamp_variety')
|
preamp_variety = kwargs.pop('preamp_variety')
|
||||||
@@ -267,7 +289,7 @@ def _check_fiber_vs_raman_fiber(equipment):
|
|||||||
if 'RamanFiber' not in equipment:
|
if 'RamanFiber' not in equipment:
|
||||||
return
|
return
|
||||||
for fiber_type in set(equipment['Fiber'].keys()) & set(equipment['RamanFiber'].keys()):
|
for fiber_type in set(equipment['Fiber'].keys()) & set(equipment['RamanFiber'].keys()):
|
||||||
for attr in ('dispersion', 'dispersion-slope', 'gamma', 'pmd-coefficient'):
|
for attr in ('dispersion', 'dispersion-slope', 'effective_area', 'gamma', 'pmd-coefficient'):
|
||||||
fiber = equipment['Fiber'][fiber_type]
|
fiber = equipment['Fiber'][fiber_type]
|
||||||
raman = equipment['RamanFiber'][fiber_type]
|
raman = equipment['RamanFiber'][fiber_type]
|
||||||
a = getattr(fiber, attr, None)
|
a = getattr(fiber, attr, None)
|
||||||
@@ -475,12 +497,12 @@ def requests_from_json(json_data, equipment):
|
|||||||
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
||||||
_check_one_request(params, f_max_from_si)
|
params['effective_freq_slot'] = req['path-constraints']['te-bandwidth'].get('effective-freq-slot', [None])[0]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
params['path_bandwidth'] = req['path-constraints']['te-bandwidth']['path_bandwidth']
|
params['path_bandwidth'] = req['path-constraints']['te-bandwidth']['path_bandwidth']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
_check_one_request(params, f_max_from_si)
|
||||||
requests_list.append(PathRequest(**params))
|
requests_list.append(PathRequest(**params))
|
||||||
return requests_list
|
return requests_list
|
||||||
|
|
||||||
@@ -506,6 +528,22 @@ def _check_one_request(params, f_max_from_si):
|
|||||||
max recommanded nb of channels is {max_recommanded_nb_channels}.'''
|
max recommanded nb of channels is {max_recommanded_nb_channels}.'''
|
||||||
_logger.critical(msg)
|
_logger.critical(msg)
|
||||||
raise ServiceError(msg)
|
raise ServiceError(msg)
|
||||||
|
# Transponder mode already selected; will it fit to the requested bandwidth?
|
||||||
|
if params['trx_mode'] is not None and params['effective_freq_slot'] is not None \
|
||||||
|
and params['effective_freq_slot']['M'] is not None:
|
||||||
|
_, requested_m = compute_spectrum_slot_vs_bandwidth(params['path_bandwidth'],
|
||||||
|
params['spacing'],
|
||||||
|
params['bit_rate'])
|
||||||
|
# params['effective_freq_slot']['M'] value should be bigger than the computed requested_m (simple estimate)
|
||||||
|
# TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of
|
||||||
|
# superchannel closed packing.
|
||||||
|
|
||||||
|
if requested_m > params['effective_freq_slot']['M']:
|
||||||
|
msg = f'requested M {params["effective_freq_slot"]["M"]} number of slots for request' +\
|
||||||
|
f'{params["request_id"]} should be greater than {requested_m} to support request' +\
|
||||||
|
f'{params["path_bandwidth"] * 1e-9} Gbit/s with {params["trx_type"]} {params["trx_mode"]}'
|
||||||
|
_logger.critical(msg)
|
||||||
|
raise ServiceError(msg)
|
||||||
|
|
||||||
|
|
||||||
def disjunctions_from_json(json_data):
|
def disjunctions_from_json(json_data):
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class Request_element(Element):
|
|||||||
'technology': 'flexi-grid',
|
'technology': 'flexi-grid',
|
||||||
'trx_type': self.trx_type,
|
'trx_type': self.trx_type,
|
||||||
'trx_mode': self.mode,
|
'trx_mode': self.mode,
|
||||||
'effective-freq-slot': [{'N': 'null', 'M': 'null'}],
|
'effective-freq-slot': [{'N': None, 'M': None}],
|
||||||
'spacing': self.spacing,
|
'spacing': self.spacing,
|
||||||
'max-nb-of-channel': self.nb_channel,
|
'max-nb-of-channel': self.nb_channel,
|
||||||
'output-power': self.power
|
'output-power': self.power
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from logging import getLogger
|
|||||||
from networkx import (dijkstra_path, NetworkXNoPath,
|
from networkx import (dijkstra_path, NetworkXNoPath,
|
||||||
all_simple_paths, shortest_simple_paths)
|
all_simple_paths, shortest_simple_paths)
|
||||||
from networkx.utils import pairwise
|
from networkx.utils import pairwise
|
||||||
from numpy import mean
|
from numpy import mean, argmin
|
||||||
from gnpy.core.elements import Transceiver, Roadm
|
from gnpy.core.elements import Transceiver, Roadm
|
||||||
from gnpy.core.utils import lin2db
|
from gnpy.core.utils import lin2db
|
||||||
from gnpy.core.info import create_input_spectral_information
|
from gnpy.core.info import create_input_spectral_information
|
||||||
@@ -32,12 +32,12 @@ from math import ceil
|
|||||||
|
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
RequestParams = namedtuple('RequestParams', 'request_id source destination bidir trx_type' +
|
RequestParams = namedtuple('RequestParams', 'request_id source destination bidir trx_type'
|
||||||
' trx_mode nodes_list loose_list spacing power nb_channel f_min' +
|
' trx_mode nodes_list loose_list spacing power nb_channel f_min'
|
||||||
' f_max format baud_rate OSNR bit_rate roll_off tx_osnr' +
|
' f_max format baud_rate OSNR penalties bit_rate'
|
||||||
' min_spacing cost path_bandwidth')
|
' roll_off tx_osnr min_spacing cost path_bandwidth effective_freq_slot')
|
||||||
DisjunctionParams = namedtuple('DisjunctionParams', 'disjunction_id relaxable link' +
|
DisjunctionParams = namedtuple('DisjunctionParams', 'disjunction_id relaxable link_diverse'
|
||||||
'_diverse node_diverse disjunctions_req')
|
' node_diverse disjunctions_req')
|
||||||
|
|
||||||
|
|
||||||
class PathRequest:
|
class PathRequest:
|
||||||
@@ -62,12 +62,16 @@ class PathRequest:
|
|||||||
self.f_max = params.f_max
|
self.f_max = params.f_max
|
||||||
self.format = params.format
|
self.format = params.format
|
||||||
self.OSNR = params.OSNR
|
self.OSNR = params.OSNR
|
||||||
|
self.penalties = params.penalties
|
||||||
self.bit_rate = params.bit_rate
|
self.bit_rate = params.bit_rate
|
||||||
self.roll_off = params.roll_off
|
self.roll_off = params.roll_off
|
||||||
self.tx_osnr = params.tx_osnr
|
self.tx_osnr = params.tx_osnr
|
||||||
self.min_spacing = params.min_spacing
|
self.min_spacing = params.min_spacing
|
||||||
self.cost = params.cost
|
self.cost = params.cost
|
||||||
self.path_bandwidth = params.path_bandwidth
|
self.path_bandwidth = params.path_bandwidth
|
||||||
|
if params.effective_freq_slot is not None:
|
||||||
|
self.N = params.effective_freq_slot['N']
|
||||||
|
self.M = params.effective_freq_slot['M']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '\n\t'.join([f'{type(self).__name__} {self.request_id}',
|
return '\n\t'.join([f'{type(self).__name__} {self.request_id}',
|
||||||
@@ -75,7 +79,7 @@ class PathRequest:
|
|||||||
f'destination: {self.destination}'])
|
f'destination: {self.destination}'])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.baud_rate is not None:
|
if self.baud_rate is not None and self.bit_rate is not None:
|
||||||
temp = self.baud_rate * 1e-9
|
temp = self.baud_rate * 1e-9
|
||||||
temp2 = self.bit_rate * 1e-9
|
temp2 = self.bit_rate * 1e-9
|
||||||
else:
|
else:
|
||||||
@@ -129,7 +133,7 @@ BLOCKING_NOPATH = ['NO_PATH', 'NO_PATH_WITH_CONSTRAINT',
|
|||||||
'NO_FEASIBLE_BAUDRATE_WITH_SPACING',
|
'NO_FEASIBLE_BAUDRATE_WITH_SPACING',
|
||||||
'NO_COMPUTED_SNR']
|
'NO_COMPUTED_SNR']
|
||||||
BLOCKING_NOMODE = ['NO_FEASIBLE_MODE', 'MODE_NOT_FEASIBLE']
|
BLOCKING_NOMODE = ['NO_FEASIBLE_MODE', 'MODE_NOT_FEASIBLE']
|
||||||
BLOCKING_NOSPECTRUM = 'NO_SPECTRUM'
|
BLOCKING_NOSPECTRUM = ['NO_SPECTRUM', 'NOT_ENOUGH_RESERVED_SPECTRUM']
|
||||||
|
|
||||||
|
|
||||||
class ResultElement:
|
class ResultElement:
|
||||||
@@ -162,7 +166,11 @@ class ResultElement:
|
|||||||
}
|
}
|
||||||
pro_list.append(temp)
|
pro_list.append(temp)
|
||||||
index += 1
|
index += 1
|
||||||
if self.path_request.M > 0:
|
if not hasattr(self.path_request, 'blocking_reason'):
|
||||||
|
# M and N values should not be None at this point
|
||||||
|
if self.path_request.M is None or self.path_request.N is None:
|
||||||
|
raise ServiceError('request {self.path_id} should have positive non null n and m values.')
|
||||||
|
|
||||||
temp = {
|
temp = {
|
||||||
'path-route-object': {
|
'path-route-object': {
|
||||||
'index': index,
|
'index': index,
|
||||||
@@ -174,12 +182,14 @@ class ResultElement:
|
|||||||
}
|
}
|
||||||
pro_list.append(temp)
|
pro_list.append(temp)
|
||||||
index += 1
|
index += 1
|
||||||
elif self.path_request.M == 0 and hasattr(self.path_request, 'blocking_reason'):
|
|
||||||
# if the path is blocked due to spectrum, no label object is created, but
|
|
||||||
# the json response includes a detailed path for user infromation.
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
raise ServiceError('request {self.path_id} should have positive path bandwidth value.')
|
# if the path is blocked, no label object is created, but
|
||||||
|
# the json response includes a detailed path for user information.
|
||||||
|
# M and N values should be None at this point
|
||||||
|
if self.path_request.M is not None or self.path_request.N is not None:
|
||||||
|
raise ServiceError('request {self.path_id} should not have label M and N values at this point.')
|
||||||
|
|
||||||
|
|
||||||
if isinstance(element, Transceiver):
|
if isinstance(element, Transceiver):
|
||||||
temp = {
|
temp = {
|
||||||
'path-route-object': {
|
'path-route-object': {
|
||||||
@@ -339,10 +349,12 @@ def propagate(path, req, equipment):
|
|||||||
else:
|
else:
|
||||||
si = el(si)
|
si = el(si)
|
||||||
path[0].update_snr(req.tx_osnr)
|
path[0].update_snr(req.tx_osnr)
|
||||||
|
path[0].calc_penalties(req.penalties)
|
||||||
if any(isinstance(el, Roadm) for el in path):
|
if any(isinstance(el, Roadm) for el in path):
|
||||||
path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr)
|
path[-1].update_snr(req.tx_osnr, equipment['Roadm']['default'].add_drop_osnr)
|
||||||
else:
|
else:
|
||||||
path[-1].update_snr(req.tx_osnr)
|
path[-1].update_snr(req.tx_osnr)
|
||||||
|
path[-1].calc_penalties(req.penalties)
|
||||||
return si
|
return si
|
||||||
|
|
||||||
|
|
||||||
@@ -377,11 +389,13 @@ def propagate_and_optimize_mode(path, req, equipment):
|
|||||||
for this_mode in modes_to_explore:
|
for this_mode in modes_to_explore:
|
||||||
if path[-1].snr is not None:
|
if path[-1].snr is not None:
|
||||||
path[0].update_snr(this_mode['tx_osnr'])
|
path[0].update_snr(this_mode['tx_osnr'])
|
||||||
|
path[0].calc_penalties(this_mode['penalties'])
|
||||||
if any(isinstance(el, Roadm) for el in path):
|
if any(isinstance(el, Roadm) for el in path):
|
||||||
path[-1].update_snr(this_mode['tx_osnr'], equipment['Roadm']['default'].add_drop_osnr)
|
path[-1].update_snr(this_mode['tx_osnr'], equipment['Roadm']['default'].add_drop_osnr)
|
||||||
else:
|
else:
|
||||||
path[-1].update_snr(this_mode['tx_osnr'])
|
path[-1].update_snr(this_mode['tx_osnr'])
|
||||||
if round(min(path[-1].snr + lin2db(this_br / (12.5e9))), 2) \
|
path[-1].calc_penalties(this_mode['penalties'])
|
||||||
|
if round(min(path[-1].snr_01nm - path[-1].total_penalty), 2) \
|
||||||
> this_mode['OSNR'] + equipment['SI']['default'].sys_margins:
|
> this_mode['OSNR'] + equipment['SI']['default'].sys_margins:
|
||||||
return path, this_mode
|
return path, this_mode
|
||||||
else:
|
else:
|
||||||
@@ -389,7 +403,6 @@ def propagate_and_optimize_mode(path, req, equipment):
|
|||||||
else:
|
else:
|
||||||
req.blocking_reason = 'NO_COMPUTED_SNR'
|
req.blocking_reason = 'NO_COMPUTED_SNR'
|
||||||
return path, None
|
return path, None
|
||||||
|
|
||||||
# only get to this point if no baudrate/mode satisfies OSNR requirement
|
# only get to this point if no baudrate/mode satisfies OSNR requirement
|
||||||
|
|
||||||
# returns the last propagated path and mode
|
# returns the last propagated path and mode
|
||||||
@@ -696,8 +709,8 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
|
|||||||
# in each loop, dpath is updated with a path for rq that satisfies
|
# in each loop, dpath is updated with a path for rq that satisfies
|
||||||
# disjunction with each path in dpath
|
# disjunction with each path in dpath
|
||||||
# for example, assume set of requests in the vector (disjunction_list) is {rq1,rq2, rq3}
|
# for example, assume set of requests in the vector (disjunction_list) is {rq1,rq2, rq3}
|
||||||
# rq1 p1: abfhg
|
# rq1 p1: aefhg
|
||||||
# p2: aefhg
|
# p2: abfhg
|
||||||
# p3: abcg
|
# p3: abcg
|
||||||
# rq2 p8: bf
|
# rq2 p8: bf
|
||||||
# rq3 p4: abcgh
|
# rq3 p4: abcgh
|
||||||
@@ -714,6 +727,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
|
|||||||
# after second loop:
|
# after second loop:
|
||||||
# dpath = [ p3 p8 p6 ]
|
# dpath = [ p3 p8 p6 ]
|
||||||
# since p1 and p4 are not disjoint
|
# since p1 and p4 are not disjoint
|
||||||
|
# p1 and p6 are not disjoint
|
||||||
# p1 and p7 are not disjoint
|
# p1 and p7 are not disjoint
|
||||||
# p3 and p4 are not disjoint
|
# p3 and p4 are not disjoint
|
||||||
# p3 and p7 are not disjoint
|
# p3 and p7 are not disjoint
|
||||||
@@ -737,7 +751,6 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
|
|||||||
temp.append(temp2)
|
temp.append(temp2)
|
||||||
# print(f' coucou {elem1}: \t{temp}')
|
# print(f' coucou {elem1}: \t{temp}')
|
||||||
dpath = temp
|
dpath = temp
|
||||||
# print(dpath)
|
|
||||||
candidates[dis.disjunction_id] = dpath
|
candidates[dis.disjunction_id] = dpath
|
||||||
|
|
||||||
# for i in disjunctions_list:
|
# for i in disjunctions_list:
|
||||||
@@ -788,33 +801,34 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
|
|||||||
# TODO: keep a version without the loose constraint
|
# TODO: keep a version without the loose constraint
|
||||||
for this_d in disjunctions_list:
|
for this_d in disjunctions_list:
|
||||||
temp = []
|
temp = []
|
||||||
|
alternatetemp = []
|
||||||
for j, sol in enumerate(candidates[this_d.disjunction_id]):
|
for j, sol in enumerate(candidates[this_d.disjunction_id]):
|
||||||
testispartok = True
|
testispartok = True
|
||||||
|
testispartnokloose = True
|
||||||
for pth in sol:
|
for pth in sol:
|
||||||
# print(f'test {allpaths[id(pth)].req.request_id}')
|
# print(f'test {allpaths[id(pth)].req.request_id}')
|
||||||
# print(f'length of route {len(allpaths[id(pth)].req.nodes_list)}')
|
# print(f'length of route {len(allpaths[id(pth)].req.nodes_list)}')
|
||||||
if allpaths[id(pth)].req.nodes_list:
|
if allpaths[id(pth)].req.nodes_list:
|
||||||
# if pth does not containt the ordered list node, remove sol from the candidate
|
# if any pth from sol does not contain the ordered list node,
|
||||||
# except if this was the last solution: then check if the constraint is loose
|
# remove sol from the candidate, except if constraint was loose:
|
||||||
# or not
|
# then keep sol as an alternate solution
|
||||||
if not ispart(allpaths[id(pth)].req.nodes_list, pth):
|
if not ispart(allpaths[id(pth)].req.nodes_list, pth):
|
||||||
# print(f'nb of solutions {len(temp)}')
|
|
||||||
if j < len(candidates[this_d.disjunction_id]) - 1:
|
|
||||||
msg = f'removing {sol}'
|
|
||||||
LOGGER.info(msg)
|
|
||||||
testispartok = False
|
|
||||||
# break
|
|
||||||
else:
|
|
||||||
if 'LOOSE' in allpaths[id(pth)].req.loose_list:
|
|
||||||
LOGGER.info(f'Could not apply route constraint' +
|
|
||||||
f'{allpaths[id(pth)].req.nodes_list} on request' +
|
|
||||||
f' {allpaths[id(pth)].req.request_id}')
|
|
||||||
else:
|
|
||||||
LOGGER.info(f'removing last solution from candidate paths\n{sol}')
|
|
||||||
testispartok = False
|
testispartok = False
|
||||||
|
if 'STRICT' in allpaths[id(pth)].req.loose_list:
|
||||||
|
LOGGER.info(f'removing solution from candidate paths\n{pth}')
|
||||||
|
testispartnokloose = False
|
||||||
|
break
|
||||||
if testispartok:
|
if testispartok:
|
||||||
temp.append(sol)
|
temp.append(sol)
|
||||||
|
elif testispartnokloose:
|
||||||
|
LOGGER.info(f'Adding solution as alternate solution not satisfying constraint\n{pth}')
|
||||||
|
alternatetemp.append(sol)
|
||||||
|
if temp:
|
||||||
candidates[this_d.disjunction_id] = temp
|
candidates[this_d.disjunction_id] = temp
|
||||||
|
elif alternatetemp:
|
||||||
|
candidates[this_d.disjunction_id] = alternatetemp
|
||||||
|
else:
|
||||||
|
candidates[this_d.disjunction_id] = []
|
||||||
|
|
||||||
# step 5 select the first combination that works
|
# step 5 select the first combination that works
|
||||||
pathreslist_disjoint = {}
|
pathreslist_disjoint = {}
|
||||||
@@ -964,7 +978,9 @@ def compare_reqs(req1, req2, disjlist):
|
|||||||
req1.format == req2.format and \
|
req1.format == req2.format and \
|
||||||
req1.OSNR == req2.OSNR and \
|
req1.OSNR == req2.OSNR and \
|
||||||
req1.roll_off == req2.roll_off and \
|
req1.roll_off == req2.roll_off and \
|
||||||
same_disj:
|
same_disj and \
|
||||||
|
getattr(req1, 'N', None) is None and getattr(req2, 'N', None) is None and \
|
||||||
|
getattr(req1, 'M', None) is None and getattr(req2, 'M', None) is None:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@@ -1096,12 +1112,16 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
|
|||||||
# means that at this point the mode was entered/forced by user and thus a
|
# means that at this point the mode was entered/forced by user and thus a
|
||||||
# baud_rate was defined
|
# baud_rate was defined
|
||||||
propagate(total_path, pathreq, equipment)
|
propagate(total_path, pathreq, equipment)
|
||||||
temp_snr01nm = round(mean(total_path[-1].snr+lin2db(pathreq.baud_rate/(12.5e9))), 2)
|
snr01nm_with_penalty = total_path[-1].snr_01nm - total_path[-1].total_penalty
|
||||||
if temp_snr01nm < pathreq.OSNR + equipment['SI']['default'].sys_margins:
|
min_ind = argmin(snr01nm_with_penalty)
|
||||||
|
if round(snr01nm_with_penalty[min_ind], 2) < pathreq.OSNR + equipment['SI']['default'].sys_margins:
|
||||||
msg = f'\tWarning! Request {pathreq.request_id} computed path from' +\
|
msg = f'\tWarning! Request {pathreq.request_id} computed path from' +\
|
||||||
f' {pathreq.source} to {pathreq.destination} does not pass with' +\
|
f' {pathreq.source} to {pathreq.destination} does not pass with {pathreq.tsp_mode}' +\
|
||||||
f' {pathreq.tsp_mode}\n\tcomputedSNR in 0.1nm = {temp_snr01nm} ' +\
|
f'\n\tcomputed SNR in 0.1nm = {round(total_path[-1].snr_01nm[min_ind], 2)}' +\
|
||||||
f'- required osnr {pathreq.OSNR} + {equipment["SI"]["default"].sys_margins} margin'
|
f'\n\tCD penalty = {round(total_path[-1].penalties["chromatic_dispersion"][min_ind], 2)}' +\
|
||||||
|
f'\n\tPMD penalty = {round(total_path[-1].penalties["pmd"][min_ind], 2)}' +\
|
||||||
|
f'\n\trequired osnr = {pathreq.OSNR}' +\
|
||||||
|
f'\n\tsystem margin = {equipment["SI"]["default"].sys_margins}'
|
||||||
print(msg)
|
print(msg)
|
||||||
LOGGER.warning(msg)
|
LOGGER.warning(msg)
|
||||||
pathreq.blocking_reason = 'MODE_NOT_FEASIBLE'
|
pathreq.blocking_reason = 'MODE_NOT_FEASIBLE'
|
||||||
@@ -1141,17 +1161,20 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
|
|||||||
print(f'\tPath (roadsm) {[r.uid for r in rev_p if isinstance(r,Roadm)]}\n')
|
print(f'\tPath (roadsm) {[r.uid for r in rev_p if isinstance(r,Roadm)]}\n')
|
||||||
propagate(rev_p, pathreq, equipment)
|
propagate(rev_p, pathreq, equipment)
|
||||||
propagated_reversed_path = rev_p
|
propagated_reversed_path = rev_p
|
||||||
temp_snr01nm = round(mean(propagated_reversed_path[-1].snr +\
|
snr01nm_with_penalty = rev_p[-1].snr_01nm - rev_p[-1].total_penalty
|
||||||
lin2db(pathreq.baud_rate/(12.5e9))), 2)
|
min_ind = argmin(snr01nm_with_penalty)
|
||||||
if temp_snr01nm < pathreq.OSNR + equipment['SI']['default'].sys_margins:
|
if round(snr01nm_with_penalty[min_ind], 2) < pathreq.OSNR + equipment['SI']['default'].sys_margins:
|
||||||
msg = f'\tWarning! Request {pathreq.request_id} computed path from' +\
|
msg = f'\tWarning! Request {pathreq.request_id} computed path from' +\
|
||||||
f' {pathreq.source} to {pathreq.destination} does not pass with' +\
|
f' {pathreq.source} to {pathreq.destination} does not pass with {pathreq.tsp_mode}' +\
|
||||||
f' {pathreq.tsp_mode}\n' +\
|
f'\n\tcomputed SNR in 0.1nm = {round(rev_p[-1].snr_01nm[min_ind], 2)}' +\
|
||||||
f'\tcomputedSNR in 0.1nm = {temp_snr01nm} -' \
|
f'\n\tCD penalty = {round(rev_p[-1].penalties["chromatic_dispersion"][min_ind], 2)}' +\
|
||||||
f' required osnr {pathreq.OSNR} + {equipment["SI"]["default"].sys_margins} margin'
|
f'\n\tPMD penalty = {round(rev_p[-1].penalties["pmd"][min_ind], 2)}' +\
|
||||||
|
f'\n\trequired osnr = {pathreq.OSNR}' +\
|
||||||
|
f'\n\tsystem margin = {equipment["SI"]["default"].sys_margins}'
|
||||||
print(msg)
|
print(msg)
|
||||||
LOGGER.warning(msg)
|
LOGGER.warning(msg)
|
||||||
# TODO selection of mode should also be on reversed direction !!
|
# TODO selection of mode should also be on reversed direction !!
|
||||||
|
if not hasattr(pathreq, 'blocking_reason'):
|
||||||
pathreq.blocking_reason = 'MODE_NOT_FEASIBLE'
|
pathreq.blocking_reason = 'MODE_NOT_FEASIBLE'
|
||||||
else:
|
else:
|
||||||
propagated_reversed_path = []
|
propagated_reversed_path = []
|
||||||
@@ -1168,3 +1191,15 @@ def compute_path_with_disjunction(network, equipment, pathreqlist, pathlist):
|
|||||||
# print to have a nice output
|
# print to have a nice output
|
||||||
print('')
|
print('')
|
||||||
return path_res_list, reversed_path_res_list, propagated_reversed_path_res_list
|
return path_res_list, reversed_path_res_list, propagated_reversed_path_res_list
|
||||||
|
|
||||||
|
|
||||||
|
def compute_spectrum_slot_vs_bandwidth(bandwidth, spacing, bit_rate, slot_width=0.0125e12):
|
||||||
|
""" Compute the number of required wavelengths and the M value (number of consumed slots)
|
||||||
|
Each wavelength consumes one `spacing`, and the result is rounded up to consume a natural number of slots.
|
||||||
|
|
||||||
|
>>> compute_spectrum_slot_vs_bandwidth(400e9, 50e9, 200e9)
|
||||||
|
(2, 8)
|
||||||
|
"""
|
||||||
|
number_of_wavelengths = ceil(bandwidth / bit_rate)
|
||||||
|
total_number_of_slots = ceil(spacing / slot_width) * number_of_wavelengths
|
||||||
|
return number_of_wavelengths, total_number_of_slots
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ element/oms correspondace
|
|||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from math import ceil
|
|
||||||
from gnpy.core.elements import Roadm, Transceiver
|
from gnpy.core.elements import Roadm, Transceiver
|
||||||
from gnpy.core.exceptions import ServiceError, SpectrumError
|
from gnpy.core.exceptions import ServiceError, SpectrumError
|
||||||
|
from gnpy.topology.request import compute_spectrum_slot_vs_bandwidth
|
||||||
|
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
@@ -390,42 +390,40 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths):
|
|||||||
""" basic first fit assignment
|
""" basic first fit assignment
|
||||||
if reversed path are provided, means that occupation is bidir
|
if reversed path are provided, means that occupation is bidir
|
||||||
"""
|
"""
|
||||||
for i, pth in enumerate(pths):
|
for pth, rq, rpth in zip(pths, rqs, rpths):
|
||||||
# computes the number of channels required
|
# computes the number of channels required
|
||||||
try:
|
if hasattr(rq, 'blocking_reason'):
|
||||||
if rqs[i].blocking_reason:
|
rq.N = None
|
||||||
rqs[i].blocked = True
|
rq.M = None
|
||||||
rqs[i].N = 0
|
else:
|
||||||
rqs[i].M = 0
|
nb_wl, requested_m = compute_spectrum_slot_vs_bandwidth(rq.path_bandwidth,
|
||||||
except AttributeError:
|
rq.spacing, rq.bit_rate)
|
||||||
nb_wl = ceil(rqs[i].path_bandwidth / rqs[i].bit_rate)
|
if getattr(rq, 'M', None) is not None:
|
||||||
# computes the total nb of slots according to requested spacing
|
# Consistency check between the requested M and path_bandwidth
|
||||||
# TODO : express superchannels
|
# M value should be bigger than the computed requested_m (simple estimate)
|
||||||
# assumes that all channels must be grouped
|
# TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of
|
||||||
# TODO : enables non contiguous reservation in case of blocking
|
# superchannel closed packing.
|
||||||
requested_m = ceil(rqs[i].spacing / 0.0125e12) * nb_wl
|
if requested_m > rq.M:
|
||||||
# concatenate all path and reversed path elements to derive slots availability
|
rq.N = None
|
||||||
(center_n, startn, stopn), path_oms = spectrum_selection(pth + rpths[i], oms_list, requested_m,
|
rq.M = None
|
||||||
requested_n=None)
|
rq.blocking_reason = 'NOT_ENOUGH_RESERVED_SPECTRUM'
|
||||||
# checks that requested_m is fitting startm and stopm
|
# need to stop here for this request and not go though spectrum selection process with requested_m
|
||||||
|
continue
|
||||||
|
# use the req.M even if requested_m is smaller
|
||||||
|
requested_m = rq.M
|
||||||
|
requested_n = getattr(rq, 'N', None)
|
||||||
|
(center_n, startn, stopn), path_oms = spectrum_selection(pth + rpth, oms_list, requested_m,
|
||||||
|
requested_n)
|
||||||
|
# if requested n and m concern already occupied spectrum the previous function returns a None candidate
|
||||||
# if not None, center_n and start, stop frequencies are applicable to all oms of pth
|
# if not None, center_n and start, stop frequencies are applicable to all oms of pth
|
||||||
# checks that spectrum is not None else indicate blocking reason
|
# checks that spectrum is not None else indicate blocking reason
|
||||||
if center_n is not None:
|
if center_n is not None:
|
||||||
# checks that requested_m is fitting startm and stopm
|
|
||||||
if 2 * requested_m > (stopn - startn + 1):
|
|
||||||
msg = f'candidate: {(center_n, startn, stopn)} is not consistant ' +\
|
|
||||||
f'with {requested_m}'
|
|
||||||
LOGGER.critical(msg)
|
|
||||||
raise ValueError(msg)
|
|
||||||
|
|
||||||
for oms_elem in path_oms:
|
for oms_elem in path_oms:
|
||||||
oms_list[oms_elem].assign_spectrum(center_n, requested_m)
|
oms_list[oms_elem].assign_spectrum(center_n, requested_m)
|
||||||
oms_list[oms_elem].add_service(rqs[i].request_id, nb_wl)
|
oms_list[oms_elem].add_service(rq.request_id, nb_wl)
|
||||||
rqs[i].blocked = False
|
rq.N = center_n
|
||||||
rqs[i].N = center_n
|
rq.M = requested_m
|
||||||
rqs[i].M = requested_m
|
|
||||||
else:
|
else:
|
||||||
rqs[i].blocked = True
|
rq.N = None
|
||||||
rqs[i].N = 0
|
rq.M = None
|
||||||
rqs[i].M = 0
|
rq.blocking_reason = 'NO_SPECTRUM'
|
||||||
rqs[i].blocking_reason = 'NO_SPECTRUM'
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
matplotlib>=3.3.3,<4
|
matplotlib>=3.5.1,<4
|
||||||
networkx>=2.5,<3
|
networkx>=2.6,<3
|
||||||
numpy>=1.19.4,<2
|
numpy>=1.22.0,<2
|
||||||
pandas>=1.1.5,<2
|
pandas>=1.3.5,<2
|
||||||
pbr>=5.5.1,<6
|
pbr>=5.7.0,<6
|
||||||
scipy>=1.5.4,<2
|
scipy>=1.7.3,<2
|
||||||
xlrd>=1.2.0,<2
|
xlrd>=1.2.0,<2
|
||||||
|
|||||||
13
setup.cfg
13
setup.cfg
@@ -1,8 +1,7 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = gnpy
|
name = gnpy
|
||||||
description = Route planning and optimization tool for mesh optical networks
|
description-file = README.md
|
||||||
description-file = README.rst
|
description-content-type = text/markdown; variant=GFM
|
||||||
description-content-type = text/x-rst; charset=UTF-8
|
|
||||||
author = Telecom Infra Project
|
author = Telecom Infra Project
|
||||||
author-email = jan.kundrat@telecominfraproject.com
|
author-email = jan.kundrat@telecominfraproject.com
|
||||||
license = BSD-3-Clause
|
license = BSD-3-Clause
|
||||||
@@ -10,7 +9,7 @@ home-page = https://github.com/Telecominfraproject/oopt-gnpy
|
|||||||
project_urls =
|
project_urls =
|
||||||
Bug Tracker = https://github.com/Telecominfraproject/oopt-gnpy/issues
|
Bug Tracker = https://github.com/Telecominfraproject/oopt-gnpy/issues
|
||||||
Documentation = https://gnpy.readthedocs.io/
|
Documentation = https://gnpy.readthedocs.io/
|
||||||
python-requires = >=3.6
|
python-requires = >=3.8
|
||||||
classifier =
|
classifier =
|
||||||
Development Status :: 5 - Production/Stable
|
Development Status :: 5 - Production/Stable
|
||||||
Intended Audience :: Developers
|
Intended Audience :: Developers
|
||||||
@@ -20,10 +19,9 @@ classifier =
|
|||||||
Natural Language :: English
|
Natural Language :: English
|
||||||
Programming Language :: Python
|
Programming Language :: Python
|
||||||
Programming Language :: Python :: 3 :: Only
|
Programming Language :: Python :: 3 :: Only
|
||||||
Programming Language :: Python :: 3.6
|
|
||||||
Programming Language :: Python :: 3.7
|
|
||||||
Programming Language :: Python :: 3.8
|
Programming Language :: Python :: 3.8
|
||||||
Programming Language :: Python :: 3.9
|
Programming Language :: Python :: 3.9
|
||||||
|
Programming Language :: Python :: 3.10
|
||||||
Programming Language :: Python :: Implementation :: CPython
|
Programming Language :: Python :: Implementation :: CPython
|
||||||
Topic :: Scientific/Engineering
|
Topic :: Scientific/Engineering
|
||||||
Topic :: Scientific/Engineering :: Physics
|
Topic :: Scientific/Engineering :: Physics
|
||||||
@@ -42,9 +40,6 @@ warnerrors = True
|
|||||||
|
|
||||||
[files]
|
[files]
|
||||||
packages = gnpy
|
packages = gnpy
|
||||||
data_files =
|
|
||||||
examples = examples/*
|
|
||||||
# FIXME: solve example data files
|
|
||||||
|
|
||||||
[options.entry_points]
|
[options.entry_points]
|
||||||
console_scripts =
|
console_scripts =
|
||||||
|
|||||||
135
tests/compare.py
135
tests/compare.py
@@ -1,135 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from json import dump
|
|
||||||
from pathlib import Path
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
from collections import namedtuple
|
|
||||||
from gnpy.tools.json_io import load_json
|
|
||||||
|
|
||||||
|
|
||||||
class Results(namedtuple('Results', 'missing extra different expected actual')):
|
|
||||||
def _asdict(self):
|
|
||||||
return {'missing': self.missing,
|
|
||||||
'extra': self.extra,
|
|
||||||
'different': self.different}
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
rv = []
|
|
||||||
if self.missing:
|
|
||||||
rv.append('Missing: {len(self.missing)}/{len(self.expected)}')
|
|
||||||
rv.extend(f'\t{x}' for x in sorted(self.missing))
|
|
||||||
if self.extra:
|
|
||||||
rv.append('Extra: {len(self.extra)}/{len(self.expected)}')
|
|
||||||
rv.extend(f'\t{x}' for x in sorted(self.extra))
|
|
||||||
if self.different:
|
|
||||||
rv.append('Different: {len(self.different)}/{len(self.expected)}')
|
|
||||||
rv.extend(f'\tExpected: {x}\n\tActual: {y}' for x, y in self.different)
|
|
||||||
if not self.missing and not self.extra and not self.different:
|
|
||||||
rv.append('All match!')
|
|
||||||
return '\n'.join(rv)
|
|
||||||
|
|
||||||
|
|
||||||
class NetworksResults(namedtuple('NetworksResult', 'elements connections')):
|
|
||||||
def _asdict(self):
|
|
||||||
return {'elements': self.elements._asdict(),
|
|
||||||
'connections': self.connections._asdict()}
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return '\n'.join([
|
|
||||||
'Elements'.center(40, '='),
|
|
||||||
str(self.elements),
|
|
||||||
'Connections'.center(40, '='),
|
|
||||||
str(self.connections),
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
class ServicesResults(namedtuple('ServicesResult', 'requests synchronizations')):
|
|
||||||
def _asdict(self):
|
|
||||||
return {'requests': self.requests.asdict(),
|
|
||||||
'synchronizations': self.synchronizations.asdict()}
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return '\n'.join([
|
|
||||||
'Requests'.center(40, '='),
|
|
||||||
str(self.requests),
|
|
||||||
'Synchronizations'.center(40, '='),
|
|
||||||
str(self.synchronizations),
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
class PathsResults(namedtuple('PathsResults', 'paths')):
|
|
||||||
def _asdict(self):
|
|
||||||
return {'paths': self.paths.asdict()}
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return '\n'.join([
|
|
||||||
'Paths'.center(40, '='),
|
|
||||||
str(self.paths),
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
def compare(expected, actual, key=lambda x: x):
|
|
||||||
expected = {key(el): el for el in expected}
|
|
||||||
actual = {key(el): el for el in actual}
|
|
||||||
missing = set(expected) - set(actual)
|
|
||||||
extra = set(actual) - set(expected)
|
|
||||||
different = [(expected[x], actual[x]) for
|
|
||||||
x in set(expected) & set(actual)
|
|
||||||
if expected[x] != actual[x]]
|
|
||||||
return Results(missing, extra, different, expected, actual)
|
|
||||||
|
|
||||||
|
|
||||||
def compare_networks(expected, actual):
|
|
||||||
elements = compare(expected['elements'], actual['elements'],
|
|
||||||
key=lambda el: el['uid'])
|
|
||||||
connections = compare(expected['connections'], actual['connections'],
|
|
||||||
key=lambda el: (el['from_node'], el['to_node']))
|
|
||||||
return NetworksResults(elements, connections)
|
|
||||||
|
|
||||||
|
|
||||||
def compare_services(expected, actual):
|
|
||||||
requests = compare(expected['path-request'], actual['path-request'],
|
|
||||||
key=lambda el: el['request-id'])
|
|
||||||
synchronizations = compare(expected['path-request'], expected['path-request'],
|
|
||||||
key=lambda el: el['request-id'])
|
|
||||||
if 'synchronization' in expected.keys():
|
|
||||||
synchronizations = compare(expected['synchronization'], actual['synchronization'],
|
|
||||||
key=lambda el: el['synchronization-id'])
|
|
||||||
return ServicesResults(requests, synchronizations)
|
|
||||||
|
|
||||||
|
|
||||||
def compare_paths(expected_output, actual_output):
|
|
||||||
paths = compare(expected['path'], actual['path'], key=lambda el: el['path-id'])
|
|
||||||
return PathsResults(paths)
|
|
||||||
|
|
||||||
|
|
||||||
COMPARISONS = {
|
|
||||||
'networks': compare_networks,
|
|
||||||
'services': compare_services,
|
|
||||||
'paths': compare_paths,
|
|
||||||
}
|
|
||||||
|
|
||||||
parser = ArgumentParser()
|
|
||||||
parser.add_argument('expected_output', type=Path, metavar='FILE')
|
|
||||||
parser.add_argument('actual_output', type=Path, metavar='FILE')
|
|
||||||
parser.add_argument('-o', '--output', default=None)
|
|
||||||
parser.add_argument('-c', '--comparison', choices=COMPARISONS, default='networks')
|
|
||||||
|
|
||||||
|
|
||||||
def encode_sets(obj):
|
|
||||||
if isinstance(obj, set):
|
|
||||||
return list(obj)
|
|
||||||
raise TypeError(f'{obj!r} is not JSON serializable!')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
args = parser.parse_args()
|
|
||||||
expected = load_json(args.expected_output)
|
|
||||||
actual = load_json(args.actual_output)
|
|
||||||
|
|
||||||
result = COMPARISONS[args.comparison](expected, actual)
|
|
||||||
|
|
||||||
if args.output:
|
|
||||||
with open(args.output, 'w', encoding='utf-8') as f:
|
|
||||||
dump(result, f, default=encode_sets, indent=2, ensure_ascii=False)
|
|
||||||
else:
|
|
||||||
print(str(result))
|
|
||||||
13
tests/conftest.py
Normal file
13
tests/conftest.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 Telecom Infra Project and GNPy contributors
|
||||||
|
# see LICENSE.md for a list of contributors
|
||||||
|
#
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from gnpy.core.parameters import SimParams, NLIParams, RamanParams
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def set_sim_params(monkeypatch):
|
||||||
|
monkeypatch.setattr(SimParams, '_shared_dict', {'nli_params': NLIParams(), 'raman_params': RamanParams()})
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -63,7 +63,7 @@
|
|||||||
"Fiber":[{
|
"Fiber":[{
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
"dispersion": 1.67e-05,
|
"dispersion": 1.67e-05,
|
||||||
"gamma": 0.00127,
|
"effective_area": 83e-12,
|
||||||
"pmd_coef": 1.265e-15
|
"pmd_coef": 1.265e-15
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -85,6 +85,7 @@
|
|||||||
"target_pch_out_db": -20,
|
"target_pch_out_db": -20,
|
||||||
"add_drop_osnr": 38,
|
"add_drop_osnr": 38,
|
||||||
"pmd": 0,
|
"pmd": 0,
|
||||||
|
"pdl": 0,
|
||||||
"restrictions": {
|
"restrictions": {
|
||||||
"preamp_variety_list":[],
|
"preamp_variety_list":[],
|
||||||
"booster_variety_list":[]
|
"booster_variety_list":[]
|
||||||
|
|||||||
@@ -1,224 +0,0 @@
|
|||||||
{
|
|
||||||
"uid": "Span1",
|
|
||||||
"params": {
|
|
||||||
"length": 80,
|
|
||||||
"loss_coef": 0.2,
|
|
||||||
"length_units": "km",
|
|
||||||
"att_in": 0,
|
|
||||||
"con_in": 0.5,
|
|
||||||
"con_out": 0.5,
|
|
||||||
"type_variety": "SSMF",
|
|
||||||
"dispersion": 0.0000167,
|
|
||||||
"gamma": 0.00127,
|
|
||||||
"pmd_coef": 1.265e-15,
|
|
||||||
"raman_efficiency": {
|
|
||||||
"cr": [
|
|
||||||
0,
|
|
||||||
0.0000094,
|
|
||||||
0.0000292,
|
|
||||||
0.0000488,
|
|
||||||
0.0000682,
|
|
||||||
0.0000831,
|
|
||||||
0.000094,
|
|
||||||
0.0001014,
|
|
||||||
0.0001069,
|
|
||||||
0.0001119,
|
|
||||||
0.0001217,
|
|
||||||
0.0001268,
|
|
||||||
0.0001365,
|
|
||||||
0.000149,
|
|
||||||
0.000165,
|
|
||||||
0.000181,
|
|
||||||
0.0001977,
|
|
||||||
0.0002192,
|
|
||||||
0.0002469,
|
|
||||||
0.0002749,
|
|
||||||
0.0002999,
|
|
||||||
0.0003206,
|
|
||||||
0.0003405,
|
|
||||||
0.0003592,
|
|
||||||
0.000374,
|
|
||||||
0.0003826,
|
|
||||||
0.0003841,
|
|
||||||
0.0003826,
|
|
||||||
0.0003802,
|
|
||||||
0.0003756,
|
|
||||||
0.0003549,
|
|
||||||
0.0003795,
|
|
||||||
0.000344,
|
|
||||||
0.0002933,
|
|
||||||
0.0002024,
|
|
||||||
0.0001158,
|
|
||||||
0.0000846,
|
|
||||||
0.0000714,
|
|
||||||
0.0000686,
|
|
||||||
0.000085,
|
|
||||||
0.0000893,
|
|
||||||
0.0000901,
|
|
||||||
0.0000815,
|
|
||||||
0.0000667,
|
|
||||||
0.0000437,
|
|
||||||
0.0000328,
|
|
||||||
0.0000296,
|
|
||||||
0.0000265,
|
|
||||||
0.0000257,
|
|
||||||
0.0000281,
|
|
||||||
0.0000308,
|
|
||||||
0.0000367,
|
|
||||||
0.0000585,
|
|
||||||
0.0000663,
|
|
||||||
0.0000636,
|
|
||||||
0.000055,
|
|
||||||
0.0000406,
|
|
||||||
0.0000277,
|
|
||||||
0.0000242,
|
|
||||||
0.0000187,
|
|
||||||
0.000016,
|
|
||||||
0.000014,
|
|
||||||
0.0000113,
|
|
||||||
0.0000105,
|
|
||||||
0.0000098,
|
|
||||||
0.0000098,
|
|
||||||
0.0000113,
|
|
||||||
0.0000164,
|
|
||||||
0.0000195,
|
|
||||||
0.0000238,
|
|
||||||
0.0000226,
|
|
||||||
0.0000203,
|
|
||||||
0.0000148,
|
|
||||||
0.0000109,
|
|
||||||
0.0000098,
|
|
||||||
0.0000105,
|
|
||||||
0.0000117,
|
|
||||||
0.0000125,
|
|
||||||
0.0000121,
|
|
||||||
0.0000109,
|
|
||||||
0.0000098,
|
|
||||||
0.0000082,
|
|
||||||
0.0000066,
|
|
||||||
0.0000047,
|
|
||||||
0.0000027,
|
|
||||||
0.0000019,
|
|
||||||
0.0000012,
|
|
||||||
4e-7,
|
|
||||||
2e-7,
|
|
||||||
1e-7
|
|
||||||
],
|
|
||||||
"frequency_offset": [
|
|
||||||
0,
|
|
||||||
500000000000,
|
|
||||||
1000000000000,
|
|
||||||
1500000000000,
|
|
||||||
2000000000000,
|
|
||||||
2500000000000,
|
|
||||||
3000000000000,
|
|
||||||
3500000000000,
|
|
||||||
4000000000000,
|
|
||||||
4500000000000,
|
|
||||||
5000000000000,
|
|
||||||
5500000000000,
|
|
||||||
6000000000000,
|
|
||||||
6500000000000,
|
|
||||||
7000000000000,
|
|
||||||
7500000000000,
|
|
||||||
8000000000000,
|
|
||||||
8500000000000,
|
|
||||||
9000000000000,
|
|
||||||
9500000000000,
|
|
||||||
10000000000000,
|
|
||||||
10500000000000,
|
|
||||||
11000000000000,
|
|
||||||
11500000000000,
|
|
||||||
12000000000000,
|
|
||||||
12500000000000,
|
|
||||||
12750000000000,
|
|
||||||
13000000000000,
|
|
||||||
13250000000000,
|
|
||||||
13500000000000,
|
|
||||||
14000000000000,
|
|
||||||
14500000000000,
|
|
||||||
14750000000000,
|
|
||||||
15000000000000,
|
|
||||||
15500000000000,
|
|
||||||
16000000000000,
|
|
||||||
16500000000000,
|
|
||||||
17000000000000,
|
|
||||||
17500000000000,
|
|
||||||
18000000000000,
|
|
||||||
18250000000000,
|
|
||||||
18500000000000,
|
|
||||||
18750000000000,
|
|
||||||
19000000000000,
|
|
||||||
19500000000000,
|
|
||||||
20000000000000,
|
|
||||||
20500000000000,
|
|
||||||
21000000000000,
|
|
||||||
21500000000000,
|
|
||||||
22000000000000,
|
|
||||||
22500000000000,
|
|
||||||
23000000000000,
|
|
||||||
23500000000000,
|
|
||||||
24000000000000,
|
|
||||||
24500000000000,
|
|
||||||
25000000000000,
|
|
||||||
25500000000000,
|
|
||||||
26000000000000,
|
|
||||||
26500000000000,
|
|
||||||
27000000000000,
|
|
||||||
27500000000000,
|
|
||||||
28000000000000,
|
|
||||||
28500000000000,
|
|
||||||
29000000000000,
|
|
||||||
29500000000000,
|
|
||||||
30000000000000,
|
|
||||||
30500000000000,
|
|
||||||
31000000000000,
|
|
||||||
31500000000000,
|
|
||||||
32000000000000,
|
|
||||||
32500000000000,
|
|
||||||
33000000000000,
|
|
||||||
33500000000000,
|
|
||||||
34000000000000,
|
|
||||||
34500000000000,
|
|
||||||
35000000000000,
|
|
||||||
35500000000000,
|
|
||||||
36000000000000,
|
|
||||||
36500000000000,
|
|
||||||
37000000000000,
|
|
||||||
37500000000000,
|
|
||||||
38000000000000,
|
|
||||||
38500000000000,
|
|
||||||
39000000000000,
|
|
||||||
39500000000000,
|
|
||||||
40000000000000,
|
|
||||||
40500000000000,
|
|
||||||
41000000000000,
|
|
||||||
41500000000000,
|
|
||||||
42000000000000
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"operational": {
|
|
||||||
"temperature": 283,
|
|
||||||
"raman_pumps": [
|
|
||||||
{
|
|
||||||
"power": 0.2,
|
|
||||||
"frequency": 205000000000000,
|
|
||||||
"propagation_direction": "counterprop"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"power": 0.206,
|
|
||||||
"frequency": 201000000000000,
|
|
||||||
"propagation_direction": "counterprop"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"location": {
|
|
||||||
"latitude": 1,
|
|
||||||
"longitude": 0,
|
|
||||||
"city": null,
|
|
||||||
"region": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"raman_parameters": {
|
"raman_params": {
|
||||||
"flag_raman": true,
|
"flag": true,
|
||||||
"space_resolution": 10e3,
|
"result_spatial_resolution": 10e3,
|
||||||
"tolerance": 1e-8
|
"solver_spatial_resolution": 50
|
||||||
},
|
},
|
||||||
"nli_parameters": {
|
"nli_params": {
|
||||||
"nli_method_name": "ggn_spectrally_separated",
|
"method": "ggn_spectrally_separated",
|
||||||
"wdm_grid_size": 50e9,
|
|
||||||
"dispersion_tolerance": 1,
|
"dispersion_tolerance": 1,
|
||||||
"phase_shift_tolerance": 0.1,
|
"phase_shift_tolerance": 0.1,
|
||||||
"computed_channels": [1, 18, 37, 56, 75]
|
"computed_channels": [1, 18, 37, 56, 75]
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -64,8 +64,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -104,8 +104,8 @@
|
|||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
@@ -129,8 +129,8 @@
|
|||||||
"trx_mode": "mode 2",
|
"trx_mode": "mode 2",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
@@ -154,8 +154,8 @@
|
|||||||
"trx_mode": "mode 2",
|
"trx_mode": "mode 2",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
@@ -179,8 +179,8 @@
|
|||||||
"trx_mode": "mode 2",
|
"trx_mode": "mode 2",
|
||||||
"effective-freq-slot": [
|
"effective-freq-slot": [
|
||||||
{
|
{
|
||||||
"N": "null",
|
"N": null,
|
||||||
"M": "null"
|
"M": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
|
|||||||
@@ -12,12 +12,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager_16QAM",
|
"trx_type": "Voyager_16QAM",
|
||||||
"trx_mode": "16QAM",
|
"trx_mode": "16QAM",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -37,12 +31,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": "PS_SP64_1",
|
"trx_mode": "PS_SP64_1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -62,12 +50,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": "PS_SP64_1",
|
"trx_mode": "PS_SP64_1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -87,12 +69,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": "PS_SP64_1",
|
"trx_mode": "PS_SP64_1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -133,12 +109,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": "mode 2 - fake",
|
"trx_mode": "mode 2 - fake",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
"max-nb-of-channel": 63,
|
"max-nb-of-channel": 63,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -158,12 +128,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": "mode 2",
|
"trx_mode": "mode 2",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
"max-nb-of-channel": 63,
|
"max-nb-of-channel": 63,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -183,12 +147,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": "PS_SP64_1",
|
"trx_mode": "PS_SP64_1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -221,12 +179,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": "mode 3",
|
"trx_mode": "mode 3",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 62500000000.0,
|
"spacing": 62500000000.0,
|
||||||
"max-nb-of-channel": 76,
|
"max-nb-of-channel": 76,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -259,12 +211,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": "PS_SP64_1",
|
"trx_mode": "PS_SP64_1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -284,12 +230,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": "PS_SP64_1",
|
"trx_mode": "PS_SP64_1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -330,12 +270,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager_16QAM",
|
"trx_type": "Voyager_16QAM",
|
||||||
"trx_mode": "16QAM",
|
"trx_mode": "16QAM",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": null,
|
"output-power": null,
|
||||||
@@ -355,12 +289,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": "mode 1",
|
"trx_mode": "mode 1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": null,
|
"max-nb-of-channel": null,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -380,12 +308,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": "PS_SP64_1",
|
"trx_mode": "PS_SP64_1",
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": null,
|
"max-nb-of-channel": null,
|
||||||
"output-power": null,
|
"output-power": null,
|
||||||
@@ -405,12 +327,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "vendorA_trx-type1",
|
"trx_type": "vendorA_trx-type1",
|
||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": 80,
|
"max-nb-of-channel": 80,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -451,12 +367,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": null,
|
"max-nb-of-channel": null,
|
||||||
"output-power": 0.001,
|
"output-power": 0.001,
|
||||||
@@ -476,12 +386,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
"max-nb-of-channel": 63,
|
"max-nb-of-channel": 63,
|
||||||
"output-power": null,
|
"output-power": null,
|
||||||
@@ -501,12 +405,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 50000000000.0,
|
"spacing": 50000000000.0,
|
||||||
"max-nb-of-channel": null,
|
"max-nb-of-channel": null,
|
||||||
"output-power": null,
|
"output-power": null,
|
||||||
@@ -526,12 +424,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 75000000000.0,
|
"spacing": 75000000000.0,
|
||||||
"max-nb-of-channel": null,
|
"max-nb-of-channel": null,
|
||||||
"output-power": null,
|
"output-power": null,
|
||||||
@@ -551,12 +443,6 @@
|
|||||||
"technology": "flexi-grid",
|
"technology": "flexi-grid",
|
||||||
"trx_type": "Voyager",
|
"trx_type": "Voyager",
|
||||||
"trx_mode": null,
|
"trx_mode": null,
|
||||||
"effective-freq-slot": [
|
|
||||||
{
|
|
||||||
"n": "null",
|
|
||||||
"m": "null"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"spacing": 30000000000.0,
|
"spacing": 30000000000.0,
|
||||||
"max-nb-of-channel": null,
|
"max-nb-of-channel": null,
|
||||||
"output-power": null,
|
"output-power": null,
|
||||||
|
|||||||
97
tests/data/test_fiber_fix_expected_results.csv
Normal file
97
tests/data/test_fiber_fix_expected_results.csv
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
signal,nli
|
||||||
|
1.9952623149688793e-05,1.1158426495504604e-08
|
||||||
|
1.9952623149688793e-05,1.263949624403159e-08
|
||||||
|
1.9952623149688793e-05,1.3358478621325285e-08
|
||||||
|
1.9952623149688793e-05,1.3830775406251184e-08
|
||||||
|
1.9952623149688793e-05,1.4180462471172083e-08
|
||||||
|
1.9952623149688793e-05,1.4456701012984246e-08
|
||||||
|
1.9952623149688793e-05,1.4683973899785875e-08
|
||||||
|
1.9952623149688793e-05,1.487624147046227e-08
|
||||||
|
1.9952623149688793e-05,1.5042217041806274e-08
|
||||||
|
1.9952623149688793e-05,1.5187703614492153e-08
|
||||||
|
1.9952623149688793e-05,1.5316759790785317e-08
|
||||||
|
1.9952623149688793e-05,1.543233485150211e-08
|
||||||
|
1.9952623149688793e-05,1.553663885878994e-08
|
||||||
|
1.9952623149688793e-05,1.5631370249579246e-08
|
||||||
|
1.9952623149688793e-05,1.5717862065800704e-08
|
||||||
|
1.9952623149688793e-05,1.57971793985894e-08
|
||||||
|
1.9952623149688793e-05,1.5870186356579704e-08
|
||||||
|
1.9952623149688793e-05,1.593759332223716e-08
|
||||||
|
1.9952623149688793e-05,1.5999991070923486e-08
|
||||||
|
1.9952623149688793e-05,1.6057875903450682e-08
|
||||||
|
1.9952623149688793e-05,1.6111668489205982e-08
|
||||||
|
1.9952623149688793e-05,1.6161728217386366e-08
|
||||||
|
1.9952623149688793e-05,1.6208364281630228e-08
|
||||||
|
1.9952623149688793e-05,1.6251844350226973e-08
|
||||||
|
1.9952623149688793e-05,1.629240142540359e-08
|
||||||
|
1.9952623149688793e-05,1.6330239326114482e-08
|
||||||
|
1.9952623149688793e-05,1.6365537111728e-08
|
||||||
|
1.9952623149688793e-05,1.6398452681655655e-08
|
||||||
|
1.9952623149688793e-05,1.642912572715412e-08
|
||||||
|
1.9952623149688793e-05,1.6457680168940455e-08
|
||||||
|
1.9952623149688793e-05,1.6484226183026747e-08
|
||||||
|
1.9952623149688793e-05,1.6508861894003893e-08
|
||||||
|
1.9952623149688793e-05,1.6531674797617433e-08
|
||||||
|
1.9952623149688793e-05,1.655274296130114e-08
|
||||||
|
1.9952623149688793e-05,1.657213604125123e-08
|
||||||
|
1.9952623149688793e-05,1.6589916146838222e-08
|
||||||
|
1.9952623149688793e-05,1.660613857708963e-08
|
||||||
|
1.9952623149688793e-05,1.6620852449214096e-08
|
||||||
|
1.9952623149688793e-05,1.6634101235366932e-08
|
||||||
|
1.9952623149688793e-05,1.664592322084737e-08
|
||||||
|
1.9952623149688793e-05,1.6656351894496074e-08
|
||||||
|
1.9952623149688793e-05,1.666541628009631e-08
|
||||||
|
1.9952623149688793e-05,1.6673141215973025e-08
|
||||||
|
1.9952623149688793e-05,1.6679547588653583e-08
|
||||||
|
1.9952623149688793e-05,1.6684652525341145e-08
|
||||||
|
1.9952623149688793e-05,1.668846954900963e-08
|
||||||
|
1.9952623149688793e-05,1.66910086991187e-08
|
||||||
|
1.9952623149688793e-05,1.6692276620238304e-08
|
||||||
|
1.9952623149688793e-05,1.6692276620238304e-08
|
||||||
|
1.9952623149688793e-05,1.6691008699118703e-08
|
||||||
|
1.9952623149688793e-05,1.6688469549009633e-08
|
||||||
|
1.9952623149688793e-05,1.6684652525341148e-08
|
||||||
|
1.9952623149688793e-05,1.6679547588653586e-08
|
||||||
|
1.9952623149688793e-05,1.6673141215973028e-08
|
||||||
|
1.9952623149688793e-05,1.666541628009631e-08
|
||||||
|
1.9952623149688793e-05,1.6656351894496084e-08
|
||||||
|
1.9952623149688793e-05,1.6645923220847374e-08
|
||||||
|
1.9952623149688793e-05,1.6634101235366935e-08
|
||||||
|
1.9952623149688793e-05,1.66208524492141e-08
|
||||||
|
1.9952623149688793e-05,1.6606138577089633e-08
|
||||||
|
1.9952623149688793e-05,1.6589916146838225e-08
|
||||||
|
1.9952623149688793e-05,1.6572136041251237e-08
|
||||||
|
1.9952623149688793e-05,1.6552742961301146e-08
|
||||||
|
1.9952623149688793e-05,1.653167479761744e-08
|
||||||
|
1.9952623149688793e-05,1.6508861894003893e-08
|
||||||
|
1.9952623149688793e-05,1.648422618302675e-08
|
||||||
|
1.9952623149688793e-05,1.645768016894046e-08
|
||||||
|
1.9952623149688793e-05,1.6429125727154126e-08
|
||||||
|
1.9952623149688793e-05,1.6398452681655658e-08
|
||||||
|
1.9952623149688793e-05,1.6365537111728004e-08
|
||||||
|
1.9952623149688793e-05,1.6330239326114482e-08
|
||||||
|
1.9952623149688793e-05,1.6292401425403594e-08
|
||||||
|
1.9952623149688793e-05,1.6251844350226973e-08
|
||||||
|
1.9952623149688793e-05,1.6208364281630228e-08
|
||||||
|
1.9952623149688793e-05,1.616172821738637e-08
|
||||||
|
1.9952623149688793e-05,1.6111668489205982e-08
|
||||||
|
1.9952623149688793e-05,1.605787590345069e-08
|
||||||
|
1.9952623149688793e-05,1.5999991070923493e-08
|
||||||
|
1.9952623149688793e-05,1.5937593322237167e-08
|
||||||
|
1.9952623149688793e-05,1.5870186356579704e-08
|
||||||
|
1.9952623149688793e-05,1.5797179398589402e-08
|
||||||
|
1.9952623149688793e-05,1.571786206580071e-08
|
||||||
|
1.9952623149688793e-05,1.5631370249579252e-08
|
||||||
|
1.9952623149688793e-05,1.5536638858789946e-08
|
||||||
|
1.9952623149688793e-05,1.5432334851502114e-08
|
||||||
|
1.9952623149688793e-05,1.531675979078532e-08
|
||||||
|
1.9952623149688793e-05,1.5187703614492156e-08
|
||||||
|
1.9952623149688793e-05,1.5042217041806274e-08
|
||||||
|
1.9952623149688793e-05,1.4876241470462273e-08
|
||||||
|
1.9952623149688793e-05,1.4683973899785879e-08
|
||||||
|
1.9952623149688793e-05,1.4456701012984246e-08
|
||||||
|
1.9952623149688793e-05,1.4180462471172086e-08
|
||||||
|
1.9952623149688793e-05,1.3830775406251184e-08
|
||||||
|
1.9952623149688793e-05,1.3358478621325285e-08
|
||||||
|
1.9952623149688793e-05,1.2639496244031593e-08
|
||||||
|
1.9952623149688793e-05,1.1158426495504613e-08
|
||||||
|
6
tests/data/test_fiber_flex_expected_results.csv
Normal file
6
tests/data/test_fiber_flex_expected_results.csv
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
signal,nli
|
||||||
|
1.9952623149688793e-05,5.522326183599433e-09
|
||||||
|
1.7957360834719913e-05,4.5606601423111315e-09
|
||||||
|
2.593841009459543e-05,6.633717697038881e-09
|
||||||
|
1.5962098519751036e-05,4.3237017878447286e-09
|
||||||
|
2.3943147779626553e-05,8.311382502260195e-09
|
||||||
|
96
tests/data/test_lumped_losses_fiber_no_pumps.csv
Normal file
96
tests/data/test_lumped_losses_fiber_no_pumps.csv
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
1.000000000000000021e-03,5.915557166626927424e-04,3.840877221245049653e-04,2.466727384040633977e-04,1.573474629975438242e-04,9.994300566924636483e-05,6.331217828438720550e-05,4.004003600460594289e-05,2.529553013238426405e-05
|
||||||
|
1.000000000000000021e-03,5.910087140881509866e-04,3.835259923737136521e-04,2.462279833344210639e-04,1.570298910751132091e-04,9.972770370845923681e-05,6.317035443958771254e-05,3.994817502675088248e-05,2.523663218966317481e-05
|
||||||
|
1.000000000000000021e-03,5.904624672772724710e-04,3.829653846278134621e-04,2.457842903404500092e-04,1.567131560243821098e-04,9.951300275831494635e-05,6.302894048828063141e-05,3.985658526347281646e-05,2.517791045472703461e-05
|
||||||
|
1.000000000000000021e-03,5.899169734839467818e-04,3.824058950962419133e-04,2.453416557234028707e-04,1.563972548287988369e-04,9.929890059644241613e-05,6.288793488850426760e-05,3.976526568300959219e-05,2.511936425240675192e-05
|
||||||
|
1.000000000000000021e-03,5.893722299298780965e-04,3.818475199355363483e-04,2.449000757332959262e-04,1.560821844312877747e-04,9.908539497140619857e-05,6.274733607851797545e-05,3.967421524053715842e-05,2.506099289905929403e-05
|
||||||
|
1.000000000000000021e-03,5.888282338048204554e-04,3.812902552499899305e-04,2.444595465697163919e-04,1.557679417349789946e-04,9.887248360327203632e-05,6.260714247720703990e-05,3.958343287844485109e-05,2.500279570274922987e-05
|
||||||
|
1.000000000000000021e-03,5.882849822668304897e-04,3.807340970923119234e-04,2.440200643826254091e-04,1.554545236039297650e-04,9.866016418416755746e-05,6.246735248448248958e-05,3.949291752660743311e-05,2.494477196342878550e-05
|
||||||
|
1.000000000000000021e-03,5.877403241312353140e-04,3.801768826891299322e-04,2.435799392795756472e-04,1.551407333476893054e-04,9.844762961169771281e-05,6.232743618144160702e-05,3.940232665622856909e-05,2.488670234861411131e-05
|
||||||
|
1.000000000000000021e-03,5.871942634186000593e-04,3.796186190022559433e-04,2.431391779090945110e-04,1.548265761463755335e-04,9.823488356157069126e-05,6.218739605181586088e-05,3.931166190013138108e-05,2.482858791458364441e-05
|
||||||
|
1.000000000000000021e-03,5.866468041173980141e-04,3.790593129257516128e-04,2.426977868451053722e-04,1.545120571165502460e-04,9.802192966180839372e-05,6.204723454596646772e-05,3.922092486871354988e-05,2.477042970290643410e-05
|
||||||
|
1.000000000000000021e-03,5.860979501842715923e-04,3.784989712866057847e-04,2.422557725877665796e-04,1.541971813119806349e-04,9.780877149334107738e-05,6.190695408131255699e-05,3.913011715023943305e-05,2.471222874063606835e-05
|
||||||
|
1.000000000000000021e-03,5.855428054911818777e-04,3.779325362214322600e-04,2.418091152720060536e-04,1.538790714407033914e-04,9.759345536126727376e-05,6.176526646718061210e-05,3.903840385562048950e-05,2.465344951928800295e-05
|
||||||
|
1.000000000000000021e-03,5.849813875456967485e-04,3.773600382625630725e-04,2.413578451141304101e-04,1.535577517356502032e-04,9.737599881379701964e-05,6.162218372343696363e-05,3.894579295722817337e-05,2.459409722576532997e-05
|
||||||
|
1.000000000000000021e-03,5.844137140093277807e-04,3.767815081401627831e-04,2.409019924922280132e-04,1.532332465435331354e-04,9.715641947446165209e-05,6.147771791853056712e-05,3.885229245840823961e-05,2.453417706661341544e-05
|
||||||
|
1.000000000000000021e-03,5.838398026969793654e-04,3.761969767804803125e-04,2.404415879440078890e-04,1.529055803229076760e-04,9.693473504062415536e-05,6.133188116843621776e-05,3.875791039276530608e-05,2.447369426754818325e-05
|
||||||
|
1.000000000000000021e-03,5.832596715764015120e-04,3.756064753041117783e-04,2.399766621646476654e-04,1.525747776422469490e-04,9.671096328199675835e-05,6.118468563560254894e-05,3.866265482344967213e-05,2.441265407298631344e-05
|
||||||
|
1.000000000000000021e-03,5.826733387676383139e-04,3.750100350242446291e-04,2.395072460046293692e-04,1.522408631780071723e-04,9.648512203915507620e-05,6.103614352789890607e-05,3.856653384244465896e-05,2.435106174557538284e-05
|
||||||
|
1.000000000000000021e-03,5.820810441807425326e-04,3.744079089136845458e-04,2.390335428197917333e-04,1.519039834472631588e-04,9.625731118926498641e-05,6.088632085792882825e-05,3.846959029618343478e-05,2.428894479270876788e-05
|
||||||
|
1.000000000000000021e-03,5.814828054675655030e-04,3.738001274474016776e-04,2.385555825972570808e-04,1.515641624143126585e-04,9.602754804766522702e-05,6.073522946956701240e-05,3.837183203343020677e-05,2.422630831805138899e-05
|
||||||
|
1.000000000000000021e-03,5.808786404289665358e-04,3.731867212872194738e-04,2.380733954737781241e-04,1.512214241469207320e-04,9.579584999731260704e-05,6.058288124990010364e-05,3.827326693032387752e-05,2.416315744255338838e-05
|
||||||
|
1.000000000000000021e-03,5.802685670142343878e-04,3.725677212800349654e-04,2.375870117335689917e-04,1.508757928143868079e-04,9.556223448729982074e-05,6.042928812817623899e-05,3.817390288966712009e-05,2.409949730398197492e-05
|
||||||
|
1.000000000000000021e-03,5.796526968519212725e-04,3.719432545624587992e-04,2.370965379259533010e-04,1.505273470495264228e-04,9.532675589286383365e-05,6.027448635812982831e-05,3.807376356963088358e-05,2.403534314190221437e-05
|
||||||
|
1.000000000000000021e-03,5.790310479093865609e-04,3.713133518665244839e-04,2.366020041460938778e-04,1.501761108339581341e-04,9.508943151110322721e-05,6.011848775803337427e-05,3.797285679655886708e-05,2.397070004317041725e-05
|
||||||
|
1.000000000000000021e-03,5.784036383121742876e-04,3.706780441238009577e-04,2.361034406501071276e-04,1.498221082613785163e-04,9.485027871279472060e-05,5.996130419345521918e-05,3.787119042685209972e-05,2.390557311366359151e-05
|
||||||
|
1.000000000000000021e-03,5.777704863433433301e-04,3.700373624633735868e-04,2.356008778526011383e-04,1.494653635353745394e-04,9.460931494071504256e-05,5.980294757607067669e-05,3.776877234616485572e-05,2.383996747774973522e-05
|
||||||
|
1.000000000000000021e-03,5.771316104427772061e-04,3.693913382097967039e-04,2.350943463241932639e-04,1.491059009672212558e-04,9.436655770795449559e-05,5.964342986246977532e-05,3.766561046859827219e-05,2.377388827775711285e-05
|
||||||
|
1.000000000000000021e-03,5.764870292064976651e-04,3.687400028810397501e-04,2.345838767890191692e-04,1.487437449736715462e-04,9.412202459622686095e-05,5.948276305296108525e-05,3.756171273589169023e-05,2.370734067344167480e-05
|
||||||
|
1.000000000000000021e-03,5.758375946234993610e-04,3.680842155919215072e-04,2.340701414876563216e-04,1.483793719498717782e-04,9.387603703510192111e-05,5.932115823520561543e-05,3.745721560837426419e-05,2.364041205155829344e-05
|
||||||
|
1.000000000000000021e-03,5.751833223951592329e-04,3.674240032104748388e-04,2.335531666416808738e-04,1.480128027327277474e-04,9.362861002461524574e-05,5.915862564500113025e-05,3.735212585887714390e-05,2.357310681190604310e-05
|
||||||
|
1.000000000000000021e-03,5.745242283439769499e-04,3.667593927483133397e-04,2.330329785818580578e-04,1.476440582313571256e-04,9.337975861033522300e-05,5.899517554647101613e-05,3.724645027783519551e-05,2.350542936525477225e-05
|
||||||
|
1.000000000000000021e-03,5.738603284130473379e-04,3.660904113590355527e-04,2.325096037462197861e-04,1.472731594253864234e-04,9.312949788206356194e-05,5.883081823114703288e-05,3.714019567266727830e-05,2.343738413293735195e-05
|
||||||
|
1.000000000000000021e-03,5.731917314000997948e-04,3.654171810067180655e-04,2.319831433530600859e-04,1.469001805571756218e-04,9.287787898176902846e-05,5.866558771451522606e-05,3.703338420706373603e-05,2.336898537810763873e-05
|
||||||
|
1.000000000000000021e-03,5.725184531760584700e-04,3.647397285916569422e-04,2.314536235223777264e-04,1.465251423190001693e-04,9.262491677678542706e-05,5.849949412959568328e-05,3.692602258076439168e-05,2.330023745100291859e-05
|
||||||
|
1.000000000000000021e-03,5.718405097346714646e-04,3.640580811583470273e-04,2.309210704829702432e-04,1.461480654746279682e-04,9.237062617930094123e-05,5.833254763720848617e-05,3.681811751074023914e-05,2.323114471257928647e-05
|
||||||
|
1.000000000000000021e-03,5.711579171919053044e-04,3.633722658937428313e-04,2.303855105703487465e-04,1.457689708574830614e-04,9.211502214495855044e-05,5.816475842498649012e-05,3.670967573052717390e-05,2.316171153407365905e-05
|
||||||
|
1.000000000000000021e-03,5.704706917853448337e-04,3.626823101255147543e-04,2.298469702246577707e-04,1.453878793688169360e-04,9.185811967146480901e-05,5.799613670639434487e-05,3.660070398956385041e-05,2.309194229656875218e-05
|
||||||
|
1.000000000000000021e-03,5.697788498735841109e-04,3.619882413202942504e-04,2.293054759885765847e-04,1.450048119758659754e-04,9.159993379718755254e-05,5.782669271974067121e-05,3.649120905252569737e-05,2.302184139055488024e-05
|
||||||
|
1.000000000000000021e-03,5.690839249361781711e-04,3.612915831986411477e-04,2.287622092282637863e-04,1.446206010588695675e-04,9.134102410651873409e-05,5.765679311500335815e-05,3.638142760462866287e-05,2.295156024783083523e-05
|
||||||
|
1.000000000000000021e-03,5.683859273133331363e-04,3.605923537461036641e-04,2.282171874164802170e-04,1.442352604283837097e-04,9.108140050118301682e-05,5.748644463023418617e-05,3.627136409615889481e-05,2.288110175599186700e-05
|
||||||
|
1.000000000000000021e-03,5.676848674169825831e-04,3.598905710243090802e-04,2.276704280772651710e-04,1.438488039249314222e-04,9.082107289971861372e-05,5.731565401294060850e-05,3.616102298282374168e-05,2.281046880581413228e-05
|
||||||
|
1.000000000000000021e-03,5.669807557304629327e-04,3.591862531699841626e-04,2.271219487847658911e-04,1.434612454179789358e-04,9.056005123670258442e-05,5.714442801953895405e-05,3.605040872538299508e-05,2.273966429101268041e-05
|
||||||
|
1.000000000000000021e-03,5.662756696284717943e-04,3.584815135619230891e-04,2.265734124911083147e-04,1.430737675597642188e-04,9.029913524493678829e-05,5.697329258726415482e-05,3.593986162522089478e-05,2.266890625682277028e-05
|
||||||
|
1.000000000000000021e-03,5.655696121370722921e-04,3.577763576655677066e-04,2.260248242651153531e-04,1.426863741861267136e-04,9.003832758694041048e-05,5.680224948786493348e-05,3.582938283523433764e-05,2.259819544408493697e-05
|
||||||
|
1.000000000000000021e-03,5.648625863181645518e-04,3.570707909872514684e-04,2.254761892066869196e-04,1.422990691538204475e-04,8.977763093872482745e-05,5.663130050166089515e-05,3.571897351373497692e-05,2.252753259705453904e-05
|
||||||
|
1.000000000000000021e-03,5.641545952693012783e-04,3.563648190736888295e-04,2.249275124461922067e-04,1.419118563399853763e-04,8.951704798938974166e-05,5.646044741725799208e-05,3.560863482425828067e-05,2.245691846327665519e-05
|
||||||
|
1.000000000000000021e-03,5.634456421235028989e-04,3.556584475114634488e-04,2.243787991438712611e-04,1.415247396416227112e-04,8.925658144072659398e-05,5.628969203126926030e-05,3.549836793537420297e-05,2.238635379346144160e-05
|
||||||
|
1.000000000000000021e-03,5.627357300490819225e-04,3.549516819265270164e-04,2.238300544892383743e-04,1.411377229750731741e-04,8.899623400682166435e-05,5.611903614803531905e-05,3.538817402049950172e-05,2.231583934136070575e-05
|
||||||
|
1.000000000000000021e-03,5.620265745740795878e-04,3.542462045793823072e-04,2.232825718355581747e-04,1.407517127660701999e-04,8.873661298955798349e-05,5.594887683102661642e-05,3.527830905094599801e-05,2.224553873809700179e-05
|
||||||
|
1.000000000000000021e-03,5.613181716914067464e-04,3.535420099674467737e-04,2.227363458317740963e-04,1.403667046661989041e-04,8.847771519474716161e-05,5.577921186868756777e-05,3.516877154903826080e-05,2.217545101761858074e-05
|
||||||
|
1.000000000000000021e-03,5.606105174362018646e-04,3.528390926567629869e-04,2.221913711948466166e-04,1.399826943822104249e-04,8.821953746856249804e-05,5.561003907731979445e-05,3.505956005567386572e-05,2.210557522599888898e-05
|
||||||
|
1.000000000000000021e-03,5.599036078855734169e-04,3.521374472813410678e-04,2.216476427089692435e-04,1.395996776753266513e-04,8.796207669700402236e-05,5.544135630070159596e-05,3.495067313006486022e-05,2.203591042126611129e-05
|
||||||
|
1.000000000000000021e-03,5.591992581819900257e-04,3.514388991464684675e-04,2.211065862108586844e-04,1.392186639199167455e-04,8.770601346645835294e-05,5.527361030479937100e-05,3.484239951455165907e-05,2.196664147854661471e-05
|
||||||
|
1.000000000000000021e-03,5.584974577369657654e-04,3.507434317312190116e-04,2.205681855748304113e-04,1.388396401724235928e-04,8.745133837595373525e-05,5.510679463338290224e-05,3.473473491875524963e-05,2.189776560286087024e-05
|
||||||
|
1.000000000000000021e-03,5.577981960279812567e-04,3.500510286412654524e-04,2.200324248112712805e-04,1.384625936044855835e-04,8.719804211084999142e-05,5.494090289064881491e-05,3.462767509292537455e-05,2.182928002589032757e-05
|
||||||
|
1.000000000000000021e-03,5.571014625980537805e-04,3.493616736077873519e-04,2.194992880653100025e-04,1.380875115017372141e-04,8.694611544190507637e-05,5.477592874055209164e-05,3.452121582748434684e-05,2.176118200567564087e-05
|
||||||
|
1.000000000000000021e-03,5.564072470552914543e-04,3.486753504863699662e-04,2.189687596154907018e-04,1.377143812626113696e-04,8.669554922434540153e-05,5.461186590614181566e-05,3.441535295257522900e-05,2.169346882631773742e-05
|
||||||
|
1.000000000000000021e-03,5.557155390724777657e-04,3.479920432559456848e-04,2.184408238724854000e-04,1.373431903971786034e-04,8.644633439696230146e-05,5.444870816891464747e-05,3.431008233762035268e-05,2.162613779768559453e-05
|
||||||
|
1.000000000000000021e-03,5.550282308874212147e-04,3.473135853761227104e-04,2.179168797741835634e-04,1.369749146289257855e-04,8.619912270820690987e-05,5.428688083545962664e-05,3.420567782931384528e-05,2.155936384410790980e-05
|
||||||
|
1.000000000000000021e-03,5.543453044039096641e-04,3.466399489498413807e-04,2.173969005859271932e-04,1.366095327799803094e-04,8.595389890905566596e-05,5.412637349122350694e-05,3.410213253115887156e-05,2.149314248283782383e-05
|
||||||
|
1.000000000000000021e-03,5.536667416543260278e-04,3.459711063207645686e-04,2.168808598269340415e-04,1.362470238846985658e-04,8.571064790824490891e-05,5.396717583150281386e-05,3.399943962027434491e-05,2.142746927933548718e-05
|
||||||
|
1.000000000000000021e-03,5.529925247987736454e-04,3.453070300711248903e-04,2.163687312677279435e-04,1.358873671873677324e-04,8.546935477049620155e-05,5.380927766017944798e-05,3.389759234653519571e-05,2.136233984669994517e-05
|
||||||
|
1.000000000000000021e-03,5.523242123557685823e-04,3.446492679875326503e-04,2.158617145497228296e-04,1.355314077800207832e-04,8.523058755788532964e-05,5.365305115434923267e-05,3.379683095199963850e-05,2.129790788796336886e-05
|
||||||
|
1.000000000000000021e-03,5.516617811459008413e-04,3.439977838203789025e-04,2.153597748770509342e-04,1.351791181086447731e-04,8.499432644189092710e-05,5.349848277838686991e-05,3.369714647650299112e-05,2.123416758034315385e-05
|
||||||
|
1.000000000000000021e-03,5.510052081904127453e-04,3.433525416882428740e-04,2.148628778379304833e-04,1.348304709382760146e-04,8.476055183025699440e-05,5.334555916079864168e-05,3.359853006971443923e-05,2.117111317291617240e-05
|
||||||
|
1.000000000000000021e-03,5.503544707098636342e-04,3.427135060745518090e-04,2.143709894006651793e-04,1.344854393494213974e-04,8.452924436422564868e-05,5.319426709225049006e-05,3.350097298979682009e-05,2.110873898573355285e-05
|
||||||
|
1.000000000000000021e-03,5.497095461228062706e-04,3.420806418242862412e-04,2.138840759097000895e-04,1.341439967345312348e-04,8.430038491581448882e-05,5.304459352362807473e-05,3.340446660208796169e-05,2.104703940894962140e-05
|
||||||
|
1.000000000000000021e-03,5.490704120444732210e-04,3.414539141407250565e-04,2.134021040817290626e-04,1.338061167945246396e-04,8.407395458513211085e-05,5.289652556412503305e-05,3.330900237780223545e-05,2.098600890196449472e-05
|
||||||
|
1.000000000000000021e-03,5.484371298422446297e-04,3.408333692467681113e-04,2.129251024270059081e-04,1.334718163299163942e-04,8.384996326436759272e-05,5.275006911363530105e-05,3.321458388816914869e-05,2.092564965374723430e-05
|
||||||
|
1.000000000000000021e-03,5.478096771889333057e-04,3.402189725469309967e-04,2.124530379214265854e-04,1.331410692793207290e-04,8.362839223924152716e-05,5.260521141428185532e-05,3.312120269498457291e-05,2.086595618361951373e-05
|
||||||
|
1.000000000000000021e-03,5.471880319478338028e-04,3.396106897916775086e-04,2.119858778995733334e-04,1.328138498781884043e-04,8.340922301478033581e-05,5.246193986031627375e-05,3.302885046175365648e-05,2.080692307740899109e-05
|
||||||
|
1.000000000000000021e-03,5.465721721714859958e-04,3.390084870743713592e-04,2.115235900510876890e-04,1.324901326555763298e-04,8.319243731282516567e-05,5.232024199634728476e-05,3.293751895248773966e-05,2.074854498665493433e-05
|
||||||
|
1.000000000000000021e-03,5.459629241404544706e-04,3.384131725428774743e-04,2.110667946787101129e-04,1.321703518944146796e-04,8.297832591380873519e-05,5.218030786215170435e-05,3.284733064718059383e-05,2.069090019482566404e-05
|
||||||
|
1.000000000000000021e-03,5.453602635114507746e-04,3.378247083723790616e-04,2.106154557101209946e-04,1.318544791589579420e-04,8.276686841524559784e-05,5.204212355675735553e-05,3.275827635494999894e-05,2.063398273378693265e-05
|
||||||
|
1.000000000000000021e-03,5.447641661727002649e-04,3.372430571518834691e-04,2.101695374983407439e-04,1.315424863636820575e-04,8.255804467261116894e-05,5.190567535780167048e-05,3.267034700418964161e-05,2.057778671334094953e-05
|
||||||
|
1.000000000000000021e-03,5.441746082424759419e-04,3.366681818805845774e-04,2.097290048174083239e-04,1.312343457694375884e-04,8.235183479637930588e-05,5.177094971942625129e-05,3.258353364113958107e-05,2.052230632028256941e-05
|
||||||
|
1.000000000000000021e-03,5.435915660676414983e-04,3.361000459642789163e-04,2.092938228581225045e-04,1.309300299796617602e-04,8.214821914910500468e-05,5.163793327020207291e-05,3.249782742847867687e-05,2.046753581747058517e-05
|
||||||
|
1.000000000000000021e-03,5.430150162222109568e-04,3.355386132118161487e-04,2.088639572238308215e-04,1.306295119366350911e-04,8.194717834254394587e-05,5.150661281108238069e-05,3.241321964393507540e-05,2.041346954291065543e-05
|
||||||
|
1.000000000000000021e-03,5.424450181544462771e-04,3.349839271155603902e-04,2.084394340599780252e-04,1.303328067075743425e-04,8.174872108664715700e-05,5.137699346328779477e-05,3.232971335519106785e-05,2.036010936323692981e-05
|
||||||
|
1.000000000000000021e-03,5.418815485793469040e-04,3.344359518126675877e-04,2.080202193468776877e-04,1.300398875631312602e-04,8.155282824274543232e-05,5.124906220377890154e-05,3.224729995882103797e-05,2.030744969463951815e-05
|
||||||
|
1.000000000000000021e-03,5.413245844265015877e-04,3.338946518213946552e-04,2.076062794549138172e-04,1.297507280942760690e-04,8.135948090770286575e-05,5.112280617242197348e-05,3.216597096011364272e-05,2.025548502431296445e-05
|
||||||
|
1.000000000000000021e-03,5.407741028387587183e-04,3.333599920378552692e-04,2.071975811406991498e-04,1.294653022088876294e-04,8.116866041129419294e-05,5.099821267012491396e-05,3.208571797180734118e-05,2.020420990962221080e-05
|
||||||
|
1.000000000000000021e-03,5.402303025747014556e-04,3.328321561526745862e-04,2.067942601549091974e-04,1.291837026153304184e-04,8.098042783792958120e-05,5.087532120941394917e-05,3.200656629292941073e-05,2.015364045325785942e-05
|
||||||
|
1.000000000000000021e-03,5.396931605409548225e-04,3.323111087173311550e-04,2.063962829591101838e-04,1.289059030082810651e-04,8.079476437365657295e-05,5.075411899733799342e-05,3.192850747587867838e-05,2.010377117411100997e-05
|
||||||
|
1.000000000000000021e-03,5.391626538584482192e-04,3.317968146613820609e-04,2.060036164003212873e-04,1.286318773981824648e-04,8.061165143636152362e-05,5.063459340114707095e-05,3.185153317990099749e-05,2.005459666083220688e-05
|
||||||
|
1.000000000000000021e-03,5.386387598611086340e-04,3.312892392892789490e-04,2.056162277072543561e-04,1.283616001079104806e-04,8.043107067321031531e-05,5.051673194647494236e-05,3.177563516985718072e-05,2.000611157101859271e-05
|
||||||
|
1.000000000000000021e-03,5.381214560945620949e-04,3.307883482772016118e-04,2.052340844865845515e-04,1.280950457694747437e-04,8.025300395811590449e-05,5.040052231554306949e-05,3.170080531500530551e-05,1.995831063041139523e-05
|
||||||
|
1.000000000000000021e-03,5.376107203148404326e-04,3.302941076699326679e-04,2.048571547192701043e-04,1.278321893207613302e-04,8.007743338923888358e-05,5.028595234538581714e-05,3.162703558779804923e-05,1.991118863210237610e-05
|
||||||
|
1.000000000000000021e-03,5.371022748594453389e-04,3.298024246812891291e-04,2.044823390252625600e-04,1.275708788891961756e-04,7.990292563076895462e-05,5.017208832604374468e-05,3.155372544493714152e-05,1.986436223028797206e-05
|
||||||
|
1.000000000000000021e-03,5.365961117498912114e-04,3.293132869081722108e-04,2.041096254707852251e-04,1.273111050031557620e-04,7.972947385597059739e-05,5.005892559260894715e-05,3.148087179640124731e-05,1.981782941609088261e-05
|
||||||
|
1.000000000000000021e-03,5.360922230056120808e-04,3.288266819633119922e-04,2.037390021489647173e-04,1.270528582181514683e-04,7.955707126027152540e-05,4.994645949643470906e-05,3.140847156340457124e-05,1.977158818812822943e-05
|
||||||
|
1.000000000000000021e-03,5.355906006439992324e-04,3.283425974753378354e-04,2.033704571798752555e-04,1.267961291168465381e-04,7.938571106126265876e-05,4.983468540512894492e-05,3.133652167839010846e-05,1.972563655250571181e-05
|
||||||
|
1.000000000000000021e-03,5.350891259362026411e-04,3.278589502113704612e-04,2.030023855884717748e-04,1.265397912200834861e-04,7.921463777328526478e-05,4.972310904903239575e-05,3.126470337114675132e-05,1.967977067875568528e-05
|
||||||
|
1.000000000000000021e-03,5.345877966909636306e-04,3.273757374134148111e-04,2.026347848040474173e-04,1.262838424862170036e-04,7.904384991646645146e-05,4.961172941171763403e-05,3.119301596587686584e-05,1.963399012641590455e-05
|
||||||
|
1.000000000000000021e-03,5.340866106918126799e-04,3.268929562877650259e-04,2.022676522245876859e-04,1.260282808504260116e-04,7.887334599501782170e-05,4.950054546622813158e-05,3.112145877995456692e-05,1.958829445064508602e-05
|
||||||
|
1.000000000000000021e-03,5.335855656972701092e-04,3.264106040054970534e-04,2.019009852173301103e-04,1.257731042251948573e-04,7.870312449759831505e-05,4.938955617533215942e-05,3.105003112409614148e-05,1.954268320233478379e-05
|
||||||
|
1.000000000000000021e-03,5.330846594410641130e-04,3.259286777029715004e-04,2.015347811193284109e-04,1.255183105007985753e-04,7.853318389767883849e-05,4.927876049177821896e-05,3.097873230253197569e-05,1.949715592822227211e-05
|
||||||
|
96
tests/data/test_lumped_losses_fiber_no_raman.csv
Normal file
96
tests/data/test_lumped_losses_fiber_no_raman.csv
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
1.000000000000000021e-03,6.456542290346556703e-04,2.238721138568339957e-05
|
||||||
|
98
tests/data/test_lumped_losses_raman_fiber.csv
Normal file
98
tests/data/test_lumped_losses_raman_fiber.csv
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
1.000000000000000021e-03,6.059428294303585358e-04,4.124436878765448634e-04,2.874462507798667202e-04,2.103923932407651741e-04,1.678414792051835720e-04,1.547359756068614396e-04,1.816771264024174659e-04,3.223716208702616772e-04
|
||||||
|
1.000000000000000021e-03,6.053134417926274479e-04,4.117055522849718272e-04,2.867345754340725936e-04,2.097129658661858059e-04,1.671408382188599656e-04,1.538980727463440737e-04,1.804148897825019347e-04,3.196786917797407482e-04
|
||||||
|
1.000000000000000021e-03,6.046849734433535663e-04,4.109690875237402238e-04,2.860250085842350751e-04,2.090360511584246736e-04,1.664434237997556567e-04,1.530650313352837862e-04,1.791618737991747007e-04,3.170092948646618079e-04
|
||||||
|
1.000000000000000021e-03,6.040574211994215528e-04,4.102342878398261821e-04,2.853175420730359193e-04,2.083616379079277403e-04,1.657492189637676920e-04,1.522368203677859210e-04,1.779180061767344980e-04,3.143632101370558260e-04
|
||||||
|
1.000000000000000021e-03,6.034068048547004811e-04,4.094522032835132145e-04,2.845379038962591819e-04,2.075849237814657072e-04,1.649065028354379026e-04,1.511673145690444625e-04,1.761800891032866087e-04,3.101696013411107001e-04
|
||||||
|
1.000000000000000021e-03,6.027571485450614400e-04,4.086719523190792173e-04,2.837607352174946669e-04,2.068114158243908936e-04,1.640683639230874002e-04,1.501056331894667201e-04,1.744595725998800725e-04,3.060328853710948794e-04
|
||||||
|
1.000000000000000021e-03,6.021084488423111532e-04,4.078935283235860985e-04,2.829860258399657913e-04,2.060410983394430761e-04,1.632347745793864737e-04,1.490517152618393740e-04,1.727562758069566841e-04,3.019522704750103072e-04
|
||||||
|
1.000000000000000021e-03,6.014584946769776846e-04,4.071145901524401327e-04,2.822117789926256531e-04,2.052723360542508288e-04,1.624043320606193702e-04,1.480041851535097400e-04,1.710684425093964716e-04,2.979241342510260699e-04
|
||||||
|
1.000000000000000021e-03,6.008072907871274187e-04,4.063351463691671850e-04,2.814380028310788616e-04,2.045051334722086352e-04,1.615770319309204608e-04,1.469630126571907884e-04,1.693959447695294284e-04,2.939478272988644745e-04
|
||||||
|
1.000000000000000021e-03,6.001497788207915121e-04,4.055445944921290597e-04,2.806482406689155018e-04,2.037157793952982566e-04,1.607178158735042268e-04,1.458699426620449350e-04,1.676159912510077627e-04,2.896237141368235984e-04
|
||||||
|
1.000000000000000021e-03,5.994910374944025042e-04,4.047535948218318100e-04,2.798590565363265966e-04,2.029281739019909579e-04,1.598620980598530251e-04,1.447840125437445142e-04,1.658536074234625343e-04,2.853613427461420497e-04
|
||||||
|
1.000000000000000021e-03,5.988260139740232213e-04,4.039566207302157830e-04,2.790656268334378021e-04,2.021383019157014865e-04,1.590064003284783227e-04,1.437018088215471850e-04,1.641044980680633682e-04,2.811520890672289147e-04
|
||||||
|
1.000000000000000021e-03,5.981547295973556680e-04,4.031537149116132062e-04,2.782680029999613086e-04,2.013462168991827844e-04,1.581507747250400562e-04,1.426233730149128554e-04,1.623686402996199669e-04,2.769954674673250896e-04
|
||||||
|
1.000000000000000021e-03,5.974772058480589884e-04,4.023449202032754039e-04,2.774662364916018848e-04,2.005519721420980883e-04,1.572952728586730247e-04,1.415487458023807841e-04,1.606460099014084351e-04,2.728909933446289080e-04
|
||||||
|
1.000000000000000021e-03,5.967924602151245417e-04,4.015280354275974962e-04,2.766567170422079059e-04,1.997501120648868605e-04,1.564314572956195643e-04,1.404632320601022135e-04,1.589039550526354799e-04,2.687258582080010155e-04
|
||||||
|
1.000000000000000021e-03,5.961015210291329552e-04,4.007053572943599577e-04,2.758431797434220318e-04,1.989462429758611403e-04,1.555679612182393453e-04,1.393818318435550562e-04,1.571757793000612348e-04,2.646152969711955188e-04
|
||||||
|
1.000000000000000021e-03,5.954044103428367566e-04,3.998769294251378363e-04,2.750256766566040972e-04,1.981404183299118591e-04,1.547048355449558708e-04,1.383045830163869136e-04,1.554614480121203164e-04,2.605587686095252363e-04
|
||||||
|
1.000000000000000021e-03,5.947013777400173224e-04,3.990430339362700481e-04,2.742044609070656662e-04,1.973328535702731791e-04,1.538422664307762401e-04,1.372316495983985922e-04,1.537610729441031576e-04,2.565559887984316962e-04
|
||||||
|
1.000000000000000021e-03,5.939924446448691022e-04,3.982037130272156897e-04,2.733795825341983144e-04,1.965235995659166514e-04,1.529803013963573505e-04,1.361630645638145173e-04,1.520746117923915490e-04,2.526064078268458078e-04
|
||||||
|
1.000000000000000021e-03,5.932708072008613994e-04,3.973448313523968048e-04,2.725292879585060313e-04,1.956816407574392804e-04,1.520737532268283138e-04,1.350253536692922732e-04,1.502520417395671493e-04,2.482429369311983419e-04
|
||||||
|
1.000000000000000021e-03,5.925433291275937313e-04,3.964806700993557770e-04,2.716755655440644093e-04,1.948383564731119815e-04,1.511684275731327428e-04,1.338932464840604031e-04,1.484467502756363724e-04,2.439468427807235304e-04
|
||||||
|
1.000000000000000021e-03,5.918101288584805405e-04,3.956113769664689763e-04,2.708185566039283476e-04,1.939938721213093850e-04,1.502644330979066827e-04,1.327668256867655240e-04,1.466587172007617287e-04,2.397173806066686273e-04
|
||||||
|
1.000000000000000021e-03,5.910712282476807177e-04,3.947369945531709078e-04,2.699583111402765676e-04,1.931482375169864133e-04,1.493618135415682949e-04,1.316461114156967569e-04,1.448878476419733323e-04,2.355536787532183434e-04
|
||||||
|
1.000000000000000021e-03,5.903266492974269808e-04,3.938575655934699066e-04,2.690948791496987824e-04,1.923015022699072797e-04,1.484606121781560119e-04,1.305311230155930472e-04,1.431340460611192763e-04,2.314548735305102924e-04
|
||||||
|
1.000000000000000021e-03,5.895916361077759233e-04,3.930015889157450278e-04,2.682679585446747167e-04,1.915046725018171748e-04,1.476265343831741983e-04,1.295122987364192039e-04,1.415403000102364922e-04,2.277048762028301403e-04
|
||||||
|
1.000000000000000021e-03,5.888509505821538188e-04,3.921405251235485093e-04,2.674377005486313469e-04,1.907064029438769275e-04,1.467931904457939435e-04,1.284977589807231727e-04,1.399600943498011466e-04,2.240084844157824847e-04
|
||||||
|
1.000000000000000021e-03,5.881046147353881284e-04,3.912744162777674595e-04,2.666041537474170709e-04,1.899067416692393098e-04,1.459606238177286390e-04,1.274875313353729649e-04,1.383933775516596422e-04,2.203650745808937968e-04
|
||||||
|
1.000000000000000021e-03,5.873535041835053691e-04,3.904041908037584924e-04,2.657681073335506784e-04,1.891063272435359547e-04,1.451293640595985746e-04,1.264820875947550167e-04,1.368405966876043531e-04,2.167748460671411873e-04
|
||||||
|
1.000000000000000021e-03,5.865976375297720377e-04,3.895298843642901903e-04,2.649296021207307814e-04,1.883051991594097421e-04,1.442994447916011967e-04,1.254814426573682665e-04,1.353016807452276011e-04,2.132371421364682767e-04
|
||||||
|
1.000000000000000021e-03,5.858370334908887412e-04,3.886515327161476187e-04,2.640886789067201177e-04,1.875033967487228748e-04,1.434708992929061271e-04,1.244856108614830043e-04,1.337765582492128895e-04,2.097513117892475961e-04
|
||||||
|
1.000000000000000021e-03,5.850717109173866415e-04,3.877691717638952012e-04,2.632453785571107932e-04,1.867009592919541521e-04,1.426437606415217971e-04,1.234946061839636009e-04,1.322651576281378186e-04,2.063167108712882474e-04
|
||||||
|
1.000000000000000021e-03,5.843017841779564719e-04,3.868829399849727933e-04,2.623998297381095117e-04,1.858979973489535589e-04,1.418181214209275826e-04,1.225084976697060233e-04,1.307674705482058720e-04,2.029328092689827875e-04
|
||||||
|
1.000000000000000021e-03,5.835272719783185817e-04,3.859928727352694559e-04,2.615520723807220407e-04,1.850945488934469029e-04,1.409940129261724197e-04,1.215272967897141737e-04,1.292834223062770812e-04,1.995989685833853672e-04
|
||||||
|
1.000000000000000021e-03,5.827481931390192209e-04,3.850990054645316799e-04,2.607021463995574332e-04,1.842906517410432266e-04,1.401714661235729505e-04,1.205510144929276286e-04,1.278129378421479238e-04,1.963145562589016025e-04
|
||||||
|
1.000000000000000021e-03,5.819741190680906414e-04,3.842186528659996786e-04,2.598733678747139103e-04,1.835150990942780922e-04,1.393856353878371876e-04,1.196241043053028848e-04,1.264157249384978508e-04,1.931533527071859933e-04
|
||||||
|
1.000000000000000021e-03,5.811954906857532679e-04,3.833344911530978875e-04,2.590423495637437460e-04,1.827389251971546448e-04,1.386010231640464696e-04,1.187014313463915350e-04,1.250305871218520724e-04,1.900379005692562904e-04
|
||||||
|
1.000000000000000021e-03,5.804123268686601621e-04,3.824465553881609072e-04,2.582091305240798466e-04,1.819621668943112273e-04,1.378176602140172575e-04,1.177830097537161525e-04,1.236574657124121280e-04,1.869676369318762604e-04
|
||||||
|
1.000000000000000021e-03,5.796261981805348861e-04,3.815564763513873891e-04,2.573750710547324729e-04,1.811859034357266680e-04,1.370364232713841633e-04,1.168696105278517803e-04,1.222971239749574140e-04,1.839432835829867073e-04
|
||||||
|
1.000000000000000021e-03,5.788371166298537929e-04,3.806642767897665215e-04,2.565401959245502722e-04,1.804101566728638260e-04,1.362573268495191094e-04,1.159612279572367423e-04,1.209494737333099285e-04,1.809642226433420603e-04
|
||||||
|
1.000000000000000021e-03,5.780450942923127944e-04,3.797699794962239458e-04,2.557045298790712744e-04,1.796349483543752492e-04,1.354803852765658562e-04,1.150578560981921263e-04,1.196144270262388971e-04,1.780298433107154344e-04
|
||||||
|
1.000000000000000021e-03,5.772501433097143196e-04,3.788736073065085246e-04,2.548680976361037374e-04,1.788603001211915217e-04,1.347056126906417029e-04,1.141594887707218423e-04,1.182918961012392148e-04,1.751395417672447184e-04
|
||||||
|
1.000000000000000021e-03,5.764543993312114430e-04,3.779774418763772749e-04,2.540328419678222955e-04,1.780877776040980329e-04,1.339342982068885400e-04,1.132672798320007770e-04,1.169830787460522149e-04,1.722947974180976999e-04
|
||||||
|
1.000000000000000021e-03,5.756578658699793754e-04,3.770814893242558957e-04,2.531987675065141240e-04,1.773173809352787060e-04,1.331664323570320042e-04,1.123811939733057949e-04,1.156878429947367658e-04,1.694949148917899182e-04
|
||||||
|
1.000000000000000021e-03,5.748605464740858808e-04,3.761857558021953151e-04,2.523658789003789082e-04,1.765491102506614579e-04,1.324020056947932127e-04,1.115011960644554309e-04,1.144060580710201219e-04,1.667392091004694466e-04
|
||||||
|
1.000000000000000021e-03,5.740605208264367093e-04,3.752860221900411030e-04,2.515274179172670150e-04,1.757730484194969538e-04,1.316262968484167275e-04,1.106031805667756002e-04,1.130890327345630944e-04,1.638824360782746060e-04
|
||||||
|
1.000000000000000021e-03,5.732597217139582440e-04,3.743865400085843336e-04,2.506901966657434509e-04,1.749991992264989145e-04,1.308541788026545852e-04,1.097115653341001649e-04,1.117862964715498958e-04,1.610733229285059244e-04
|
||||||
|
1.000000000000000021e-03,5.724581527307928295e-04,3.734873153380866809e-04,2.498542195054800734e-04,1.742275621656188764e-04,1.300856406740597557e-04,1.088263113284397853e-04,1.104977038827086933e-04,1.583110954216201049e-04
|
||||||
|
1.000000000000000021e-03,5.716575664778975139e-04,3.725901351223118402e-04,2.490209518882956956e-04,1.734592774731394025e-04,1.293215843757922266e-04,1.079481792373105579e-04,1.092239503861538297e-04,1.555962288273640454e-04
|
||||||
|
1.000000000000000021e-03,5.708579584178212615e-04,3.716949912014026899e-04,2.481903820156593069e-04,1.726943281050015661e-04,1.285619816677677630e-04,1.070771097820554131e-04,1.079648627815312081e-04,1.529279069228532445e-04
|
||||||
|
1.000000000000000021e-03,5.700593240595020362e-04,3.708018755033176054e-04,2.473624982033243466e-04,1.719326971657234189e-04,1.278068045492097274e-04,1.062130442456755448e-04,1.067202699871894330e-04,1.503053277730467872e-04
|
||||||
|
1.000000000000000021e-03,5.692616589508734098e-04,3.699107800243283187e-04,2.465372888514933574e-04,1.711743678703278799e-04,1.270560252111956913e-04,1.053559244063845252e-04,1.054900029091859618e-04,1.477277031714797602e-04
|
||||||
|
1.000000000000000021e-03,5.684668249800580104e-04,3.690236622787805977e-04,2.457163959794073484e-04,1.704206404911772779e-04,1.263106878677109810e-04,1.045066466916437628e-04,1.042749156168111009e-04,1.451958181660296986e-04
|
||||||
|
1.000000000000000021e-03,5.676748100054150635e-04,3.681404996529084395e-04,2.448997907163580324e-04,1.696714800685054925e-04,1.255707452244580493e-04,1.036651297187654374e-04,1.030748062779383314e-04,1.427088285865420875e-04
|
||||||
|
1.000000000000000021e-03,5.668856019606317766e-04,3.672612697075048303e-04,2.440874444423345342e-04,1.689268519744038289e-04,1.248361504800705925e-04,1.028312930702206035e-04,1.018894759794533339e-04,1.402659065748177792e-04
|
||||||
|
1.000000000000000021e-03,5.660978860040193896e-04,3.663833351346186431e-04,2.432754355983019401e-04,1.681813812071888568e-04,1.240994738987429935e-04,1.019939514788640786e-04,1.006986246362622330e-04,1.378144424939918523e-04
|
||||||
|
1.000000000000000021e-03,5.653129566917403656e-04,3.655093013788168949e-04,2.424676550876819162e-04,1.674404214250226010e-04,1.233681396595080271e-04,1.011643116013039457e-04,9.952262825359122704e-05,1.354072260989254840e-04
|
||||||
|
1.000000000000000021e-03,5.645308021917731225e-04,3.646391464999218838e-04,2.416640749146854532e-04,1.667039386446287719e-04,1.226421015627000995e-04,1.003422934745905857e-04,9.836128786277046102e-05,1.330434286087782230e-04
|
||||||
|
1.000000000000000021e-03,5.637533512715803535e-04,3.637748048842355184e-04,2.408662573039999728e-04,1.659731272165147797e-04,1.219222820499958832e-04,9.952864742131557339e-05,9.721524794079934454e-05,1.307234068834026641e-04
|
||||||
|
1.000000000000000021e-03,5.629805832911210584e-04,3.629162394326295588e-04,2.400741573155354143e-04,1.652479360999081315e-04,1.212086174287677493e-04,9.872327382660381703e-05,9.608428430098295324e-05,1.284463004684426848e-04
|
||||||
|
1.000000000000000021e-03,5.622124777547171659e-04,3.620634133660168507e-04,2.392877304473862261e-04,1.645283148026117340e-04,1.205010447638324016e-04,9.792607442008048754e-05,9.496817636981473815e-05,1.262112668660531425e-04
|
||||||
|
1.000000000000000021e-03,5.614490142952067260e-04,3.612162901840461500e-04,2.385069325732311319e-04,1.638142133018547766e-04,1.197995017798251111e-04,9.713695214164584071e-05,9.386670693673759554e-05,1.240174806289624668e-04
|
||||||
|
1.000000000000000021e-03,5.606917876274927293e-04,3.603765175920537237e-04,2.377331235014221514e-04,1.631066878653574946e-04,1.191048135885559178e-04,9.635658300529022745e-05,9.278045936752733660e-05,1.218652818497198865e-04
|
||||||
|
1.000000000000000021e-03,5.599407711882442139e-04,3.595440474626148916e-04,2.369662455139816704e-04,1.624056743525901679e-04,1.184169030927857740e-04,9.558485302446070387e-05,9.170919453133945438e-05,1.197538170918552259e-04
|
||||||
|
1.000000000000000021e-03,5.591959386362445371e-04,3.587188321446053963e-04,2.362062415256148103e-04,1.617111093879153761e-04,1.177356942042864595e-04,9.482164989506947420e-05,9.065267746151001182e-05,1.176822517560764241e-04
|
||||||
|
1.000000000000000021e-03,5.584679347085343051e-04,3.579204847030152616e-04,2.354801209260217886e-04,1.610571916563278928e-04,1.171042314833950021e-04,9.412413419793498636e-05,8.969710985766721223e-05,1.158171674873524301e-04
|
||||||
|
1.000000000000000021e-03,5.577460350040716044e-04,3.571292104088583889e-04,2.347605938090600918e-04,1.604093154405005178e-04,1.164788453357124725e-04,9.343405219685640224e-05,8.875393403591714169e-05,1.139848385910069905e-04
|
||||||
|
1.000000000000000021e-03,5.570302142000897652e-04,3.563449642017089015e-04,2.340476072540025119e-04,1.597674235279283352e-04,1.158594695166401697e-04,9.275131062844492946e-05,8.782296490203555085e-05,1.121846347113116888e-04
|
||||||
|
1.000000000000000021e-03,5.563205323021954991e-04,3.555677864531773679e-04,2.333411773810724506e-04,1.591315117132938270e-04,1.152460793074575203e-04,9.207585166649024939e-05,8.690405384945894284e-05,1.104159825692847303e-04
|
||||||
|
1.000000000000000021e-03,5.556169640414684949e-04,3.547976323593042547e-04,2.326412517183593022e-04,1.585015234268918286e-04,1.146386094395640093e-04,9.140758389001004606e-05,8.599702078916069998e-05,1.086782756746748250e-04
|
||||||
|
1.000000000000000021e-03,5.549194843577821444e-04,3.540344575531629255e-04,2.319477783590319386e-04,1.578774027587701891e-04,1.140369954748351631e-04,9.074641718074756330e-05,8.510168863112195785e-05,1.069709201912467553e-04
|
||||||
|
1.000000000000000021e-03,5.542280683854123842e-04,3.532782180675540329e-04,2.312607059053527040e-04,1.572590943887706505e-04,1.134411737206307899e-04,9.009226260907148270e-05,8.421788308143062266e-05,1.052933342707317640e-04
|
||||||
|
1.000000000000000021e-03,5.535435592528614506e-04,3.525297669260542646e-04,2.305807244353639423e-04,1.566471216497641210e-04,1.128515385449576329e-04,8.944542244330133641e-05,8.334582247054855841e-05,1.036454797753234207e-04
|
||||||
|
1.000000000000000021e-03,5.528659293179593237e-04,3.517890550472092793e-04,2.299077767025847687e-04,1.560414233076215052e-04,1.122680202866636689e-04,8.880580140054516926e-05,8.248532556564376009e-05,1.020267728319692934e-04
|
||||||
|
1.000000000000000021e-03,5.521951511907441769e-04,3.510560338657343622e-04,2.292418061160320900e-04,1.554419388795865483e-04,1.116905502099227850e-04,8.817330560855271690e-05,8.163621425685595255e-05,1.004366420798761639e-04
|
||||||
|
1.000000000000000021e-03,5.515357570680511773e-04,3.503384240935171457e-04,2.285926195257032088e-04,1.548599664871607589e-04,1.111316359132737570e-04,8.756139732097920178e-05,8.081143045355856274e-05,9.887558842870256459e-05
|
||||||
|
1.000000000000000021e-03,5.508831499695134287e-04,3.496283778737561509e-04,2.279502431225978031e-04,1.542840041018178729e-04,1.105785086338880569e-04,8.695624145470242240e-05,7.999741899881025698e-05,9.734197099681332458e-05
|
||||||
|
1.000000000000000021e-03,5.502373034395177318e-04,3.489258487042028742e-04,2.273146231686837553e-04,1.537139948092133693e-04,1.100311043442569531e-04,8.635775141128424154e-05,7.919401605398894981e-05,9.583525507692383649e-05
|
||||||
|
1.000000000000000021e-03,5.495982753581815606e-04,3.482308738101717264e-04,2.266857730549029851e-04,1.531499327576744506e-04,1.094893985055618503e-04,8.576587362490598130e-05,7.840109070036870779e-05,9.435495486246966317e-05
|
||||||
|
1.000000000000000021e-03,5.489660394111083985e-04,3.475434070850742167e-04,2.260636396270461598e-04,1.525917617808240120e-04,1.089533281238570496e-04,8.518052329278025009e-05,7.761848365092111231e-05,9.290055631012179708e-05
|
||||||
|
1.000000000000000021e-03,5.483405695169031721e-04,3.468634028939242666e-04,2.254481703234268038e-04,1.520394263837190755e-04,1.084228310216190315e-04,8.460161684084565312e-05,7.684603831721497692e-05,9.147155629123523643e-05
|
||||||
|
1.000000000000000021e-03,5.477218398160970184e-04,3.461908160447295835e-04,2.248393131323322177e-04,1.514928716901747189e-04,1.078978457743454979e-04,8.402907183940372035e-05,7.608360066029366266e-05,9.006746210081428210e-05
|
||||||
|
1.000000000000000021e-03,5.471100509830739483e-04,3.455258336641454844e-04,2.242372067336963117e-04,1.509521904405796073e-04,1.073784265457052923e-04,8.346290305268591516e-05,7.533111218717854750e-05,8.868791149478115541e-05
|
||||||
|
1.000000000000000021e-03,5.465051768578450733e-04,3.448684100639811626e-04,2.236417986238402995e-04,1.504173273640432558e-04,1.068645117117092864e-04,8.290302835464549746e-05,7.458842111919879593e-05,8.733242665255502488e-05
|
||||||
|
1.000000000000000021e-03,5.459071915129861232e-04,3.442185000233075119e-04,2.230530368831633737e-04,1.498882278486614187e-04,1.063560404456327061e-04,8.234936680962616474e-05,7.385537825478157199e-05,8.600053991717240256e-05
|
||||||
|
1.000000000000000021e-03,5.453277270883248422e-04,3.435968835063559607e-04,2.224987019123045480e-04,1.493989071766017103e-04,1.058939742146122178e-04,8.185283432112488435e-05,7.320083692872619591e-05,8.480120525436834187e-05
|
||||||
|
1.000000000000000021e-03,5.447550756300442850e-04,3.429826158632724655e-04,2.219507707465509202e-04,1.489150144895505707e-04,1.054368625228528346e-04,8.136171358212484941e-05,7.255437084770181432e-05,8.362138199130290570e-05
|
||||||
|
1.000000000000000021e-03,5.441892122953419404e-04,3.423756544954533452e-04,2.214091954721005766e-04,1.484365007267826825e-04,1.049846526338566485e-04,8.087593753205775274e-05,7.191586230794716592e-05,8.246071125248328093e-05
|
||||||
|
1.000000000000000021e-03,5.436257869834306257e-04,3.417717090501741430e-04,2.208705585733095858e-04,1.479607869104501987e-04,1.045353737048878776e-04,8.039389156994272538e-05,7.128377081045688692e-05,8.131715986317171246e-05
|
||||||
|
1.000000000000000021e-03,5.430647907230928004e-04,3.411707635569704330e-04,2.203348411819341208e-04,1.474878525008424264e-04,1.040890016129762040e-04,7.991554062444546221e-05,7.065802258502740848e-05,8.019045690600123673e-05
|
||||||
|
1.000000000000000021e-03,5.425062145452035425e-04,3.405728020832017003e-04,2.198020245085192449e-04,1.470176770797095381e-04,1.036455124224165388e-04,7.944084996986793814e-05,7.003854478529189314e-05,7.908033605497744685e-05
|
||||||
|
1.000000000000000021e-03,5.419500494783734655e-04,3.399778087230425684e-04,2.192720898259863408e-04,1.465502403299397984e-04,1.032048823605461293e-04,7.896978519468913008e-05,6.942526543493823701e-05,7.798653539704048551e-05
|
||||||
|
1.000000000000000021e-03,5.413941311127808435e-04,3.393835756573481376e-04,2.187432334857416756e-04,1.460841531649274296e-04,1.027660304092932323e-04,7.850144313387483587e-05,6.881729624423716459e-05,7.690779566810491681e-05
|
||||||
|
1.000000000000000021e-03,5.408384570747234218e-04,3.387900992487282684e-04,2.182154508640741402e-04,1.456194096560940569e-04,1.023289477092565169e-04,7.803580657419308998e-05,6.821458972979072498e-05,7.584390730667668775e-05
|
||||||
|
1.000000000000000021e-03,5.402830249660243826e-04,3.381973758275843189e-04,2.176887373150658610e-04,1.451560038709627043e-04,1.018936254270842219e-04,7.757285840469518032e-05,6.761709884283491779e-05,7.479466373034050742e-05
|
||||||
|
1.000000000000000021e-03,5.397131798668998448e-04,3.375789411508863902e-04,2.171273238640323091e-04,1.446496280566233409e-04,1.014059885387841374e-04,7.704415358894297196e-05,6.692941074150365747e-05,7.359880640935691578e-05
|
||||||
|
1.000000000000000021e-03,5.391436022217508317e-04,3.369613465901344558e-04,2.165671485747253328e-04,1.441448734692186333e-04,1.009205829600201576e-04,7.651897498112265308e-05,6.624864922679121694e-05,7.242198835523922060e-05
|
||||||
|
1.223599761281599736e-03,2.870574988594920204e-03,5.410558860144323162e-03,9.740321680379944794e-03,1.718226620812626088e-02,3.032327552654904765e-02,5.460894525232919822e-02,1.025522470341594938e-01,2.059999999999999887e-01
|
||||||
|
4.083745694274921144e-03,8.369042825128880300e-03,1.439530071705045523e-02,2.397223043565064812e-02,3.897486419880552555e-02,6.202545653148217042e-02,9.626510461383173956e-02,1.437785279168776742e-01,2.000000000000000111e-01
|
||||||
|
36
tests/data/test_lumped_losses_raman_fiber_config.json
Normal file
36
tests/data/test_lumped_losses_raman_fiber_config.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"uid": "Span1",
|
||||||
|
"params": {
|
||||||
|
"length": 80,
|
||||||
|
"loss_coef": 0.2,
|
||||||
|
"length_units": "km",
|
||||||
|
"att_in": 0,
|
||||||
|
"con_in": 0.5,
|
||||||
|
"con_out": 0.0,
|
||||||
|
"lumped_losses": [
|
||||||
|
{
|
||||||
|
"position": 7,
|
||||||
|
"loss": 0.5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type_variety": "SSMF",
|
||||||
|
"dispersion": 0.0000167,
|
||||||
|
"effective_area": 83e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
},
|
||||||
|
"operational": {
|
||||||
|
"temperature": 283,
|
||||||
|
"raman_pumps": [
|
||||||
|
{
|
||||||
|
"power": 0.2,
|
||||||
|
"frequency": 205000000000000,
|
||||||
|
"propagation_direction": "counterprop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"power": 0.206,
|
||||||
|
"frequency": 201000000000000,
|
||||||
|
"propagation_direction": "counterprop"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
97
tests/data/test_raman_fiber_expected_results.csv
Normal file
97
tests/data/test_raman_fiber_expected_results.csv
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
,signal,ase,nli
|
||||||
|
0,0.0002866683470642085,3.455694800734997e-08,2.1767706055953313e-07
|
||||||
|
1,0.0002842930902246378,3.4445260342151434e-08,2.20064716108892e-07
|
||||||
|
2,0.00028193841273409963,3.4334217950641774e-08,2.2239856929822977e-07
|
||||||
|
3,0.0002796041237984927,3.422381587730477e-08,2.2467937700272344e-07
|
||||||
|
4,0.00027589218358262,3.3956266402003705e-08,2.2576401766047814e-07
|
||||||
|
5,0.0002722303444814487,3.3690926476196685e-08,2.2678094635121413e-07
|
||||||
|
6,0.00026861791294303266,3.342777134334201e-08,2.2773179097640802e-07
|
||||||
|
7,0.00026505174756069215,3.316675429137828e-08,2.2861602718115889e-07
|
||||||
|
8,0.0002615312775878486,3.290785186664305e-08,2.294352005376256e-07
|
||||||
|
9,0.0002577007690018081,3.26092154155734e-08,2.2987401053105823e-07
|
||||||
|
10,0.00025392474812815994,3.231329178154223e-08,2.3024928325076607e-07
|
||||||
|
11,0.0002501957390130402,3.201993265117851e-08,2.3055653947072044e-07
|
||||||
|
12,0.0002465133077961936,3.172911082648897e-08,2.3079745224174315e-07
|
||||||
|
13,0.00024287702172285261,3.144079924487205e-08,2.309736700807475e-07
|
||||||
|
14,0.00023918644496802598,3.1142660565561954e-08,2.3099023972100006e-07
|
||||||
|
15,0.00023554415781363666,3.084719002003063e-08,2.3094533745656626e-07
|
||||||
|
16,0.0002319496781605366,3.0554358283826426e-08,2.3084061926161906e-07
|
||||||
|
17,0.000228402746264896,3.026413819712743e-08,2.306779372506828e-07
|
||||||
|
18,0.00022490287297566154,2.997650061885732e-08,2.2679314039447925e-07
|
||||||
|
19,0.0002210339853226993,2.9639081336421986e-08,2.225476971173533e-07
|
||||||
|
20,0.00021722472675673681,2.9305156366940595e-08,2.1837424228396343e-07
|
||||||
|
21,0.00021347443350916938,2.8974683300060073e-08,2.1427183120915025e-07
|
||||||
|
22,0.00020978233224910872,2.864761802749998e-08,2.1023941353936252e-07
|
||||||
|
23,0.0002061476568412488,2.832391679540816e-08,2.0627595093585302e-07
|
||||||
|
24,0.0002028237056285935,2.8034565895618217e-08,2.0263423697267893e-07
|
||||||
|
25,0.00019954715529254185,2.7748013284124615e-08,1.9905015325521452e-07
|
||||||
|
26,0.0001963174528000437,2.7464226779716075e-08,1.9552292765090665e-07
|
||||||
|
27,0.00019313475803109547,2.718318103861899e-08,1.920525003885138e-07
|
||||||
|
28,0.00018999848980183525,2.6904843987797665e-08,1.8863807494364378e-07
|
||||||
|
29,0.00018690807208013476,2.6629183784477213e-08,1.852788635171717e-07
|
||||||
|
30,0.00018386293497138034,2.635616888672288e-08,1.8197408797080072e-07
|
||||||
|
31,0.0001808626075954048,2.608576967648626e-08,1.7872307155753016e-07
|
||||||
|
32,0.00017790652540681915,2.5817954962418864e-08,1.7552504805064169e-07
|
||||||
|
33,0.00017499412908771533,2.5552693765056307e-08,1.723792598876346e-07
|
||||||
|
34,0.0001721914205512116,2.529821177538242e-08,1.69350416018518e-07
|
||||||
|
35,0.00016942913344260413,2.5046172734840803e-08,1.663699885487624e-07
|
||||||
|
36,0.0001667067703020692,2.4796549229968703e-08,1.6343730102750106e-07
|
||||||
|
37,0.00016402494737034808,2.4549324625938814e-08,1.602954566731582e-07
|
||||||
|
38,0.0001613831201060569,2.430447139995257e-08,1.5720933628441338e-07
|
||||||
|
39,0.00015878075021906192,2.406196225171638e-08,1.541780421866172e-07
|
||||||
|
40,0.00015621730558753943,2.3821770097360405e-08,1.5120068940449393e-07
|
||||||
|
41,0.000153694061439545,2.3583901792213434e-08,1.4827814327673852e-07
|
||||||
|
42,0.00015121040694331307,2.3348329147104765e-08,1.4540943949658482e-07
|
||||||
|
43,0.00014876574026315321,2.3115024224465226e-08,1.425936300160931e-07
|
||||||
|
44,0.00014623043935025647,2.2864250993313975e-08,1.397065102093322e-07
|
||||||
|
45,0.00014373723010448477,2.2616046400344574e-08,1.3687531950007013e-07
|
||||||
|
46,0.0001412854316913198,2.2370377299191064e-08,1.3409901704421416e-07
|
||||||
|
47,0.00013887544742801196,2.2127221340618422e-08,1.313775961274423e-07
|
||||||
|
48,0.0001365065605420479,2.1886545482453933e-08,1.2870998887773554e-07
|
||||||
|
49,0.00013417806673897108,2.164831702445933e-08,1.2609514810979993e-07
|
||||||
|
50,0.00013188927370907155,2.1412503578881085e-08,1.2353204666803017e-07
|
||||||
|
51,0.00012964085531237725,2.117909919147538e-08,1.2102094138348867e-07
|
||||||
|
52,0.00012743207116500861,2.094807084934547e-08,1.1856076487337955e-07
|
||||||
|
53,0.0001252621950917354,2.0719385892834214e-08,1.161504721855161e-07
|
||||||
|
54,0.00012308423338164536,2.0485363383535514e-08,1.1374627006340893e-07
|
||||||
|
55,0.00012094535834842106,2.0253755300794944e-08,1.1139168040879032e-07
|
||||||
|
56,0.00011884484242431182,2.0024527468430072e-08,1.0897675288127846e-07
|
||||||
|
57,0.00011678298769107047,1.9797656169961167e-08,1.0661409941810817e-07
|
||||||
|
58,0.0001147590394591346,1.9573107382367898e-08,1.0430256532408603e-07
|
||||||
|
59,0.00011277225867179729,1.935084744632288e-08,1.0204102225018314e-07
|
||||||
|
60,0.00011082192110664448,1.913084301808743e-08,9.982836715827351e-08
|
||||||
|
61,0.00010890831555726861,1.8913080844667903e-08,9.76644171489201e-08
|
||||||
|
62,0.00010703069380321927,1.8697527263494167e-08,9.554805889434612e-08
|
||||||
|
63,0.00010518832400867466,1.8484148971365717e-08,9.347820572370307e-08
|
||||||
|
64,0.00010353027948847247,1.8300360477604286e-08,9.158630538270034e-08
|
||||||
|
65,0.00010190114820620951,1.8118339508838893e-08,8.97332684173061e-08
|
||||||
|
66,0.00010030037817345079,1.7938063167097722e-08,8.791826040657302e-08
|
||||||
|
67,9.872746699919663e-05,1.775950920143011e-08,8.614049912759125e-08
|
||||||
|
68,9.718188342878233e-05,1.7582655209782296e-08,8.439918541238176e-08
|
||||||
|
69,9.566310719955732e-05,1.740747903977101e-08,8.269353818341506e-08
|
||||||
|
70,9.417062845393912e-05,1.7233958752991638e-08,8.102279372648069e-08
|
||||||
|
71,9.27044102709892e-05,1.7062082036004708e-08,7.938660156523957e-08
|
||||||
|
72,9.12639411274833e-05,1.6891826998956218e-08,7.778420731697601e-08
|
||||||
|
73,8.984872036936478e-05,1.6723171993235663e-08,7.621487408851861e-08
|
||||||
|
74,8.845926525396718e-05,1.6557077218868872e-08,7.467873241780861e-08
|
||||||
|
75,8.709405706837696e-05,1.6392620086127443e-08,7.352620174175576e-08
|
||||||
|
76,8.575262707251024e-05,1.6229781230847938e-08,7.239374499535451e-08
|
||||||
|
77,8.44345490553445e-05,1.6068541919248203e-08,7.128100236441453e-08
|
||||||
|
78,8.313937224726923e-05,1.5908883354530017e-08,7.018759330199112e-08
|
||||||
|
79,8.18666553697718e-05,1.5750787028460176e-08,6.91131452736768e-08
|
||||||
|
80,8.061596620368467e-05,1.5594234699428168e-08,6.80572933931087e-08
|
||||||
|
81,7.93869860927298e-05,1.54392105845737e-08,6.701976864553917e-08
|
||||||
|
82,7.81792957880057e-05,1.528569691328632e-08,6.600021709431229e-08
|
||||||
|
83,7.69924848842345e-05,1.5133676199095668e-08,6.499829226870119e-08
|
||||||
|
84,7.592423495462984e-05,1.5006007729453082e-08,6.40964585216171e-08
|
||||||
|
85,7.487323130273564e-05,1.4879695488874347e-08,6.320918435915818e-08
|
||||||
|
86,7.383915942693816e-05,1.475473179887786e-08,6.233620427401105e-08
|
||||||
|
87,7.282024738915393e-05,1.4631093950979863e-08,6.147602236758762e-08
|
||||||
|
88,7.181625694043332e-05,1.4508775744557438e-08,6.062843750629826e-08
|
||||||
|
89,7.082695384072487e-05,1.4387771381868581e-08,5.979325194092954e-08
|
||||||
|
90,6.985210770121701e-05,1.4268075471622408e-08,5.8970271173546604e-08
|
||||||
|
91,6.889061932028676e-05,1.414966436041678e-08,5.8158567240485706e-08
|
||||||
|
92,6.79423037538828e-05,1.4032534237451406e-08,5.7357984009008465e-08
|
||||||
|
93,6.700697867481953e-05,1.3916681725635683e-08,5.656836755557654e-08
|
||||||
|
94,6.594003301527265e-05,1.3765768410137306e-08,5.5667634894222326e-08
|
||||||
|
95,6.489000516837228e-05,1.3616343300622314e-08,5.4781184522010985e-08
|
||||||
|
@@ -1,97 +0,0 @@
|
|||||||
,signal,ase,nli
|
|
||||||
0,0.0002869472910749756,3.829244288314411e-08,2.1570435023738975e-07
|
|
||||||
1,0.0002844264441819097,3.810807396068084e-08,2.1799950841473497e-07
|
|
||||||
2,0.00028192866252406385,3.792544000755193e-08,2.2023841125047751e-07
|
|
||||||
3,0.0002794537215642667,3.7744517714620316e-08,2.2242189941355056e-07
|
|
||||||
4,0.00027562432957345563,3.739256592350871e-08,2.2343448272115905e-07
|
|
||||||
5,0.0002718482755003939,3.7044482870002475e-08,2.2437826192962336e-07
|
|
||||||
6,0.00026812479793132313,3.670020704375223e-08,2.2525495466693408e-07
|
|
||||||
7,0.000264450700138397,3.635954085714981e-08,2.2606415187873477e-07
|
|
||||||
8,0.0002608253488030976,3.602242835595967e-08,2.2680748521505387e-07
|
|
||||||
9,0.0002569046888856947,3.564392097524325e-08,2.2718285844823122e-07
|
|
||||||
10,0.0002530414048172964,3.52696660940159e-08,2.2749429758474536e-07
|
|
||||||
11,0.0002492279873569917,3.489974200864255e-08,2.277374766527899e-07
|
|
||||||
12,0.00024546394589921574,3.453407358954537e-08,2.2791414400785136e-07
|
|
||||||
13,0.00024174879169001578,3.4172586853993816e-08,2.280260208417818e-07
|
|
||||||
14,0.00023798746912554602,3.3802283179520985e-08,2.2798420759778034e-07
|
|
||||||
15,0.00023427697848580554,3.343627022987542e-08,2.2788101592695744e-07
|
|
||||||
16,0.0002306167836320285,3.307447309241581e-08,2.2771816297650914e-07
|
|
||||||
17,0.00022700656967539738,3.2716831574363364e-08,2.274975560288182e-07
|
|
||||||
18,0.00022344579480967338,3.236327278261661e-08,2.2361822442592406e-07
|
|
||||||
19,0.00021953361935365365,3.195819964288877e-08,2.1939761734541424e-07
|
|
||||||
20,0.000215683131390894,3.155821693631402e-08,2.152494588710531e-07
|
|
||||||
21,0.0002118936126056039,3.116322947665684e-08,2.1117277567387026e-07
|
|
||||||
22,0.00020816423698459974,3.0773146233359933e-08,2.0716649124095414e-07
|
|
||||||
23,0.000204494186708796,3.0387877710694614e-08,2.0322954179937734e-07
|
|
||||||
24,0.0002011608152067422,3.0044038268833097e-08,1.9963693210325328e-07
|
|
||||||
25,0.0001978756946189507,2.9704204306604607e-08,1.9610141536963302e-07
|
|
||||||
26,0.00019463824873067792,2.9368307297032184e-08,1.9262221997374404e-07
|
|
||||||
27,0.00019144860669288407,2.903632861769827e-08,1.8919927457566036e-07
|
|
||||||
28,0.00018830616497929743,2.870820070744311e-08,1.8583178406705711e-07
|
|
||||||
29,0.0001852103256336822,2.838385708911634e-08,1.8251896218718027e-07
|
|
||||||
30,0.0001821604972098109,2.8063232252848876e-08,1.7926003240910756e-07
|
|
||||||
31,0.00017915618670059162,2.774625963676283e-08,1.76054318231953e-07
|
|
||||||
32,0.00017619680881745593,2.7432875871797347e-08,1.729010553429381e-07
|
|
||||||
33,0.0001732817839023698,2.712301856538676e-08,1.6979948820365403e-07
|
|
||||||
34,0.0001704966413678542,2.6828122477482957e-08,1.6683312331765736e-07
|
|
||||||
35,0.00016775189226190024,2.6536528664560742e-08,1.639139770351803e-07
|
|
||||||
36,0.00016504703499518105,2.624818226917535e-08,1.6104139135569604e-07
|
|
||||||
37,0.00016238266779776653,2.5963117448579666e-08,1.5795381794641793e-07
|
|
||||||
38,0.0001597582427278871,2.568127942199337e-08,1.5492098715709327e-07
|
|
||||||
39,0.0001571732182027887,2.5402614261982925e-08,1.5194201541883415e-07
|
|
||||||
40,0.00015462705891567335,2.5127068868391087e-08,1.4901603171959048e-07
|
|
||||||
41,0.00015212101646395513,2.4854550603641668e-08,1.4614388817380648e-07
|
|
||||||
42,0.00014965447757985992,2.4585009902449718e-08,1.4332463586635585e-07
|
|
||||||
43,0.0001472268380950584,2.4318397887399997e-08,1.4055734193945962e-07
|
|
||||||
44,0.0001447164668892332,2.4034551917480693e-08,1.377259000826997e-07
|
|
||||||
45,0.00014224784112376056,2.3753930444781328e-08,1.3494914625940223e-07
|
|
||||||
46,0.000139820283675003,2.3476479506890216e-08,1.3222606385781202e-07
|
|
||||||
47,0.00013743418748444287,2.3202247900619965e-08,1.295566531341862e-07
|
|
||||||
48,0.00013508884015386686,2.2931181973013504e-08,1.2693987096025158e-07
|
|
||||||
49,0.00013278354172498307,2.2663228905058608e-08,1.2437469442130953e-07
|
|
||||||
50,0.00013051760419724657,2.2398336706395863e-08,1.2186012017917007e-07
|
|
||||||
51,0.00012829168984638487,2.2136423459712534e-08,1.1939640981689728e-07
|
|
||||||
52,0.00012610506317956756,2.1877440279108582e-08,1.1698252030563078e-07
|
|
||||||
53,0.00012395700285919374,2.1621338937233993e-08,1.1461743054419825e-07
|
|
||||||
54,0.00012180241033650921,2.136015630373758e-08,1.1225922783040025e-07
|
|
||||||
55,0.0001196865090578088,2.11019103466444e-08,1.0994951537260489e-07
|
|
||||||
56,0.00011760857776205185,2.0846552296319304e-08,1.0757395097863843e-07
|
|
||||||
57,0.00011556891128259512,2.0594154864038522e-08,1.0524972555992818e-07
|
|
||||||
58,0.00011356676177304645,2.0344670536408355e-08,1.0297570549834491e-07
|
|
||||||
59,0.00011160139690545148,2.009805268169949e-08,1.007507830554809e-07
|
|
||||||
60,0.00010967209909252316,1.9854255584746143e-08,9.857387536569294e-08
|
|
||||||
61,0.00010777915187088834,1.961321154131787e-08,9.644480679617587e-08
|
|
||||||
62,0.00010592181397175025,1.9374877782865603e-08,9.43624842461164e-08
|
|
||||||
63,0.00010409936038609485,1.913921236065976e-08,9.232584080120623e-08
|
|
||||||
64,0.00010246447558376296,1.8936229484424864e-08,9.046927135292076e-08
|
|
||||||
65,0.00010085803630103994,1.873544193319646e-08,8.865067925960422e-08
|
|
||||||
66,9.927950010555374e-05,1.8536821682157304e-08,8.686925127148483e-08
|
|
||||||
67,9.772837346090753e-05,1.834034757300294e-08,8.512422533827403e-08
|
|
||||||
68,9.62041343011343e-05,1.8145993316507615e-08,8.341482250640209e-08
|
|
||||||
69,9.470627135912848e-05,1.7953733512786736e-08,8.174028142913557e-08
|
|
||||||
70,9.32342835979764e-05,1.776354374489084e-08,8.009985766376519e-08
|
|
||||||
71,9.178813743816069e-05,1.757538990695628e-08,7.849321446941075e-08
|
|
||||||
72,9.036733009485282e-05,1.7389250225057777e-08,7.691961625609573e-08
|
|
||||||
73,8.897136946428169e-05,1.7205104136353174e-08,7.537834446343352e-08
|
|
||||||
74,8.760740745801088e-05,1.7025340034280735e-08,7.38751341742058e-08
|
|
||||||
75,8.626710469266231e-05,1.6847609082084475e-08,7.274492099364066e-08
|
|
||||||
76,8.495000573672366e-05,1.6671897815367364e-08,7.16342744751107e-08
|
|
||||||
77,8.365569697520734e-05,1.6498202874185357e-08,7.054284583689086e-08
|
|
||||||
78,8.238374036673638e-05,1.6326516066391613e-08,6.94702656996508e-08
|
|
||||||
79,8.11337070649851e-05,1.615683240442047e-08,6.84161724378069e-08
|
|
||||||
80,7.990517700271111e-05,1.5989150837085435e-08,6.738021182875641e-08
|
|
||||||
81,7.869784230919362e-05,1.5823472723367315e-08,6.63621242598539e-08
|
|
||||||
82,7.751129541079501e-05,1.5659808141896922e-08,6.536156604375558e-08
|
|
||||||
83,7.634513730458697e-05,1.5498175122781168e-08,6.437820072038669e-08
|
|
||||||
84,7.530262080974513e-05,1.5364277079429572e-08,6.349909645089698e-08
|
|
||||||
85,7.427675504203511e-05,1.523236493234819e-08,6.263403294276124e-08
|
|
||||||
86,7.326723873728716e-05,1.510251249079146e-08,6.178275615432246e-08
|
|
||||||
87,7.227232864620995e-05,1.4974078108462424e-08,6.094379608687809e-08
|
|
||||||
88,7.1291797553153e-05,1.4847055996011248e-08,6.011696114034367e-08
|
|
||||||
89,7.032542203609039e-05,1.4721440784517874e-08,5.930206291361685e-08
|
|
||||||
90,6.937298231673965e-05,1.4597227547292096e-08,5.849891607818969e-08
|
|
||||||
91,6.843339696762385e-05,1.447443282270653e-08,5.7706608718023645e-08
|
|
||||||
92,6.750649045006057e-05,1.4353051811356354e-08,5.6924992809748396e-08
|
|
||||||
93,6.65920896785063e-05,1.4233080214004659e-08,5.615392239860827e-08
|
|
||||||
94,6.554258932109667e-05,1.407504972937325e-08,5.5268928972034444e-08
|
|
||||||
95,6.450957734109368e-05,1.3918655180382722e-08,5.439783940506079e-08
|
|
||||||
|
38
tests/data/test_science_utils_fiber_config.json
Normal file
38
tests/data/test_science_utils_fiber_config.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"uid": "Span1",
|
||||||
|
"params": {
|
||||||
|
"length": 80,
|
||||||
|
"loss_coef": 0.2,
|
||||||
|
"length_units": "km",
|
||||||
|
"att_in": 0,
|
||||||
|
"con_in": 0.5,
|
||||||
|
"con_out": 0.5,
|
||||||
|
"type_variety": "SSMF",
|
||||||
|
"dispersion": 0.0000167,
|
||||||
|
"effective_area": 83e-12,
|
||||||
|
"pmd_coef": 1.265e-15
|
||||||
|
},
|
||||||
|
"operational": {
|
||||||
|
"temperature": 283,
|
||||||
|
"raman_pumps": [
|
||||||
|
{
|
||||||
|
"power": 224.403e-3,
|
||||||
|
"frequency": 205e12,
|
||||||
|
"propagation_direction": "counterprop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"power": 231.135e-3,
|
||||||
|
"frequency": 201e12,
|
||||||
|
"propagation_direction": "counterprop"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"location": {
|
||||||
|
"latitude": 1,
|
||||||
|
"longitude": 0,
|
||||||
|
"city": null,
|
||||||
|
"region": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ Transceiver trx_Stockholm
|
|||||||
OSNR ASE (signal bw, dB): 30.98
|
OSNR ASE (signal bw, dB): 30.98
|
||||||
CD (ps/nm): 0.00
|
CD (ps/nm): 0.00
|
||||||
PMD (ps): 0.00
|
PMD (ps): 0.00
|
||||||
|
PDL (dB): 0.00
|
||||||
Roadm roadm_Stockholm
|
Roadm roadm_Stockholm
|
||||||
effective loss (dB): 22.00
|
effective loss (dB): 22.00
|
||||||
pch out (dBm): -20.00
|
pch out (dBm): -20.00
|
||||||
@@ -229,7 +230,8 @@ Transceiver trx_Gothenburg
|
|||||||
OSNR ASE (0.1nm, dB): 21.20
|
OSNR ASE (0.1nm, dB): 21.20
|
||||||
OSNR ASE (signal bw, dB): 17.18
|
OSNR ASE (signal bw, dB): 17.18
|
||||||
CD (ps/nm): 8350.42
|
CD (ps/nm): 8350.42
|
||||||
PMD (ps): 0.89
|
PMD (ps): 7.99
|
||||||
|
PDL (dB): 3.74
|
||||||
|
|
||||||
Transmission result for input power = 2.00 dBm:
|
Transmission result for input power = 2.00 dBm:
|
||||||
Final GSNR (0.1 nm): [1;36;40m18.90 dB[0m
|
Final GSNR (0.1 nm): [1;36;40m18.90 dB[0m
|
||||||
241
tests/invocation/openroadm-v5-Stockholm-Gothenburg
Normal file
241
tests/invocation/openroadm-v5-Stockholm-Gothenburg
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
There are 96 channels propagating
|
||||||
|
Power mode is set to True
|
||||||
|
=> it can be modified in eqpt_config.json - Span
|
||||||
|
|
||||||
|
There are 6 fiber spans over 500 km between trx_Stockholm and trx_Gothenburg
|
||||||
|
|
||||||
|
Now propagating between trx_Stockholm and trx_Gothenburg:
|
||||||
|
|
||||||
|
Propagating with input power = [1;36;40m2.00 dBm[0m:
|
||||||
|
Transceiver trx_Stockholm
|
||||||
|
GSNR (0.1nm, dB): 35.00
|
||||||
|
GSNR (signal bw, dB): 30.98
|
||||||
|
OSNR ASE (0.1nm, dB): 35.00
|
||||||
|
OSNR ASE (signal bw, dB): 30.98
|
||||||
|
CD (ps/nm): 0.00
|
||||||
|
PMD (ps): 0.00
|
||||||
|
PDL (dB): 0.00
|
||||||
|
Roadm roadm_Stockholm
|
||||||
|
effective loss (dB): 22.00
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
|
||||||
|
type_variety: openroadm_mw_mw_booster
|
||||||
|
effective gain(dB): 22.00
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): -inf
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -0.18
|
||||||
|
Power Out (dBm): 21.82
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Fiber fiber (Stockholm → Norrköping)_(1/2)
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 81.63
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 16.33
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -14.33
|
||||||
|
Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
|
||||||
|
type_variety: openroadm_ila_low_noise
|
||||||
|
effective gain(dB): 16.33
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 8.01
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): 5.51
|
||||||
|
Power Out (dBm): 21.84
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Fiber fiber (Stockholm → Norrköping)_(2/2)
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 81.63
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 16.33
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -14.33
|
||||||
|
Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
|
||||||
|
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||||
|
effective gain(dB): 16.33
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 11.44
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): 5.53
|
||||||
|
Power Out (dBm): 21.86
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Roadm roadm_Norrköping
|
||||||
|
effective loss (dB): 22.00
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
|
||||||
|
type_variety: openroadm_mw_mw_booster
|
||||||
|
effective gain(dB): 22.00
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): -inf
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -0.18
|
||||||
|
Power Out (dBm): 21.82
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Fiber fiber (Norrköping → Linköping)
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 45.99
|
||||||
|
pad att_in (dB): 1.80
|
||||||
|
total loss (dB): 11.00
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -9.00
|
||||||
|
Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
|
||||||
|
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||||
|
effective gain(dB): 11.00
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 16.00
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): 10.83
|
||||||
|
Power Out (dBm): 21.83
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Roadm roadm_Linköping
|
||||||
|
effective loss (dB): 22.00
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
|
||||||
|
type_variety: openroadm_mw_mw_booster
|
||||||
|
effective gain(dB): 22.00
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): -inf
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -0.18
|
||||||
|
Power Out (dBm): 21.82
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Fiber fiber (Linköping → Jönköping)
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 134.02
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 26.80
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -24.80
|
||||||
|
Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
|
||||||
|
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||||
|
effective gain(dB): 26.80
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 8.01
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -4.97
|
||||||
|
Power Out (dBm): 21.86
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Roadm roadm_Jönköping
|
||||||
|
effective loss (dB): 22.00
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
|
||||||
|
type_variety: openroadm_mw_mw_booster
|
||||||
|
effective gain(dB): 22.00
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): -inf
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -0.18
|
||||||
|
Power Out (dBm): 21.82
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Fiber fiber (Jönköping → Borås)
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 89.12
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 17.82
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -15.82
|
||||||
|
Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
|
||||||
|
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||||
|
effective gain(dB): 17.82
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 10.54
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): 4.01
|
||||||
|
Power Out (dBm): 21.84
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Roadm roadm_Borås
|
||||||
|
effective loss (dB): 22.00
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
|
||||||
|
type_variety: openroadm_mw_mw_booster
|
||||||
|
effective gain(dB): 22.00
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): -inf
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -0.18
|
||||||
|
Power Out (dBm): 21.82
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Fiber fiber (Borås → Gothenburg)
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 67.64
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 13.53
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -11.53
|
||||||
|
Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
|
||||||
|
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
|
||||||
|
effective gain(dB): 13.53
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 13.54
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): 8.30
|
||||||
|
Power Out (dBm): 21.84
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 2.00
|
||||||
|
effective pch (dBm): 2.00
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Roadm roadm_Gothenburg
|
||||||
|
effective loss (dB): 22.00
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Transceiver trx_Gothenburg
|
||||||
|
GSNR (0.1nm, dB): 19.27
|
||||||
|
GSNR (signal bw, dB): 15.24
|
||||||
|
OSNR ASE (0.1nm, dB): 21.84
|
||||||
|
OSNR ASE (signal bw, dB): 17.82
|
||||||
|
CD (ps/nm): 8350.42
|
||||||
|
PMD (ps): 7.99
|
||||||
|
PDL (dB): 3.74
|
||||||
|
|
||||||
|
Transmission result for input power = 2.00 dBm:
|
||||||
|
Final GSNR (0.1 nm): [1;36;40m19.27 dB[0m
|
||||||
|
|
||||||
|
(No source node specified: picked trx_Stockholm)
|
||||||
|
|
||||||
|
(No destination node specified: picked trx_Gothenburg)
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
[1;34;40mComputing path requests gnpy/example-data/meshTopologyExampleV2.xls into JSON format[0m
|
|
||||||
[1;34;40mList of disjunctions[0m
|
[1;34;40mList of disjunctions[0m
|
||||||
[Disjunction 3
|
[Disjunction 3
|
||||||
relaxable: false
|
relaxable: false
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Transceiver Site_A
|
|||||||
OSNR ASE (signal bw, dB): 35.92
|
OSNR ASE (signal bw, dB): 35.92
|
||||||
CD (ps/nm): 0.00
|
CD (ps/nm): 0.00
|
||||||
PMD (ps): 0.00
|
PMD (ps): 0.00
|
||||||
|
PDL (dB): 0.00
|
||||||
Fiber Span1
|
Fiber Span1
|
||||||
type_variety: SSMF
|
type_variety: SSMF
|
||||||
length (km): 80.00
|
length (km): 80.00
|
||||||
@@ -42,6 +43,7 @@ Transceiver Site_B
|
|||||||
OSNR ASE (signal bw, dB): 29.21
|
OSNR ASE (signal bw, dB): 29.21
|
||||||
CD (ps/nm): 1336.00
|
CD (ps/nm): 1336.00
|
||||||
PMD (ps): 0.36
|
PMD (ps): 0.36
|
||||||
|
PDL (dB): 0.00
|
||||||
|
|
||||||
Transmission result for input power = 0.00 dBm:
|
Transmission result for input power = 0.00 dBm:
|
||||||
Final GSNR (0.1 nm): [1;36;40m31.17 dB[0m
|
Final GSNR (0.1 nm): [1;36;40m31.17 dB[0m
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Transceiver Site_A
|
|||||||
OSNR ASE (signal bw, dB): 35.92
|
OSNR ASE (signal bw, dB): 35.92
|
||||||
CD (ps/nm): 0.00
|
CD (ps/nm): 0.00
|
||||||
PMD (ps): 0.00
|
PMD (ps): 0.00
|
||||||
|
PDL (dB): 0.00
|
||||||
RamanFiber Span1
|
RamanFiber Span1
|
||||||
type_variety: SSMF
|
type_variety: SSMF
|
||||||
length (km): 80.00
|
length (km): 80.00
|
||||||
@@ -21,109 +22,112 @@ RamanFiber Span1
|
|||||||
total loss (dB): 17.00
|
total loss (dB): 17.00
|
||||||
(includes conn loss (dB) in: 0.50 out: 0.50)
|
(includes conn loss (dB) in: 0.50 out: 0.50)
|
||||||
(conn loss out includes EOL margin defined in eqpt_config.json)
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
pch out (dBm): -7.74
|
pch out (dBm): -7.71
|
||||||
|
Fused Fused1
|
||||||
|
loss (dB): 0.00
|
||||||
Edfa Edfa1
|
Edfa Edfa1
|
||||||
type_variety: std_low_gain
|
type_variety: std_low_gain
|
||||||
effective gain(dB): 5.74
|
effective gain(dB): 5.71
|
||||||
(before att_in and before output VOA)
|
(before att_in and before output VOA)
|
||||||
noise figure (dB): 13.26
|
noise figure (dB): 13.29
|
||||||
(including att_in)
|
(including att_in)
|
||||||
pad att_in (dB): 2.26
|
pad att_in (dB): 2.29
|
||||||
Power In (dBm): 11.07
|
Power In (dBm): 11.11
|
||||||
Power Out (dBm): 16.82
|
Power Out (dBm): 16.82
|
||||||
Delta_P (dB): -2.00
|
Delta_P (dB): -2.00
|
||||||
target pch (dBm): -2.00
|
target pch (dBm): -2.00
|
||||||
effective pch (dBm): -2.00
|
effective pch (dBm): -2.00
|
||||||
output VOA (dB): 0.00
|
output VOA (dB): 0.00
|
||||||
Transceiver Site_B
|
Transceiver Site_B
|
||||||
GSNR (0.1nm, dB): 31.43
|
GSNR (0.1nm, dB): 31.44
|
||||||
GSNR (signal bw, dB): 27.35
|
GSNR (signal bw, dB): 27.36
|
||||||
OSNR ASE (0.1nm, dB): 34.18
|
OSNR ASE (0.1nm, dB): 34.22
|
||||||
OSNR ASE (signal bw, dB): 30.10
|
OSNR ASE (signal bw, dB): 30.14
|
||||||
CD (ps/nm): 1336.00
|
CD (ps/nm): 1336.00
|
||||||
PMD (ps): 0.36
|
PMD (ps): 0.36
|
||||||
|
PDL (dB): 0.00
|
||||||
|
|
||||||
Transmission result for input power = 0.00 dBm:
|
Transmission result for input power = 0.00 dBm:
|
||||||
Final GSNR (0.1 nm): [1;36;40m31.43 dB[0m
|
Final GSNR (0.1 nm): [1;36;40m31.44 dB[0m
|
||||||
|
|
||||||
The GSNR per channel at the end of the line is:
|
The GSNR per channel at the end of the line is:
|
||||||
Ch. # Channel frequency (THz) Channel power (dBm) OSNR ASE (signal bw, dB) SNR NLI (signal bw, dB) GSNR (signal bw, dB)
|
Ch. # Channel frequency (THz) Channel power (dBm) OSNR ASE (signal bw, dB) SNR NLI (signal bw, dB) GSNR (signal bw, dB)
|
||||||
1 191.35 0.21 31.56 31.47 28.50
|
1 191.35 0.18 31.61 31.43 28.51
|
||||||
2 191.40 0.17 31.54 31.38 28.45
|
2 191.40 0.14 31.59 31.34 28.45
|
||||||
3 191.45 0.14 31.52 31.30 28.40
|
3 191.45 0.11 31.57 31.26 28.40
|
||||||
4 191.50 0.10 31.50 31.22 28.34
|
4 191.50 0.07 31.55 31.17 28.35
|
||||||
5 191.55 0.04 31.47 31.14 28.29
|
5 191.55 0.02 31.52 31.09 28.29
|
||||||
6 191.60 -0.02 31.44 31.06 28.23
|
6 191.60 -0.04 31.49 31.02 28.24
|
||||||
7 191.65 -0.08 31.41 30.98 28.18
|
7 191.65 -0.10 31.46 30.94 28.18
|
||||||
8 191.70 -0.14 31.37 30.90 28.12
|
8 191.70 -0.16 31.43 30.86 28.13
|
||||||
9 191.75 -0.20 31.34 30.83 28.07
|
9 191.75 -0.21 31.40 30.79 28.07
|
||||||
10 191.80 -0.26 31.31 30.75 28.01
|
10 191.80 -0.28 31.36 30.71 28.02
|
||||||
11 191.85 -0.33 31.27 30.68 27.96
|
11 191.85 -0.34 31.33 30.64 27.96
|
||||||
12 191.90 -0.39 31.24 30.61 27.90
|
12 191.90 -0.40 31.29 30.57 27.91
|
||||||
13 191.95 -0.46 31.20 30.54 27.85
|
13 191.95 -0.47 31.26 30.50 27.85
|
||||||
14 192.00 -0.52 31.17 30.47 27.79
|
14 192.00 -0.53 31.22 30.43 27.80
|
||||||
15 192.05 -0.59 31.13 30.40 27.74
|
15 192.05 -0.60 31.18 30.36 27.74
|
||||||
16 192.10 -0.66 31.10 30.33 27.69
|
16 192.10 -0.66 31.15 30.30 27.69
|
||||||
17 192.15 -0.72 31.06 30.26 27.63
|
17 192.15 -0.73 31.11 30.23 27.64
|
||||||
18 192.20 -0.79 31.02 30.20 27.58
|
18 192.20 -0.79 31.07 30.16 27.58
|
||||||
19 192.25 -0.86 30.98 30.21 27.57
|
19 192.25 -0.86 31.04 30.17 27.57
|
||||||
20 192.30 -0.94 30.94 30.21 27.55
|
20 192.30 -0.94 30.99 30.18 27.56
|
||||||
21 192.35 -1.01 30.90 30.22 27.54
|
21 192.35 -1.01 30.95 30.19 27.54
|
||||||
22 192.40 -1.09 30.86 30.23 27.52
|
22 192.40 -1.08 30.91 30.20 27.53
|
||||||
23 192.45 -1.16 30.81 30.23 27.50
|
23 192.45 -1.16 30.86 30.20 27.51
|
||||||
24 192.50 -1.24 30.77 30.24 27.49
|
24 192.50 -1.23 30.82 30.21 27.49
|
||||||
25 192.55 -1.31 30.73 30.25 27.47
|
25 192.55 -1.30 30.78 30.22 27.48
|
||||||
26 192.60 -1.38 30.69 30.25 27.46
|
26 192.60 -1.37 30.74 30.23 27.46
|
||||||
27 192.65 -1.45 30.65 30.26 27.44
|
27 192.65 -1.44 30.70 30.23 27.45
|
||||||
28 192.70 -1.52 30.61 30.27 27.42
|
28 192.70 -1.51 30.65 30.24 27.43
|
||||||
29 192.75 -1.59 30.56 30.28 27.41
|
29 192.75 -1.58 30.61 30.25 27.42
|
||||||
30 192.80 -1.66 30.52 30.28 27.39
|
30 192.80 -1.65 30.57 30.26 27.40
|
||||||
31 192.85 -1.73 30.48 30.29 27.37
|
31 192.85 -1.72 30.53 30.27 27.38
|
||||||
32 192.90 -1.80 30.44 30.30 27.36
|
32 192.90 -1.79 30.48 30.27 27.37
|
||||||
33 192.95 -1.87 30.39 30.30 27.34
|
33 192.95 -1.86 30.44 30.28 27.35
|
||||||
34 193.00 -1.94 30.35 30.31 27.32
|
34 193.00 -1.93 30.40 30.29 27.33
|
||||||
35 193.05 -2.01 30.31 30.32 27.30
|
35 193.05 -2.00 30.35 30.30 27.32
|
||||||
36 193.10 -2.08 30.27 30.33 27.29
|
36 193.10 -2.07 30.31 30.30 27.30
|
||||||
37 193.15 -2.15 30.22 30.33 27.27
|
37 193.15 -2.14 30.27 30.31 27.28
|
||||||
38 193.20 -2.22 30.18 30.35 27.25
|
38 193.20 -2.20 30.22 30.33 27.27
|
||||||
39 193.25 -2.29 30.14 30.37 27.24
|
39 193.25 -2.27 30.18 30.35 27.25
|
||||||
40 193.30 -2.36 30.09 30.39 27.23
|
40 193.30 -2.34 30.14 30.37 27.24
|
||||||
41 193.35 -2.43 30.05 30.40 27.21
|
41 193.35 -2.41 30.09 30.38 27.23
|
||||||
42 193.40 -2.49 30.01 30.42 27.20
|
42 193.40 -2.48 30.05 30.40 27.21
|
||||||
43 193.45 -2.56 29.96 30.44 27.18
|
43 193.45 -2.55 30.00 30.42 27.20
|
||||||
44 193.50 -2.63 29.92 30.46 27.17
|
44 193.50 -2.61 29.96 30.44 27.18
|
||||||
45 193.55 -2.70 29.87 30.47 27.15
|
45 193.55 -2.69 29.91 30.46 27.16
|
||||||
46 193.60 -2.78 29.83 30.49 27.13
|
46 193.60 -2.76 29.86 30.47 27.15
|
||||||
47 193.65 -2.85 29.78 30.51 27.12
|
47 193.65 -2.83 29.82 30.49 27.13
|
||||||
48 193.70 -2.92 29.73 30.53 27.10
|
48 193.70 -2.90 29.77 30.51 27.11
|
||||||
49 193.75 -2.99 29.68 30.54 27.08
|
49 193.75 -2.98 29.72 30.53 27.10
|
||||||
50 193.80 -3.06 29.64 30.56 27.06
|
50 193.80 -3.05 29.67 30.55 27.08
|
||||||
51 193.85 -3.14 29.59 30.58 27.05
|
51 193.85 -3.12 29.62 30.57 27.06
|
||||||
52 193.90 -3.21 29.54 30.60 27.03
|
52 193.90 -3.19 29.58 30.58 27.04
|
||||||
53 193.95 -3.28 29.49 30.62 27.01
|
53 193.95 -3.26 29.53 30.60 27.02
|
||||||
54 194.00 -3.35 29.44 30.64 26.99
|
54 194.00 -3.33 29.48 30.62 27.00
|
||||||
55 194.05 -3.42 29.39 30.65 26.97
|
55 194.05 -3.41 29.43 30.64 26.98
|
||||||
56 194.10 -3.50 29.34 30.67 26.95
|
56 194.10 -3.48 29.38 30.66 26.96
|
||||||
57 194.15 -3.57 29.29 30.73 26.94
|
57 194.15 -3.55 29.33 30.72 26.96
|
||||||
58 194.20 -3.64 29.24 30.79 26.94
|
58 194.20 -3.63 29.28 30.78 26.95
|
||||||
59 194.25 -3.72 29.19 30.85 26.93
|
59 194.25 -3.70 29.23 30.83 26.95
|
||||||
60 194.30 -3.79 29.14 30.91 26.93
|
60 194.30 -3.77 29.18 30.89 26.94
|
||||||
61 194.35 -3.86 29.09 30.97 26.92
|
61 194.35 -3.85 29.12 30.96 26.93
|
||||||
62 194.40 -3.93 29.04 31.03 26.91
|
62 194.40 -3.92 29.07 31.02 26.93
|
||||||
63 194.45 -4.01 28.99 31.09 26.90
|
63 194.45 -3.99 29.02 31.08 26.92
|
||||||
64 194.50 -4.08 28.94 31.15 26.90
|
64 194.50 -4.06 28.97 31.14 26.91
|
||||||
65 194.55 -4.14 28.89 31.22 26.89
|
65 194.55 -4.13 28.92 31.21 26.91
|
||||||
66 194.60 -4.21 28.85 31.28 26.88
|
66 194.60 -4.19 28.88 31.27 26.90
|
||||||
67 194.65 -4.28 28.80 31.35 26.88
|
67 194.65 -4.26 28.83 31.34 26.89
|
||||||
68 194.70 -4.34 28.75 31.41 26.87
|
68 194.70 -4.33 28.78 31.41 26.89
|
||||||
69 194.75 -4.41 28.70 31.48 26.86
|
69 194.75 -4.39 28.73 31.47 26.88
|
||||||
70 194.80 -4.47 28.66 31.55 26.86
|
70 194.80 -4.46 28.68 31.54 26.87
|
||||||
71 194.85 -4.54 28.61 31.62 26.85
|
71 194.85 -4.52 28.64 31.61 26.86
|
||||||
72 194.90 -4.60 28.56 31.69 26.84
|
72 194.90 -4.59 28.59 31.68 26.86
|
||||||
73 194.95 -4.67 28.51 31.77 26.83
|
73 194.95 -4.65 28.54 31.76 26.85
|
||||||
74 195.00 -4.73 28.47 31.84 26.82
|
74 195.00 -4.72 28.49 31.83 26.84
|
||||||
75 195.05 -4.80 28.42 31.91 26.81
|
75 195.05 -4.78 28.44 31.91 26.83
|
||||||
76 195.10 -4.86 28.37 31.91 26.78
|
76 195.10 -4.85 28.39 31.91 26.79
|
||||||
|
|
||||||
(No source node specified: picked Site_A)
|
(No source node specified: picked Site_A)
|
||||||
|
|
||||||
|
|||||||
328
tests/invocation/transmission_saturated
Normal file
328
tests/invocation/transmission_saturated
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
There are 96 channels propagating
|
||||||
|
Power mode is set to True
|
||||||
|
=> it can be modified in eqpt_config.json - Span
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Lorient_KMA to Loudeac
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING[0m: WARNING: effective gain in Node east edfa in Lannion_CAS to Stbrieuc is above user specified amplifier std_low_gain
|
||||||
|
max flat gain: 16dB ; required gain: 23.0dB. Please check amplifier type.
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Rennes_STA to Stbrieuc
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING[0m: WARNING: effective gain in Node east edfa in Lannion_CAS to Morlaix is above user specified amplifier std_low_gain
|
||||||
|
max flat gain: 16dB ; required gain: 23.5dB. Please check amplifier type.
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Brest_KLA to Morlaix
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Lorient_KMA to Loudeac
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING[0m: WARNING: effective gain in Node west edfa in Lannion_CAS to Corlay is above user specified amplifier test
|
||||||
|
max flat gain: 25dB ; required gain: 29.82dB. Please check amplifier type.
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Lorient_KMA to Vannes_KBE
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Vannes_KBE to Lorient_KMA
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Lorient_KMA to Quimper
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Quimper to Lorient_KMA
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Brest_KLA to Quimper
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Vannes_KBE to Lorient_KMA
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Lorient_KMA to Vannes_KBE
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Vannes_KBE to Ploermel
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Ploermel to Vannes_KBE
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Rennes_STA to Ploermel
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Rennes_STA to Stbrieuc
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Stbrieuc to Rennes_STA
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Lannion_CAS to Stbrieuc
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Rennes_STA to Ploermel
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Vannes_KBE to Ploermel
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Brest_KLA to Morlaix
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING[0m: WARNING: effective gain in Node east edfa in Brest_KLA to Quimper is above user specified amplifier std_low_gain
|
||||||
|
max flat gain: 16dB ; required gain: 23.0dB. Please check amplifier type.
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in Quimper to Lorient_KMA
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in Lorient_KMA to Quimper
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in a to b
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in b to a
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in a to c
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in c to a
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in b to a
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in a to b
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in b to f
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in f to b
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in c to a
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in a to c
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in d to c
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in c to f
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in f to c
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in d to c
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in c to d
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in d to e
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in e to d
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in e to d
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in d to e
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in e to g
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in g to e
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in f to c
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in c to f
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in f to b
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in b to f
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in f to h
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in h to f
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in g to e
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in e to g
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in g to h
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in h to g
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in h to f
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in f to h
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node east edfa in h to g
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
[1;31;40mWARNING:[0m target gain and power in node west edfa in g to h
|
||||||
|
is beyond all available amplifiers capabilities and/or extended_gain_range:
|
||||||
|
a power reduction of -1.82 is applied
|
||||||
|
|
||||||
|
|
||||||
|
There are 3 fiber spans over 130 km between trx Lannion_CAS and trx Lorient_KMA
|
||||||
|
|
||||||
|
Now propagating between trx Lannion_CAS and trx Lorient_KMA:
|
||||||
|
|
||||||
|
Propagating with input power = [1;36;40m3.00 dBm[0m:
|
||||||
|
Transceiver trx Lannion_CAS
|
||||||
|
GSNR (0.1nm, dB): 100.00
|
||||||
|
GSNR (signal bw, dB): 95.92
|
||||||
|
OSNR ASE (0.1nm, dB): 100.00
|
||||||
|
OSNR ASE (signal bw, dB): 95.92
|
||||||
|
CD (ps/nm): 0.00
|
||||||
|
PMD (ps): 0.00
|
||||||
|
PDL (dB): 0.00
|
||||||
|
Roadm roadm Lannion_CAS
|
||||||
|
effective loss (dB): 23.00
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Edfa east edfa in Lannion_CAS to Corlay
|
||||||
|
type_variety: test
|
||||||
|
effective gain(dB): 21.18
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 6.13
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -0.18
|
||||||
|
Power Out (dBm): 21.01
|
||||||
|
Delta_P (dB): 0.00
|
||||||
|
target pch (dBm): 3.00
|
||||||
|
effective pch (dBm): 1.18
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Fiber fiber (Lannion_CAS → Corlay)-F061
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 20.00
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 4.00
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -2.82
|
||||||
|
Fused west fused spans in Corlay
|
||||||
|
loss (dB): 1.00
|
||||||
|
Fiber fiber (Corlay → Loudeac)-F010
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 50.00
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 10.00
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -13.82
|
||||||
|
Fused west fused spans in Loudeac
|
||||||
|
loss (dB): 1.00
|
||||||
|
Fiber fiber (Loudeac → Lorient_KMA)-F054
|
||||||
|
type_variety: SSMF
|
||||||
|
length (km): 60.00
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
total loss (dB): 12.00
|
||||||
|
(includes conn loss (dB) in: 0.00 out: 0.00)
|
||||||
|
(conn loss out includes EOL margin defined in eqpt_config.json)
|
||||||
|
pch out (dBm): -26.82
|
||||||
|
Edfa west edfa in Lorient_KMA to Loudeac
|
||||||
|
type_variety: test
|
||||||
|
effective gain(dB): 28.00
|
||||||
|
(before att_in and before output VOA)
|
||||||
|
noise figure (dB): 5.76
|
||||||
|
(including att_in)
|
||||||
|
pad att_in (dB): 0.00
|
||||||
|
Power In (dBm): -6.99
|
||||||
|
Power Out (dBm): 21.04
|
||||||
|
Delta_P (dB): -1.82
|
||||||
|
target pch (dBm): 1.18
|
||||||
|
effective pch (dBm): 1.18
|
||||||
|
output VOA (dB): 0.00
|
||||||
|
Roadm roadm Lorient_KMA
|
||||||
|
effective loss (dB): 21.18
|
||||||
|
pch out (dBm): -20.00
|
||||||
|
Transceiver trx Lorient_KMA
|
||||||
|
GSNR (0.1nm, dB): 23.94
|
||||||
|
GSNR (signal bw, dB): 19.85
|
||||||
|
OSNR ASE (0.1nm, dB): 24.29
|
||||||
|
OSNR ASE (signal bw, dB): 20.20
|
||||||
|
CD (ps/nm): 2171.00
|
||||||
|
PMD (ps): 0.46
|
||||||
|
PDL (dB): 0.00
|
||||||
|
|
||||||
|
Transmission result for input power = 3.00 dBm:
|
||||||
|
Final GSNR (0.1 nm): [1;36;40m23.94 dB[0m
|
||||||
|
|
||||||
|
(Invalid source node 'lannion' replaced with trx Lannion_CAS)
|
||||||
|
|
||||||
|
(Invalid destination node 'lorient' replaced with trx Lorient_KMA)
|
||||||
@@ -80,13 +80,12 @@ def si(nch_and_spacing, bw):
|
|||||||
def test_variable_gain_nf(gain, nf_expected, setup_edfa_variable_gain, si):
|
def test_variable_gain_nf(gain, nf_expected, setup_edfa_variable_gain, si):
|
||||||
"""=> unitary test for variable gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
"""=> unitary test for variable gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
||||||
edfa = setup_edfa_variable_gain
|
edfa = setup_edfa_variable_gain
|
||||||
frequencies = array([c.frequency for c in si.carriers])
|
si.signal /= db2lin(gain)
|
||||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
si.nli /= db2lin(gain)
|
||||||
pin = pin / db2lin(gain)
|
si.ase /= db2lin(gain)
|
||||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
|
||||||
edfa.operational.gain_target = gain
|
edfa.operational.gain_target = gain
|
||||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels))
|
||||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
edfa.interpol_params(si)
|
||||||
result = edfa.nf
|
result = edfa.nf
|
||||||
assert pytest.approx(nf_expected, abs=0.01) == result[0]
|
assert pytest.approx(nf_expected, abs=0.01) == result[0]
|
||||||
|
|
||||||
@@ -95,23 +94,20 @@ def test_variable_gain_nf(gain, nf_expected, setup_edfa_variable_gain, si):
|
|||||||
def test_fixed_gain_nf(gain, nf_expected, setup_edfa_fixed_gain, si):
|
def test_fixed_gain_nf(gain, nf_expected, setup_edfa_fixed_gain, si):
|
||||||
"""=> unitary test for fixed gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
"""=> unitary test for fixed gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
|
||||||
edfa = setup_edfa_fixed_gain
|
edfa = setup_edfa_fixed_gain
|
||||||
frequencies = array([c.frequency for c in si.carriers])
|
si.signal /= db2lin(gain)
|
||||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
si.nli /= db2lin(gain)
|
||||||
pin = pin / db2lin(gain)
|
si.ase /= db2lin(gain)
|
||||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
|
||||||
edfa.operational.gain_target = gain
|
edfa.operational.gain_target = gain
|
||||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels))
|
||||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
edfa.interpol_params(si)
|
||||||
|
|
||||||
assert pytest.approx(nf_expected, abs=0.01) == edfa.nf[0]
|
assert pytest.approx(nf_expected, abs=0.01) == edfa.nf[0]
|
||||||
|
|
||||||
|
|
||||||
def test_si(si, nch_and_spacing):
|
def test_si(si, nch_and_spacing):
|
||||||
"""basic total power check of the channel comb generation"""
|
"""basic total power check of the channel comb generation"""
|
||||||
nb_channel = nch_and_spacing[0]
|
nb_channel = nch_and_spacing[0]
|
||||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
p_tot = sum(si.signal + si.ase + si.nli)
|
||||||
p_tot = pin.sum()
|
expected_p_tot = si.signal[0] * nb_channel
|
||||||
expected_p_tot = si.carriers[0].power.signal * nb_channel
|
|
||||||
assert pytest.approx(expected_p_tot, abs=0.01) == p_tot
|
assert pytest.approx(expected_p_tot, abs=0.01) == p_tot
|
||||||
|
|
||||||
|
|
||||||
@@ -122,14 +118,13 @@ def test_compare_nf_models(gain, setup_edfa_variable_gain, si):
|
|||||||
between gain_min and gain_flatmax some discrepancy is expected but target < 0.5dB
|
between gain_min and gain_flatmax some discrepancy is expected but target < 0.5dB
|
||||||
=> unitary test for Edfa._calc_nf (and Edfa.interpol_params)"""
|
=> unitary test for Edfa._calc_nf (and Edfa.interpol_params)"""
|
||||||
edfa = setup_edfa_variable_gain
|
edfa = setup_edfa_variable_gain
|
||||||
frequencies = array([c.frequency for c in si.carriers])
|
si.signal /= db2lin(gain)
|
||||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
si.nli /= db2lin(gain)
|
||||||
pin = pin / db2lin(gain)
|
si.ase /= db2lin(gain)
|
||||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
|
||||||
edfa.operational.gain_target = gain
|
edfa.operational.gain_target = gain
|
||||||
# edfa is variable gain type
|
# edfa is variable gain type
|
||||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels))
|
||||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
edfa.interpol_params(si)
|
||||||
nf_model = edfa.nf[0]
|
nf_model = edfa.nf[0]
|
||||||
|
|
||||||
# change edfa type variety to a polynomial
|
# change edfa type variety to a polynomial
|
||||||
@@ -155,7 +150,7 @@ def test_compare_nf_models(gain, setup_edfa_variable_gain, si):
|
|||||||
edfa = Edfa(**el_config)
|
edfa = Edfa(**el_config)
|
||||||
|
|
||||||
# edfa is variable gain type
|
# edfa is variable gain type
|
||||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
edfa.interpol_params(si)
|
||||||
nf_poly = edfa.nf[0]
|
nf_poly = edfa.nf[0]
|
||||||
print(nf_poly, nf_model)
|
print(nf_poly, nf_model)
|
||||||
assert pytest.approx(nf_model, abs=0.5) == nf_poly
|
assert pytest.approx(nf_model, abs=0.5) == nf_poly
|
||||||
@@ -183,21 +178,16 @@ def test_ase_noise(gain, si, setup_trx, bw):
|
|||||||
si = span(si)
|
si = span(si)
|
||||||
print(span)
|
print(span)
|
||||||
|
|
||||||
frequencies = array([c.frequency for c in si.carriers])
|
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, neq_ch=lin2db(si.number_of_channels))
|
||||||
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
edfa.interpol_params(si)
|
||||||
baud_rates = array([c.baud_rate for c in si.carriers])
|
|
||||||
pref = Pref(0, -gain, lin2db(len(frequencies)))
|
|
||||||
edfa.interpol_params(frequencies, pin, baud_rates, pref)
|
|
||||||
nf = edfa.nf
|
nf = edfa.nf
|
||||||
print('nf', nf)
|
print('nf', nf)
|
||||||
pin = lin2db(pin[0] * 1e3)
|
pin = lin2db((si.signal[0] + si.ase[0] + si.nli[0]) * 1e3)
|
||||||
osnr_expected = pin - nf[0] + 58
|
osnr_expected = pin - nf[0] + 58
|
||||||
|
|
||||||
si = edfa(si)
|
si = edfa(si)
|
||||||
print(edfa)
|
print(edfa)
|
||||||
pout = array([c.power.signal for c in si.carriers])
|
osnr = lin2db(si.signal[0] / si.ase[0]) - lin2db(12.5e9 / bw)
|
||||||
pase = array([c.power.ase for c in si.carriers])
|
|
||||||
osnr = lin2db(pout[0] / pase[0]) - lin2db(12.5e9 / bw)
|
|
||||||
assert pytest.approx(osnr_expected, abs=0.01) == osnr
|
assert pytest.approx(osnr_expected, abs=0.01) == osnr
|
||||||
|
|
||||||
trx = setup_trx
|
trx = setup_trx
|
||||||
|
|||||||
@@ -4,18 +4,18 @@
|
|||||||
# License: BSD 3-Clause Licence
|
# License: BSD 3-Clause Licence
|
||||||
# Copyright (c) 2018, Telecom Infra Project
|
# Copyright (c) 2018, Telecom Infra Project
|
||||||
|
|
||||||
"""
|
'''
|
||||||
@author: esther.lerouzic
|
@author: esther.lerouzic
|
||||||
checks that computed paths are disjoint as specified in the json service file
|
checks that computed paths are disjoint as specified in the json service file
|
||||||
that computed paths do not loop
|
that computed paths do not loop
|
||||||
that include node constraints are correctly taken into account
|
that include node constraints are correctly taken into account
|
||||||
"""
|
'''
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pytest
|
import pytest
|
||||||
from gnpy.core.equipment import trx_mode_params
|
from gnpy.core.equipment import trx_mode_params
|
||||||
from gnpy.core.network import build_network
|
from gnpy.core.network import build_network
|
||||||
from gnpy.core.exceptions import ServiceError
|
from gnpy.core.exceptions import ServiceError, DisjunctionError
|
||||||
from gnpy.core.utils import automatic_nch, lin2db
|
from gnpy.core.utils import automatic_nch, lin2db
|
||||||
from gnpy.core.elements import Roadm
|
from gnpy.core.elements import Roadm
|
||||||
from gnpy.topology.request import (compute_path_dsjctn, isdisjoint, find_reversed_path, PathRequest,
|
from gnpy.topology.request import (compute_path_dsjctn, isdisjoint, find_reversed_path, PathRequest,
|
||||||
@@ -31,8 +31,8 @@ EQPT_LIBRARY_NAME = Path(__file__).parent.parent / 'tests/data/eqpt_config.json'
|
|||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def serv(test_setup):
|
def serv(test_setup):
|
||||||
""" common setup for service list
|
''' common setup for service list
|
||||||
"""
|
'''
|
||||||
network, equipment = test_setup
|
network, equipment = test_setup
|
||||||
data = load_requests(SERVICE_FILE_NAME, equipment, bidir=False, network=network, network_filename=NETWORK_FILE_NAME)
|
data = load_requests(SERVICE_FILE_NAME, equipment, bidir=False, network=network, network_filename=NETWORK_FILE_NAME)
|
||||||
rqs = requests_from_json(data, equipment)
|
rqs = requests_from_json(data, equipment)
|
||||||
@@ -43,12 +43,12 @@ def serv(test_setup):
|
|||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def test_setup():
|
def test_setup():
|
||||||
""" common setup for tests: builds network, equipment and oms only once
|
''' common setup for tests: builds network, equipment and oms only once
|
||||||
"""
|
'''
|
||||||
equipment = load_equipment(EQPT_LIBRARY_NAME)
|
equipment = load_equipment(EQPT_LIBRARY_NAME)
|
||||||
network = load_network(NETWORK_FILE_NAME, equipment)
|
network = load_network(NETWORK_FILE_NAME, equipment)
|
||||||
# Build the network once using the default power defined in SI in eqpt config
|
# Build the network once using the default power defined in SI in eqpt config
|
||||||
# power density : db2linp(ower_dbm": 0)/power_dbm": 0 * nb channels as defined by
|
# power density : db2linp(ower_dbm': 0)/power_dbm': 0 * nb channels as defined by
|
||||||
# spacing, f_min and f_max
|
# spacing, f_min and f_max
|
||||||
p_db = equipment['SI']['default'].power_dbm
|
p_db = equipment['SI']['default'].power_dbm
|
||||||
|
|
||||||
@@ -61,9 +61,9 @@ def test_setup():
|
|||||||
|
|
||||||
|
|
||||||
def test_disjunction(serv):
|
def test_disjunction(serv):
|
||||||
""" service_file contains sevaral combination of disjunction constraint. The test checks
|
''' service_file contains sevaral combination of disjunction constraint. The test checks
|
||||||
that computed paths with disjunction constraint are effectively disjoint
|
that computed paths with disjunction constraint are effectively disjoint
|
||||||
"""
|
'''
|
||||||
network, equipment, rqs, dsjn = serv
|
network, equipment, rqs, dsjn = serv
|
||||||
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
||||||
print(dsjn)
|
print(dsjn)
|
||||||
@@ -86,8 +86,8 @@ def test_disjunction(serv):
|
|||||||
|
|
||||||
|
|
||||||
def test_does_not_loop_back(serv):
|
def test_does_not_loop_back(serv):
|
||||||
""" check that computed paths do not loop back ie each element appears only once
|
''' check that computed paths do not loop back ie each element appears only once
|
||||||
"""
|
'''
|
||||||
network, equipment, rqs, dsjn = serv
|
network, equipment, rqs, dsjn = serv
|
||||||
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
||||||
test = True
|
test = True
|
||||||
@@ -107,33 +107,35 @@ def test_does_not_loop_back(serv):
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
def create_rq(equipment, srce, dest, bdir, nd_list, ls_list):
|
def create_rq(equipment, srce, dest, bdir, node_list, loose_list, rqid='test_request'):
|
||||||
""" create the usual request list according to parameters
|
''' create the usual request list according to parameters
|
||||||
"""
|
'''
|
||||||
requests_list = []
|
requests_list = []
|
||||||
params = {}
|
params = {
|
||||||
params['request_id'] = 'test_request'
|
'request_id': rqid,
|
||||||
params['source'] = srce
|
'source': srce,
|
||||||
params['bidir'] = bdir
|
'bidir': bdir,
|
||||||
params['destination'] = dest
|
'destination': dest,
|
||||||
params['trx_type'] = 'Voyager'
|
'trx_type': 'Voyager',
|
||||||
params['trx_mode'] = 'mode 1'
|
'trx_mode': 'mode 1',
|
||||||
|
'spacing': 50000000000.0,
|
||||||
|
'nodes_list': node_list,
|
||||||
|
'loose_list': loose_list,
|
||||||
|
'path_bandwidth': 100.0e9,
|
||||||
|
'power': 1.0,
|
||||||
|
'effective_freq_slot': None,
|
||||||
|
}
|
||||||
params['format'] = params['trx_mode']
|
params['format'] = params['trx_mode']
|
||||||
params['spacing'] = 50000000000.0
|
|
||||||
params['nodes_list'] = nd_list
|
|
||||||
params['loose_list'] = ls_list
|
|
||||||
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True)
|
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True)
|
||||||
params.update(trx_params)
|
params.update(trx_params)
|
||||||
params['power'] = 1.0
|
|
||||||
f_min = params['f_min']
|
f_min = params['f_min']
|
||||||
f_max_from_si = params['f_max']
|
f_max_from_si = params['f_max']
|
||||||
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
|
||||||
params['path_bandwidth'] = 100000000000.0
|
|
||||||
requests_list.append(PathRequest(**params))
|
requests_list.append(PathRequest(**params))
|
||||||
return requests_list
|
return requests_list
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('srce, dest, result, pth, nd_list, ls_list', [
|
@pytest.mark.parametrize('srce, dest, result, pth, node_list, loose_list', [
|
||||||
['a', 'trx h', 'fail', 'no_path', [], []],
|
['a', 'trx h', 'fail', 'no_path', [], []],
|
||||||
['trx a', 'h', 'fail', 'no_path', [], []],
|
['trx a', 'h', 'fail', 'no_path', [], []],
|
||||||
['trx a', 'trx h', 'pass', 'found_path', [], []],
|
['trx a', 'trx h', 'pass', 'found_path', [], []],
|
||||||
@@ -148,8 +150,8 @@ def create_rq(equipment, srce, dest, bdir, nd_list, ls_list):
|
|||||||
['trx a', 'trx h', 'pass', 'found_path', ['trx a', 'roadm g'], ['STRICT', 'STRICT']],
|
['trx a', 'trx h', 'pass', 'found_path', ['trx a', 'roadm g'], ['STRICT', 'STRICT']],
|
||||||
['trx a', 'trx h', 'pass', 'found_path', ['trx h'], ['STRICT']],
|
['trx a', 'trx h', 'pass', 'found_path', ['trx h'], ['STRICT']],
|
||||||
['trx a', 'trx h', 'pass', 'found_path', ['roadm a'], ['STRICT']]])
|
['trx a', 'trx h', 'pass', 'found_path', ['roadm a'], ['STRICT']]])
|
||||||
def test_include_constraints(test_setup, srce, dest, result, pth, nd_list, ls_list):
|
def test_include_constraints(test_setup, srce, dest, result, pth, node_list, loose_list):
|
||||||
""" check that all combinations of constraints are correctly handled:
|
''' check that all combinations of constraints are correctly handled:
|
||||||
- STRICT/LOOSE
|
- STRICT/LOOSE
|
||||||
- correct names/incorrect names -> pass/fail
|
- correct names/incorrect names -> pass/fail
|
||||||
- possible include/impossible include
|
- possible include/impossible include
|
||||||
@@ -161,20 +163,82 @@ def test_include_constraints(test_setup, srce, dest, result, pth, nd_list, ls_li
|
|||||||
| cannot be applied | no_path | found_path
|
| cannot be applied | no_path | found_path
|
||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
0 | | computation stops
|
0 | | computation stops
|
||||||
"""
|
'''
|
||||||
network, equipment = test_setup
|
network, equipment = test_setup
|
||||||
dsjn = []
|
dsjn = []
|
||||||
bdir = False
|
bdir = False
|
||||||
rqs = create_rq(equipment, srce, dest, bdir, nd_list, ls_list)
|
rqs = create_rq(equipment, srce, dest, bdir, node_list, loose_list)
|
||||||
print(rqs)
|
print(rqs)
|
||||||
if result == 'fail':
|
if result == 'fail':
|
||||||
with pytest.raises(ServiceError):
|
with pytest.raises(ServiceError):
|
||||||
rqs = correct_json_route_list(network, rqs)
|
rqs = correct_json_route_list(network, rqs)
|
||||||
else:
|
else:
|
||||||
rqs = correct_json_route_list(network, rqs)
|
rqs = correct_json_route_list(network, rqs)
|
||||||
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
paths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
||||||
# if loose, one path can be returned
|
# if loose, one path can be returned
|
||||||
if pths[0]:
|
if paths[0]:
|
||||||
assert pth == 'found_path'
|
assert pth == 'found_path'
|
||||||
else:
|
else:
|
||||||
assert pth == 'no_path'
|
assert pth == 'no_path'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('dis1, dis2, node_list1, loose_list1, result, expected_paths', [
|
||||||
|
[['1', '2', '3'], ['2', '3'], [], [], 'pass',
|
||||||
|
[['roadm a', 'roadm c', 'roadm d', 'roadm e', 'roadm g'],
|
||||||
|
['roadm c', 'roadm f'],
|
||||||
|
['roadm a', 'roadm b', 'roadm f', 'roadm h']]],
|
||||||
|
[['1', '2', '3'], ['2', '3'], ['b'], ['STRICT'], 'fail', []],
|
||||||
|
[['1', '2'], ['2', '3'], [], [], 'pass',
|
||||||
|
[['roadm a', 'roadm c', 'roadm d', 'roadm e', 'roadm g'],
|
||||||
|
['roadm c', 'roadm f'],
|
||||||
|
['roadm a', 'roadm b', 'roadm f', 'roadm h']]],
|
||||||
|
[['1', '2'], ['2', '3'], ['roadm e'], ['LOOSE'], 'pass',
|
||||||
|
[['roadm a', 'roadm c', 'roadm d', 'roadm e', 'roadm g'],
|
||||||
|
['roadm c', 'roadm f'],
|
||||||
|
['roadm a', 'roadm b', 'roadm f', 'roadm h']]],
|
||||||
|
[['1', '2'], ['2', '3'], ['roadm c | roadm f'], ['LOOSE'], 'pass',
|
||||||
|
[['roadm a', 'roadm c', 'roadm d', 'roadm e', 'roadm g'],
|
||||||
|
['roadm c', 'roadm f'],
|
||||||
|
['roadm a', 'roadm b', 'roadm f', 'roadm h']]]])
|
||||||
|
def test_create_disjunction(test_setup, dis1, dis2, node_list1, loose_list1, result, expected_paths):
|
||||||
|
""" verifies that the expected result is obtained for a set of particular constraints:
|
||||||
|
in particular, verifies that:
|
||||||
|
- multiple disjunction constraints are correcly handled
|
||||||
|
- in case a loose constraint can not be met, the first alternate candidate is selected
|
||||||
|
instead of the last one (last case).
|
||||||
|
"""
|
||||||
|
network, equipment = test_setup
|
||||||
|
|
||||||
|
json_data = {
|
||||||
|
'synchronization': [{
|
||||||
|
'synchronization-id': 'x',
|
||||||
|
'svec': {
|
||||||
|
'relaxable': 'false',
|
||||||
|
'disjointness': 'node link',
|
||||||
|
'request-id-number': dis1
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'synchronization-id': 'y',
|
||||||
|
'svec': {
|
||||||
|
'relaxable': 'false',
|
||||||
|
'disjointness': 'node link',
|
||||||
|
'request-id-number': dis2
|
||||||
|
}
|
||||||
|
}]}
|
||||||
|
dsjn = disjunctions_from_json(json_data)
|
||||||
|
bdir = False
|
||||||
|
rqs = create_rq(equipment, 'trx a', 'trx g', bdir, node_list1, loose_list1, '1') +\
|
||||||
|
create_rq(equipment, 'trx c', 'trx f', bdir, [], [], '2') +\
|
||||||
|
create_rq(equipment, 'trx a', 'trx h', bdir, [], [], '3')
|
||||||
|
|
||||||
|
if result == 'fail':
|
||||||
|
with pytest.raises(DisjunctionError):
|
||||||
|
paths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
||||||
|
else:
|
||||||
|
paths = compute_path_dsjctn(network, equipment, rqs, dsjn)
|
||||||
|
path_names = []
|
||||||
|
for path in paths:
|
||||||
|
roadm_names = [e.uid for e in path if isinstance(e, Roadm)]
|
||||||
|
path_names.append(roadm_names)
|
||||||
|
assert path_names == expected_paths
|
||||||
|
# if loose, one path can be returned
|
||||||
|
|||||||
50
tests/test_info.py
Normal file
50
tests/test_info.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from numpy import array, zeros, ones
|
||||||
|
from numpy.testing import assert_array_equal
|
||||||
|
|
||||||
|
from gnpy.core.info import create_arbitrary_spectral_information
|
||||||
|
from gnpy.core.exceptions import SpectrumError
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_arbitrary_spectral_information():
|
||||||
|
si = create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12],
|
||||||
|
baud_rate=32e9, signal=[1, 1, 1])
|
||||||
|
assert_array_equal(si.baud_rate, array([32e9, 32e9, 32e9]))
|
||||||
|
assert_array_equal(si.slot_width, array([37.5e9, 37.5e9, 37.5e9]))
|
||||||
|
assert_array_equal(si.signal, ones(3))
|
||||||
|
assert_array_equal(si.nli, zeros(3))
|
||||||
|
assert_array_equal(si.ase, zeros(3))
|
||||||
|
assert_array_equal(si.roll_off, zeros(3))
|
||||||
|
assert_array_equal(si.chromatic_dispersion, zeros(3))
|
||||||
|
assert_array_equal(si.pmd, zeros(3))
|
||||||
|
assert_array_equal(si.channel_number, array([1, 2, 3]))
|
||||||
|
assert_array_equal(si.number_of_channels, 3)
|
||||||
|
assert_array_equal(si.df, array([[0, 50e9, 100e9], [-50e9, 0, 50e9], [-100e9, -50e9, 0]]))
|
||||||
|
|
||||||
|
with pytest.raises(SpectrumError, match='Spectra cannot be summed: channels overlapping.'):
|
||||||
|
si += si
|
||||||
|
|
||||||
|
si = create_arbitrary_spectral_information(frequency=array([193.35e12, 193.3e12, 193.25e12]),
|
||||||
|
slot_width=array([50e9, 50e9, 50e9]),
|
||||||
|
baud_rate=32e9, signal=array([1, 2, 3]))
|
||||||
|
assert_array_equal(si.signal, array([3, 2, 1]))
|
||||||
|
|
||||||
|
with pytest.raises(SpectrumError, match='Spectrum baud rate, including the roll off, '
|
||||||
|
r'larger than the slot width for channels: \[1, 3\].'):
|
||||||
|
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1,
|
||||||
|
baud_rate=[64e9, 32e9, 64e9], slot_width=50e9)
|
||||||
|
with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral '
|
||||||
|
r'distances between channels: \[\(1, 2\), \(3, 4\)\].'):
|
||||||
|
create_arbitrary_spectral_information(frequency=[193.26e12, 193.3e12, 193.35e12, 193.39e12], signal=1,
|
||||||
|
baud_rate=32e9, slot_width=50e9)
|
||||||
|
with pytest.raises(SpectrumError, match='Spectrum required slot widths larger than the frequency spectral '
|
||||||
|
r'distances between channels: \[\(1, 2\), \(2, 3\)\].'):
|
||||||
|
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=1, baud_rate=49e9,
|
||||||
|
roll_off=0.1)
|
||||||
|
|
||||||
|
with pytest.raises(SpectrumError,
|
||||||
|
match='Dimension mismatch in input fields.'):
|
||||||
|
create_arbitrary_spectral_information(frequency=[193.25e12, 193.3e12, 193.35e12], signal=[1, 2], baud_rate=49e9)
|
||||||
@@ -11,20 +11,24 @@ SRC_ROOT = Path(__file__).parent.parent
|
|||||||
|
|
||||||
@pytest.mark.parametrize("output, handler, args", (
|
@pytest.mark.parametrize("output, handler, args", (
|
||||||
('transmission_main_example', transmission_main_example, []),
|
('transmission_main_example', transmission_main_example, []),
|
||||||
|
('transmission_saturated', transmission_main_example,
|
||||||
|
['tests/data/testTopology_expected.json', 'lannion', 'lorient', '-e', 'tests/data/eqpt_config.json', '--pow', '3']),
|
||||||
('path_requests_run', path_requests_run, []),
|
('path_requests_run', path_requests_run, []),
|
||||||
('transmission_main_example__raman', transmission_main_example,
|
('transmission_main_example__raman', transmission_main_example,
|
||||||
['gnpy/example-data/raman_edfa_example_network.json', '--sim', 'gnpy/example-data/sim_params.json', '--show-channels', ]),
|
['gnpy/example-data/raman_edfa_example_network.json', '--sim', 'gnpy/example-data/sim_params.json', '--show-channels', ]),
|
||||||
('openroadm-Stockholm-Gothenburg', transmission_main_example,
|
('openroadm-v4-Stockholm-Gothenburg', transmission_main_example,
|
||||||
['-e', 'gnpy/example-data/eqpt_config_openroadm.json', 'gnpy/example-data/Sweden_OpenROADM_example_network.json', ]),
|
['-e', 'gnpy/example-data/eqpt_config_openroadm_ver4.json', 'gnpy/example-data/Sweden_OpenROADMv4_example_network.json', ]),
|
||||||
|
('openroadm-v5-Stockholm-Gothenburg', transmission_main_example,
|
||||||
|
['-e', 'gnpy/example-data/eqpt_config_openroadm_ver5.json', 'gnpy/example-data/Sweden_OpenROADMv5_example_network.json', ]),
|
||||||
))
|
))
|
||||||
def test_example_invocation(capfdbinary, output, handler, args):
|
def test_example_invocation(capfd, output, handler, args):
|
||||||
'''Make sure that our examples produce useful output'''
|
'''Make sure that our examples produce useful output'''
|
||||||
os.chdir(SRC_ROOT)
|
os.chdir(SRC_ROOT)
|
||||||
expected = open(SRC_ROOT / 'tests' / 'invocation' / output, mode='rb').read()
|
expected = open(SRC_ROOT / 'tests' / 'invocation' / output, mode='r', encoding='utf-8').read()
|
||||||
handler(args)
|
handler(args)
|
||||||
captured = capfdbinary.readouterr()
|
captured = capfd.readouterr()
|
||||||
assert captured.out == expected
|
assert captured.out == expected
|
||||||
assert captured.err == b''
|
assert captured.err == ''
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('program', ('gnpy-transmission-example', 'gnpy-path-request'))
|
@pytest.mark.parametrize('program', ('gnpy-transmission-example', 'gnpy-path-request'))
|
||||||
@@ -39,7 +43,7 @@ def test_run_wrapper(program):
|
|||||||
|
|
||||||
def test_conversion_xls():
|
def test_conversion_xls():
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
('gnpy-convert-xls', SRC_ROOT / 'tests' / 'data' / 'testTopology.xls', '--output', '/dev/null'),
|
('gnpy-convert-xls', SRC_ROOT / 'tests' / 'data' / 'testTopology.xls', '--output', os.path.devnull),
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, universal_newlines=True)
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, universal_newlines=True)
|
||||||
assert proc.stderr == ''
|
assert proc.stderr == ''
|
||||||
assert '/dev/null' in proc.stdout
|
assert os.path.devnull in proc.stdout
|
||||||
|
|||||||
@@ -1,26 +1,23 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from pathlib import Path
|
"""
|
||||||
|
Checks that the class SimParams behaves as a mutable Singleton.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
from gnpy.core.parameters import SimParams
|
from gnpy.core.parameters import SimParams
|
||||||
from gnpy.core.science_utils import Simulation
|
|
||||||
from gnpy.tools.json_io import load_json
|
|
||||||
|
|
||||||
TEST_DIR = Path(__file__).parent
|
|
||||||
DATA_DIR = TEST_DIR / 'data'
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('set_sim_params')
|
||||||
def test_sim_parameters():
|
def test_sim_parameters():
|
||||||
j = load_json(DATA_DIR / 'sim_params.json')
|
sim_params = {'nli_params': {}, 'raman_params': {}}
|
||||||
sim_params = SimParams(**j)
|
SimParams.set_params(sim_params)
|
||||||
Simulation.set_params(sim_params)
|
s1 = SimParams.get()
|
||||||
s1 = Simulation.get_simulation()
|
assert s1.nli_params.method == 'gn_model_analytic'
|
||||||
assert s1.sim_params.raman_params.flag_raman
|
s2 = SimParams.get()
|
||||||
s2 = Simulation.get_simulation()
|
assert not s1.raman_params.flag
|
||||||
assert s2.sim_params.raman_params.flag_raman
|
sim_params['raman_params']['flag'] = True
|
||||||
j['raman_parameters']['flag_raman'] = False
|
SimParams.set_params(sim_params)
|
||||||
sim_params = SimParams(**j)
|
assert s2.raman_params.flag
|
||||||
Simulation.set_params(sim_params)
|
assert s1.raman_params.flag
|
||||||
assert not s2.sim_params.raman_params.flag_raman
|
|
||||||
assert not s1.sim_params.raman_params.flag_raman
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import shutil
|
|||||||
from pandas import read_csv
|
from pandas import read_csv
|
||||||
from xlrd import open_workbook
|
from xlrd import open_workbook
|
||||||
import pytest
|
import pytest
|
||||||
from tests.compare import compare_networks, compare_services
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from gnpy.core.utils import automatic_nch, lin2db
|
from gnpy.core.utils import automatic_nch, lin2db
|
||||||
from gnpy.core.network import build_network
|
from gnpy.core.network import build_network
|
||||||
@@ -56,15 +55,7 @@ def test_excel_json_generation(tmpdir, xls_input, expected_json_output):
|
|||||||
actual_json_output = xls_copy.with_suffix('.json')
|
actual_json_output = xls_copy.with_suffix('.json')
|
||||||
actual = load_json(actual_json_output)
|
actual = load_json(actual_json_output)
|
||||||
unlink(actual_json_output)
|
unlink(actual_json_output)
|
||||||
expected = load_json(expected_json_output)
|
assert actual == load_json(expected_json_output)
|
||||||
|
|
||||||
results = compare_networks(expected, actual)
|
|
||||||
assert not results.elements.missing
|
|
||||||
assert not results.elements.extra
|
|
||||||
assert not results.elements.different
|
|
||||||
assert not results.connections.missing
|
|
||||||
assert not results.connections.extra
|
|
||||||
assert not results.connections.different
|
|
||||||
|
|
||||||
# assume xls entries
|
# assume xls entries
|
||||||
# test that the build network gives correct results in gain mode
|
# test that the build network gives correct results in gain mode
|
||||||
@@ -95,15 +86,7 @@ def test_auto_design_generation_fromxlsgainmode(tmpdir, xls_input, expected_json
|
|||||||
save_network(network, actual_json_output)
|
save_network(network, actual_json_output)
|
||||||
actual = load_json(actual_json_output)
|
actual = load_json(actual_json_output)
|
||||||
unlink(actual_json_output)
|
unlink(actual_json_output)
|
||||||
expected = load_json(expected_json_output)
|
assert actual == load_json(expected_json_output)
|
||||||
|
|
||||||
results = compare_networks(expected, actual)
|
|
||||||
assert not results.elements.missing
|
|
||||||
assert not results.elements.extra
|
|
||||||
assert not results.elements.different
|
|
||||||
assert not results.connections.missing
|
|
||||||
assert not results.connections.extra
|
|
||||||
assert not results.connections.different
|
|
||||||
|
|
||||||
# test that autodesign creates same file as an input file already autodesigned
|
# test that autodesign creates same file as an input file already autodesigned
|
||||||
|
|
||||||
@@ -134,15 +117,7 @@ def test_auto_design_generation_fromjson(tmpdir, json_input, power_mode):
|
|||||||
save_network(network, actual_json_output)
|
save_network(network, actual_json_output)
|
||||||
actual = load_json(actual_json_output)
|
actual = load_json(actual_json_output)
|
||||||
unlink(actual_json_output)
|
unlink(actual_json_output)
|
||||||
expected = load_json(json_input)
|
assert actual == load_json(json_input)
|
||||||
|
|
||||||
results = compare_networks(expected, actual)
|
|
||||||
assert not results.elements.missing
|
|
||||||
assert not results.elements.extra
|
|
||||||
assert not results.elements.different
|
|
||||||
assert not results.connections.missing
|
|
||||||
assert not results.connections.extra
|
|
||||||
assert not results.connections.different
|
|
||||||
|
|
||||||
# test services creation
|
# test services creation
|
||||||
|
|
||||||
@@ -162,15 +137,7 @@ def test_excel_service_json_generation(xls_input, expected_json_output):
|
|||||||
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
|
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
|
||||||
build_network(network, equipment, p_db, p_total_db)
|
build_network(network, equipment, p_db, p_total_db)
|
||||||
from_xls = read_service_sheet(xls_input, equipment, network, network_filename=DATA_DIR / 'testTopology.xls')
|
from_xls = read_service_sheet(xls_input, equipment, network, network_filename=DATA_DIR / 'testTopology.xls')
|
||||||
expected = load_json(expected_json_output)
|
assert from_xls == load_json(expected_json_output)
|
||||||
|
|
||||||
results = compare_services(expected, from_xls)
|
|
||||||
assert not results.requests.missing
|
|
||||||
assert not results.requests.extra
|
|
||||||
assert not results.requests.different
|
|
||||||
assert not results.synchronizations.missing
|
|
||||||
assert not results.synchronizations.extra
|
|
||||||
assert not results.synchronizations.different
|
|
||||||
|
|
||||||
# TODO verify that requested bandwidth is not zero !
|
# TODO verify that requested bandwidth is not zero !
|
||||||
|
|
||||||
@@ -243,35 +210,6 @@ def test_csv_response_generation(tmpdir, json_input):
|
|||||||
print(type(list(resp[column])[-1]))
|
print(type(list(resp[column])[-1]))
|
||||||
|
|
||||||
|
|
||||||
def compare_response(exp_resp, act_resp):
|
|
||||||
""" False if the keys are different in the nested dicts as well
|
|
||||||
"""
|
|
||||||
print(exp_resp)
|
|
||||||
print(act_resp)
|
|
||||||
test = True
|
|
||||||
for key in act_resp.keys():
|
|
||||||
if key not in exp_resp.keys():
|
|
||||||
print(f'{key} is not expected')
|
|
||||||
return False
|
|
||||||
if isinstance(act_resp[key], dict):
|
|
||||||
test = compare_response(exp_resp[key], act_resp[key])
|
|
||||||
if test:
|
|
||||||
for key in exp_resp.keys():
|
|
||||||
if key not in act_resp.keys():
|
|
||||||
print(f'{key} is expected')
|
|
||||||
return False
|
|
||||||
if isinstance(exp_resp[key], dict):
|
|
||||||
test = compare_response(exp_resp[key], act_resp[key])
|
|
||||||
|
|
||||||
# at this point exp_resp and act_resp have the same keys. Check if their values are the same
|
|
||||||
for key in act_resp.keys():
|
|
||||||
if not isinstance(act_resp[key], dict):
|
|
||||||
if exp_resp[key] != act_resp[key]:
|
|
||||||
print(f'expected value :{exp_resp[key]}\n actual value: {act_resp[key]}')
|
|
||||||
return False
|
|
||||||
return test
|
|
||||||
|
|
||||||
|
|
||||||
# test json answers creation
|
# test json answers creation
|
||||||
@pytest.mark.parametrize('xls_input, expected_response_file', {
|
@pytest.mark.parametrize('xls_input, expected_response_file', {
|
||||||
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_response.json',
|
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_response.json',
|
||||||
@@ -304,11 +242,12 @@ def test_json_response_generation(xls_input, expected_response_file):
|
|||||||
|
|
||||||
result = []
|
result = []
|
||||||
for i, pth in enumerate(propagatedpths):
|
for i, pth in enumerate(propagatedpths):
|
||||||
# test ServiceError handling : when M is zero at this point, the
|
# test ServiceError handling : when M is None at this point, the
|
||||||
# json result should not be created if there is no blocking reason
|
# json result should not be created if there is no blocking reason
|
||||||
if i == 1:
|
if i == 1:
|
||||||
my_rq = deepcopy(rqs[i])
|
my_rq = deepcopy(rqs[i])
|
||||||
my_rq.M = 0
|
my_rq.M = None
|
||||||
|
my_rq.N = None
|
||||||
with pytest.raises(ServiceError):
|
with pytest.raises(ServiceError):
|
||||||
ResultElement(my_rq, pth, reversed_propagatedpths[i]).json
|
ResultElement(my_rq, pth, reversed_propagatedpths[i]).json
|
||||||
|
|
||||||
@@ -327,7 +266,7 @@ def test_json_response_generation(xls_input, expected_response_file):
|
|||||||
if i == 2:
|
if i == 2:
|
||||||
# compare response must be False because z-a metric is missing
|
# compare response must be False because z-a metric is missing
|
||||||
# (request with bidir option to cover bidir case)
|
# (request with bidir option to cover bidir case)
|
||||||
assert not compare_response(expected['response'][i], response)
|
assert expected['response'][i] != response
|
||||||
print(f'response {response["response-id"]} should not match')
|
print(f'response {response["response-id"]} should not match')
|
||||||
expected['response'][2]['path-properties']['z-a-path-metric'] = [
|
expected['response'][2]['path-properties']['z-a-path-metric'] = [
|
||||||
{'metric-type': 'SNR-bandwidth', 'accumulative-value': 22.809999999999999},
|
{'metric-type': 'SNR-bandwidth', 'accumulative-value': 22.809999999999999},
|
||||||
@@ -338,8 +277,7 @@ def test_json_response_generation(xls_input, expected_response_file):
|
|||||||
{'metric-type': 'path_bandwidth', 'accumulative-value': 60000000000.0}]
|
{'metric-type': 'path_bandwidth', 'accumulative-value': 60000000000.0}]
|
||||||
# test should be OK now
|
# test should be OK now
|
||||||
else:
|
else:
|
||||||
assert compare_response(expected['response'][i], response)
|
assert expected['response'][i] == response
|
||||||
print(f'response {response["response-id"]} is not correct')
|
|
||||||
|
|
||||||
# test the correspondance names dict in case of excel input
|
# test the correspondance names dict in case of excel input
|
||||||
# test that using the created json network still works with excel input
|
# test that using the created json network still works with excel input
|
||||||
@@ -420,10 +358,12 @@ def test_excel_ila_constraints(source, destination, route_list, hoptype, expecte
|
|||||||
'cost': None,
|
'cost': None,
|
||||||
'roll_off': 0,
|
'roll_off': 0,
|
||||||
'tx_osnr': 0,
|
'tx_osnr': 0,
|
||||||
|
'penalties': None,
|
||||||
'min_spacing': None,
|
'min_spacing': None,
|
||||||
'nb_channel': 0,
|
'nb_channel': 0,
|
||||||
'power': 0,
|
'power': 0,
|
||||||
'path_bandwidth': 0,
|
'path_bandwidth': 0,
|
||||||
|
'effective_freq_slot': None
|
||||||
}
|
}
|
||||||
request = PathRequest(**params)
|
request = PathRequest(**params)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ checks that restrictions in roadms are correctly applied during autodesign
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pytest
|
import pytest
|
||||||
|
from numpy.testing import assert_allclose
|
||||||
|
|
||||||
from gnpy.core.utils import lin2db, automatic_nch
|
from gnpy.core.utils import lin2db, automatic_nch
|
||||||
from gnpy.core.elements import Fused, Roadm, Edfa
|
from gnpy.core.elements import Fused, Roadm, Edfa
|
||||||
from gnpy.core.network import build_network
|
from gnpy.core.network import build_network
|
||||||
@@ -207,8 +209,9 @@ def test_restrictions(restrictions, equipment):
|
|||||||
raise AssertionError()
|
raise AssertionError()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('power_dbm', [0, +1, -2])
|
||||||
@pytest.mark.parametrize('prev_node_type, effective_pch_out_db', [('edfa', -20.0), ('fused', -22.0)])
|
@pytest.mark.parametrize('prev_node_type, effective_pch_out_db', [('edfa', -20.0), ('fused', -22.0)])
|
||||||
def test_roadm_target_power(prev_node_type, effective_pch_out_db):
|
def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
|
||||||
''' Check that egress power of roadm is equal to target power if input power is greater
|
''' Check that egress power of roadm is equal to target power if input power is greater
|
||||||
than target power else, that it is equal to input power. Use a simple two hops A-B-C topology
|
than target power else, that it is equal to input power. Use a simple two hops A-B-C topology
|
||||||
for the test where the prev_node in ROADM B is either an amplifier or a fused, so that the target
|
for the test where the prev_node in ROADM B is either an amplifier or a fused, so that the target
|
||||||
@@ -225,51 +228,58 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db):
|
|||||||
prev_node['params'] = {'loss': 0}
|
prev_node['params'] = {'loss': 0}
|
||||||
json_network['elements'].append(prev_node)
|
json_network['elements'].append(prev_node)
|
||||||
network = network_from_json(json_network, equipment)
|
network = network_from_json(json_network, equipment)
|
||||||
# Build the network once using the default power defined in SI in eqpt config
|
p_total_db = power_dbm + lin2db(automatic_nch(equipment['SI']['default'].f_min,
|
||||||
p_db = equipment['SI']['default'].power_dbm
|
|
||||||
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,
|
|
||||||
equipment['SI']['default'].f_max,
|
equipment['SI']['default'].f_max,
|
||||||
equipment['SI']['default'].spacing))
|
equipment['SI']['default'].spacing))
|
||||||
|
|
||||||
build_network(network, equipment, p_db, p_total_db)
|
build_network(network, equipment, power_dbm, p_total_db)
|
||||||
|
|
||||||
params = {}
|
params = {'request_id': 0,
|
||||||
params['request_id'] = 0
|
'trx_type': '',
|
||||||
params['trx_type'] = ''
|
'trx_mode': '',
|
||||||
params['trx_mode'] = ''
|
'source': 'trx node A',
|
||||||
params['source'] = 'trx node A'
|
'destination': 'trx node C',
|
||||||
params['destination'] = 'trx node C'
|
'bidir': False,
|
||||||
params['bidir'] = False
|
'nodes_list': ['trx node C'],
|
||||||
params['nodes_list'] = ['trx node C']
|
'loose_list': ['strict'],
|
||||||
params['loose_list'] = ['strict']
|
'format': '',
|
||||||
params['format'] = ''
|
'path_bandwidth': 100e9,
|
||||||
params['path_bandwidth'] = 100e9
|
'effective_freq_slot': None,
|
||||||
|
}
|
||||||
trx_params = trx_mode_params(equipment)
|
trx_params = trx_mode_params(equipment)
|
||||||
params.update(trx_params)
|
params.update(trx_params)
|
||||||
req = PathRequest(**params)
|
req = PathRequest(**params)
|
||||||
|
req.power = db2lin(power_dbm - 30)
|
||||||
path = compute_constrained_path(network, req)
|
path = compute_constrained_path(network, req)
|
||||||
si = create_input_spectral_information(
|
si = create_input_spectral_information(
|
||||||
req.f_min, req.f_max, req.roll_off, req.baud_rate,
|
req.f_min, req.f_max, req.roll_off, req.baud_rate,
|
||||||
req.power, req.spacing)
|
req.power, req.spacing)
|
||||||
for i, el in enumerate(path):
|
for i, el in enumerate(path):
|
||||||
if isinstance(el, Roadm):
|
if isinstance(el, Roadm):
|
||||||
carriers_power_in_roadm = min([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
|
min_power_in_roadm = min(si.signal + si.ase + si.nli)
|
||||||
si = el(si, degree=path[i + 1].uid)
|
si = el(si, degree=path[i + 1].uid)
|
||||||
|
power_out_roadm = si.signal + si.ase + si.nli
|
||||||
if el.uid == 'roadm node B':
|
if el.uid == 'roadm node B':
|
||||||
print('input', carriers_power_in_roadm)
|
print('input', min_power_in_roadm)
|
||||||
assert el.effective_pch_out_db == effective_pch_out_db
|
# if previous was an EDFA, power level at ROADM input is enough for the ROADM to apply its
|
||||||
for carrier in si.carriers:
|
# target power (as specified in equipment ie -20 dBm)
|
||||||
print(carrier.power.signal + carrier.power.nli + carrier.power.ase)
|
# if it is a Fused, the input power to the ROADM is smaller than the target power, and the
|
||||||
power = carrier.power.signal + carrier.power.nli + carrier.power.ase
|
# ROADM cannot apply this target. In this case, it is assumed that the ROADM has 0 dB loss
|
||||||
|
# so the output power will be the same as the input power, which for this particular case
|
||||||
|
# corresponds to -22dBm + power_dbm
|
||||||
|
# next step (for ROADM modelling) will be to apply a minimum loss for ROADMs !
|
||||||
if prev_node_type == 'edfa':
|
if prev_node_type == 'edfa':
|
||||||
# edfa prev_node sets input power to roadm to a high enough value:
|
# edfa prev_node sets input power to roadm to a high enough value:
|
||||||
|
# check that target power is correctly set in the ROADM
|
||||||
|
assert_allclose(el.pch_out_db, effective_pch_out_db, rtol=1e-3)
|
||||||
# Check that egress power of roadm is equal to target power
|
# Check that egress power of roadm is equal to target power
|
||||||
assert power == pytest.approx(db2lin(effective_pch_out_db - 30), rel=1e-3)
|
assert_allclose(power_out_roadm, db2lin(effective_pch_out_db - 30), rtol=1e-3)
|
||||||
elif prev_node_type == 'fused':
|
elif prev_node_type == 'fused':
|
||||||
# fused prev_node does reamplfy power after fiber propagation, so input power
|
# fused prev_node does reamplfy power after fiber propagation, so input power
|
||||||
# to roadm is low.
|
# to roadm is low.
|
||||||
|
# check that target power correctly reports power_dbm from previous propagation
|
||||||
|
assert_allclose(el.pch_out_db, effective_pch_out_db + power_dbm, rtol=1e-3)
|
||||||
# Check that egress power of roadm is equalized to the min carrier input power.
|
# Check that egress power of roadm is equalized to the min carrier input power.
|
||||||
assert power == pytest.approx(carriers_power_in_roadm, rel=1e-3)
|
assert_allclose(power_out_roadm, min_power_in_roadm, rtol=1e-3)
|
||||||
else:
|
else:
|
||||||
si = el(si)
|
si = el(si)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# @Author: Alessio Ferrari
|
|
||||||
"""
|
"""
|
||||||
Checks that RamanFiber propagates properly the spectral information. In this way, also the RamanSolver and the NliSolver
|
Checks that RamanFiber propagates properly the spectral information. In this way, also the RamanSolver and the NliSolver
|
||||||
are tested.
|
are tested.
|
||||||
@@ -9,40 +9,120 @@ are tested.
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pandas import read_csv
|
from pandas import read_csv
|
||||||
from numpy.testing import assert_allclose
|
from numpy.testing import assert_allclose
|
||||||
|
from numpy import array, genfromtxt
|
||||||
|
import pytest
|
||||||
|
|
||||||
from gnpy.core.info import create_input_spectral_information
|
from gnpy.core.info import create_input_spectral_information, create_arbitrary_spectral_information
|
||||||
from gnpy.core.elements import RamanFiber
|
from gnpy.core.elements import Fiber, RamanFiber
|
||||||
from gnpy.core.parameters import SimParams
|
from gnpy.core.parameters import SimParams
|
||||||
from gnpy.core.science_utils import Simulation
|
|
||||||
from gnpy.tools.json_io import load_json
|
from gnpy.tools.json_io import load_json
|
||||||
|
from gnpy.core.exceptions import NetworkTopologyError
|
||||||
|
from gnpy.core.science_utils import RamanSolver
|
||||||
|
|
||||||
TEST_DIR = Path(__file__).parent
|
TEST_DIR = Path(__file__).parent
|
||||||
|
|
||||||
|
|
||||||
def test_raman_fiber():
|
def test_fiber():
|
||||||
""" Test the accuracy of propagating the RamanFiber."""
|
""" Test the accuracy of propagating the Fiber."""
|
||||||
# spectral information generation
|
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json'))
|
||||||
power = 1e-3
|
|
||||||
eqpt_params = load_json(TEST_DIR / 'data' / 'eqpt_config.json')
|
|
||||||
spectral_info_params = eqpt_params['SI'][0]
|
|
||||||
spectral_info_params.pop('power_dbm')
|
|
||||||
spectral_info_params.pop('power_range_db')
|
|
||||||
spectral_info_params.pop('tx_osnr')
|
|
||||||
spectral_info_params.pop('sys_margins')
|
|
||||||
spectral_info_input = create_input_spectral_information(power=power, **spectral_info_params)
|
|
||||||
|
|
||||||
sim_params = SimParams(**load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
# fix grid spectral information generation
|
||||||
Simulation.set_params(sim_params)
|
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
|
||||||
fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'raman_fiber_config.json'))
|
baud_rate=32e9, power=1e-3, spacing=50e9)
|
||||||
|
# propagation
|
||||||
|
spectral_info_out = fiber(spectral_info_input)
|
||||||
|
|
||||||
|
p_signal = spectral_info_out.signal
|
||||||
|
p_nli = spectral_info_out.nli
|
||||||
|
|
||||||
|
expected_results = read_csv(TEST_DIR / 'data' / 'test_fiber_fix_expected_results.csv')
|
||||||
|
assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
|
||||||
|
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
|
||||||
|
|
||||||
|
# flex grid spectral information generation
|
||||||
|
frequency = 191e12 + array([0, 50e9, 150e9, 225e9, 275e9])
|
||||||
|
slot_width = array([37.5e9, 50e9, 75e9, 50e9, 37.5e9])
|
||||||
|
baud_rate = array([32e9, 42e9, 64e9, 42e9, 32e9])
|
||||||
|
signal = 1e-3 + array([0, -1e-4, 3e-4, -2e-4, +2e-4])
|
||||||
|
spectral_info_input = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width,
|
||||||
|
signal=signal, baud_rate=baud_rate, roll_off=0.15)
|
||||||
|
|
||||||
# propagation
|
# propagation
|
||||||
spectral_info_out = fiber(spectral_info_input)
|
spectral_info_out = fiber(spectral_info_input)
|
||||||
|
|
||||||
p_signal = [carrier.power.signal for carrier in spectral_info_out.carriers]
|
p_signal = spectral_info_out.signal
|
||||||
p_ase = [carrier.power.ase for carrier in spectral_info_out.carriers]
|
p_nli = spectral_info_out.nli
|
||||||
p_nli = [carrier.power.nli for carrier in spectral_info_out.carriers]
|
|
||||||
|
|
||||||
expected_results = read_csv(TEST_DIR / 'data' / 'test_science_utils_expected_results.csv')
|
expected_results = read_csv(TEST_DIR / 'data' / 'test_fiber_flex_expected_results.csv')
|
||||||
|
assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
|
||||||
|
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('set_sim_params')
|
||||||
|
def test_raman_fiber():
|
||||||
|
""" Test the accuracy of propagating the RamanFiber."""
|
||||||
|
# spectral information generation
|
||||||
|
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
|
||||||
|
baud_rate=32e9, power=1e-3, spacing=50e9)
|
||||||
|
SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||||
|
fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json'))
|
||||||
|
|
||||||
|
# propagation
|
||||||
|
spectral_info_out = fiber(spectral_info_input)
|
||||||
|
|
||||||
|
p_signal = spectral_info_out.signal
|
||||||
|
p_ase = spectral_info_out.ase
|
||||||
|
p_nli = spectral_info_out.nli
|
||||||
|
|
||||||
|
expected_results = read_csv(TEST_DIR / 'data' / 'test_raman_fiber_expected_results.csv')
|
||||||
assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
|
assert_allclose(p_signal, expected_results['signal'], rtol=1e-3)
|
||||||
assert_allclose(p_ase, expected_results['ase'], rtol=1e-3)
|
assert_allclose(p_ase, expected_results['ase'], rtol=1e-3)
|
||||||
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
|
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"loss, position, errmsg",
|
||||||
|
((0.5, -2, "Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded."),
|
||||||
|
(0.5, 81, "Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded.")))
|
||||||
|
@pytest.mark.usefixtures('set_sim_params')
|
||||||
|
def test_fiber_lumped_losses(loss, position, errmsg, set_sim_params):
|
||||||
|
""" Lumped losses length sanity checking."""
|
||||||
|
SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||||
|
fiber_dict = load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json')
|
||||||
|
fiber_dict['params']['lumped_losses'] = [{'position': position, 'loss': loss}]
|
||||||
|
with pytest.raises(NetworkTopologyError) as e:
|
||||||
|
Fiber(**fiber_dict)
|
||||||
|
assert str(e.value) == errmsg
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures('set_sim_params')
|
||||||
|
def test_fiber_lumped_losses_srs(set_sim_params):
|
||||||
|
""" Test the accuracy of Fiber with lumped losses propagation."""
|
||||||
|
# spectral information generation
|
||||||
|
spectral_info_input = create_input_spectral_information(f_min=191.3e12, f_max=196.1e12, roll_off=0.15,
|
||||||
|
baud_rate=32e9, power=1e-3, spacing=50e9)
|
||||||
|
|
||||||
|
SimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
|
||||||
|
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json'))
|
||||||
|
raman_fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json'))
|
||||||
|
|
||||||
|
# propagation
|
||||||
|
# without Raman pumps
|
||||||
|
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(
|
||||||
|
spectral_info_input, fiber)
|
||||||
|
power_profile = stimulated_raman_scattering.power_profile
|
||||||
|
expected_power_profile = genfromtxt(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_pumps.csv', delimiter=',')
|
||||||
|
assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
|
||||||
|
|
||||||
|
# with Raman pumps
|
||||||
|
expected_power_profile = genfromtxt(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber.csv', delimiter=',')
|
||||||
|
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(
|
||||||
|
spectral_info_input, raman_fiber)
|
||||||
|
power_profile = stimulated_raman_scattering.power_profile
|
||||||
|
assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
|
||||||
|
|
||||||
|
# without Stimulated Raman Scattering
|
||||||
|
expected_power_profile = genfromtxt(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_raman.csv', delimiter=',')
|
||||||
|
stimulated_raman_scattering = RamanSolver.calculate_attenuation_profile(spectral_info_input, fiber)
|
||||||
|
power_profile = stimulated_raman_scattering.power_profile
|
||||||
|
assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
|
||||||
|
|||||||
@@ -17,11 +17,12 @@ import pytest
|
|||||||
from gnpy.core.network import build_network
|
from gnpy.core.network import build_network
|
||||||
from gnpy.core.utils import lin2db, automatic_nch
|
from gnpy.core.utils import lin2db, automatic_nch
|
||||||
from gnpy.core.elements import Roadm, Transceiver
|
from gnpy.core.elements import Roadm, Transceiver
|
||||||
from gnpy.core.exceptions import SpectrumError
|
from gnpy.core.exceptions import ServiceError, SpectrumError
|
||||||
from gnpy.topology.request import compute_path_dsjctn, find_reversed_path, deduplicate_disjunctions
|
from gnpy.topology.request import compute_path_dsjctn, find_reversed_path, deduplicate_disjunctions, PathRequest
|
||||||
from gnpy.topology.spectrum_assignment import (build_oms_list, align_grids, nvalue_to_frequency,
|
from gnpy.topology.spectrum_assignment import (build_oms_list, align_grids, nvalue_to_frequency,
|
||||||
bitmap_sum, Bitmap, spectrum_selection, pth_assign_spectrum)
|
bitmap_sum, Bitmap, spectrum_selection, pth_assign_spectrum)
|
||||||
from gnpy.tools.json_io import load_equipment, load_network, requests_from_json, disjunctions_from_json
|
from gnpy.tools.json_io import (load_equipment, load_network, requests_from_json, disjunctions_from_json,
|
||||||
|
_check_one_request)
|
||||||
|
|
||||||
TEST_DIR = Path(__file__).parent
|
TEST_DIR = Path(__file__).parent
|
||||||
DATA_DIR = TEST_DIR / 'data'
|
DATA_DIR = TEST_DIR / 'data'
|
||||||
@@ -267,6 +268,109 @@ def test_spectrum_assignment_on_path(equipment, setup, requests):
|
|||||||
assert center_n is not None and startn is not None and stopn is not None
|
assert center_n is not None and startn is not None and stopn is not None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def request_set():
|
||||||
|
""" creates default request dict
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
'request_id': '0',
|
||||||
|
'source': 'trx a',
|
||||||
|
'bidir': False,
|
||||||
|
'destination': 'trx g',
|
||||||
|
'trx_type': 'Voyager',
|
||||||
|
'trx_mode': 'mode 1',
|
||||||
|
'format': 'mode1',
|
||||||
|
'spacing': 50e9,
|
||||||
|
'nodes_list': [],
|
||||||
|
'loose_list': [],
|
||||||
|
'f_min': 191.1e12,
|
||||||
|
'f_max': 196.3e12,
|
||||||
|
'baud_rate': 32e9,
|
||||||
|
'OSNR': 14,
|
||||||
|
'bit_rate': 100e9,
|
||||||
|
'cost': 1,
|
||||||
|
'roll_off': 0.15,
|
||||||
|
'tx_osnr': 38,
|
||||||
|
'penalties': {},
|
||||||
|
'min_spacing': 37.5e9,
|
||||||
|
'nb_channel': None,
|
||||||
|
'power': 0,
|
||||||
|
'path_bandwidth': 800e9}
|
||||||
|
|
||||||
|
|
||||||
|
def test_freq_slot_exist(setup, equipment, request_set):
|
||||||
|
""" test that assignment works even if effective_freq_slot is not populated
|
||||||
|
"""
|
||||||
|
network, oms_list = setup
|
||||||
|
params = request_set
|
||||||
|
params['effective_freq_slot'] = None
|
||||||
|
rqs = [PathRequest(**params)]
|
||||||
|
paths = compute_path_dsjctn(network, equipment, rqs, [])
|
||||||
|
pth_assign_spectrum(paths, rqs, oms_list, [find_reversed_path(paths[0])])
|
||||||
|
assert rqs[0].N == -256
|
||||||
|
assert rqs[0].M == 32
|
||||||
|
|
||||||
|
|
||||||
|
def test_inconsistant_freq_slot(setup, equipment, request_set):
|
||||||
|
""" test that an inconsistant M correctly raises an error
|
||||||
|
"""
|
||||||
|
network, oms_list = setup
|
||||||
|
params = request_set
|
||||||
|
# minimum required nb of slots is 32 (800Gbit/100Gbit/s channels each occupying 50GHz ie 4 slots)
|
||||||
|
params['effective_freq_slot'] = {'N': 0, 'M': 4}
|
||||||
|
with pytest.raises(ServiceError):
|
||||||
|
_check_one_request(params, 196.05e12)
|
||||||
|
params['trx_mode'] = None
|
||||||
|
rqs = [PathRequest(**params)]
|
||||||
|
paths = compute_path_dsjctn(network, equipment, rqs, [])
|
||||||
|
pth_assign_spectrum(paths, rqs, oms_list, [find_reversed_path(paths[0])])
|
||||||
|
assert rqs[0].blocking_reason == 'NOT_ENOUGH_RESERVED_SPECTRUM'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('n, m, final_n, final_m, blocking_reason', [
|
||||||
|
# regular requests that should be correctly assigned:
|
||||||
|
(-100, 32, -100, 32, None),
|
||||||
|
(150, 50, 150, 50, None),
|
||||||
|
# if n is None, there should be an assignment (enough spectrum cases)
|
||||||
|
# and the center frequency should be set on the lower part of the spectrum based on m value if it exists
|
||||||
|
# or based on 32
|
||||||
|
(None, 32, -256, 32, None),
|
||||||
|
(None, 40, -248, 40, None),
|
||||||
|
(-100, None, -100, 32, None),
|
||||||
|
(None, None, -256, 32, None),
|
||||||
|
# -280 and 60 center indexes should result in unfeasible spectrum, either out of band or
|
||||||
|
# overlapping with occupied spectrum. The requested spectrum is not available
|
||||||
|
(-280, None, None, None, 'NO_SPECTRUM'),
|
||||||
|
(-60, 40, None, None, 'NO_SPECTRUM'),
|
||||||
|
# 20 is smaller than min 32 required nb of slots so should also be blocked
|
||||||
|
(-60, 20, None, None, 'NOT_ENOUGH_RESERVED_SPECTRUM')
|
||||||
|
])
|
||||||
|
def test_n_m_requests(setup, equipment, n, m, final_n, final_m, blocking_reason, request_set):
|
||||||
|
""" test that various N and M values for a request end up with the correct path assgnment
|
||||||
|
"""
|
||||||
|
network, oms_list = setup
|
||||||
|
# add an occupation on one of the span of the expected path OMS list on both directions
|
||||||
|
# as defined by its offsets within the OMS list: [17, 20, 13, 22] and reversed path [19, 16, 21, 26]
|
||||||
|
expected_path = [17, 20, 13, 22]
|
||||||
|
expected_oms = [13, 16, 17, 19, 20, 21, 22, 26]
|
||||||
|
some_oms = oms_list[expected_oms[3]]
|
||||||
|
some_oms.assign_spectrum(-30, 32) # means that spectrum is occupied from indexes -62 to 1 on reversed path
|
||||||
|
params = request_set
|
||||||
|
params['effective_freq_slot'] = {'N': n, 'M': m}
|
||||||
|
rqs = [PathRequest(**params)]
|
||||||
|
|
||||||
|
paths = compute_path_dsjctn(network, equipment, rqs, [])
|
||||||
|
# check that the computed path is the expected one (independant of blocking issues due to spectrum)
|
||||||
|
path_oms = list(set([e.oms_id for e in paths[0] if not isinstance(e, (Transceiver, Roadm))]))
|
||||||
|
assert path_oms == expected_path
|
||||||
|
# function to be tested:
|
||||||
|
pth_assign_spectrum(paths, rqs, oms_list, [find_reversed_path(paths[0])])
|
||||||
|
# check that spectrum is correctly assigned
|
||||||
|
assert rqs[0].N == final_n
|
||||||
|
assert rqs[0].M == final_m
|
||||||
|
assert getattr(rqs[0], 'blocking_reason', None) == blocking_reason
|
||||||
|
|
||||||
|
|
||||||
def test_reversed_direction(equipment, setup, requests, services):
|
def test_reversed_direction(equipment, setup, requests, services):
|
||||||
""" checks that if spectrum is selected on one direction it is also selected on reversed
|
""" checks that if spectrum is selected on one direction it is also selected on reversed
|
||||||
direction
|
direction
|
||||||
|
|||||||
4
tox.ini
4
tox.ini
@@ -4,7 +4,7 @@ skipsdist = True
|
|||||||
[testenv]
|
[testenv]
|
||||||
deps =
|
deps =
|
||||||
-r{toxinidir}/requirements.txt
|
-r{toxinidir}/requirements.txt
|
||||||
pytest>=5.0.0,<6
|
pytest>=6.2.5,<7
|
||||||
cover: pytest-cov
|
cover: pytest-cov
|
||||||
linters: flake8
|
linters: flake8
|
||||||
linters: pep8-naming
|
linters: pep8-naming
|
||||||
@@ -19,6 +19,7 @@ commands =
|
|||||||
pytest {env:CI_COVERAGE_OPTS:} -vv {posargs}
|
pytest {env:CI_COVERAGE_OPTS:} -vv {posargs}
|
||||||
cover: coverage html -d cover
|
cover: coverage html -d cover
|
||||||
cover: coverage xml -o cover/coverage.xml
|
cover: coverage xml -o cover/coverage.xml
|
||||||
|
python setup.py bdist_wheel
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
deps =
|
deps =
|
||||||
@@ -42,3 +43,4 @@ commands =
|
|||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
max-complexity = 15
|
max-complexity = 15
|
||||||
|
ignore = N806
|
||||||
|
|||||||
Reference in New Issue
Block a user