29 Commits

Author SHA1 Message Date
EstherLerouzic
d9924acbf1 complete tests with the --power option tests
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ia7be6b86b82cc0317a5ba48086ef63f67d490990
2021-10-04 11:10:52 +02:00
EstherLerouzic
0a98744938 Add tests on equalization
- checks that the req.initial_spectrum is correctly read and
  taken into account
- checks that power spectral density equalization gives exact
  same power as power equalisation for the same spectrum
- checks that power delta _p is correctly applied on boosters
  even with PSD equalization
- checks that target_power is correctly translated to higher
  baudrates, when PSD is applied

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic4890410f2677b8717b7b7025063d1ac7fb73563
2021-10-04 11:08:49 +02:00
EstherLerouzic
2d5909560e Small refactor: use more meaningful names for variables
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I17dff12c1e81827dfb4be869e59c9be85797dba4
2021-10-04 11:02:24 +02:00
EstherLerouzic
4c6f381e61 Add Roadm uid when raising error
in case parameters are not correct, catch the ParameterError
and raises it again with the uid of the ROADM to ease debug

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I1f85f0e9e9226fc613d35611774c739adb2104c7
2021-10-04 11:02:18 +02:00
EstherLerouzic
ceeb28f57e Introduce equalization choices in ROADMs
Before this change, all channels are set to the same
target_pch_out_db powe, whatever their rate. With this change,
we enable 3 equalizations (taht can be mixed)
- power
- power spectral density (psd)
- user defined power delta

the behaviour of the software is changed as follows:

propagation case:
----------------
eqpt config defines the policy for the whole network:
without any other indication in ROADM instances,
"target_pch_out_db" means power equalization
"target_psd_out_mWperGHz" measn psd equalization
(user defined delta depends on -spectrum option inputs)

psd is computed using channel baud rate for the bandwidth
"Roadm":[{
    "target_pch_out_db": -20,
    xor "target_psd_out_mWperGHz": 3.125e-4, (eg -20dBm for 32 Gbauds)
    "add_drop_osnr": 38,
    "pmd": 0,
    ...}]

-> if target_pch_out is present in a roadm, it overrides the general default for this roadm equalization
-> if target_psd_out is present in a roadm, it overrides the general default for this roadm equalization
only one of the two can be present in a roadm

the same per_degree dictionnary is added to handle per_degre psd
similarly to target_pch_out, if a per_degree_psd is defined it overrides the general(network) or general(roadm) settings

eg:
    {
      "uid": "roadm A",
      "type": "Roadm",
      "params": {
        "target_pch_out_db": -20,
        "per_degree_pch_out_db": {
          "edfa in roadm A to toto": -18,
        }
      }
    },
    means that target power is -20 dBm for all degrees except "edfa in roadm A to toto" where it is -18dBm

    {
      "uid": "roadm A",
      "type": "Roadm",
      "params": {
        "target_psd_out_mWperGHz": 2.717e-4,
        "per_degree_psd_out_mWperGHz": {
          "edfa in roadm A to toto": 4.3e-4,
        }
      }
    },

means that target psd is -2.717e-4 mw/GHz for all degrees except "edfa in roadm A to toto" where it is 4.3e-4.

mixing is permited as long as no same degree are listed in the dict
    {
      "uid": "roadm A",
      "type": "Roadm",
      "params": {
        "target_pch_out_db": -20,
        "per_degree_psd_out_mWperGHz": {
          "edfa in roadm A to toto": 4.3e-4,
        }
      }
    },
means that roadm A uses power equalization on all its degrees except "edfa in roadm A to toto" where it is power_sectral density

------------------
initial spectrum mix

initial spectrum mix can be defined by user in a json file composed of a list of {"f_min", "f_max", "baud_rate", "spacing" "power_dbm", "roll_off", "tx_osnr"}. these fmin-fmax should not overlap.
this file will be used  with transmission main only. (hard to define a mix in case of planning)

if the user does not set power in ths file, it is assumed that the default equalisation is used.
if the user sets initial powers, this mix of power has to be used (p_span0_per_channel refers to this)
if p_span0_per_channel is empty, the equalization of the roadm is used

----------------------

power sweep behaviour in ROADMs:
expected behaviour is that per degree power / psd is not changed by power sweep or change of power of a
propagation request:
	target power is the result of the roadm design and is the best (highest) power that can be supported by
	roadms given the add power range.  the rationale behind that is that to have best OSNR at booster, it is
	required to have the highest possible power. but this power is constrained by add/drop and express stages
	loss and power out limitation of the amps in these stages. So it is probably not possible to increase it
	for limitations issues and not desirable to decrease it for performance issues.

	(as a side remark, given the current behaiour, I think that renaming target_pch_out_db into
	target_pch_out_dbm would make sense)
so current behaviour when we apply power sweep or --pow option, is that this does not affect the power out
from the ROADM. only the target power at the output of amps

with PSD, the same rule applies: power sweep or --pow option can be used to change the propagated reference
power/psd. the proposed behaviour depends on the OMS add roadm:
- if roadm degree equalization is power, then same behaviour as today
- if roadm degree equallization is psd, then
      o --pow  is interpreted as the power of the reference channel defined in SI container in eqpt_config
        and its psd is used for propagation.
      o power sweep is interpreted in the same way with a translation on carriers
eg :
suppose that we have SI in eqpt_config:
      "SI":[{
            "f_min": 191.3e12,
            "baud_rate": 32e9,
            "f_max":195.1e12,
            "spacing": 50e9,
            "power_dbm": 0,
            "power_range_db": [-1,1,1],
            "roll_off": 0.15,
            "tx_osnr": 40,
            "sys_margins": 2
            }],
and psd equalization in roadms
    {
      "uid": "roadm A",
      "type": "Roadm",
      "params": {
        "target_psd_out_mWperGHz": 2.717e-4,
      }
    },
    {
      "uid": "edfa in roadm A to toto",
      "type": "Edfa",
      "type_variety": "standrd_medium_gain",
      "operational": {
        "gain_target": 22,
        "delta_p": 2,
        "tilt_target": 0.0,
        "out_voa": 0
      }
    },
then we use the power steps of the power_range_db to compute resulting powers of each carrier out of the booster amp.
power_db = psd2powerdbm(target_psd_out_mWperGHz, baud_rate)
sweep = power_db + delta_power for delta_power in power_range_db
assuming one 32Gbaud and one 64Gbaud carriers:
                32 Gbaud        64 Gbaud
roadmA out pow
(sig+ase+nli)   -20dBm         -17dBm

edfa out pow
range[
	-1          1dBm            4dBm
	 0          2dBm            5dBm
	 1          3dBm            6dBm
]

-------------------------

design case:
design is performed based on the reference channel set defined in SI in equipement config.
(independantly of equalization process)
      "SI":[{
            "f_min": 191.3e12,
            "baud_rate": 32e9,
            "f_max":195.1e12,
            "spacing": 50e9,
            "power_dbm": -1,
            "power_range_db": [0,0,1],
            "roll_off": 0.15,
            "tx_osnr": 40,
            "sys_margins": 2
            }],

delta_p values of amps refer to this reference channel, but are applicable for any baudrate during propagation
eg
    {
      "uid": "roadm A",
      "type": "Roadm",
      "params": {
        "target_psd_out_mWperGHz": 2.717e-4,
      }
    },
    {
      "uid": "edfa in roadm A to toto",
      "type": "Edfa",
      "type_variety": "standard_medium_gain",
      "operational": {
        "gain_target": 22,
        "delta_p": 2,
        "tilt_target": 0.0,
        "out_voa": 0
      }
    },

then outpower for a 64 Gbaud carrier will be +4 =
= lin2db(db2lin(power_dbm + delta_p)/32e9 * 64e9)
= lin2db( db2lin(power_dbm + delta_p) * 2)
= powerdbm + delta + 3 = 4 dBm

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I28bcfeb72b0e74380b087762bb92ba5d39219eb3
2021-10-04 11:00:34 +02:00
EstherLerouzic
7c90ae4809 Add invocation results of -spectrum option
Results correspond to the example of spectrum files

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I030ecff3b0248f986d9d487edf508b9c448515d1
2021-10-04 10:41:08 +02:00
EstherLerouzic
603b28ac08 Add example files for -spectrum option
initial_spectrum1.json reproduces exactly the case of SI
initial_spectrum2.json sets half of the spectrum with 50GHz 32Gbauds and
half with 75GHz 64 Gbauds. Power setting is not set for the second half,
So that equalization will depend on ROADM settings.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I66b0cf9d0f107f13e7ae9b75e57095265c476a57
2021-10-04 10:41:08 +02:00
EstherLerouzic
79059e13e8 Minor refactor: use watt2dbm function
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I09c3e923a8e1565d2ab07596c393bb5b2dc30f6c
2021-10-04 10:41:08 +02:00
EstherLerouzic
a9d616818a Print per label channel power of elements
Per channel power prints were previously only showing the noiseless
reference channel power and only an average power.
With this change, we add a new information on the print:
the average total power (signal + noise + non-linear noise).
If there are several spectrum types propagating, the average per spectrum
is displayed using the label.
For this purpose, label and total power are recorded in each element
upon propagation.

Note that the difference between this total power and the existing
channel power represents the added noise for the considered OMS.
Indeed ROADMs equalize per channel total power, so that power displayed
in 'total pch (dBm)' may contain some noise contribution accumulated with
previous propagation.
Because 'pch out (dBm)' is for the noiseless reference, it is exactly
set to the target power and 'total pch (dBm)' is always matching
'pch out (dBm)' in ROADM prints.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Idc8d949386a4826123c21a60008b50c51ac182e2
2021-10-04 10:41:08 +02:00
EstherLerouzic
f0b56bcaff Print results per spectrum label
If propagated spectrum has mixed rates, then prints results (GSNR and OSNR)
for each propagated spectrum type according to its label.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ie2aff966e7324eb5fc3e58086e43dd39f73da8c8
2021-10-04 10:41:08 +02:00
EstherLerouzic
4b94481ecb Add a -spectrum option to input external file to define spectrum
The option is only set for gnpy-transmission-main.

The spectrum file is a list of of spectrum objects, each defining
fmin, fmax and spectrum attributes using the same definition as SI
in eqpt_config.json. the object list should be contiguous spectrum
definitions and not overlapping. For now, I have not integrated the
possibility to directly use transceivers type and mode in the list.
user can define sets of contiguous channels and a label to identify
the spectrum bands. If no label are defined, th program justs uses
the index + baud rate of the spectrum bands as label.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ibc01e59e461e5e933e95d23dacbc5289e275ccf7
2021-10-04 10:41:08 +02:00
EstherLerouzic
e851220f81 Change precision of --show-channels to 5 digits
Flexgrid precision is 6.25GHz so --show-channels should be at least 5 digits

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I7de4254ab18508320133371e0d8cc8b5e08f0d2f
2021-10-04 10:41:08 +02:00
EstherLerouzic
496ec25661 Add a test with long propagation
Existing tests only cover short distances, and effect on accumulated
noise, especially when crossing ROADMs with equalization, are not well
reported on elements power prints.
With this long path, I can catch more printing inconsistencies.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I2d0e8ccbbd387a2cd6c645c07f4b5f75e4617c30
2021-10-04 10:41:08 +02:00
EstherLerouzic
93dfadca35 Change ref_power to ref_carrier
P_span0 and p_spani record powers for the noiseless reference, but not
its other attributes (baud rate, roll-off, ...). we add this ref_carrier
specification in the function call. This will be usefull for example
to compute power spectral density.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ic7441afa12ca5273ff99dea0268e439276107257
2021-10-04 10:41:06 +02:00
EstherLerouzic
12e58e3dbf Add a user defined initial spectrum in propagation functions
A new function is added to use requests specs based on transceivers
and on user definition of mixed rates and powers.

Propagation functions are changed so that, if the user defines a
specific distribution, then they use it else they use as before,
all identical channels based on the initial request. In this case,
as before this change, we assume full load, with same channel for
the spectral info and not the resulting mixt of channels after
routing.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Icf56396837b77009e98accd27fcebd2dded6d112
2021-10-04 10:40:25 +02:00
EstherLerouzic
5c32805073 Change pref from a scalar to a list of per channel delta power
The idea behind this change is to reproduce the exact same behaviour as
with the scalar, but accounting for variable levels of powers.

- delete the  neq_ch: equivalent channel count in dB because with mixed
  rates and power such a value has limited utility
- instead creates a vector that records the 'user defined' distribution
  of power.

This vector is used as a reference for channel equalization out of the
ROADM. For example, if user specifies:
    freq1: 1dBm, freq2: +3dBm, freq3:-3dBm,
recorded in p_span0_per_channel and if power for the reference channel
is 0dBm (recorded in p_span0), the same relative power difference will
be applied on each degree of ROADMs.

target_pch_out_db is the target power for the reference channel so
p_out_target[f1, f2, f3] = target_pch_out_db + \
                           p_span0_per_channel[f1, f2, f3] - p_span0
                         = -19, -16, -22

- in amplifier: the saturation is computed based on this vector
p_span0_per_channel, instead of the nb of channels.
The target of the future refactor will be to use the effective
carrier's power. I prefer to have this first step, because this is
how it is implemented today (ie based on the noiseless reference),
and I would like first to add more behaviour tests before doing
this refactor (would it be needed).

- in spectralInfo class, change pref to a Pref object to ease spectral
information operations to enable __add__ operation also on
p_span0_per_channel.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: Ifacea50e77a2eb4306d80c640e5277b491185488

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I591027cdd08e89098330c7d77d6f50212f4d4724
2021-10-04 10:30:47 +02:00
EstherLerouzic
c5b3914e25 Prepare for Pref definition
Mainly changes self.pch_out_db to self.ref_pch_out_dbm in order
to reflect real unit for the value and to remind that this value
is defined for a reference noiseless channel (whose power is recorded
in p_spani in Pref).

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: If0e008c3efc36ce73c9df01c76cf46985543d9fa
2021-10-04 10:22:33 +02:00
EstherLerouzic
4f9193fab4 Add utilities
- to create a reference channel based on SI
- to convert from to watt, mW, dBm, power spectral density ...

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
Change-Id: I9b9684c1ad096aa54d01ef3f0242ecd2dcae79aa
2021-10-04 10:04:06 +02:00
AndreaDAmico
72edade853 Restructure Transceiver with new spectral information
Change-Id: Iec9a6e4a510b8020aed8804d4a594b2b0429e28d
2021-10-04 10:04:06 +02:00
AndreaDAmico
541ee734a4 EDFA new spectral information restructuring
Change-Id: Ia30e0e9bd666e83394c7a0740b2117a2d9c9d485
2021-10-04 10:04:06 +02:00
AndreaDAmico
d312c99ee1 Fused new spectral information restructuring
Change-Id: Ie4dd989e2fd72682820845d21c43afed177f0f2f
2021-10-04 10:04:06 +02:00
AndreaDAmico
839f4fea6c Roadm new spectral information restructuring
Change-Id: I5c7c615e8278bff79dc74af10810589a15cc7535
2021-10-04 10:04:06 +02:00
Giacomo Borraccini
05da89fbf2 Management of lumped losses along a fiber span
Change-Id: I73a6baa321aca4d041cafa180f47afed824ce267
2021-10-04 10:04:06 +02:00
AndreaDAmico
3377906002 Raman Solver restructuring and speed up
Raman Solver restructuring and speed up

In this change, the RamanSolver is completely restructured in order to obtain a simplified and faster solution of the Raman equation. Additionally, the inter-channel Raman effect can be evaluated also in the standard fiber, when no Raman pumping is present. The same is true for the GGN model.

The Raman pump parameter pump_loss_coef has been removed as the loss coefficient value evaluated at the pump frequency has to be included within the fiber loss_coef parameter.

This change induces variations in some expected test results as the Raman profile solution is calculated by a completely distinct algorithm. Nevertheless, these variations are negligible being lower than 0.1dB.

Change-Id: Iaa40fbb23c555571497e1ff3bf19dbcbfcadf96b
2021-10-04 10:04:06 +02:00
AndreaDAmico
ac16df54d1 Fiber propagation of new Spectral Information.
Modification of the Fiber and the NliSolver in order to properly propagate the new definition of the spectral information taking advantage of the numpy array structures.

In the previous version, the propagation of the spectral information was implemented by means of for cycles over each channel, in turn.
In this change the propagation is applied directly on the newly defined spectral information attributes as numpy arrays.

Additional changes:
- Simplification of the FiberParameters and the NliParameters;
- Previous issues regarding the loss_coef definition along the frequency are solved;
- New test in test_science_utils.py verifing that the fiber propagation provides the correct values in case of a few cases of flex grid spectra.

Change-Id: Id71f36effba35fc3ed4bbf2481a3cf6566ccb51c
2021-10-04 10:03:55 +02:00
AndreaDAmico
def82b6515 Simulation Parameters
This change siplifies the structure of the simulation parameters, removing the gnpy.science_utils.simulation layer, provides some documentation of the parameters and define a mock fixture for testing in safe mode

Change-Id: If5ef341e0585586127d5dae3f39dca2c232236f1
2021-09-15 17:56:19 +02:00
AndreaDAmico
3910803dfa Small change on Raman pump parameters
Getter and setter removed from the class PumpParams. The propagation direction is cast to lower case string within the PumpParams constructor.

Change-Id: Ice28affe8bcffbf8adcebb5cb096be8100081511
2021-09-15 17:56:19 +02:00
AndreaDAmico
c75d66b46d Add documentation of simulation parameters
Change-Id: I02173f500fed8c065a30de5d23e318bce2a90c33
2021-09-15 17:56:19 +02:00
AndreaDAmico
e8db766eec New definition of spectral information
It allows the definition of an arbitrary spectral information.
It is fully back-compatible.

Change-Id: Id050e9f0a0d30780a49ecfbe8b96271fe47bcedc
2021-09-15 17:56:19 +02:00
44 changed files with 4284 additions and 1368 deletions

View File

@@ -61,25 +61,33 @@ Fiber
The fiber library currently describes SSMF and NZDF but additional fiber types can be entered by the user following the same model:
+----------------------+-----------+------------------------------------------+
| field | type | description |
+======================+===========+==========================================+
| ``type_variety`` | (string) | a unique name to ID the fiber in the |
| | | JSON or Excel template topology input |
| | | file |
+----------------------+-----------+------------------------------------------+
| ``dispersion`` | (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}` |
+----------------------+-----------+------------------------------------------+
| ``gamma`` | (number) | :math:`2\pi\times n^2/(\lambda*A_{eff})`,|
| | | in :math:`w^{-1} \times m^{-1}`. |
+----------------------+-----------+------------------------------------------+
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) |
| | | coefficient. In |
| | | :math:`s\times\sqrt{m}^{-1}`. |
+----------------------+-----------+------------------------------------------+
+----------------------------+-----------+------------------------------------------+
| field | type | description |
+============================+===========+==========================================+
| ``type_variety`` | (string) | a unique name to ID the fiber in the |
| | | JSON or Excel template topology input |
| | | file |
+----------------------------+-----------+------------------------------------------+
| ``dispersion`` | (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}` |
+----------------------------+-----------+------------------------------------------+
| ``gamma`` | (number) | :math:`2\pi\times n^2/(\lambda*A_{eff})`,|
| | | in :math:`w^{-1} \times m^{-1}`. |
+----------------------------+-----------+------------------------------------------+
| ``pmd_coef`` | (number) | Polarization mode dispersion (PMD) |
| | | coefficient. In |
| | | :math:`s\times\sqrt{m}^{-1}`. |
+----------------------------+-----------+------------------------------------------+
| ``lumped_losses.loss`` | (number) | Array of lumped loss , expressed in dB, |
| | | values along the fiber due to spool |
| | | junctions. |
+----------------------------+-----------+------------------------------------------+
| ``lumped_losses.position`` | (number) | Array of positions, expressed in km, |
| | | of the lumped losses along the fiber |
| | | due to spool junctions. |
+----------------------------+-----------+------------------------------------------+
Transceiver
~~~~~~~~~~~
@@ -176,6 +184,33 @@ 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.
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.
A global variable of ``gnpy.parameters.SimParams`` is created for each simulation and it is shared between all the fiber
instances, assuring a coherent simulation.
+--------------------------------------------+-----------+---------------------------------------------+
| field | type | description |
+============================================+===========+=============================================+
| ``raman_params.flag`` | (boolean) | Enable/Disable Raman profile evaluation |
+--------------------------------------------+-----------+---------------------------------------------+
| ``raman_params.result_spatial_resolution`` | (number) | Spatial resolution of the output |
| | | Raman profile |
+--------------------------------------------+-----------+---------------------------------------------+
| ``raman_params.solver_spatial_resolution`` | (number) | Spatial step for the iterative solution |
| | | of the first order differential equation |
+--------------------------------------------+-----------+---------------------------------------------+
| ``nli_params.method`` | (string) | Model used for the NLI evaluation |
+--------------------------------------------+-----------+---------------------------------------------+
| ``nli_params.dispersion_tolerance`` | (number) | Tuning parameter for the NliSolver |
+--------------------------------------------+-----------+---------------------------------------------+
| ``nli_params.phase_shift_tolerance`` | (number) | Tuning parameter for the NliSolver |
+--------------------------------------------+-----------+---------------------------------------------+
| ``nli_params.computed_channels`` | (number) | The channels on which the NLI is |
| | | explicitly evaluated |
+--------------------------------------------+-----------+---------------------------------------------+
Span
~~~~

View File

@@ -20,13 +20,19 @@ unique identifier and a printable name, and provide the :py:meth:`__call__` meth
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, minimum
from scipy.constants import h, c
from scipy.interpolate import interp1d
from collections import namedtuple
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
from gnpy.core.parameters import FiberParams, PumpParams
from gnpy.core.science_utils import NliSolver, RamanSolver, propagate_raman_fiber, _psi
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum, per_label_summary, pretty_summary_print,\
watt2dbm, psd2powerdbm, psdmwperghz, powerdbm2psdmwperghz
from gnpy.core.parameters import RoadmParams, FusedParams, FiberParams, PumpParams, EdfaParams, EdfaOperational
from gnpy.core.science_utils import NliSolver, RamanSolver
from gnpy.core.info import SpectralInformation
from gnpy.core import ansi_escapes
from gnpy.core.exceptions import NetworkTopologyError, ParametersError
class Location(namedtuple('Location', 'latitude longitude city region')):
@@ -83,28 +89,24 @@ class Transceiver(_Node):
def _calc_cd(self, spectral_info):
""" 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):
"""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_snr(self, spectral_info):
with errstate(divide='ignore'):
self.baud_rate = [c.baud_rate for c in spectral_info.carriers]
ratio_01nm = [lin2db(12.5e9 / b_rate) for b_rate in self.baud_rate]
self.label = spectral_info.label
self.baud_rate = spectral_info.baud_rate
ratio_01nm = lin2db(12.5e9 / self.baud_rate)
# set raw values to record original calculation, before update_snr()
self.raw_osnr_ase = [lin2db(divide(c.power.signal, c.power.ase))
for c in spectral_info.carriers]
self.raw_osnr_ase_01nm = [ase - ratio for ase, ratio
in zip(self.raw_osnr_ase, ratio_01nm)]
self.raw_osnr_nli = [lin2db(divide(c.power.signal, c.power.nli))
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.raw_osnr_ase = lin2db(spectral_info.signal / spectral_info.ase)
self.raw_osnr_ase_01nm = self.raw_osnr_ase - ratio_01nm
self.raw_osnr_nli = lin2db(spectral_info.signal / spectral_info.nli)
self.raw_snr = lin2db(spectral_info.signal / (spectral_info.ase + spectral_info.nli))
self.raw_snr_01nm = self.raw_snr - ratio_01nm
self.osnr_ase = self.raw_osnr_ase
self.osnr_ase_01nm = self.raw_osnr_ase_01nm
@@ -124,14 +126,10 @@ class Transceiver(_Node):
for s in args:
snr_added += db2lin(-s)
snr_added = -lin2db(snr_added)
self.osnr_ase = list(map(lambda x, y: snr_sum(x, y, snr_added),
self.raw_osnr_ase, self.baud_rate))
self.snr = list(map(lambda x, y: snr_sum(x, y, snr_added),
self.raw_snr, self.baud_rate))
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))
self.osnr_ase = snr_sum(self.raw_osnr_ase, self.baud_rate, snr_added)
self.snr = snr_sum(self.raw_snr, self.baud_rate, snr_added)
self.osnr_ase_01nm = snr_sum(self.raw_osnr_ase_01nm, 12.5e9, snr_added)
self.snr_01nm = snr_sum(self.raw_snr_01nm, 12.5e9, snr_added)
@property
def to_json(self):
@@ -156,19 +154,19 @@ class Transceiver(_Node):
if self.snr is None or self.osnr_ase is None:
return f'{type(self).__name__} {self.uid}'
snr = round(mean(self.snr), 2)
osnr_ase = round(mean(self.osnr_ase), 2)
osnr_ase_01nm = round(mean(self.osnr_ase_01nm), 2)
snr_01nm = round(mean(self.snr_01nm), 2)
snr = per_label_summary(self.snr, self.label)
osnr_ase = per_label_summary(self.osnr_ase, self.label)
osnr_ase_01nm = per_label_summary(self.osnr_ase_01nm, self.label)
snr_01nm = per_label_summary(self.snr_01nm, self.label)
cd = mean(self.chromatic_dispersion)
pmd = mean(self.pmd)
return '\n'.join([f'{type(self).__name__} {self.uid}',
f' GSNR (0.1nm, dB): {snr_01nm:.2f}',
f' GSNR (signal bw, dB): {snr:.2f}',
f' OSNR ASE (0.1nm, dB): {osnr_ase_01nm:.2f}',
f' OSNR ASE (signal bw, dB): {osnr_ase:.2f}',
f' GSNR (0.1nm, dB): {pretty_summary_print(snr_01nm)}',
f' GSNR (signal bw, dB): {pretty_summary_print(snr)}',
f' OSNR ASE (0.1nm, dB): {pretty_summary_print(osnr_ase_01nm)}',
f' OSNR ASE (signal bw, dB): {pretty_summary_print(osnr_ase)}',
f' CD (ps/nm): {cd:.2f}',
f' PMD (ps): {pmd:.2f}'])
@@ -179,29 +177,41 @@ class Transceiver(_Node):
return spectral_info
RoadmParams = namedtuple('RoadmParams', 'target_pch_out_db add_drop_osnr pmd restrictions per_degree_pch_out_db')
class Roadm(_Node):
def __init__(self, *args, params, **kwargs):
if 'per_degree_pch_out_db' not in params.keys():
params['per_degree_pch_out_db'] = {}
super().__init__(*args, params=RoadmParams(**params), **kwargs)
def __init__(self, *args, params=None, **kwargs):
if not params:
params = {}
try:
super().__init__(*args, params=RoadmParams(**params), **kwargs)
except ParametersError as e:
raise ParametersError('Config error in ', kwargs['uid'], ' .', e)
# target power as defined by user
self.target_pch_out_dbm = self.params.target_pch_out_db
# reference power is target power by default. depending on propagation this may change (due to equalization)
self.ref_pch_out_dbm = self.params.target_pch_out_db
self.loss = 0 # auto-design interest
self.effective_loss = None
self.effective_pch_out_db = self.params.target_pch_out_db
self.ref_effective_loss = None
self.passive = True
self.restrictions = self.params.restrictions
self.per_degree_pch_out_db = self.params.per_degree_pch_out_db
# element contains the two types of equalisation parameters, but only one is not None or empty
self.target_psd_out_mWperGHz = self.params.target_psd_out_mWperGHz
self.per_degree_pch_psd = self.params.per_degree_pch_psd
@property
def to_json(self):
if self.ref_pch_out_dbm:
equalisation, value = 'target_pch_out_db', self.ref_pch_out_dbm
perdegree, perdegreevalue = 'per_degree_pch_out_db', self.per_degree_pch_out_db
if self.target_psd_out_mWperGHz:
equalisation, value = 'target_psd_out_mWperGHz', self.target_psd_out_mWperGHz
perdegree, perdegreevalue = 'per_degree_psd_out_mWperGHz', self.per_degree_pch_psd
return {'uid': self.uid,
'type': type(self).__name__,
'params': {
'target_pch_out_db': self.effective_pch_out_db,
equalisation: value,
'restrictions': self.restrictions,
'per_degree_pch_out_db': self.per_degree_pch_out_db
perdegree: perdegreevalue
},
'metadata': {
'location': self.metadata['location']._asdict()
@@ -212,14 +222,16 @@ class Roadm(_Node):
return f'{type(self).__name__}(uid={self.uid!r}, loss={self.loss!r})'
def __str__(self):
if self.effective_loss is None:
if self.ref_effective_loss is None:
return f'{type(self).__name__} {self.uid}'
total_pch = pretty_summary_print(per_label_summary(self.pch_out_dbm, self.label))
return '\n'.join([f'{type(self).__name__} {self.uid}',
f' effective loss (dB): {self.effective_loss:.2f}',
f' pch out (dBm): {self.effective_pch_out_db:.2f}'])
f' effective loss (dB): {self.ref_effective_loss:.2f}',
f' pch out (dBm): {self.ref_pch_out_dbm:.2f}',
f' total pch (dBm): {total_pch}'])
def propagate(self, pref, *carriers, degree):
def propagate(self, spectral_info, degree):
# pin_target and loss are read from eqpt_config.json['Roadm']
# all ingress channels in xpress are set to this power level
# but add channels are not, so we define an effective loss
@@ -228,39 +240,72 @@ class Roadm(_Node):
# if a target power has been defined for this degree use it else use the global one.
# 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
# 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
self.effective_pch_out_db = min(pref.p_spani, per_degree_pch)
self.effective_loss = pref.p_spani - self.effective_pch_out_db
carriers_power = array([c.power.signal + c.power.nli + c.power.ase for c in carriers])
carriers_att = list(map(lambda x: lin2db(x * 1e3) - per_degree_pch, carriers_power))
exceeding_att = -min(list(filter(lambda x: x < 0, carriers_att)), default=0)
carriers_att = list(map(lambda x: db2lin(x + exceeding_att), carriers_att))
for carrier_att, carrier in zip(carriers_att, carriers):
pwr = carrier.power
pwr = pwr._replace(signal=pwr.signal / carrier_att,
nli=pwr.nli / carrier_att,
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):
return pref._replace(p_span0=pref.p_span0, p_spani=self.effective_pch_out_db)
# TODO maybe add a minimum loss for the ROADM
# check equalization: if ref_pch_out_dbm is defined then use it
# change per_degree_pch from scalar to an array / add a ref_power, ref_baudrate ...
ref_baud_rate = spectral_info.pref.ref_carrier['baud_rate']
if self.target_pch_out_dbm:
per_degree_pch = self.per_degree_pch_out_db[degree] \
if degree in self.per_degree_pch_out_db else self.target_pch_out_dbm
ref_per_degree_pch = per_degree_pch
per_degree_pch = per_degree_pch * ones(len(spectral_info.channel_number))
elif self.target_psd_out_mWperGHz:
per_degree_pch = psd2powerdbm(self.per_degree_pch_psd[degree], spectral_info.baud_rate) \
if degree in self.per_degree_pch_psd \
else psd2powerdbm(self.target_psd_out_mWperGHz, spectral_info.baud_rate)
ref_per_degree_pch = psd2powerdbm(self.per_degree_pch_psd[degree], ref_baud_rate) \
if degree in self.per_degree_pch_psd \
else psd2powerdbm(self.target_psd_out_mWperGHz, ref_baud_rate)
# definition of ref_pch_out_db for the reference channel: depending on propagation input power (p_spani) might
# be smaller than the target power out of the roadm on this degree then use the min value between both
self.ref_pch_out_dbm = min(spectral_info.pref.p_spani, ref_per_degree_pch)
# definition of effective_loss: value for the reference channel
self.ref_effective_loss = spectral_info.pref.p_spani - self.ref_pch_out_dbm
input_power = spectral_info.signal + spectral_info.nli + spectral_info.ase
# computation of the per channel target power according to equalization policy
if self.target_pch_out_dbm:
min_power = watt2dbm(min(input_power))
per_degree_pch = minimum(per_degree_pch, min_power)
elif self.target_psd_out_mWperGHz:
# Assume that channels with same baudrate are equalized to the same power.
# Applies the same min strategy if the input power is lower than the target one:
# use the min psd of all carriers.
# If all carriers have identical baud_rate, the target power is the min power
# of the carrier compared to per_degree_pch (same as power equalization)
min_psd = min(psdmwperghz(input_power, spectral_info.baud_rate))
temp = powerdbm2psdmwperghz(per_degree_pch, spectral_info.baud_rate)
per_degree_pch = psd2powerdbm(minimum(temp, min_psd), spectral_info.baud_rate)
# target power should follow same delta power as in p_span0_per_channel
# if no specific delta, then apply equalization (later on)
pref = spectral_info.pref
delta_channel_power = pref.p_span0_per_channel - pref.p_span0
delta_power = watt2dbm(input_power) - (per_degree_pch + delta_channel_power)
spectral_info.apply_attenuation_db(delta_power)
spectral_info.pmd = sqrt(spectral_info.pmd ** 2 + self.params.pmd ** 2)
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
self.label = spectral_info.label
def update_pref(self, spectral_info):
""" updates the value in Pref in spectral_info. p_span0 and p_span0_per_channel are unchanged, only p_spani
which contains the power for the reference channel after propagation in the ROADM.
p_span0_per_channel corresponds exactly to the current mix of channels {freq: pow},
it serves as reference to compute delta_power wrt ref channel.
So, we implement two main equalisation: all channels with same power or same psd plus
a user defined delta power based on p_span0_per_channel vector
"""
spectral_info.pref = spectral_info.pref._replace(p_spani=self.ref_pch_out_dbm)
def __call__(self, spectral_info, degree):
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers, degree=degree))
pref = self.update_pref(spectral_info.pref)
return spectral_info._replace(carriers=carriers, pref=pref)
FusedParams = namedtuple('FusedParams', 'loss')
self.propagate(spectral_info, degree=degree)
self.update_pref(spectral_info)
return spectral_info
class Fused(_Node):
def __init__(self, *args, params=None, **kwargs):
if params is None:
# default loss value if not mentioned in loaded network json
params = {'loss': 1}
if not params:
params = {}
super().__init__(*args, params=FusedParams(**params), **kwargs)
self.loss = self.params.loss
self.passive = True
@@ -284,23 +329,17 @@ class Fused(_Node):
return '\n'.join([f'{type(self).__name__} {self.uid}',
f' loss (dB): {self.loss:.2f}'])
def propagate(self, *carriers):
attenuation = db2lin(self.loss)
def propagate(self, spectral_info):
spectral_info.apply_attenuation_db(self.loss)
for carrier in carriers:
pwr = carrier.power
pwr = pwr._replace(signal=pwr.signal / attenuation,
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 update_pref(self, spectral_info):
spectral_info.pref = spectral_info.pref._replace(p_span0=spectral_info.pref.p_span0,
p_spani=spectral_info.pref.p_spani - self.loss)
def __call__(self, spectral_info):
carriers = tuple(self.propagate(*spectral_info.carriers))
pref = self.update_pref(spectral_info.pref)
return spectral_info._replace(carriers=carriers, pref=pref)
self.propagate(spectral_info)
self.update_pref(spectral_info)
return spectral_info
class Fiber(_Node):
@@ -309,7 +348,31 @@ class Fiber(_Node):
params = {}
super().__init__(*args, params=FiberParams(**params), **kwargs)
self.pch_out_db = None
self.nli_solver = NliSolver(self)
self.passive = True
# Raman efficiency matrix function of the delta 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
if self.params.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(
f"Lumped loss positions must be between 0 and the fiber length ({1e-3 * self.params.length} km), " +
f"boundaries excluded.")
self.lumped_losses = db2lin(- lumped_losses_power) # [linear units]
self.z_lumped_losses = array(z_lumped_losses) * 1e3 # [m]
else:
self.lumped_losses = None
self.z_lumped_losses = None
@property
def to_json(self):
@@ -339,6 +402,7 @@ class Fiber(_Node):
if self.pch_out_db is None:
return f'{type(self).__name__} {self.uid}'
total_pch = pretty_summary_print(per_label_summary(self.pch_out_dbm, self.label))
return '\n'.join([f'{type(self).__name__} {self.uid}',
f' type_variety: {self.type_variety}',
f' length (km): {self.params.length * 1e-3:.2f}',
@@ -346,38 +410,52 @@ class Fiber(_Node):
f' total loss (dB): {self.loss:.2f}',
f' (includes conn loss (dB) in: {self.params.con_in:.2f} out: {self.params.con_out:.2f})',
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}',
f' total pch (dBm): {total_pch}'])
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 as e:
print(ansi_escapes.red +
f'\n WARNING {e} ' + 'Value extrapolated.' + ansi_escapes.reset)
loss_coef = interp1d(self.params.f_loss_ref, self.params.loss_coef, bounds_error=False,
fill_value='extrapolate')(frequency)
else:
loss_coef = full(frequency.size, self.params.loss_coef)
return squeeze(loss_coef)
@property
def loss(self):
"""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 passive(self):
return True
def lin_attenuation(self, frequency):
return 1 / db2lin(self.params.length * self.loss_coef_func(frequency))
def alpha(self, frequencies):
"""It returns the values of the series expansion of attenuation coefficient alpha(f) for all f in frequencies
def alpha(self, frequency):
"""Returns the linear exponent attenuation coefficient such that
:math: `lin_attenuation = e^{- alpha length}`
:param frequencies: frequencies of series expansion [Hz]
:return: alpha: power attenuation coefficient for f in frequencies [Neper/m]
:param frequency: the frequency at which alpha is computed [Hz]
:return: alpha: power attenuation coefficient for f in frequency [Neper/m]
"""
if type(self.params.loss_coef) == dict:
alpha = interp(frequencies, self.params.f_loss_ref, self.params.lin_loss_exp)
else:
alpha = self.params.lin_loss_exp * ones(frequencies.shape)
return self.loss_coef_func(frequency) / (10 * log10(exp(1)))
return alpha
def cr(self, frequency):
"""Returns the raman efficiency matrix including the vibrational loss
def alpha0(self, f_ref=193.5e12):
"""It returns the zero element of the series expansion of attenuation coefficient alpha(f) in the
reference frequency f_ref
:param f_ref: reference frequency of series expansion [Hz]
:return: alpha0: power attenuation coefficient in f_ref [Neper/m]
:param frequency: the frequency at which cr is computed [Hz]
:return: cr: raman efficiency matrix [1 / (W 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):
"""Returns accumulated chromatic dispersion (CD).
@@ -398,70 +476,50 @@ class Fiber(_Node):
"""differential group delay (PMD) [s]"""
return self.params.pmd_coef * sqrt(self.params.length)
def _gn_analytic(self, carrier, *carriers):
r"""Computes the nonlinear interference power on a single carrier.
The method uses eq. 120 from `arXiv:1209.0394 <https://arxiv.org/abs/1209.0394>`__.
: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
def propagate(self, spectral_info: SpectralInformation):
"""Modifies the spectral information computing the attenuation, the non-linear interference generation,
the CD and PMD accumulation.
"""
# 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
for interfering_carrier in carriers:
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
# inter channels Raman effect
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(spectral_info, self)
g_nli *= (16 / 27) * (self.params.gamma * self.params.effective_length)**2 \
/ (2 * pi * abs(self.params.beta2) * self.params.asymptotic_length)
# NLI noise evaluated at the fiber input
spectral_info.nli += NliSolver.compute_nli(spectral_info, stimulated_raman_scattering, self)
carrier_nli = carrier.baud_rate * g_nli
return carrier_nli
# 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)
def propagate(self, *carriers):
r"""Generator that computes the fiber propagation: attenuation, non-linear interference generation, CD
accumulation and PMD accumulation.
# apply the attenuation due to the fiber losses
attenuation_fiber = stimulated_raman_scattering.loss_profile[:, -1]
spectral_info.apply_attenuation_lin(attenuation_fiber)
:param: \*carriers: the channels at the input of the fiber
:yield: carrier: the next channel at the output of the fiber
"""
# apply the attenuation due to the output connector loss
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
attenuation = db2lin(self.params.con_in + self.params.att_in)
chan = []
for carrier in carriers:
pwr = carrier.power
pwr = pwr._replace(signal=pwr.signal / attenuation,
nli=pwr.nli / attenuation,
ase=pwr.ase / attenuation)
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 update_pref(self, spectral_info):
# 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:
# power_out - power_in. We use the total signal power (sum on all channels) to compute
# this loss, because pref is a noiseless reference.
loss = round(lin2db(self._psig_in / sum(spectral_info.signal)), 2)
self.pch_out_db = spectral_info.pref.p_spani - loss
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
self.label = spectral_info.label
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):
carriers = tuple(self.propagate(*spectral_info.carriers))
pref = self.update_pref(spectral_info.pref)
return spectral_info._replace(carriers=carriers, pref=pref)
# _psig_in records the total signal power of the spectral information before propagation.
self._psig_in = sum(spectral_info.signal)
self.propagate(spectral_info)
self.update_pref(spectral_info)
return spectral_info
class RamanFiber(Fiber):
@@ -471,74 +529,39 @@ class RamanFiber(Fiber):
self.raman_pumps = tuple(PumpParams(p['power'], p['frequency'], p['propagation_direction'])
for p in self.operational['raman_pumps'])
else:
self.raman_pumps = None
self.raman_solver = RamanSolver(self)
raise NetworkTopologyError(f'Fiber element uid:{self.uid} '
f'defined as RamanFiber without raman pumps description')
self.temperature = self.operational['temperature'] if 'temperature' in self.operational else None
@property
def to_json(self):
return dict(super().to_json, operational=self.operational)
def propagate(self, spectral_info: SpectralInformation):
"""Modifies the spectral information computing the attenuation, the non-linear interference generation,
the CD and PMD accumulation.
"""
# 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 update_pref(self, pref, *carriers):
pch_out_db = lin2db(mean([carrier.power.signal for carrier in carriers])) + 30
self.pch_out_db = round(pch_out_db, 2)
return pref._replace(p_span0=pref.p_span0, p_spani=self.pch_out_db)
# Raman pumps and inter channel Raman effect
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(spectral_info, self)
spontaneous_raman_scattering = \
RamanSolver.calculate_spontaneous_raman_scattering(spectral_info, stimulated_raman_scattering, self)
def __call__(self, spectral_info):
carriers = tuple(self.propagate(*spectral_info.carriers))
pref = self.update_pref(spectral_info.pref, *carriers)
return spectral_info._replace(carriers=carriers, pref=pref)
# nli and ase noise evaluated at the fiber input
spectral_info.nli += NliSolver.compute_nli(spectral_info, stimulated_raman_scattering, self)
spectral_info.ase += spontaneous_raman_scattering
def propagate(self, *carriers):
for propagated_carrier in propagate_raman_fiber(self, *carriers):
chromatic_dispersion = propagated_carrier.chromatic_dispersion + \
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)
# apply the attenuation due to the fiber losses
attenuation_fiber = stimulated_raman_scattering.loss_profile[:spectral_info.number_of_channels, -1]
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
spectral_info.apply_attenuation_lin(attenuation_fiber)
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})')
# apply the attenuation due to the output connector loss
attenuation_out_db = self.params.con_out
spectral_info.apply_attenuation_db(attenuation_out_db)
class Edfa(_Node):
@@ -548,12 +571,7 @@ class Edfa(_Node):
if operational is None:
operational = {}
self.variety_list = kwargs.pop('variety_list', None)
super().__init__(
*args,
params=EdfaParams(**params),
operational=EdfaOperational(**operational),
**kwargs
)
super().__init__(*args, params=EdfaParams(**params), operational=EdfaOperational(**operational), **kwargs)
self.interpol_dgt = None # interpolated dynamic gain tilt
self.interpol_gain_ripple = None # gain ripple
self.interpol_nf_ripple = None # nf_ripple
@@ -605,6 +623,7 @@ class Edfa(_Node):
if self.pin_db is None or self.pout_db is None:
return f'{type(self).__name__} {self.uid}'
nf = mean(self.nf)
total_pch = pretty_summary_print(per_label_summary(self.pch_out_dbm, self.label))
return '\n'.join([f'{type(self).__name__} {self.uid}',
f' type_variety: {self.params.type_variety}',
f' effective gain(dB): {self.effective_gain:.2f}',
@@ -617,36 +636,45 @@ class Edfa(_Node):
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' effective pch (dBm): {self.effective_pch_out_db:.2f}',
f' total pch (dBm): {total_pch}',
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
:param spectral_info: instance of gnpy.core.info.SpectralInformation
:return: None
"""
# 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
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
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
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))
"""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"""
pref = spectral_info.pref
if self.delta_p is not None:
self.target_pch_out_db = round(self.delta_p + pref.p_span0, 2)
self.effective_gain = self.target_pch_out_db - pref.p_spani
"""check power saturation and correct effective gain & power accordingly:"""
# compute the sum of powers of carriers at the input of the amplifier accounting for the expected power mixt
delta_channel_power = pref.p_span0_per_channel - pref.p_span0
input_total_power = lin2db(sum([db2lin(pref.p_spani + d) for d in delta_channel_power]))
self.effective_gain = min(
self.effective_gain,
self.params.p_max - (pref.p_spani + pref.neq_ch)
# self.params.p_max - (pref.p_spani + pref.neq_ch)
self.params.p_max - input_total_power
)
#print(self.uid, self.effective_gain, self.operational.gain_target)
self.effective_pch_out_db = round(pref.p_spani + self.effective_gain, 2)
@@ -656,7 +684,7 @@ class Edfa(_Node):
self.nf = self._calc_nf()
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))
# ase & nli are only calculated in signal bandwidth
# pout_db is not the absolute full output power (negligible if sufficient channels)
@@ -725,14 +753,10 @@ class Edfa(_Node):
else:
return self.interpol_nf_ripple + nf_avg # input VOA = 1 for 1 NF degradation
def noise_profile(self, df):
"""noise_profile(bw) computes amplifier ASE (W) in signal bandwidth (Hz)
Noise is calculated at amplifier input
:bw: signal bandwidth = baud rate in Hz
:type bw: float
def noise_profile(self, spectral_info):
"""Computes amplifier ASE noise integrated over the signal bandwidth. This is calculated at amplifier input.
:param spectral_info: instance of gnpy.core.info.SpectralInformation
:return: the asepower in W in the signal bandwidth bw for 96 channels
:return type: numpy array of float
@@ -767,7 +791,7 @@ class Edfa(_Node):
quoting power spectral density in the same BW for both signal and ASE,
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
def _gain_profile(self, pin, err_tolerance=1.0e-11, simple_opt=True):
@@ -873,30 +897,24 @@ class Edfa(_Node):
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`"""
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
self.interpol_params(freq, pin, brate, pref)
self.interpol_params(spectral_info)
gains = db2lin(self.gprofile)
carrier_ases = self.noise_profile(brate)
att = db2lin(self.out_voa)
ase = self.noise_profile(spectral_info)
spectral_info.ase += ase
for gain, carrier_ase, carrier in zip(gains, carrier_ases, carriers):
pwr = carrier.power
pwr = pwr._replace(signal=pwr.signal * gain / att,
nli=pwr.nli * gain / att,
ase=(pwr.ase + carrier_ase) * gain / att)
yield carrier._replace(power=pwr)
spectral_info.apply_gain_db(self.gprofile - self.out_voa)
self.pch_out_dbm = watt2dbm(spectral_info.signal + spectral_info.nli + spectral_info.ase)
self.label = spectral_info.label
def update_pref(self, pref):
return pref._replace(p_span0=pref.p_span0,
p_spani=pref.p_spani + self.effective_gain - self.out_voa)
def update_pref(self, spectral_info):
spectral_info.pref = \
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):
carriers = tuple(self.propagate(spectral_info.pref, *spectral_info.carriers))
pref = self.update_pref(spectral_info.pref)
return spectral_info._replace(carriers=carriers, pref=pref)
self.propagate(spectral_info)
self.update_pref(spectral_info)
return spectral_info

View File

@@ -66,7 +66,6 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F
trx_params['min_spacing'] = None
nch = automatic_nch(trx_params['f_min'], trx_params['f_max'], trx_params['spacing'])
trx_params['nb_channel'] = nch
print(f'There are {nch} channels propagating')
trx_params['power'] = db2lin(default_si_data.power_dbm) * 1e-3

View File

@@ -8,20 +8,31 @@ gnpy.core.info
This module contains classes for modelling :class:`SpectralInformation`.
"""
from __future__ import annotations
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, db2lin, watt2dbm
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')):
"""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')):
""" Class containing the parameters of a WDM signal.
:param channel_number: channel number in the WDM grid
:param frequency: central frequency of the signal (Hz)
: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 power (gnpy.core.info.Power): power of signal, ASE noise and NLI (W)
:param chromatic_dispersion: chromatic dispersion (s/m)
@@ -29,28 +40,257 @@ class Channel(namedtuple('Channel', 'channel_number frequency baud_rate roll_off
"""
class Pref(namedtuple('Pref', 'p_span0, p_spani, neq_ch ')):
class Pref(namedtuple('Pref', 'p_span0, p_spani, p_span0_per_channel, ref_carrier')):
"""noiseless reference power in dBm:
p_span0: inital target carrier power
p_spani: carrier power after element i
neq_ch: equivalent channel count in dB"""
p_span0: inital target carrier power for a reference channel defined by user
p_spani: carrier power after element i for a reference channel defined by user
neq_ch: equivalent channel count in dB -> almost never used : suppress it
p_span0_per_channel: (per frequency) target per channel power for the actual mix
of channels
"""
class SpectralInformation(namedtuple('SpectralInformation', 'pref carriers')):
class SpectralInformation(object):
""" Class containing the parameters of the entire WDM comb."""
def __new__(cls, pref, carriers):
return super().__new__(cls, pref, carriers)
def __init__(self, frequency: array, baud_rate: array, slot_width: array, signal: array, nli: array, ase: array,
roll_off: array, chromatic_dispersion: array, pmd: array, ref_power: Pref, label: str):
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._channel_number = [*range(1, self._number_of_channels + 1)]
self._pref = ref_power
self._label = label
@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
@property
def label(self):
return self._label
@pmd.setter
def pmd(self, pmd):
self._pmd = pmd
@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)
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:
pref = Pref(self.pref.p_span0, self.pref.p_spani,
append(self.pref.p_span0_per_channel, other.pref.p_span0_per_channel), self.pref.ref_carrier)
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),
ref_power=pref,
label=append(self.label, other.label))
except SpectrumError:
raise SpectrumError('Spectra cannot be summed: channels overlapping.')
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
pref = lin2db(power * 1e3)
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.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.,
ref_power: Pref = None,
label: string = None):
"""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)
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,
ref_power=ref_power, label=label)
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, ref_carrier=None):
""" Creates a fixed slot width spectral information with flat power.
all arguments are scalar values"""
nb_channel = automatic_nch(f_min, f_max, spacing)
si = SpectralInformation(
pref=Pref(pref, pref, lin2db(nb_channel)),
carriers=[
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
frequency = [(f_min + spacing * i) for i in range(1, nb_channel + 1)]
p_span0 = watt2dbm(power)
p_spani = watt2dbm(power)
p_span0_per_channel = watt2dbm(power) * ones(nb_channel)
label = ["0" for i in range(nb_channel)]
return create_arbitrary_spectral_information(frequency, slot_width=spacing, signal=power, baud_rate=baud_rate,
roll_off=roll_off,
ref_power=Pref(p_span0=p_span0, p_spani=p_spani,
p_span0_per_channel=p_span0_per_channel,
ref_carrier=ref_carrier),
label=label)
def use_initial_spectrum(initial_spectrum, ref_carrier):
""" initial spectrum is a dict with key = carrier frequency, and value a dict with power,
baudrate and roll off for this carrier. ref_carrier contains the reference carrier (power, baudrate, ...)
used for the reference channel
"""
frequency = list(initial_spectrum.keys())
signal = [s['power'] for s in initial_spectrum.values()]
roll_off = [s['roll_off'] for s in initial_spectrum.values()]
baud_rate = [s['baud_rate'] for s in initial_spectrum.values()]
slot_width = [s['spacing'] for s in initial_spectrum.values()]
label = [s['label'] for s in initial_spectrum.values()]
p_span0 = watt2dbm(ref_carrier['req_power'])
p_spani = watt2dbm(ref_carrier['req_power'])
p_span0_per_channel = [watt2dbm(s['power']) for s in initial_spectrum.values()]
return create_arbitrary_spectral_information(frequency=frequency, signal=signal, baud_rate=baud_rate,
slot_width=slot_width, roll_off=roll_off,
ref_power=Pref(p_span0=p_span0, p_spani=p_spani,
p_span0_per_channel=p_span0_per_channel,
ref_carrier=ref_carrier),
label=label)

View File

@@ -11,7 +11,7 @@ Working with networks which consist of network elements
from operator import attrgetter
from gnpy.core import ansi_escapes, elements
from gnpy.core.exceptions import ConfigurationError, NetworkTopologyError
from gnpy.core.utils import round2float, convert_length
from gnpy.core.utils import round2float, convert_length, psd2powerdbm
from collections import namedtuple
@@ -236,8 +236,15 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
""" this node can be a transceiver or a ROADM (same function called in both cases)
"""
power_mode = equipment['Span']['default'].power_mode
ref_br = equipment['SI']['default'].baud_rate
next_oms = (n for n in network.successors(this_node) if not isinstance(n, elements.Transceiver))
this_node_degree = {k: v for k, v in this_node.per_degree_pch_out_db.items()} if hasattr(this_node, 'per_degree_pch_out_db') else {}
this_node_degree = {}
this_node_degree_psd = {}
if hasattr(this_node, 'per_degree_pch_out_db'):
this_node_degree = {k: v for k, v in this_node.per_degree_pch_out_db.items()}
if hasattr(this_node, 'per_degree_pch_psd'):
this_node_degree_psd = {k: v for k, v in this_node.per_degree_pch_psd.items()}
# TODO: check that the same degree does not appear in both dicts
for oms in next_oms:
# go through all the OMS departing from the ROADM
prev_node = this_node
@@ -246,12 +253,22 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
# node = find_last_node(next_node)
# next_node = next(n for n in network.successors(node))
# next_node = find_last_node(next_node)
if node.uid not in this_node_degree:
if node.uid not in this_node_degree and node.uid not in this_node_degree_psd:
# if no target power is defined on this degree or no per degree target power is given use the global one
# if target_pch_out_db is not an attribute, then the element must be a transceiver
this_node_degree[node.uid] = getattr(this_node.params, 'target_pch_out_db', 0)
this_node_degree[node.uid] = 0 # default value if this_node is a transceiver
if isinstance(this_node, elements.Roadm):
if this_node.params.target_pch_out_db:
this_node_degree[node.uid] = this_node.params.target_pch_out_db
elif this_node.params.target_psd_out_mWperGHz:
this_node_degree_psd[node.uid] = this_node.params.target_psd_out_mWperGHz
else:
raise ConfigurationError(this_node.uid,
'needs either a target_pch_out_db or a target_psd_out_mWperGHz')
# use the target power on this degree
prev_dp = this_node_degree[node.uid] - pref_ch_db
if node.uid in this_node_degree:
prev_dp = this_node_degree[node.uid] - pref_ch_db
if node.uid in this_node_degree_psd:
prev_dp = psd2powerdbm(this_node_degree_psd[node.uid], ref_br) - pref_ch_db
dp = prev_dp
prev_voa = 0
voa = 0
@@ -329,6 +346,7 @@ def set_egress_amplifier(network, this_node, equipment, pref_ch_db, pref_total_d
if isinstance(this_node, elements.Roadm):
this_node.per_degree_pch_out_db = {k: v for k, v in this_node_degree.items()}
this_node.per_degree_pch_psd = {k: v for k, v in this_node_degree_psd.items()}
def add_roadm_booster(network, roadm):

View File

@@ -9,9 +9,9 @@ This module contains all parameters to configure standard network elements.
"""
from scipy.constants import c, pi
from numpy import squeeze, log10, exp
from numpy import asarray
from gnpy.core.utils import db2lin, convert_length
from gnpy.core.utils import convert_length
from gnpy.core.exceptions import ParametersError
@@ -28,110 +28,89 @@ class Parameters:
class PumpParams(Parameters):
def __init__(self, power, frequency, propagation_direction):
self._power = power
self._frequency = frequency
self._propagation_direction = propagation_direction
@property
def power(self):
return self._power
@property
def frequency(self):
return self._frequency
@property
def propagation_direction(self):
return self._propagation_direction
self.power = power
self.frequency = frequency
self.propagation_direction = propagation_direction.lower()
class RamanParams(Parameters):
def __init__(self, **kwargs):
self._flag_raman = kwargs['flag_raman']
self._space_resolution = kwargs['space_resolution'] if 'space_resolution' in kwargs else None
self._tolerance = kwargs['tolerance'] if 'tolerance' in kwargs else None
@property
def flag_raman(self):
return self._flag_raman
@property
def space_resolution(self):
return self._space_resolution
@property
def tolerance(self):
return self._tolerance
def __init__(self, flag=False, result_spatial_resolution=10e3, solver_spatial_resolution=50):
""" Simulation parameters used within the Raman Solver
:params flag: boolean for enabling/disable the evaluation of the Raman power profile in frequency and position
: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
"""
self.flag = flag
self.result_spatial_resolution = result_spatial_resolution # [m]
self.solver_spatial_resolution = solver_spatial_resolution # [m]
class NLIParams(Parameters):
def __init__(self, **kwargs):
self._nli_method_name = kwargs['nli_method_name']
self._wdm_grid_size = kwargs['wdm_grid_size']
self._dispersion_tolerance = kwargs['dispersion_tolerance']
self._phase_shift_tolerance = kwargs['phase_shift_tolerance']
self._f_cut_resolution = None
self._f_pump_resolution = None
self._computed_channels = kwargs['computed_channels'] if 'computed_channels' in kwargs else None
@property
def nli_method_name(self):
return self._nli_method_name
@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
def __init__(self, method='gn_model_analytic', dispersion_tolerance=1, phase_shift_tolerance=0.1,
computed_channels=None):
""" Simulation parameters used within the Nli Solver
:params method: formula for NLI calculation
:params dispersion_tolerance: tuning parameter for ggn model solution
:params phase_shift_tolerance: tuning parameter for ggn model solution
:params computed_channels: the NLI is evaluated for these channels and extrapolated for the others
"""
self.method = method.lower()
self.dispersion_tolerance = dispersion_tolerance
self.phase_shift_tolerance = phase_shift_tolerance
self.computed_channels = computed_channels
class SimParams(Parameters):
def __init__(self, **kwargs):
try:
if 'nli_parameters' in kwargs:
self._nli_params = NLIParams(**kwargs['nli_parameters'])
else:
self._nli_params = None
if 'raman_parameters' in kwargs:
self._raman_params = RamanParams(**kwargs['raman_parameters'])
else:
self._raman_params = None
except KeyError as e:
raise ParametersError(f'Simulation parameters must include {e}. Configuration: {kwargs}')
_shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
def __init__(self):
if type(self) == SimParams:
raise NotImplementedError('Instances of SimParams cannot be generated')
@classmethod
def set_params(cls, sim_params):
cls._shared_dict['nli_params'] = NLIParams(**sim_params.get('nli_params', {}))
cls._shared_dict['raman_params'] = RamanParams(**sim_params.get('raman_params', {}))
@classmethod
def get(cls):
self = cls.__new__(cls)
return self
@property
def nli_params(self):
return self._nli_params
return self._shared_dict['nli_params']
@property
def raman_params(self):
return self._raman_params
return self._shared_dict['raman_params']
@classmethod
def default(cls):
cls._shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
class RoadmParams(Parameters):
def __init__(self, **kwargs):
self.target_pch_out_db = kwargs['target_pch_out_db'] if 'target_pch_out_db' in kwargs else None
self.target_psd_out_mWperGHz = \
kwargs['target_psd_out_mWperGHz'] if 'target_psd_out_mWperGHz' in kwargs else None
if self.target_pch_out_db is not None and self.target_psd_out_mWperGHz is not None:
raise ParametersError('ROADM config contains per channel power and psd. Please choose only one', kwargs)
self.per_degree_pch_out_db = kwargs['per_degree_pch_out_db'] if 'per_degree_pch_out_db' in kwargs else {}
self.per_degree_pch_psd = \
kwargs['per_degree_psd_out_mWperGHz'] if 'per_degree_psd_out_mWperGHz' in kwargs else {}
try:
self.add_drop_osnr = kwargs['add_drop_osnr']
self.pmd = kwargs['pmd']
self.restrictions = kwargs['restrictions']
except KeyError as e:
raise ParametersError(f'ROADM configurations json must include {e}. Configuration: {kwargs}')
class FusedParams(Parameters):
def __init__(self, **kwargs):
self.loss = kwargs['loss'] if 'loss' in kwargs else 1
class FiberParams(Parameters):
@@ -139,24 +118,24 @@ class FiberParams(Parameters):
try:
self._length = convert_length(kwargs['length'], kwargs['length_units'])
# 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
# the None value will be updated in network.py[build_network]
# with default values from eqpt_config.json[Spans]
self._con_in = kwargs['con_in'] if 'con_in' in kwargs else None
self._con_out = kwargs['con_out'] if 'con_out' in kwargs else None
self._con_in = kwargs.get('con_in')
self._con_out = kwargs.get('con_out')
if 'ref_wavelength' in kwargs:
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:
self._ref_frequency = kwargs['ref_frequency']
self._ref_wavelength = c / self.ref_frequency
self._ref_wavelength = c / self._ref_frequency
else:
self._ref_wavelength = 1550e-9
self._ref_frequency = c / self.ref_wavelength
self._ref_frequency = 193.5e12 # conventional central C band frequency [Hz]
self._ref_wavelength = c / self._ref_frequency
self._dispersion = kwargs['dispersion'] # s/m/m
self._dispersion_slope = kwargs['dispersion_slope'] if 'dispersion_slope' in kwargs else \
-2 * self._dispersion/self.ref_wavelength # s/m/m/m
self._dispersion_slope = \
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)
# 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
@@ -166,18 +145,15 @@ class FiberParams(Parameters):
self._gamma = kwargs['gamma'] # 1/W/m
self._pmd_coef = kwargs['pmd_coef'] # s/sqrt(m)
if type(kwargs['loss_coef']) == dict:
self._loss_coef = squeeze(kwargs['loss_coef']['loss_coef_power']) * 1e-3 # lineic loss dB/m
self._f_loss_ref = squeeze(kwargs['loss_coef']['frequency']) # Hz
self._loss_coef = asarray(kwargs['loss_coef']['value']) * 1e-3 # lineic loss dB/m
self._f_loss_ref = asarray(kwargs['loss_coef']['frequency']) # Hz
else:
self._loss_coef = kwargs['loss_coef'] * 1e-3 # lineic loss dB/m
self._f_loss_ref = 193.5e12 # Hz
self._lin_attenuation = db2lin(self.length * self.loss_coef)
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
self._loss_coef = asarray(kwargs['loss_coef']) * 1e-3 # lineic loss dB/m
self._f_loss_ref = asarray(193.5e12) # Hz
# 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
# lumped losses
self._lumped_losses = kwargs['lumped_losses'] if 'lumped_losses' in kwargs else None
except KeyError as e:
raise ParametersError(f'Fiber configurations json must include {e}. Configuration: {kwargs}')
@@ -210,6 +186,10 @@ class FiberParams(Parameters):
def con_out(self):
return self._con_out
@property
def lumped_losses(self):
return self._lumped_losses
@con_out.setter
def con_out(self, con_out):
self._con_out = con_out
@@ -254,32 +234,60 @@ class FiberParams(Parameters):
def f_loss_ref(self):
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
def raman_efficiency(self):
return self._raman_efficiency
@property
def pumps_loss_coef(self):
return self._pumps_loss_coef
def asdict(self):
dictionary = super().asdict()
dictionary['loss_coef'] = self.loss_coef * 1e3
dictionary['length_units'] = 'm'
if not self.lumped_losses:
dictionary.pop('lumped_losses')
if not self.raman_efficiency:
dictionary.pop('raman_efficiency')
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})')

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,9 @@ This module contains utility functions that are used with gnpy.
"""
from csv import writer
from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and
from numpy import pi, cos, sqrt, log10, linspace, zeros, shape, where, logical_and, mean
from scipy import constants
from copy import deepcopy
from gnpy.core.exceptions import ConfigurationError
@@ -106,6 +107,69 @@ def db2lin(value):
return 10**(value / 10)
def watt2dbm(value):
""" Convert watt units to dbm
>>> round(watt2dbm(0.001), 1)
0.0
>>> round(watt2dbm(0.02), 1)
13.0
"""
return lin2db(value * 1e3)
def dbm2watt(value):
""" Convert dbm units to watt
>>> round(dbm2watt(0), 4)
0.001
>>> round(dbm2watt(-3), 4)
0.0005
>>> round(dbm2watt(13), 4)
0.02
"""
return db2lin(value) * 1e-3
def psd2powerdbm(psd_mwperghz, baudrate_baud):
""" computes power in dbm based on baudrate in bauds and psd in mw/GHz
>>> round(psd2powerdbm(0.031176, 64e9),3)
3.0
>>> round(psd2powerdbm(0.062352, 32e9),3)
3.0
>>> round(psd2powerdbm(0.015625, 64e9),3)
0.0
"""
return lin2db(baudrate_baud * psd_mwperghz * 1e-9)
def powerdbm2psdmwperghz(power_dbm, baudrate_baud):
""" computes power spectral density in mW/GHz based on baudrate in bauds and power in dBm
>>> powerdbm2psdmwperghz(0, 64e9)
0.015625
>>> round(powerdbm2psdmwperghz(3, 64e9), 6)
0.031176
>>> round(powerdbm2psdmwperghz(3, 32e9), 6)
0.062352
"""
return db2lin(power_dbm) / (baudrate_baud * 1e-9)
def psdmwperghz(power_watt, baudrate_baud):
""" computes power spectral density in mW/GHz based on baudrate in bauds and power in W
>>> psdmwperghz(2e-3, 32e9)
0.0625
>>> psdmwperghz(1e-3, 64e9)
0.015625
>>> psdmwperghz(0.5e-3, 32e9)
0.015625
"""
return power_watt * 1e3 / (baudrate_baud * 1e-9)
def round2float(number, step):
"""Round a floating point number so that its "resolution" is not bigger than 'step'
@@ -166,6 +230,30 @@ def snr_sum(snr, bw, snr_added, bw_added=12.5e9):
return snr
def per_label_summary(values, labels):
""" computes the average per defined spectrum band, using labels
"""
label_set = sorted(set(labels))
summary = {}
for label in label_set:
vals = [values[i] for i, lab in enumerate(labels) if lab == label]
summary[label] = round(mean(vals), 2)
return summary
def pretty_summary_print(summary):
"""
"""
if len(summary) == 1:
return f'{round(list(summary.values())[0], 2):.2f}'
text = ''
for label, value in summary.items():
text += f'{label}: {value:.2f}, '
return text
def deltawl2deltaf(delta_wl, wavelength):
""" deltawl2deltaf(delta_wl, wavelength):
delta_wl is BW in wavelength units
@@ -228,6 +316,30 @@ def rrc(ffs, baud_rate, alpha):
return sqrt(hf)
def merge_equalization(params, extra_params):
""" Updates equalization type
if target_pch_out_db in params, then do not add target_psd_out_mWperGHz from extra_params
and reversaly. if both exist: raise an error, if none exist add the one in extra_params
"""
extra = deepcopy(extra_params)
if 'target_pch_out_db' in params.keys() and params['target_pch_out_db'] is not None and\
'target_psd_out_mWperGHz' in params.keys() and params['target_psd_out_mWperGHz'] is not None:
return None
if 'target_pch_out_db' in params.keys() and params['target_pch_out_db'] is not None:
extra.__dict__.pop('target_psd_out_mWperGHz')
return extra
if 'target_psd_out_mWperGHz' in params.keys() and params['target_psd_out_mWperGHz'] is not None:
extra.__dict__.pop('target_pch_out_db')
return extra
if extra.target_pch_out_db is not None:
extra.__dict__.pop('target_psd_out_mWperGHz')
return extra
if extra.target_psd_out_mWperGHz is not None:
extra.__dict__.pop('target_pch_out_db')
return extra
return None
def merge_amplifier_restrictions(dict1, dict2):
"""Updates contents of dicts recursively

View File

@@ -181,19 +181,45 @@
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"gamma": 0.00127,
"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
]
}
},
{
"type_variety": "NZDF",
"dispersion": 0.5e-05,
"gamma": 0.00146,
"pmd_coef": 1.265e-15
"pmd_coef": 1.265e-15,
"raman_efficiency": null
},
{
"type_variety": "LOF",
"dispersion": 2.2e-05,
"gamma": 0.000843,
"pmd_coef": 1.265e-15
"pmd_coef": 1.265e-15,
"raman_efficiency": null
}
],
"RamanFiber":[{

View File

@@ -39,19 +39,45 @@
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"gamma": 0.00127,
"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
]
}
},
{
"type_variety": "NZDF",
"dispersion": 0.5e-05,
"gamma": 0.00146,
"pmd_coef": 1.265e-15
"pmd_coef": 1.265e-15,
"raman_efficiency": null
},
{
"type_variety": "LOF",
"dispersion": 2.2e-05,
"gamma": 0.000843,
"pmd_coef": 1.265e-15
"pmd_coef": 1.265e-15,
"raman_efficiency": null
}
],
"RamanFiber":[

View File

@@ -0,0 +1,12 @@
{
"SI":[
{
"f_min": 191.3e12,
"f_max": 196.1e12,
"baud_rate": 32e9,
"spacing": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
}
]
}

View File

@@ -0,0 +1,21 @@
{
"SI":[
{
"f_min": 191.35e12,
"f_max":193.1e12,
"baud_rate": 32e9,
"spacing": 50e9,
"power_dbm": 0,
"roll_off": 0.15,
"tx_osnr": 40
},
{
"f_min": 193.1625e12,
"f_max":195.1e12,
"baud_rate": 64e9,
"spacing": 75e9,
"roll_off": 0.15,
"tx_osnr": 40
}
]
}

View File

@@ -1,14 +1,13 @@
{
"raman_parameters": {
"flag_raman": true,
"space_resolution": 10e3,
"tolerance": 1e-8
"raman_params": {
"flag": true,
"result_spatial_resolution": 10e3,
"solver_spatial_resolution": 50
},
"nli_parameters": {
"nli_method_name": "ggn_spectrally_separated",
"wdm_grid_size": 50e9,
"dispersion_tolerance": 1,
"phase_shift_tolerance": 0.1,
"computed_channels": [1, 18, 37, 56, 75]
"nli_params": {
"method": "ggn_spectrally_separated",
"dispersion_tolerance": 1,
"phase_shift_tolerance": 0.1,
"computed_channels": [1, 18, 37, 56, 75]
}
}
}

View File

@@ -15,21 +15,23 @@ import sys
from math import ceil
from numpy import linspace, mean
from pathlib import Path
from copy import deepcopy
import gnpy.core.ansi_escapes as ansi_escapes
from gnpy.core.elements import Transceiver, Fiber, RamanFiber
from gnpy.core.equipment import trx_mode_params
import gnpy.core.exceptions as exceptions
from gnpy.core.network import build_network
from gnpy.core.parameters import SimParams
from gnpy.core.science_utils import Simulation
from gnpy.core.utils import db2lin, lin2db, automatic_nch
from gnpy.topology.request import (ResultElement, jsontocsv, compute_path_dsjctn, requests_aggregation,
BLOCKING_NOPATH, correct_json_route_list,
deduplicate_disjunctions, compute_path_with_disjunction,
PathRequest, compute_constrained_path, propagate)
PathRequest, compute_constrained_path, propagate, update_spectrum_power)
from gnpy.topology.spectrum_assignment import build_oms_list, pth_assign_spectrum
from gnpy.tools.json_io import load_equipment, load_network, load_json, load_requests, save_network, \
requests_from_json, disjunctions_from_json, save_json
requests_from_json, disjunctions_from_json, save_json, load_initial_spectrum,\
_spectrum_from_json
from gnpy.tools.plots import plot_baseline, plot_results
_logger = logging.getLogger(__name__)
@@ -57,14 +59,14 @@ def load_common_data(equipment_filename, topology_filename, simulation_filename,
if save_raw_network_filename is not None:
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}')
sim_params = SimParams(**load_json(simulation_filename)) if simulation_filename is not None else None
if not sim_params:
if not simulation_filename:
SimParams.default()
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} '
f'RamanFiber requires passing simulation params via --sim-params')
sys.exit(1)
else:
Simulation.set_params(sim_params)
SimParams.set_params(load_json(simulation_filename))
except exceptions.EquipmentConfigError as e:
print(f'{ansi_escapes.red}Configuration error in the equipment library:{ansi_escapes.reset} {e}')
sys.exit(1)
@@ -119,6 +121,7 @@ def transmission_main_example(args=None):
parser.add_argument('-pl', '--plot', action='store_true')
parser.add_argument('-l', '--list-nodes', action='store_true', help='list all transceiver nodes')
parser.add_argument('-po', '--power', default=0, help='channel ref power in dBm')
parser.add_argument('-spectrum', '--mixed-rate-spectrum-file', help='user defined mixed rate spectrum json file')
parser.add_argument('source', nargs='?', help='source node')
parser.add_argument('destination', nargs='?', help='destination node')
@@ -196,11 +199,18 @@ def transmission_main_example(args=None):
trx_params['power'] = db2lin(float(args.power)) * 1e-3
params.update(trx_params)
req = PathRequest(**params)
if args.mixed_rate_spectrum_file:
req.initial_spectrum = load_initial_spectrum(args.mixed_rate_spectrum_file, equipment)
print('warning: user input for spectrum used for propagation instead of SI')
nb_channels = len(req.initial_spectrum)
else:
nb_channels = req.nb_channel
print(f'There are {nb_channels} channels propagating')
power_mode = equipment['Span']['default'].power_mode
print('\n'.join([f'Power mode is set to {power_mode}',
f'=> it can be modified in eqpt_config.json - Span']))
# Keep the reference channel for design: the one from SI, with full load same channels
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)
try:
@@ -227,9 +237,20 @@ def transmission_main_example(args=None):
power_range = list(linspace(p_start, p_stop, p_num))
except TypeError:
print('invalid power range definition in eqpt_config, should be power_range_db: [lower, upper, step]')
if hasattr(req, 'initial_spectrum'):
record_intial_spectrum = req.initial_spectrum
for dp_db in power_range:
req.power = db2lin(pref_ch_db + dp_db) * 1e-3
# if initial spectrum did not contain any power, now we need to use this one.
# note the initial power defines a differential wrt req.power so that if req.power is set to 2mW (3dBm)
# and initial spectrum was set to 0, this sets a initial per channel delta power to -3dB, so that
# whatever the equalization, -3 dB is applied on all channels (ie initial power in initial spectrum pre-empts
# pow option)
if hasattr(req, 'initial_spectrum'):
# without deepcopy, the previous dp setting is recorded as a user defined and spectrum is not properly
# updated for the power sweep dp_db
req.initial_spectrum = deepcopy(record_intial_spectrum)
update_spectrum_power(req)
if power_mode:
print(f'\nPropagating with input power = {ansi_escapes.cyan}{lin2db(req.power*1e3):.2f} dBm{ansi_escapes.reset}:')
else:
@@ -265,9 +286,9 @@ def transmission_main_example(args=None):
ch_freq = final_carrier.frequency * 1e-12
ch_power = lin2db(final_carrier.power.signal * 1e3)
print(
'{:5}{:26.2f}{:26.2f}{:28.2f}{:28.2f}{:28.2f}' .format(
'{:5}{:26.5f}{:26.2f}{:28.2f}{:28.2f}{:28.2f}' .format(
final_carrier.channel_number, round(
ch_freq, 2), round(
ch_freq, 5), round(
ch_power, 2), round(
ch_osnr, 2), round(
ch_snr_nl, 2), round(

View File

@@ -17,7 +17,8 @@ from gnpy.core import ansi_escapes, elements
from gnpy.core.equipment import trx_mode_params
from gnpy.core.exceptions import ConfigurationError, EquipmentConfigError, NetworkTopologyError, ServiceError
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, dbm2watt,
merge_equalization)
from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth
from gnpy.tools.convert import xls_to_json_data
from gnpy.tools.service_sheet import read_service_sheet
@@ -46,7 +47,9 @@ class _JsonThing:
clean_kwargs = {k: v for k, v in kwargs.items() if v != ''}
for k, v in default_values.items():
setattr(self, k, clean_kwargs.get(k, v))
if k not in clean_kwargs and name != 'Amp':
if k not in clean_kwargs and name != 'Amp' and \
(k == 'target_psd_out_mWperGHz' and 'target_pch_out_db' not in clean_kwargs) and \
(k == 'target_pch_out_db' and 'target_psd_out_mWperGHz' not in clean_kwargs):
print(ansi_escapes.red +
f'\n WARNING missing {k} attribute in eqpt_config.json[{name}]' +
f'\n default value is {k} = {v}' +
@@ -91,7 +94,8 @@ class Span(_JsonThing):
class Roadm(_JsonThing):
default_values = {
'target_pch_out_db': -17,
'target_pch_out_db': None,
'target_psd_out_mWperGHz': None,
'add_drop_osnr': 100,
'pmd': 0,
'restrictions': {
@@ -116,18 +120,6 @@ class Transceiver(_JsonThing):
class Fiber(_JsonThing):
default_values = {
'type_variety': '',
'dispersion': None,
'gamma': 0,
'pmd_coef': 0
}
def __init__(self, **kwargs):
self.update_attr(self.default_values, kwargs, 'Fiber')
class RamanFiber(_JsonThing):
default_values = {
'type_variety': '',
'dispersion': None,
@@ -136,6 +128,17 @@ class RamanFiber(_JsonThing):
'raman_efficiency': None
}
def __init__(self, **kwargs):
self.update_attr(self.default_values, kwargs, 'Fiber')
if self.raman_efficiency is not None:
for param in ('cr', 'frequency_offset'):
if param not in self.raman_efficiency:
raise EquipmentConfigError(f'Fiber.raman_efficiency: missing "{param}" parameter')
if self.raman_efficiency['frequency_offset'] != sorted(self.raman_efficiency['frequency_offset']):
raise EquipmentConfigError(f'Fiber.raman_efficiency.frequency_offset is not sorted')
class RamanFiber(Fiber):
def __init__(self, **kwargs):
self.update_attr(self.default_values, kwargs, 'RamanFiber')
for param in ('cr', 'frequency_offset'):
@@ -237,11 +240,50 @@ def _automatic_spacing(baud_rate):
return min((s[1] for s in spacing_list if s[0] > baud_rate), default=baud_rate * 1.2)
def _spectrum_from_json(json_data, equipment):
""" json_data is a list of spectrum partitions each with {fmin, fmax, baudrate, roll_off, power and tx_osnr}
creates the per freq dict of carrier's dict
"""
spectrum = {}
# min freq is fmin - spacing/2 (numbering starts at 0)
previous_part_max_freq = json_data[0]['f_min'] - json_data[0]['spacing'] / 2
for index, part in enumerate(json_data):
# add a label to the partition for the printings
if 'label' not in part.keys():
part['label'] = f'{index}-{round(part["baud_rate"] * 1e-9, 2)}'
index = 1 # starting freq is exactly f_min + spacing to be consistent with utils.automatic_nch
# first partition min frequency is f_min + spacing - spacing/2
current_part_min_freq = part['f_min'] + part['spacing'] / 2 # supposes that carriers are centered on frequency
if 'power_dbm' in part:
# user defined partition power.
part['power'] = dbm2watt(part['power_dbm'])
else:
part['power'] = None
if previous_part_max_freq <= current_part_min_freq:
# check that previous part last channel does not overlap on next part first channel
# TODO use functions from andrea to check consistency of spectrum instead
current_freq = part['f_min'] + index * part['spacing']
while current_freq <= part['f_max']:
spectrum[current_freq] = part
index += 1
current_freq = part['f_min'] + index * part['spacing']
previous_part_max_freq = current_freq - part['spacing'] / 2
else:
raise ValueError('not a valid initial spectrum definition')
return spectrum
def load_equipment(filename):
json_data = load_json(filename)
return _equipment_from_json(json_data, filename)
def load_initial_spectrum(filename, equipment):
json_data = load_json(filename)
return _spectrum_from_json(json_data['SI'], equipment)
def _update_dual_stage(equipment):
edfa_dict = equipment['Edfa']
for edfa in edfa_dict.values():
@@ -374,6 +416,10 @@ def network_from_json(json_data, equipment):
elif variety in equipment[typ]:
extra_params = equipment[typ][variety]
temp = el_config.setdefault('params', {})
if typ == 'Roadm':
# if equalisation is not defined in the element config, then retrieve the general one from SI
# else use the one from the element config. Only one type of equalisation is allowed.
extra_params = merge_equalization(temp, extra_params)
temp = merge_amplifier_restrictions(temp, extra_params.__dict__)
el_config['params'] = temp
el_config['type_variety'] = variety

View File

@@ -22,8 +22,8 @@ from networkx import (dijkstra_path, NetworkXNoPath,
from networkx.utils import pairwise
from numpy import mean
from gnpy.core.elements import Transceiver, Roadm
from gnpy.core.utils import lin2db
from gnpy.core.info import create_input_spectral_information
from gnpy.core.utils import lin2db, dbm2watt
from gnpy.core.info import create_input_spectral_information, use_initial_spectrum
from gnpy.core.exceptions import ServiceError, DisjunctionError
import gnpy.core.ansi_escapes as ansi_escapes
from copy import deepcopy
@@ -338,10 +338,34 @@ def compute_constrained_path(network, req):
return total_path
def ref_carrier(req_power, equipment):
""" the function creates a reference with SI information, and carries also request's power
"""
ref_carrier = {key: getattr(equipment['SI']['default'], key) for key in
['f_min', 'f_max', 'baud_rate', 'spacing', 'roll_off', 'tx_osnr']}
ref_carrier['power'] = dbm2watt(equipment['SI']['default'].power_dbm)
ref_carrier['req_power'] = req_power
return ref_carrier
def update_spectrum_power(req):
""" Initial user defined spectrum may not contain power, in this case use the request's one
as default value.
"""
for spectrum in req.initial_spectrum.values():
if spectrum['power'] is None:
spectrum['power'] = req.power
def propagate(path, req, equipment):
si = create_input_spectral_information(
req.f_min, req.f_max, req.roll_off, req.baud_rate,
req.power, req.spacing)
""" propagates signals in each element according to initial spectrum set by user
"""
if hasattr(req, 'initial_spectrum'):
si = use_initial_spectrum(req.initial_spectrum, ref_carrier=ref_carrier(req.power, equipment))
else:
si = create_input_spectral_information(
req.f_min, req.f_max, req.roll_off, req.baud_rate,
req.power, req.spacing, ref_carrier=ref_carrier(req.power, equipment))
for i, el in enumerate(path):
if isinstance(el, Roadm):
si = el(si, degree=path[i+1].uid)
@@ -375,9 +399,18 @@ def propagate_and_optimize_mode(path, req, equipment):
# step2: computes propagation for each baudrate: stop and select the first that passes
# TODO: the case of roll of is not included: for now use SI one
# TODO: if the loop in mode optimization does not have a feasible path, then bugs
spc_info = create_input_spectral_information(req.f_min, req.f_max,
equipment['SI']['default'].roll_off,
this_br, req.power, req.spacing)
if hasattr(req, 'initial_spectrum'):
# add the current explored mode caracteristic on the initial spectrum
# maybe use a copy instead of changing the request ?
for e in req.initial_spectrum.values():
if e['baud_rate'] is None:
e['baud_rate'] = this_br
spc_info = use_initial_spectrum(req.initial_spectrum, ref_carrier=ref_carrier(req.power, equipment))
else:
spc_info = create_input_spectral_information(req.f_min, req.f_max,
equipment['SI']['default'].roll_off,
this_br, req.power, req.spacing,
ref_carrier=ref_carrier(req.power, equipment))
for i, el in enumerate(path):
if isinstance(el, Roadm):
spc_info = el(spc_info, degree=path[i+1].uid)

View File

@@ -64,7 +64,31 @@
"type_variety": "SSMF",
"dispersion": 1.67e-05,
"gamma": 0.00127,
"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":[{

View File

@@ -1,14 +1,13 @@
{
"raman_parameters": {
"flag_raman": true,
"space_resolution": 10e3,
"tolerance": 1e-8
"raman_params": {
"flag": true,
"result_spatial_resolution": 10e3,
"solver_spatial_resolution": 50
},
"nli_parameters": {
"nli_method_name": "ggn_spectrally_separated",
"wdm_grid_size": 50e9,
"nli_params": {
"method": "ggn_spectrally_separated",
"dispersion_tolerance": 1,
"phase_shift_tolerance": 0.1,
"computed_channels": [1, 18, 37, 56, 75]
}
}
}

View 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
1 signal nli
2 1.9952623149688793e-05 1.1158426495504604e-08
3 1.9952623149688793e-05 1.263949624403159e-08
4 1.9952623149688793e-05 1.3358478621325285e-08
5 1.9952623149688793e-05 1.3830775406251184e-08
6 1.9952623149688793e-05 1.4180462471172083e-08
7 1.9952623149688793e-05 1.4456701012984246e-08
8 1.9952623149688793e-05 1.4683973899785875e-08
9 1.9952623149688793e-05 1.487624147046227e-08
10 1.9952623149688793e-05 1.5042217041806274e-08
11 1.9952623149688793e-05 1.5187703614492153e-08
12 1.9952623149688793e-05 1.5316759790785317e-08
13 1.9952623149688793e-05 1.543233485150211e-08
14 1.9952623149688793e-05 1.553663885878994e-08
15 1.9952623149688793e-05 1.5631370249579246e-08
16 1.9952623149688793e-05 1.5717862065800704e-08
17 1.9952623149688793e-05 1.57971793985894e-08
18 1.9952623149688793e-05 1.5870186356579704e-08
19 1.9952623149688793e-05 1.593759332223716e-08
20 1.9952623149688793e-05 1.5999991070923486e-08
21 1.9952623149688793e-05 1.6057875903450682e-08
22 1.9952623149688793e-05 1.6111668489205982e-08
23 1.9952623149688793e-05 1.6161728217386366e-08
24 1.9952623149688793e-05 1.6208364281630228e-08
25 1.9952623149688793e-05 1.6251844350226973e-08
26 1.9952623149688793e-05 1.629240142540359e-08
27 1.9952623149688793e-05 1.6330239326114482e-08
28 1.9952623149688793e-05 1.6365537111728e-08
29 1.9952623149688793e-05 1.6398452681655655e-08
30 1.9952623149688793e-05 1.642912572715412e-08
31 1.9952623149688793e-05 1.6457680168940455e-08
32 1.9952623149688793e-05 1.6484226183026747e-08
33 1.9952623149688793e-05 1.6508861894003893e-08
34 1.9952623149688793e-05 1.6531674797617433e-08
35 1.9952623149688793e-05 1.655274296130114e-08
36 1.9952623149688793e-05 1.657213604125123e-08
37 1.9952623149688793e-05 1.6589916146838222e-08
38 1.9952623149688793e-05 1.660613857708963e-08
39 1.9952623149688793e-05 1.6620852449214096e-08
40 1.9952623149688793e-05 1.6634101235366932e-08
41 1.9952623149688793e-05 1.664592322084737e-08
42 1.9952623149688793e-05 1.6656351894496074e-08
43 1.9952623149688793e-05 1.666541628009631e-08
44 1.9952623149688793e-05 1.6673141215973025e-08
45 1.9952623149688793e-05 1.6679547588653583e-08
46 1.9952623149688793e-05 1.6684652525341145e-08
47 1.9952623149688793e-05 1.668846954900963e-08
48 1.9952623149688793e-05 1.66910086991187e-08
49 1.9952623149688793e-05 1.6692276620238304e-08
50 1.9952623149688793e-05 1.6692276620238304e-08
51 1.9952623149688793e-05 1.6691008699118703e-08
52 1.9952623149688793e-05 1.6688469549009633e-08
53 1.9952623149688793e-05 1.6684652525341148e-08
54 1.9952623149688793e-05 1.6679547588653586e-08
55 1.9952623149688793e-05 1.6673141215973028e-08
56 1.9952623149688793e-05 1.666541628009631e-08
57 1.9952623149688793e-05 1.6656351894496084e-08
58 1.9952623149688793e-05 1.6645923220847374e-08
59 1.9952623149688793e-05 1.6634101235366935e-08
60 1.9952623149688793e-05 1.66208524492141e-08
61 1.9952623149688793e-05 1.6606138577089633e-08
62 1.9952623149688793e-05 1.6589916146838225e-08
63 1.9952623149688793e-05 1.6572136041251237e-08
64 1.9952623149688793e-05 1.6552742961301146e-08
65 1.9952623149688793e-05 1.653167479761744e-08
66 1.9952623149688793e-05 1.6508861894003893e-08
67 1.9952623149688793e-05 1.648422618302675e-08
68 1.9952623149688793e-05 1.645768016894046e-08
69 1.9952623149688793e-05 1.6429125727154126e-08
70 1.9952623149688793e-05 1.6398452681655658e-08
71 1.9952623149688793e-05 1.6365537111728004e-08
72 1.9952623149688793e-05 1.6330239326114482e-08
73 1.9952623149688793e-05 1.6292401425403594e-08
74 1.9952623149688793e-05 1.6251844350226973e-08
75 1.9952623149688793e-05 1.6208364281630228e-08
76 1.9952623149688793e-05 1.616172821738637e-08
77 1.9952623149688793e-05 1.6111668489205982e-08
78 1.9952623149688793e-05 1.605787590345069e-08
79 1.9952623149688793e-05 1.5999991070923493e-08
80 1.9952623149688793e-05 1.5937593322237167e-08
81 1.9952623149688793e-05 1.5870186356579704e-08
82 1.9952623149688793e-05 1.5797179398589402e-08
83 1.9952623149688793e-05 1.571786206580071e-08
84 1.9952623149688793e-05 1.5631370249579252e-08
85 1.9952623149688793e-05 1.5536638858789946e-08
86 1.9952623149688793e-05 1.5432334851502114e-08
87 1.9952623149688793e-05 1.531675979078532e-08
88 1.9952623149688793e-05 1.5187703614492156e-08
89 1.9952623149688793e-05 1.5042217041806274e-08
90 1.9952623149688793e-05 1.4876241470462273e-08
91 1.9952623149688793e-05 1.4683973899785879e-08
92 1.9952623149688793e-05 1.4456701012984246e-08
93 1.9952623149688793e-05 1.4180462471172086e-08
94 1.9952623149688793e-05 1.3830775406251184e-08
95 1.9952623149688793e-05 1.3358478621325285e-08
96 1.9952623149688793e-05 1.2639496244031593e-08
97 1.9952623149688793e-05 1.1158426495504613e-08

View 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
1 signal nli
2 1.9952623149688793e-05 5.522326183599433e-09
3 1.7957360834719913e-05 4.5606601423111315e-09
4 2.593841009459543e-05 6.633717697038881e-09
5 1.5962098519751036e-05 4.3237017878447286e-09
6 2.3943147779626553e-05 8.311382502260195e-09

View File

@@ -0,0 +1,810 @@
{
"network_name": "Example Network - long path",
"elements": [{
"uid": "Site_A",
"type": "Transceiver",
"metadata": {
"location": {
"city": "Site A",
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "roadm Site A",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster A",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span1",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa1",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span2",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa2",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span3",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa3",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span4",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa4",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span5",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa5",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site C",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster C",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span6",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa6",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span7",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa7",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span8",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa8",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span9",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa9",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span10",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa10",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site D",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster D",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span11",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa11",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span12",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa12",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site E",
"metadata": {
"location": {
"city": "Site A",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "booster E",
"type": "Edfa",
"type_variety": "std_medium_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 0,
"longitude": 0
}
}
},
{
"uid": "Span13",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa13",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span14",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa14",
"type": "Edfa",
"type_variety": "test_fixed_gain",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "Span15",
"type": "Fiber",
"type_variety": "SSMF",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km"
},
"metadata": {
"location": {
"region": "",
"latitude": 1,
"longitude": 0
}
}
},
{
"uid": "Edfa15",
"type": "Edfa",
"type_variety": "test",
"operational": {
"gain_target": 16,
"tilt_target": 0
},
"metadata": {
"location": {
"region": "",
"latitude": 2,
"longitude": 0
}
}
},
{
"uid": "roadm Site B",
"metadata": {
"location": {
"city": "Site B",
"region": "RLD",
"latitude": 0.0,
"longitude": 0.0
}
},
"type": "Roadm"
},
{
"uid": "Site_B",
"type": "Transceiver",
"metadata": {
"location": {
"city": "Site B",
"region": "",
"latitude": 3,
"longitude": 0
}
}
}
],
"connections": [{
"from_node": "Site_A",
"to_node": "roadm Site A"
},
{
"from_node": "roadm Site A",
"to_node": "booster A"
},
{
"from_node": "booster A",
"to_node": "Span1"
},
{
"from_node": "Span1",
"to_node": "Edfa1"
},
{
"from_node": "Edfa1",
"to_node": "Span2"
},
{
"from_node": "Span2",
"to_node": "Edfa2"
},
{
"from_node": "Edfa2",
"to_node": "Span3"
},
{
"from_node": "Span3",
"to_node": "Edfa3"
},
{
"from_node": "Edfa3",
"to_node": "Span4"
},
{
"from_node": "Span4",
"to_node": "Edfa4"
},
{
"from_node": "Edfa4",
"to_node": "Span5"
},
{
"from_node": "Span5",
"to_node": "Edfa5"
},
{
"from_node": "Edfa5",
"to_node": "roadm Site C"
},
{
"from_node": "roadm Site C",
"to_node": "booster C"
},
{
"from_node": "booster C",
"to_node": "Span6"
},
{
"from_node": "Span6",
"to_node": "Edfa6"
},
{
"from_node": "Edfa6",
"to_node": "Span7"
},
{
"from_node": "Span7",
"to_node": "Edfa7"
},
{
"from_node": "Edfa7",
"to_node": "Span8"
},
{
"from_node": "Span8",
"to_node": "Edfa8"
},
{
"from_node": "Edfa8",
"to_node": "Span9"
},
{
"from_node": "Span9",
"to_node": "Edfa9"
},
{
"from_node": "Edfa9",
"to_node": "Span10"
},
{
"from_node": "Span10",
"to_node": "Edfa10"
},
{
"from_node": "Edfa10",
"to_node": "roadm Site D"
},
{
"from_node": "roadm Site D",
"to_node": "booster D"
},
{
"from_node": "booster D",
"to_node": "Span11"
},
{
"from_node": "Span11",
"to_node": "Edfa11"
},
{
"from_node": "Edfa11",
"to_node": "Span12"
},
{
"from_node": "Span12",
"to_node": "Edfa12"
},
{
"from_node": "Edfa12",
"to_node": "roadm Site E"
},
{
"from_node": "roadm Site E",
"to_node": "booster E"
},
{
"from_node": "booster E",
"to_node": "Span13"
},
{
"from_node": "Span13",
"to_node": "Edfa13"
},
{
"from_node": "Edfa13",
"to_node": "Span14"
},
{
"from_node": "Span14",
"to_node": "Edfa14"
},
{
"from_node": "Edfa14",
"to_node": "Span15"
},
{
"from_node": "Span15",
"to_node": "Edfa15"
},
{
"from_node": "Edfa15",
"to_node": "roadm Site B"
},
{
"from_node": "roadm Site B",
"to_node": "Site_B"
}
]
}

View File

@@ -0,0 +1,212 @@
{
"uid": "Span1",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km",
"att_in": 0,
"con_in": 0.5,
"con_out": 0.5,
"lumped_losses": [
{"position": 7, "loss": 0.5}
],
"type_variety": "SSMF",
"dispersion": 0.0000167,
"pmd_coef": 1.265e-15,
"gamma": 0.00127,
"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
]
}
},
"metadata": {
"location": {
"latitude": 1,
"longitude": 0,
"city": null,
"region": ""
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,227 @@
{
"uid": "Span1",
"params": {
"length": 80,
"loss_coef": 0.2,
"length_units": "km",
"att_in": 0,
"con_in": 0.5,
"con_out": 0.5,
"lumped_losses": [
{"position": 7, "loss": 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": ""
}
}
}

View File

@@ -0,0 +1,97 @@
signal,nli,ase
0,0.0002866705468946441,2.177394829242565e-07,3.4557191793558825e-08
1,0.00028429526393394377,2.2012781143543237e-07,3.4445502692391435e-08
2,0.00028194056061390773,2.224623221237509e-07,3.433445887467792e-08
3,0.00027960624613715477,2.247437720846811e-07,3.422405538481241e-08
4,0.0002758942662605477,2.2582870905131877e-07,3.3956503060525654e-08
5,0.0002722323881863356,2.2684591469841408e-07,3.369116031853938e-08
6,0.000268619918350984,2.277970173994804e-07,3.342800240189267e-08
7,0.000265053715317489,2.2868149265452554e-07,3.31669825978832e-08
8,0.0002615332083291819,2.2950088648412205e-07,3.2908077452451265e-08
9,0.0002577026598717891,2.29939807349622e-07,3.260943794608576e-08
10,0.0002539265998701895,2.303151728478784e-07,3.23135112959506e-08
11,0.000250197552301535,2.3062250247045e-07,3.2020149186684304e-08
12,0.0002465150832963999,2.3086346975365183e-07,3.172932441983654e-08
13,0.00024287876009092854,2.3103972369261411e-07,3.144100993235306e-08
14,0.00023918814592805183,2.31056283673814e-07,3.114286828089368e-08
15,0.00023554582204055567,2.310113542844721e-07,3.084739480128956e-08
16,0.00023195130631956971,2.3090659197839515e-07,3.055456016860592e-08
17,0.00022840433901323014,2.307438494055778e-07,3.026433722256217e-08
18,0.0002249044309608348,2.2685792845882788e-07,2.997669682160718e-08
19,0.00022103550529979762,2.2261125752357212e-07,2.963927431547004e-08
20,0.0002172262095203314,2.184365961387324e-07,2.9305346170341454e-08
21,0.0002134758798406954,2.1433299933606587e-07,2.8974869975180298e-08
22,0.0002097837429161198,2.102994164488689e-07,2.8647801621001083e-08
23,0.00020614903259761412,2.063348088289235e-07,2.8324097353256504e-08
24,0.00020282505012919792,2.0269204338245043e-07,2.8034743773023506e-08
25,0.00019954846914292654,1.9910692504926397e-07,2.7748188517931413e-08
26,0.0001963187365960183,1.955786814668348e-07,2.7464399406269038e-08
27,0.00019313601236366093,1.9210725283739872e-07,2.71833510938317e-08
28,0.00018999971525214364,1.886918423998114e-07,2.6905011507090682e-08
29,0.00018690926921963096,1.8533166212086657e-07,2.6629348802784474e-08
30,0.00018386410436192706,1.820259336310992e-07,2.635633143849771e-08
31,0.00018086374979011733,1.7877397998150293e-07,2.6085929795727407e-08
32,0.00017790764094943303,1.7557503471789446e-07,2.5818112682654427e-08
33,0.00017499521851272397,1.724283400529523e-07,2.5552849119349174e-08
34,0.00017219248535735765,1.6939862390063425e-07,2.529836490008028e-08
35,0.00016943017410898177,1.664173382700801e-07,2.5046323660212428e-08
36,0.0001667077872998461,1.634838065100415e-07,2.4796697985876285e-08
37,0.0001640259411699002,1.6034105983552547e-07,2.4549471241938992e-08
38,0.00016138409116954428,1.5725405329068436e-07,2.430461590519894e-08
39,0.00015878169900055325,1.542218889375427e-07,2.4062104674963863e-08
40,0.000156218232533133,1.5124368154127442e-07,2.38219104669703e-08
41,0.00015369496700007087,1.4832029668067725e-07,2.3584040136547525e-08
42,0.00015121129156099526,1.4545076976680713e-07,2.3348465494119215e-08
43,0.0001487666043717642,1.4263415247435296e-07,2.3115158601715748e-08
44,0.00014623128236243723,1.3974620462259893e-07,2.286438328716338e-08
45,0.0001437380524819555,1.3691420205996233e-07,2.2616176641497093e-08
46,0.00014128623388642375,1.341371036381095e-07,2.237050551788219e-08
47,0.00013887622989024388,1.3141490263262782e-07,2.212734756671424e-08
48,0.0001365073237114033,1.2874653085981584e-07,2.188666974535913e-08
49,0.0001341788110461389,1.261309408287838e-07,2.164843935312404e-08
50,0.00013188999957562474,1.2356710508422937e-07,2.1412624001807218e-08
51,0.00012964156315983818,1.2105528052343852e-07,2.1179217737017218e-08
52,0.00012743276140549773,1.1859439945261603e-07,2.0948187545405114e-08
53,0.00012526286812817946,1.1618341661515935e-07,2.0719500766867955e-08
54,0.00012308488924719652,1.1377852622228216e-07,2.0485476408751836e-08
55,0.00012094599744462103,1.1142326262451022e-07,2.0253866505294597e-08
56,0.00011884546514357594,1.0900764486089363e-07,2.0024636879854262e-08
57,0.00011678359442245642,1.0664431621844869e-07,1.979776381558453e-08
58,0.00011475963058254594,1.0433212166698539e-07,1.957321328901385e-08
59,0.0001127728345582037,1.0206993253017356e-07,1.9350951640370864e-08
60,0.00011082248211829082,9.98566454499784e-08,1.9130945525479478e-08
61,0.00010890886205398466,9.769207746885406e-08,1.891318169113191e-08
62,0.00010703122613605297,9.557511493642398e-08,1.869762647432104e-08
63,0.00010518884252011888,9.350467086701759e-08,1.8484246571416752e-08
64,0.0001035307857887024,9.161223068914851e-08,1.8300456694513304e-08
65,0.00010190164256706024,8.97586650563189e-08,1.8118434361985188e-08
66,0.00010030086086057541,8.79431393062173e-08,1.7938156675563083e-08
67,9.872793827240711e-05,8.616487098950027e-08,1.77596013840066e-08
68,9.718234354198392e-05,8.44230607070921e-08,1.7582746084973536e-08
69,9.56635564008908e-05,8.271692715563019e-08,1.7407568625796667e-08
70,9.417106698591262e-05,8.10457064001203e-08,1.7234047067791308e-08
71,9.270483837325431e-05,7.94090478608544e-08,1.7062169097342785e-08
72,9.12643590341385e-05,7.780619693716166e-08,1.6891912824320277e-08
73,8.984912830909168e-05,7.623641652299821e-08,1.672325659984075e-08
74,8.845966357642775e-05,7.469983729150625e-08,1.6557160644411184e-08
75,8.709444598783118e-05,7.354697815082507e-08,1.6392702347411626e-08
76,8.575300679829195e-05,7.241419869922277e-08,1.6229862344426664e-08
77,8.443491979213314e-05,7.130113901851255e-08,1.606862190142917e-08
78,8.313973419504378e-05,7.020741845194848e-08,1.5908962221377164e-08
79,8.186700872392319e-05,6.913266435764513e-08,1.5750864795797952e-08
80,8.061631115512539e-05,6.807651174398117e-08,1.559431138284531e-08
81,7.938732282855929e-05,6.703869151817475e-08,1.5439286199449887e-08
82,7.817962449101943e-05,6.601884964150396e-08,1.5285771474772338e-08
83,7.699280573302815e-05,6.50166395433403e-08,1.513374972211717e-08
84,7.592454893921724e-05,6.411454919552573e-08,1.5006080388275954e-08
85,7.487353856336685e-05,6.322702259986013e-08,1.4879767295630751e-08
86,7.383946010084118e-05,6.235379417263942e-08,1.475480276556073e-08
87,7.282054160428152e-05,6.149336759142648e-08,1.4631164089327954e-08
88,7.181654482227581e-05,6.064554166461607e-08,1.4508845066183491e-08
89,7.082723551235707e-05,5.981011858595996e-08,1.4387839898262193e-08
90,6.985238328334553e-05,5.8986903801432673e-08,1.4268143194153057e-08
91,6.889088892692634e-05,5.8174969083648444e-08,1.4149731300144923e-08
92,6.794256749705261e-05,5.737415825476245e-08,1.4032600405332526e-08
93,6.700723666457587e-05,5.658431734677192e-08,1.3916747132522929e-08
94,6.59402843027997e-05,5.5683328527685944e-08,1.3765832836854687e-08
95,6.489024990134964e-05,5.479662609442341e-08,1.3616406761560667e-08
1 signal,nli,ase
2 0,0.0002866705468946441,2.177394829242565e-07,3.4557191793558825e-08
3 1,0.00028429526393394377,2.2012781143543237e-07,3.4445502692391435e-08
4 2,0.00028194056061390773,2.224623221237509e-07,3.433445887467792e-08
5 3,0.00027960624613715477,2.247437720846811e-07,3.422405538481241e-08
6 4,0.0002758942662605477,2.2582870905131877e-07,3.3956503060525654e-08
7 5,0.0002722323881863356,2.2684591469841408e-07,3.369116031853938e-08
8 6,0.000268619918350984,2.277970173994804e-07,3.342800240189267e-08
9 7,0.000265053715317489,2.2868149265452554e-07,3.31669825978832e-08
10 8,0.0002615332083291819,2.2950088648412205e-07,3.2908077452451265e-08
11 9,0.0002577026598717891,2.29939807349622e-07,3.260943794608576e-08
12 10,0.0002539265998701895,2.303151728478784e-07,3.23135112959506e-08
13 11,0.000250197552301535,2.3062250247045e-07,3.2020149186684304e-08
14 12,0.0002465150832963999,2.3086346975365183e-07,3.172932441983654e-08
15 13,0.00024287876009092854,2.3103972369261411e-07,3.144100993235306e-08
16 14,0.00023918814592805183,2.31056283673814e-07,3.114286828089368e-08
17 15,0.00023554582204055567,2.310113542844721e-07,3.084739480128956e-08
18 16,0.00023195130631956971,2.3090659197839515e-07,3.055456016860592e-08
19 17,0.00022840433901323014,2.307438494055778e-07,3.026433722256217e-08
20 18,0.0002249044309608348,2.2685792845882788e-07,2.997669682160718e-08
21 19,0.00022103550529979762,2.2261125752357212e-07,2.963927431547004e-08
22 20,0.0002172262095203314,2.184365961387324e-07,2.9305346170341454e-08
23 21,0.0002134758798406954,2.1433299933606587e-07,2.8974869975180298e-08
24 22,0.0002097837429161198,2.102994164488689e-07,2.8647801621001083e-08
25 23,0.00020614903259761412,2.063348088289235e-07,2.8324097353256504e-08
26 24,0.00020282505012919792,2.0269204338245043e-07,2.8034743773023506e-08
27 25,0.00019954846914292654,1.9910692504926397e-07,2.7748188517931413e-08
28 26,0.0001963187365960183,1.955786814668348e-07,2.7464399406269038e-08
29 27,0.00019313601236366093,1.9210725283739872e-07,2.71833510938317e-08
30 28,0.00018999971525214364,1.886918423998114e-07,2.6905011507090682e-08
31 29,0.00018690926921963096,1.8533166212086657e-07,2.6629348802784474e-08
32 30,0.00018386410436192706,1.820259336310992e-07,2.635633143849771e-08
33 31,0.00018086374979011733,1.7877397998150293e-07,2.6085929795727407e-08
34 32,0.00017790764094943303,1.7557503471789446e-07,2.5818112682654427e-08
35 33,0.00017499521851272397,1.724283400529523e-07,2.5552849119349174e-08
36 34,0.00017219248535735765,1.6939862390063425e-07,2.529836490008028e-08
37 35,0.00016943017410898177,1.664173382700801e-07,2.5046323660212428e-08
38 36,0.0001667077872998461,1.634838065100415e-07,2.4796697985876285e-08
39 37,0.0001640259411699002,1.6034105983552547e-07,2.4549471241938992e-08
40 38,0.00016138409116954428,1.5725405329068436e-07,2.430461590519894e-08
41 39,0.00015878169900055325,1.542218889375427e-07,2.4062104674963863e-08
42 40,0.000156218232533133,1.5124368154127442e-07,2.38219104669703e-08
43 41,0.00015369496700007087,1.4832029668067725e-07,2.3584040136547525e-08
44 42,0.00015121129156099526,1.4545076976680713e-07,2.3348465494119215e-08
45 43,0.0001487666043717642,1.4263415247435296e-07,2.3115158601715748e-08
46 44,0.00014623128236243723,1.3974620462259893e-07,2.286438328716338e-08
47 45,0.0001437380524819555,1.3691420205996233e-07,2.2616176641497093e-08
48 46,0.00014128623388642375,1.341371036381095e-07,2.237050551788219e-08
49 47,0.00013887622989024388,1.3141490263262782e-07,2.212734756671424e-08
50 48,0.0001365073237114033,1.2874653085981584e-07,2.188666974535913e-08
51 49,0.0001341788110461389,1.261309408287838e-07,2.164843935312404e-08
52 50,0.00013188999957562474,1.2356710508422937e-07,2.1412624001807218e-08
53 51,0.00012964156315983818,1.2105528052343852e-07,2.1179217737017218e-08
54 52,0.00012743276140549773,1.1859439945261603e-07,2.0948187545405114e-08
55 53,0.00012526286812817946,1.1618341661515935e-07,2.0719500766867955e-08
56 54,0.00012308488924719652,1.1377852622228216e-07,2.0485476408751836e-08
57 55,0.00012094599744462103,1.1142326262451022e-07,2.0253866505294597e-08
58 56,0.00011884546514357594,1.0900764486089363e-07,2.0024636879854262e-08
59 57,0.00011678359442245642,1.0664431621844869e-07,1.979776381558453e-08
60 58,0.00011475963058254594,1.0433212166698539e-07,1.957321328901385e-08
61 59,0.0001127728345582037,1.0206993253017356e-07,1.9350951640370864e-08
62 60,0.00011082248211829082,9.98566454499784e-08,1.9130945525479478e-08
63 61,0.00010890886205398466,9.769207746885406e-08,1.891318169113191e-08
64 62,0.00010703122613605297,9.557511493642398e-08,1.869762647432104e-08
65 63,0.00010518884252011888,9.350467086701759e-08,1.8484246571416752e-08
66 64,0.0001035307857887024,9.161223068914851e-08,1.8300456694513304e-08
67 65,0.00010190164256706024,8.97586650563189e-08,1.8118434361985188e-08
68 66,0.00010030086086057541,8.79431393062173e-08,1.7938156675563083e-08
69 67,9.872793827240711e-05,8.616487098950027e-08,1.77596013840066e-08
70 68,9.718234354198392e-05,8.44230607070921e-08,1.7582746084973536e-08
71 69,9.56635564008908e-05,8.271692715563019e-08,1.7407568625796667e-08
72 70,9.417106698591262e-05,8.10457064001203e-08,1.7234047067791308e-08
73 71,9.270483837325431e-05,7.94090478608544e-08,1.7062169097342785e-08
74 72,9.12643590341385e-05,7.780619693716166e-08,1.6891912824320277e-08
75 73,8.984912830909168e-05,7.623641652299821e-08,1.672325659984075e-08
76 74,8.845966357642775e-05,7.469983729150625e-08,1.6557160644411184e-08
77 75,8.709444598783118e-05,7.354697815082507e-08,1.6392702347411626e-08
78 76,8.575300679829195e-05,7.241419869922277e-08,1.6229862344426664e-08
79 77,8.443491979213314e-05,7.130113901851255e-08,1.606862190142917e-08
80 78,8.313973419504378e-05,7.020741845194848e-08,1.5908962221377164e-08
81 79,8.186700872392319e-05,6.913266435764513e-08,1.5750864795797952e-08
82 80,8.061631115512539e-05,6.807651174398117e-08,1.559431138284531e-08
83 81,7.938732282855929e-05,6.703869151817475e-08,1.5439286199449887e-08
84 82,7.817962449101943e-05,6.601884964150396e-08,1.5285771474772338e-08
85 83,7.699280573302815e-05,6.50166395433403e-08,1.513374972211717e-08
86 84,7.592454893921724e-05,6.411454919552573e-08,1.5006080388275954e-08
87 85,7.487353856336685e-05,6.322702259986013e-08,1.4879767295630751e-08
88 86,7.383946010084118e-05,6.235379417263942e-08,1.475480276556073e-08
89 87,7.282054160428152e-05,6.149336759142648e-08,1.4631164089327954e-08
90 88,7.181654482227581e-05,6.064554166461607e-08,1.4508845066183491e-08
91 89,7.082723551235707e-05,5.981011858595996e-08,1.4387839898262193e-08
92 90,6.985238328334553e-05,5.8986903801432673e-08,1.4268143194153057e-08
93 91,6.889088892692634e-05,5.8174969083648444e-08,1.4149731300144923e-08
94 92,6.794256749705261e-05,5.737415825476245e-08,1.4032600405332526e-08
95 93,6.700723666457587e-05,5.658431734677192e-08,1.3916747132522929e-08
96 94,6.59402843027997e-05,5.5683328527685944e-08,1.3765832836854687e-08
97 95,6.489024990134964e-05,5.479662609442341e-08,1.3616406761560667e-08

View File

@@ -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
1 signal ase nli
2 0 0.0002869472910749756 3.829244288314411e-08 2.1570435023738975e-07
3 1 0.0002844264441819097 3.810807396068084e-08 2.1799950841473497e-07
4 2 0.00028192866252406385 3.792544000755193e-08 2.2023841125047751e-07
5 3 0.0002794537215642667 3.7744517714620316e-08 2.2242189941355056e-07
6 4 0.00027562432957345563 3.739256592350871e-08 2.2343448272115905e-07
7 5 0.0002718482755003939 3.7044482870002475e-08 2.2437826192962336e-07
8 6 0.00026812479793132313 3.670020704375223e-08 2.2525495466693408e-07
9 7 0.000264450700138397 3.635954085714981e-08 2.2606415187873477e-07
10 8 0.0002608253488030976 3.602242835595967e-08 2.2680748521505387e-07
11 9 0.0002569046888856947 3.564392097524325e-08 2.2718285844823122e-07
12 10 0.0002530414048172964 3.52696660940159e-08 2.2749429758474536e-07
13 11 0.0002492279873569917 3.489974200864255e-08 2.277374766527899e-07
14 12 0.00024546394589921574 3.453407358954537e-08 2.2791414400785136e-07
15 13 0.00024174879169001578 3.4172586853993816e-08 2.280260208417818e-07
16 14 0.00023798746912554602 3.3802283179520985e-08 2.2798420759778034e-07
17 15 0.00023427697848580554 3.343627022987542e-08 2.2788101592695744e-07
18 16 0.0002306167836320285 3.307447309241581e-08 2.2771816297650914e-07
19 17 0.00022700656967539738 3.2716831574363364e-08 2.274975560288182e-07
20 18 0.00022344579480967338 3.236327278261661e-08 2.2361822442592406e-07
21 19 0.00021953361935365365 3.195819964288877e-08 2.1939761734541424e-07
22 20 0.000215683131390894 3.155821693631402e-08 2.152494588710531e-07
23 21 0.0002118936126056039 3.116322947665684e-08 2.1117277567387026e-07
24 22 0.00020816423698459974 3.0773146233359933e-08 2.0716649124095414e-07
25 23 0.000204494186708796 3.0387877710694614e-08 2.0322954179937734e-07
26 24 0.0002011608152067422 3.0044038268833097e-08 1.9963693210325328e-07
27 25 0.0001978756946189507 2.9704204306604607e-08 1.9610141536963302e-07
28 26 0.00019463824873067792 2.9368307297032184e-08 1.9262221997374404e-07
29 27 0.00019144860669288407 2.903632861769827e-08 1.8919927457566036e-07
30 28 0.00018830616497929743 2.870820070744311e-08 1.8583178406705711e-07
31 29 0.0001852103256336822 2.838385708911634e-08 1.8251896218718027e-07
32 30 0.0001821604972098109 2.8063232252848876e-08 1.7926003240910756e-07
33 31 0.00017915618670059162 2.774625963676283e-08 1.76054318231953e-07
34 32 0.00017619680881745593 2.7432875871797347e-08 1.729010553429381e-07
35 33 0.0001732817839023698 2.712301856538676e-08 1.6979948820365403e-07
36 34 0.0001704966413678542 2.6828122477482957e-08 1.6683312331765736e-07
37 35 0.00016775189226190024 2.6536528664560742e-08 1.639139770351803e-07
38 36 0.00016504703499518105 2.624818226917535e-08 1.6104139135569604e-07
39 37 0.00016238266779776653 2.5963117448579666e-08 1.5795381794641793e-07
40 38 0.0001597582427278871 2.568127942199337e-08 1.5492098715709327e-07
41 39 0.0001571732182027887 2.5402614261982925e-08 1.5194201541883415e-07
42 40 0.00015462705891567335 2.5127068868391087e-08 1.4901603171959048e-07
43 41 0.00015212101646395513 2.4854550603641668e-08 1.4614388817380648e-07
44 42 0.00014965447757985992 2.4585009902449718e-08 1.4332463586635585e-07
45 43 0.0001472268380950584 2.4318397887399997e-08 1.4055734193945962e-07
46 44 0.0001447164668892332 2.4034551917480693e-08 1.377259000826997e-07
47 45 0.00014224784112376056 2.3753930444781328e-08 1.3494914625940223e-07
48 46 0.000139820283675003 2.3476479506890216e-08 1.3222606385781202e-07
49 47 0.00013743418748444287 2.3202247900619965e-08 1.295566531341862e-07
50 48 0.00013508884015386686 2.2931181973013504e-08 1.2693987096025158e-07
51 49 0.00013278354172498307 2.2663228905058608e-08 1.2437469442130953e-07
52 50 0.00013051760419724657 2.2398336706395863e-08 1.2186012017917007e-07
53 51 0.00012829168984638487 2.2136423459712534e-08 1.1939640981689728e-07
54 52 0.00012610506317956756 2.1877440279108582e-08 1.1698252030563078e-07
55 53 0.00012395700285919374 2.1621338937233993e-08 1.1461743054419825e-07
56 54 0.00012180241033650921 2.136015630373758e-08 1.1225922783040025e-07
57 55 0.0001196865090578088 2.11019103466444e-08 1.0994951537260489e-07
58 56 0.00011760857776205185 2.0846552296319304e-08 1.0757395097863843e-07
59 57 0.00011556891128259512 2.0594154864038522e-08 1.0524972555992818e-07
60 58 0.00011356676177304645 2.0344670536408355e-08 1.0297570549834491e-07
61 59 0.00011160139690545148 2.009805268169949e-08 1.007507830554809e-07
62 60 0.00010967209909252316 1.9854255584746143e-08 9.857387536569294e-08
63 61 0.00010777915187088834 1.961321154131787e-08 9.644480679617587e-08
64 62 0.00010592181397175025 1.9374877782865603e-08 9.43624842461164e-08
65 63 0.00010409936038609485 1.913921236065976e-08 9.232584080120623e-08
66 64 0.00010246447558376296 1.8936229484424864e-08 9.046927135292076e-08
67 65 0.00010085803630103994 1.873544193319646e-08 8.865067925960422e-08
68 66 9.927950010555374e-05 1.8536821682157304e-08 8.686925127148483e-08
69 67 9.772837346090753e-05 1.834034757300294e-08 8.512422533827403e-08
70 68 9.62041343011343e-05 1.8145993316507615e-08 8.341482250640209e-08
71 69 9.470627135912848e-05 1.7953733512786736e-08 8.174028142913557e-08
72 70 9.32342835979764e-05 1.776354374489084e-08 8.009985766376519e-08
73 71 9.178813743816069e-05 1.757538990695628e-08 7.849321446941075e-08
74 72 9.036733009485282e-05 1.7389250225057777e-08 7.691961625609573e-08
75 73 8.897136946428169e-05 1.7205104136353174e-08 7.537834446343352e-08
76 74 8.760740745801088e-05 1.7025340034280735e-08 7.38751341742058e-08
77 75 8.626710469266231e-05 1.6847609082084475e-08 7.274492099364066e-08
78 76 8.495000573672366e-05 1.6671897815367364e-08 7.16342744751107e-08
79 77 8.365569697520734e-05 1.6498202874185357e-08 7.054284583689086e-08
80 78 8.238374036673638e-05 1.6326516066391613e-08 6.94702656996508e-08
81 79 8.11337070649851e-05 1.615683240442047e-08 6.84161724378069e-08
82 80 7.990517700271111e-05 1.5989150837085435e-08 6.738021182875641e-08
83 81 7.869784230919362e-05 1.5823472723367315e-08 6.63621242598539e-08
84 82 7.751129541079501e-05 1.5659808141896922e-08 6.536156604375558e-08
85 83 7.634513730458697e-05 1.5498175122781168e-08 6.437820072038669e-08
86 84 7.530262080974513e-05 1.5364277079429572e-08 6.349909645089698e-08
87 85 7.427675504203511e-05 1.523236493234819e-08 6.263403294276124e-08
88 86 7.326723873728716e-05 1.510251249079146e-08 6.178275615432246e-08
89 87 7.227232864620995e-05 1.4974078108462424e-08 6.094379608687809e-08
90 88 7.1291797553153e-05 1.4847055996011248e-08 6.011696114034367e-08
91 89 7.032542203609039e-05 1.4721440784517874e-08 5.930206291361685e-08
92 90 6.937298231673965e-05 1.4597227547292096e-08 5.849891607818969e-08
93 91 6.843339696762385e-05 1.447443282270653e-08 5.7706608718023645e-08
94 92 6.750649045006057e-05 1.4353051811356354e-08 5.6924992809748396e-08
95 93 6.65920896785063e-05 1.4233080214004659e-08 5.615392239860827e-08
96 94 6.554258932109667e-05 1.407504972937325e-08 5.5268928972034444e-08
97 95 6.450957734109368e-05 1.3918655180382722e-08 5.439783940506079e-08

View File

@@ -17,6 +17,7 @@ Transceiver trx_Stockholm
Roadm roadm_Stockholm
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -29,6 +30,7 @@ Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(1/2)
type_variety: SSMF
@@ -37,7 +39,8 @@ Fiber fiber (Stockholm → Norrköping)_(1/2)
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
pch out (dBm): -14.33
total pch (dBm): -14.31
Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
type_variety: openroadm_ila_low_noise
effective gain(dB): 16.33
@@ -50,6 +53,7 @@ Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.02
output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(2/2)
type_variety: SSMF
@@ -58,7 +62,8 @@ Fiber fiber (Stockholm → Norrköping)_(2/2)
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
pch out (dBm): -14.33
total pch (dBm): -14.30
Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
type_variety: openroadm_mw_mw_preamp
effective gain(dB): 16.33
@@ -71,10 +76,12 @@ Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.04
output VOA (dB): 0.00
Roadm roadm_Norrköping
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -87,6 +94,7 @@ Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Norrköping → Linköping)
type_variety: SSMF
@@ -95,7 +103,8 @@ Fiber fiber (Norrköping → Linköping)
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
pch out (dBm): -9.00
total pch (dBm): -9.00
Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
type_variety: openroadm_mw_mw_preamp
effective gain(dB): 11.00
@@ -108,10 +117,12 @@ Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.01
output VOA (dB): 0.00
Roadm roadm_Linköping
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -124,6 +135,7 @@ Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Linköping → Jönköping)
type_variety: SSMF
@@ -132,7 +144,8 @@ Fiber fiber (Linköping → Jönköping)
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
pch out (dBm): -24.80
total pch (dBm): -24.79
Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
type_variety: openroadm_mw_mw_preamp
effective gain(dB): 26.80
@@ -145,10 +158,12 @@ Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.04
output VOA (dB): 0.00
Roadm roadm_Jönköping
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -161,6 +176,7 @@ Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Jönköping → Borås)
type_variety: SSMF
@@ -169,7 +185,8 @@ Fiber fiber (Jönköping → Borås)
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
pch out (dBm): -15.82
total pch (dBm): -15.81
Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
type_variety: openroadm_mw_mw_preamp
effective gain(dB): 17.82
@@ -182,10 +199,12 @@ Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.02
output VOA (dB): 0.00
Roadm roadm_Borås
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -198,6 +217,7 @@ Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Borås → Gothenburg)
type_variety: SSMF
@@ -206,7 +226,8 @@ Fiber fiber (Borås → Gothenburg)
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
pch out (dBm): -11.53
total pch (dBm): -11.52
Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
type_variety: openroadm_mw_mw_preamp
effective gain(dB): 13.53
@@ -219,10 +240,12 @@ Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.02
output VOA (dB): 0.00
Roadm roadm_Gothenburg
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Transceiver trx_Gothenburg
GSNR (0.1nm, dB): 18.90
GSNR (signal bw, dB): 14.88

View File

@@ -17,6 +17,7 @@ Transceiver trx_Stockholm
Roadm roadm_Stockholm
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -29,6 +30,7 @@ Edfa Edfa_booster_roadm_Stockholm_to_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(1/2)
type_variety: SSMF
@@ -37,7 +39,8 @@ Fiber fiber (Stockholm → Norrköping)_(1/2)
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
pch out (dBm): -14.33
total pch (dBm): -14.31
Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
type_variety: openroadm_ila_low_noise
effective gain(dB): 16.33
@@ -50,6 +53,7 @@ Edfa Edfa_fiber (Stockholm → Norrköping)_(1/2)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.02
output VOA (dB): 0.00
Fiber fiber (Stockholm → Norrköping)_(2/2)
type_variety: SSMF
@@ -58,7 +62,8 @@ Fiber fiber (Stockholm → Norrköping)_(2/2)
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
pch out (dBm): -14.33
total pch (dBm): -14.30
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
@@ -71,10 +76,12 @@ Edfa Edfa_preamp_roadm_Norrköping_from_fiber (Stockholm → Norrköping)_(2/2)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.04
output VOA (dB): 0.00
Roadm roadm_Norrköping
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -87,6 +94,7 @@ Edfa Edfa_booster_roadm_Norrköping_to_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Norrköping → Linköping)
type_variety: SSMF
@@ -95,7 +103,8 @@ Fiber fiber (Norrköping → Linköping)
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
pch out (dBm): -9.00
total pch (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
@@ -108,10 +117,12 @@ Edfa Edfa_preamp_roadm_Linköping_from_fiber (Norrköping → Linköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.01
output VOA (dB): 0.00
Roadm roadm_Linköping
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -124,6 +135,7 @@ Edfa Edfa_booster_roadm_Linköping_to_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Linköping → Jönköping)
type_variety: SSMF
@@ -132,7 +144,8 @@ Fiber fiber (Linköping → Jönköping)
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
pch out (dBm): -24.80
total pch (dBm): -24.79
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
@@ -145,10 +158,12 @@ Edfa Edfa_preamp_roadm_Jönköping_from_fiber (Linköping → Jönköping)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.04
output VOA (dB): 0.00
Roadm roadm_Jönköping
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -161,6 +176,7 @@ Edfa Edfa_booster_roadm_Jönköping_to_fiber (Jönköping → Borås)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Jönköping → Borås)
type_variety: SSMF
@@ -169,7 +185,8 @@ Fiber fiber (Jönköping → Borås)
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
pch out (dBm): -15.82
total pch (dBm): -15.81
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
@@ -182,10 +199,12 @@ Edfa Edfa_preamp_roadm_Borås_from_fiber (Jönköping → Borås)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.01
output VOA (dB): 0.00
Roadm roadm_Borås
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (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
@@ -198,6 +217,7 @@ Edfa Edfa_booster_roadm_Borås_to_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.00
output VOA (dB): 0.00
Fiber fiber (Borås → Gothenburg)
type_variety: SSMF
@@ -206,7 +226,8 @@ Fiber fiber (Borås → Gothenburg)
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
pch out (dBm): -11.53
total pch (dBm): -11.52
Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
type_variety: openroadm_mw_mw_preamp_worstcase_ver5
effective gain(dB): 13.53
@@ -219,12 +240,14 @@ Edfa Edfa_preamp_roadm_Gothenburg_from_fiber (Borås → Gothenburg)
Delta_P (dB): 0.00
target pch (dBm): 2.00
effective pch (dBm): 2.00
total pch (dBm): 2.02
output VOA (dB): 0.00
Roadm roadm_Gothenburg
effective loss (dB): 22.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Transceiver trx_Gothenburg
GSNR (0.1nm, dB): 19.27
GSNR (0.1nm, dB): 19.26
GSNR (signal bw, dB): 15.24
OSNR ASE (0.1nm, dB): 21.84
OSNR ASE (signal bw, dB): 17.82
@@ -232,7 +255,7 @@ Transceiver trx_Gothenburg
PMD (ps): 0.89
Transmission result for input power = 2.00 dBm:
Final GSNR (0.1 nm): 19.27 dB
Final GSNR (0.1 nm): 19.26 dB
(No source node specified: picked trx_Stockholm)

View File

@@ -0,0 +1,98 @@
warning: user input for spectrum used for propagation instead of SI
There are 96 channels propagating
Power mode is set to True
=> it can be modified in eqpt_config.json - Span
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 = 0.00 dBm:
Transceiver trx Lannion_CAS
GSNR (0.1nm, dB): 40.00
GSNR (signal bw, dB): 35.92
OSNR ASE (0.1nm, dB): 40.00
OSNR ASE (signal bw, dB): 35.92
CD (ps/nm): 0.00
PMD (ps): 0.00
Roadm roadm Lannion_CAS
effective loss (dB): 20.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Edfa east edfa in Lannion_CAS to Corlay
type_variety: std_medium_gain
effective gain(dB): 21.00
(before att_in and before output VOA)
noise figure (dB): 6.36
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 20.83
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
total pch (dBm): 1.01
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): -3.00
total pch (dBm): -2.99
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): -14.00
total pch (dBm): -13.99
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): -27.00
total pch (dBm): -26.99
Edfa west edfa in Lorient_KMA to Loudeac
type_variety: std_high_gain
effective gain(dB): 28.00
(before att_in and before output VOA)
noise figure (dB): 5.92
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -7.17
Power Out (dBm): 20.87
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
total pch (dBm): 1.05
output VOA (dB): 0.00
Roadm roadm Lorient_KMA
effective loss (dB): 21.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Transceiver trx Lorient_KMA
GSNR (0.1nm, dB): 23.58
GSNR (signal bw, dB): 19.50
OSNR ASE (0.1nm, dB): 23.88
OSNR ASE (signal bw, dB): 19.80
CD (ps/nm): 2171.00
PMD (ps): 0.46
Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 23.58 dB
(No source node specified: picked trx Lannion_CAS)
(No destination node specified: picked trx Lorient_KMA)

View File

@@ -0,0 +1,98 @@
warning: user input for spectrum used for propagation instead of SI
There are 60 channels propagating
Power mode is set to True
=> it can be modified in eqpt_config.json - Span
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 = 0.00 dBm:
Transceiver trx Lannion_CAS
GSNR (0.1nm, dB): 0-32.0: 40.00, 1-64.0: 40.00,
GSNR (signal bw, dB): 0-32.0: 35.92, 1-64.0: 32.91,
OSNR ASE (0.1nm, dB): 0-32.0: 40.00, 1-64.0: 40.00,
OSNR ASE (signal bw, dB): 0-32.0: 35.92, 1-64.0: 32.91,
CD (ps/nm): 0.00
PMD (ps): 0.00
Roadm roadm Lannion_CAS
effective loss (dB): 20.00
pch out (dBm): -20.00
total pch (dBm): 0-32.0: -20.00, 1-64.0: -20.00,
Edfa east edfa in Lannion_CAS to Corlay
type_variety: std_medium_gain
effective gain(dB): 21.00
(before att_in and before output VOA)
noise figure (dB): 6.36
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -2.22
Power Out (dBm): 18.79
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
total pch (dBm): 0-32.0: 1.01, 1-64.0: 1.02,
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): -3.00
total pch (dBm): 0-32.0: -2.99, 1-64.0: -2.98,
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): -14.00
total pch (dBm): 0-32.0: -13.99, 1-64.0: -13.98,
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): -27.00
total pch (dBm): 0-32.0: -26.99, 1-64.0: -26.98,
Edfa west edfa in Lorient_KMA to Loudeac
type_variety: std_high_gain
effective gain(dB): 28.00
(before att_in and before output VOA)
noise figure (dB): 5.92
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -9.21
Power Out (dBm): 18.84
Delta_P (dB): 1.00
target pch (dBm): 1.00
effective pch (dBm): 1.00
total pch (dBm): 0-32.0: 1.04, 1-64.0: 1.09,
output VOA (dB): 0.00
Roadm roadm Lorient_KMA
effective loss (dB): 21.00
pch out (dBm): -20.00
total pch (dBm): 0-32.0: -20.00, 1-64.0: -20.00,
Transceiver trx Lorient_KMA
GSNR (0.1nm, dB): 0-32.0: 23.66, 1-64.0: 23.81,
GSNR (signal bw, dB): 0-32.0: 19.57, 1-64.0: 16.72,
OSNR ASE (0.1nm, dB): 0-32.0: 23.91, 1-64.0: 23.87,
OSNR ASE (signal bw, dB): 0-32.0: 19.83, 1-64.0: 16.78,
CD (ps/nm): 2171.00
PMD (ps): 0.46
Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 23.72 dB
(No source node specified: picked trx Lannion_CAS)
(No destination node specified: picked trx Lorient_KMA)

View File

@@ -21,7 +21,8 @@ Fiber Span1
total loss (dB): 17.00
(includes conn loss (dB) in: 0.50 out: 0.50)
(conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -17.00
pch out (dBm): -17.00
total pch (dBm): -17.00
Edfa Edfa1
type_variety: std_low_gain
effective gain(dB): 15.00
@@ -34,6 +35,7 @@ Edfa Edfa1
Delta_P (dB): -2.00
target pch (dBm): -2.00
effective pch (dBm): -2.00
total pch (dBm): -1.99
output VOA (dB): 0.00
Transceiver Site_B
GSNR (0.1nm, dB): 31.17

View File

@@ -21,109 +21,111 @@ RamanFiber Span1
total loss (dB): 17.00
(includes conn loss (dB) in: 0.50 out: 0.50)
(conn loss out includes EOL margin defined in eqpt_config.json)
pch out (dBm): -7.74
pch out (dBm): -7.71
total pch (dBm): -7.96
Edfa Edfa1
type_variety: std_low_gain
effective gain(dB): 5.74
effective gain(dB): 5.71
(before att_in and before output VOA)
noise figure (dB): 13.26
noise figure (dB): 13.29
(including att_in)
pad att_in (dB): 2.26
Power In (dBm): 11.07
pad att_in (dB): 2.29
Power In (dBm): 11.11
Power Out (dBm): 16.82
Delta_P (dB): -2.00
target pch (dBm): -2.00
effective pch (dBm): -2.00
total pch (dBm): -2.25
output VOA (dB): 0.00
Transceiver Site_B
GSNR (0.1nm, dB): 31.43
GSNR (signal bw, dB): 27.35
OSNR ASE (0.1nm, dB): 34.18
OSNR ASE (signal bw, dB): 30.10
GSNR (0.1nm, dB): 31.44
GSNR (signal bw, dB): 27.36
OSNR ASE (0.1nm, dB): 34.22
OSNR ASE (signal bw, dB): 30.14
CD (ps/nm): 1336.00
PMD (ps): 0.36
Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 31.43 dB
Final GSNR (0.1 nm): 31.44 dB
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)
1 191.35 0.21 31.56 31.47 28.50
2 191.40 0.17 31.54 31.38 28.45
3 191.45 0.14 31.52 31.30 28.40
4 191.50 0.10 31.50 31.22 28.34
5 191.55 0.04 31.47 31.14 28.29
6 191.60 -0.02 31.44 31.06 28.23
7 191.65 -0.08 31.41 30.98 28.18
8 191.70 -0.14 31.37 30.90 28.12
9 191.75 -0.20 31.34 30.83 28.07
10 191.80 -0.26 31.31 30.75 28.01
11 191.85 -0.33 31.27 30.68 27.96
12 191.90 -0.39 31.24 30.61 27.90
13 191.95 -0.46 31.20 30.54 27.85
14 192.00 -0.52 31.17 30.47 27.79
15 192.05 -0.59 31.13 30.40 27.74
16 192.10 -0.66 31.10 30.33 27.69
17 192.15 -0.72 31.06 30.26 27.63
18 192.20 -0.79 31.02 30.20 27.58
19 192.25 -0.86 30.98 30.21 27.57
20 192.30 -0.94 30.94 30.21 27.55
21 192.35 -1.01 30.90 30.22 27.54
22 192.40 -1.09 30.86 30.23 27.52
23 192.45 -1.16 30.81 30.23 27.50
24 192.50 -1.24 30.77 30.24 27.49
25 192.55 -1.31 30.73 30.25 27.47
26 192.60 -1.38 30.69 30.25 27.46
27 192.65 -1.45 30.65 30.26 27.44
28 192.70 -1.52 30.61 30.27 27.42
29 192.75 -1.59 30.56 30.28 27.41
30 192.80 -1.66 30.52 30.28 27.39
31 192.85 -1.73 30.48 30.29 27.37
32 192.90 -1.80 30.44 30.30 27.36
33 192.95 -1.87 30.39 30.30 27.34
34 193.00 -1.94 30.35 30.31 27.32
35 193.05 -2.01 30.31 30.32 27.30
36 193.10 -2.08 30.27 30.33 27.29
37 193.15 -2.15 30.22 30.33 27.27
38 193.20 -2.22 30.18 30.35 27.25
39 193.25 -2.29 30.14 30.37 27.24
40 193.30 -2.36 30.09 30.39 27.23
41 193.35 -2.43 30.05 30.40 27.21
42 193.40 -2.49 30.01 30.42 27.20
43 193.45 -2.56 29.96 30.44 27.18
44 193.50 -2.63 29.92 30.46 27.17
45 193.55 -2.70 29.87 30.47 27.15
46 193.60 -2.78 29.83 30.49 27.13
47 193.65 -2.85 29.78 30.51 27.12
48 193.70 -2.92 29.73 30.53 27.10
49 193.75 -2.99 29.68 30.54 27.08
50 193.80 -3.06 29.64 30.56 27.06
51 193.85 -3.14 29.59 30.58 27.05
52 193.90 -3.21 29.54 30.60 27.03
53 193.95 -3.28 29.49 30.62 27.01
54 194.00 -3.35 29.44 30.64 26.99
55 194.05 -3.42 29.39 30.65 26.97
56 194.10 -3.50 29.34 30.67 26.95
57 194.15 -3.57 29.29 30.73 26.94
58 194.20 -3.64 29.24 30.79 26.94
59 194.25 -3.72 29.19 30.85 26.93
60 194.30 -3.79 29.14 30.91 26.93
61 194.35 -3.86 29.09 30.97 26.92
62 194.40 -3.93 29.04 31.03 26.91
63 194.45 -4.01 28.99 31.09 26.90
64 194.50 -4.08 28.94 31.15 26.90
65 194.55 -4.14 28.89 31.22 26.89
66 194.60 -4.21 28.85 31.28 26.88
67 194.65 -4.28 28.80 31.35 26.88
68 194.70 -4.34 28.75 31.41 26.87
69 194.75 -4.41 28.70 31.48 26.86
70 194.80 -4.47 28.66 31.55 26.86
71 194.85 -4.54 28.61 31.62 26.85
72 194.90 -4.60 28.56 31.69 26.84
73 194.95 -4.67 28.51 31.77 26.83
74 195.00 -4.73 28.47 31.84 26.82
75 195.05 -4.80 28.42 31.91 26.81
76 195.10 -4.86 28.37 31.91 26.78
1 191.35000 0.18 31.61 31.42 28.51
2 191.40000 0.14 31.59 31.34 28.45
3 191.45000 0.11 31.57 31.25 28.40
4 191.50000 0.07 31.55 31.17 28.35
5 191.55000 0.02 31.52 31.09 28.29
6 191.60000 -0.04 31.49 31.01 28.23
7 191.65000 -0.10 31.46 30.93 28.18
8 191.70000 -0.16 31.43 30.86 28.12
9 191.75000 -0.21 31.40 30.78 28.07
10 191.80000 -0.28 31.36 30.71 28.01
11 191.85000 -0.34 31.33 30.64 27.96
12 191.90000 -0.40 31.29 30.56 27.90
13 191.95000 -0.47 31.26 30.49 27.85
14 192.00000 -0.53 31.22 30.43 27.80
15 192.05000 -0.60 31.18 30.36 27.74
16 192.10000 -0.66 31.15 30.29 27.69
17 192.15000 -0.73 31.11 30.23 27.64
18 192.20000 -0.79 31.07 30.16 27.58
19 192.25000 -0.86 31.04 30.17 27.57
20 192.30000 -0.94 30.99 30.18 27.55
21 192.35000 -1.01 30.95 30.18 27.54
22 192.40000 -1.08 30.91 30.19 27.52
23 192.45000 -1.16 30.86 30.20 27.51
24 192.50000 -1.23 30.82 30.21 27.49
25 192.55000 -1.30 30.78 30.21 27.48
26 192.60000 -1.37 30.74 30.22 27.46
27 192.65000 -1.44 30.70 30.23 27.45
28 192.70000 -1.51 30.65 30.24 27.43
29 192.75000 -1.58 30.61 30.25 27.41
30 192.80000 -1.65 30.57 30.25 27.40
31 192.85000 -1.72 30.53 30.26 27.38
32 192.90000 -1.79 30.48 30.27 27.36
33 192.95000 -1.86 30.44 30.28 27.35
34 193.00000 -1.93 30.40 30.28 27.33
35 193.05000 -2.00 30.35 30.29 27.31
36 193.10000 -2.07 30.31 30.30 27.30
37 193.15000 -2.14 30.27 30.31 27.28
38 193.20000 -2.20 30.22 30.33 27.26
39 193.25000 -2.27 30.18 30.34 27.25
40 193.30000 -2.34 30.14 30.36 27.24
41 193.35000 -2.41 30.09 30.38 27.22
42 193.40000 -2.48 30.05 30.40 27.21
43 193.45000 -2.55 30.00 30.41 27.19
44 193.50000 -2.61 29.96 30.43 27.18
45 193.55000 -2.69 29.91 30.45 27.16
46 193.60000 -2.76 29.86 30.47 27.15
47 193.65000 -2.83 29.82 30.49 27.13
48 193.70000 -2.90 29.77 30.51 27.11
49 193.75000 -2.98 29.72 30.52 27.09
50 193.80000 -3.05 29.67 30.54 27.08
51 193.85000 -3.12 29.62 30.56 27.06
52 193.90000 -3.19 29.58 30.58 27.04
53 193.95000 -3.26 29.53 30.60 27.02
54 194.00000 -3.33 29.48 30.62 27.00
55 194.05000 -3.41 29.43 30.64 26.98
56 194.10000 -3.48 29.38 30.66 26.96
57 194.15000 -3.55 29.33 30.71 26.96
58 194.20000 -3.63 29.28 30.77 26.95
59 194.25000 -3.70 29.23 30.83 26.94
60 194.30000 -3.77 29.18 30.89 26.94
61 194.35000 -3.85 29.12 30.95 26.93
62 194.40000 -3.92 29.07 31.01 26.92
63 194.45000 -3.99 29.02 31.07 26.92
64 194.50000 -4.06 28.97 31.14 26.91
65 194.55000 -4.13 28.92 31.20 26.90
66 194.60000 -4.19 28.88 31.27 26.90
67 194.65000 -4.26 28.83 31.33 26.89
68 194.70000 -4.33 28.78 31.40 26.89
69 194.75000 -4.39 28.73 31.47 26.88
70 194.80000 -4.46 28.68 31.54 26.87
71 194.85000 -4.52 28.64 31.61 26.86
72 194.90000 -4.59 28.59 31.68 26.85
73 194.95000 -4.65 28.54 31.75 26.85
74 195.00000 -4.72 28.49 31.83 26.84
75 195.05000 -4.78 28.44 31.90 26.83
76 195.10000 -4.85 28.39 31.90 26.79
(No source node specified: picked Site_A)

View File

@@ -0,0 +1,451 @@
There are 96 channels propagating
Power mode is set to True
=> it can be modified in eqpt_config.json - Span
There are 15 fiber spans over 1200 km between Site_A and Site_B
Now propagating between Site_A and Site_B:
Propagating with input power = 0.00 dBm:
Transceiver Site_A
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
Roadm roadm Site A
effective loss (dB): 20.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Edfa booster A
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.01
output VOA (dB): 0.00
Fiber Span1
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.99
Edfa Edfa1
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.84
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.02
output VOA (dB): 0.00
Fiber Span2
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.98
Edfa Edfa2
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.03
output VOA (dB): 0.00
Fiber Span3
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.97
Edfa Edfa3
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.85
Power Out (dBm): 19.86
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.04
output VOA (dB): 0.00
Fiber Span4
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.96
Edfa Edfa4
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.86
Power Out (dBm): 19.87
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.05
output VOA (dB): 0.00
Fiber Span5
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.95
Edfa Edfa5
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.87
Power Out (dBm): 19.88
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.06
output VOA (dB): 0.00
Roadm roadm Site C
effective loss (dB): 20.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Edfa booster C
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.01
output VOA (dB): 0.00
Fiber Span6
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.99
Edfa Edfa6
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.83
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.02
output VOA (dB): 0.00
Fiber Span7
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.98
Edfa Edfa7
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.03
output VOA (dB): 0.00
Fiber Span8
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.97
Edfa Edfa8
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.85
Power Out (dBm): 19.86
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.04
output VOA (dB): 0.00
Fiber Span9
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.96
Edfa Edfa9
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.86
Power Out (dBm): 19.87
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.05
output VOA (dB): 0.00
Fiber Span10
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.95
Edfa Edfa10
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.87
Power Out (dBm): 19.88
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.06
output VOA (dB): 0.00
Roadm roadm Site D
effective loss (dB): 20.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Edfa booster D
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.01
output VOA (dB): 0.00
Fiber Span11
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.99
Edfa Edfa11
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.83
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.02
output VOA (dB): 0.00
Fiber Span12
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.98
Edfa Edfa12
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.03
output VOA (dB): 0.00
Roadm roadm Site E
effective loss (dB): 20.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Edfa booster E
type_variety: std_medium_gain
effective gain(dB): 20.00
(before att_in and before output VOA)
noise figure (dB): 6.58
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): -0.18
Power Out (dBm): 19.83
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.01
output VOA (dB): 0.00
Fiber Span13
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.99
Edfa Edfa13
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.83
Power Out (dBm): 19.84
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.02
output VOA (dB): 0.00
Fiber Span14
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.98
Edfa Edfa14
type_variety: test_fixed_gain
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 9.00
(including att_in)
pad att_in (dB): 4.00
Power In (dBm): 3.84
Power Out (dBm): 19.85
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.03
output VOA (dB): 0.00
Fiber Span15
type_variety: SSMF
length (km): 80.00
pad att_in (dB): 0.00
total loss (dB): 16.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): -16.00
total pch (dBm): -15.97
Edfa Edfa15
type_variety: test
effective gain(dB): 16.00
(before att_in and before output VOA)
noise figure (dB): 8.86
(including att_in)
pad att_in (dB): 0.00
Power In (dBm): 3.85
Power Out (dBm): 19.86
Delta_P (dB): 0.00
target pch (dBm): 0.00
effective pch (dBm): 0.00
total pch (dBm): 0.04
output VOA (dB): 0.00
Roadm roadm Site B
effective loss (dB): 20.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Transceiver Site_B
GSNR (0.1nm, dB): 17.85
GSNR (signal bw, dB): 13.77
OSNR ASE (0.1nm, dB): 19.70
OSNR ASE (signal bw, dB): 15.62
CD (ps/nm): 20040.00
PMD (ps): 1.39
Transmission result for input power = 0.00 dBm:
Final GSNR (0.1 nm): 17.85 dB
(No source node specified: picked Site_A)
(No destination node specified: picked Site_B)

View File

@@ -253,6 +253,7 @@ Transceiver trx Lannion_CAS
Roadm roadm Lannion_CAS
effective loss (dB): 23.00
pch out (dBm): -20.00
total pch (dBm): -20.00
Edfa east edfa in Lannion_CAS to Corlay
type_variety: test
effective gain(dB): 21.18
@@ -265,6 +266,7 @@ Edfa east edfa in Lannion_CAS to Corlay
Delta_P (dB): 0.00
target pch (dBm): 3.00
effective pch (dBm): 1.18
total pch (dBm): 1.18
output VOA (dB): 0.00
Fiber fiber (Lannion_CAS → Corlay)-F061
type_variety: SSMF
@@ -273,7 +275,8 @@ Fiber fiber (Lannion_CAS → Corlay)-F061
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
pch out (dBm): -2.82
total pch (dBm): -2.81
Fused west fused spans in Corlay
loss (dB): 1.00
Fiber fiber (Corlay → Loudeac)-F010
@@ -283,7 +286,8 @@ Fiber fiber (Corlay → Loudeac)-F010
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
pch out (dBm): -13.82
total pch (dBm): -13.81
Fused west fused spans in Loudeac
loss (dB): 1.00
Fiber fiber (Loudeac → Lorient_KMA)-F054
@@ -293,7 +297,8 @@ Fiber fiber (Loudeac → Lorient_KMA)-F054
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
pch out (dBm): -26.82
total pch (dBm): -26.81
Edfa west edfa in Lorient_KMA to Loudeac
type_variety: test
effective gain(dB): 28.00
@@ -306,10 +311,12 @@ Edfa west edfa in Lorient_KMA to Loudeac
Delta_P (dB): -1.82
target pch (dBm): 1.18
effective pch (dBm): 1.18
total pch (dBm): 1.22
output VOA (dB): 0.00
Roadm roadm Lorient_KMA
effective loss (dB): 21.18
pch out (dBm): -20.00
total pch (dBm): -20.00
Transceiver trx Lorient_KMA
GSNR (0.1nm, dB): 23.94
GSNR (signal bw, dB): 19.85

View File

@@ -80,13 +80,12 @@ def si(nch_and_spacing, bw):
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)"""
edfa = setup_edfa_variable_gain
frequencies = array([c.frequency for c in si.carriers])
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
pin = pin / db2lin(gain)
baud_rates = array([c.baud_rate for c in si.carriers])
si.signal /=db2lin(gain)
si.nli /= db2lin(gain)
si.ase /= db2lin(gain)
edfa.operational.gain_target = gain
pref = Pref(0, -gain, lin2db(len(frequencies)))
edfa.interpol_params(frequencies, pin, baud_rates, pref)
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
edfa.interpol_params(si)
result = edfa.nf
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):
"""=> unitary test for fixed gain model Edfa._calc_nf() (and Edfa.interpol_params)"""
edfa = setup_edfa_fixed_gain
frequencies = array([c.frequency for c in si.carriers])
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
pin = pin / db2lin(gain)
baud_rates = array([c.baud_rate for c in si.carriers])
si.signal /= db2lin(gain)
si.nli /= db2lin(gain)
si.ase /= db2lin(gain)
edfa.operational.gain_target = gain
pref = Pref(0, -gain, lin2db(len(frequencies)))
edfa.interpol_params(frequencies, pin, baud_rates, pref)
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
edfa.interpol_params(si)
assert pytest.approx(nf_expected, abs=0.01) == edfa.nf[0]
def test_si(si, nch_and_spacing):
"""basic total power check of the channel comb generation"""
nb_channel = nch_and_spacing[0]
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
p_tot = pin.sum()
expected_p_tot = si.carriers[0].power.signal * nb_channel
p_tot = sum(si.signal + si.ase + si.nli)
expected_p_tot = si.signal[0] * nb_channel
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
=> unitary test for Edfa._calc_nf (and Edfa.interpol_params)"""
edfa = setup_edfa_variable_gain
frequencies = array([c.frequency for c in si.carriers])
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
pin = pin / db2lin(gain)
baud_rates = array([c.baud_rate for c in si.carriers])
si.signal /=db2lin(gain)
si.nli /= db2lin(gain)
si.ase /= db2lin(gain)
edfa.operational.gain_target = gain
# edfa is variable gain type
pref = Pref(0, -gain, lin2db(len(frequencies)))
edfa.interpol_params(frequencies, pin, baud_rates, pref)
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
edfa.interpol_params(si)
nf_model = edfa.nf[0]
# 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 is variable gain type
edfa.interpol_params(frequencies, pin, baud_rates, pref)
edfa.interpol_params(si)
nf_poly = edfa.nf[0]
print(nf_poly, nf_model)
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)
print(span)
frequencies = array([c.frequency for c in si.carriers])
pin = array([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
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)
si.pref = si.pref._replace(p_span0=0, p_spani=-gain, p_span0_per_channel=zeros(len(si.signal)))
edfa.interpol_params(si)
nf = edfa.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
si = edfa(si)
print(edfa)
pout = array([c.power.signal for c in si.carriers])
pase = array([c.power.ase for c in si.carriers])
osnr = lin2db(pout[0] / pase[0]) - lin2db(12.5e9 / bw)
osnr = lin2db(si.signal[0] / si.ase[0]) - lin2db(12.5e9 / bw)
assert pytest.approx(osnr_expected, abs=0.01) == osnr
trx = setup_trx

317
tests/test_equalization.py Normal file
View File

@@ -0,0 +1,317 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: Esther Le Rouzic
# @Date: 2019-05-22
"""
@author: esther.lerouzic
checks that new equalization option give the same output as old one:
"""
from pathlib import Path
import pytest
from numpy.testing import assert_allclose, assert_array_equal, assert_raises
from gnpy.core.utils import lin2db, automatic_nch, dbm2watt, powerdbm2psdmwperghz, watt2dbm
from gnpy.core.network import build_network
from gnpy.core.elements import Roadm
from gnpy.core.info import create_input_spectral_information
from gnpy.core.equipment import trx_mode_params
from gnpy.tools.json_io import network_from_json, load_equipment, load_network, _spectrum_from_json, load_json
from gnpy.topology.request import PathRequest, compute_constrained_path, propagate, update_spectrum_power, ref_carrier
TEST_DIR = Path(__file__).parent
EQPT_FILENAME = TEST_DIR / 'data/eqpt_config.json'
NETWORK_FILENAME = TEST_DIR / 'data/testTopology_expected.json'
def net_setup(equipment):
""" common setup for tests: builds network, equipment and oms only once
"""
network = load_network(NETWORK_FILENAME, equipment)
spectrum = equipment['SI']['default']
p_db = spectrum.power_dbm
p_total_db = p_db + lin2db(automatic_nch(spectrum.f_min, spectrum.f_max, spectrum.spacing))
build_network(network, equipment, p_db, p_total_db)
return network
def create_voyager_req(equipment, source, dest, bidir, nodes_list, loose_list, mode, spacing, power_dbm):
""" create the usual request list according to parameters
"""
params = {'request_id': 'test_request',
'source': source,
'bidir': bidir,
'destination': dest,
'trx_type': 'Voyager',
'trx_mode': mode,
'format': mode,
'spacing': spacing,
'nodes_list': nodes_list,
'loose_list': loose_list,
'path_bandwidth': 100.0e9,
'effective_freq_slot': None}
trx_params = trx_mode_params(equipment, params['trx_type'], params['trx_mode'], True)
params.update(trx_params)
params['power'] = dbm2watt(power_dbm) if power_dbm else dbm2watt(equipment['SI']['default'].power_dbm)
f_min = params['f_min']
f_max_from_si = params['f_max']
params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing'])
return PathRequest(**params)
@pytest.mark.parametrize('power_dbm', [0, 1, -2, None])
@pytest.mark.parametrize('mode, spacing', (['mode 1', 50e9], ['mode 2', 75e9]))
def test_initial_spectrum(mode, spacing, power_dbm):
""" checks that propagation using the user defined spectrum identical to SI, gives same result as SI
"""
# first propagate without any req.initial_spectrum attribute
equipment = load_equipment(EQPT_FILENAME)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
mode, spacing, power_dbm)
network = net_setup(equipment)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
# then creates req.initial_spectrum attribute exactly corresponding to -spectrum option files
temp = [{
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
"f_max": 196.1e12,
"baud_rate": req.baud_rate,
"spacing": spacing,
"roll_off": 0.15,
"tx_osnr": 40
}]
if power_dbm:
temp[0]['power_dbm'] = power_dbm
req.initial_spectrum = _spectrum_from_json(temp, equipment)
update_spectrum_power(req)
infos_actual = propagate(path, req, equipment)
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
assert_array_equal(infos_expected.signal, infos_actual.signal)
assert_array_equal(infos_expected.nli, infos_actual.nli)
assert_array_equal(infos_expected.ase, infos_actual.ase)
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
def test_initial_spectrum_not_identical():
""" checks that user defined spectrum overrides spectrum defined in SI
"""
# first propagate without any req.initial_spectrum attribute
equipment = load_equipment(EQPT_FILENAME)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, 0)
network = net_setup(equipment)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
# then creates req.initial_spectrum attribute exactly corresponding to -spectrum option files
temp = [{
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
"f_max": 196.1e12,
"baud_rate": 40e9,
"spacing": 62.5e9,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp, equipment)
update_spectrum_power(req)
infos_actual = propagate(path, req, equipment)
assert_raises(AssertionError, assert_array_equal, infos_expected.baud_rate, infos_actual.baud_rate)
assert_raises(AssertionError, assert_array_equal, infos_expected.slot_width, infos_actual.slot_width)
assert_raises(AssertionError, assert_array_equal, infos_expected.signal, infos_actual.signal)
assert_raises(AssertionError, assert_array_equal, infos_expected.nli, infos_actual.nli)
assert_raises(AssertionError, assert_array_equal, infos_expected.ase, infos_actual.ase)
assert_raises(AssertionError, assert_array_equal, infos_expected.channel_number, infos_actual.channel_number)
assert_raises(AssertionError, assert_array_equal, infos_expected.number_of_channels, infos_actual.number_of_channels)
@pytest.mark.parametrize('with_initial_spectrum', [None, 0, +2, -0.5])
def test_target_psd_out_mwperghz(with_initial_spectrum):
""" checks that if target_psd_out_mWperGHz is defined, it is used as equalization, and it gives same result if
computed target is the same
"""
equipment = load_equipment(EQPT_FILENAME)
network = net_setup(equipment)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, 0)
if with_initial_spectrum:
temp = [{
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_max and not SI !
"f_max": 196.1e12,
"baud_rate": req.baud_rate,
"power_dbm": with_initial_spectrum,
"spacing": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp, equipment)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
# change default equalization to power spectral density
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz', powerdbm2psdmwperghz(-20, 32e9))
# create a second instance with this roadm settings,
network2 = net_setup(equipment)
path2 = compute_constrained_path(network2, req)
infos_actual = propagate(path2, req, equipment)
# since baudrate is the same, resulting propagation should be the same as for power equalization
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
assert_array_equal(infos_expected.signal, infos_actual.signal)
assert_array_equal(infos_expected.nli, infos_actual.nli)
assert_array_equal(infos_expected.ase, infos_actual.ase)
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)
def ref_network():
""" Create a network instance with a instance of propagated path
"""
equipment = load_equipment(EQPT_FILENAME)
network = net_setup(equipment)
req0 = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, 0)
path0 = compute_constrained_path(network, req0)
_ = propagate(path0, req0, equipment)
return network
@pytest.mark.parametrize('deltap', [0, +1.2, -0.5])
def test_target_psd_out_mwperghz_deltap(deltap):
""" checks that if target_psd_out_mWperGHz is defined, delta_p of amps is correctly updated
Power over 1.2dBm saturate amp with this test: TODO add a test on this saturation
"""
equipment = load_equipment(EQPT_FILENAME)
network = net_setup(equipment)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, deltap)
temp = [{
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_mix and not SI !
"f_max": 196.1e12,
"baud_rate": req.baud_rate,
"spacing": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp, equipment)
update_spectrum_power(req)
path = compute_constrained_path(network, req)
_ = propagate(path, req, equipment)
# check that gain of booster is changed accordingly whereas gain of preamp and ila is not (no saturation case)
boosters = ['east edfa in Brest_KLA to Quimper', 'east edfa in Lorient_KMA to Vannes_KBE']
ila_preamps = ['east edfa in Quimper to Lorient_KMA', 'west edfa in Lorient_KMA to Quimper',
'west edfa in Vannes_KBE to Lorient_KMA']
for amp in boosters + ila_preamps:
expected_amp = next(n for n in ref_network() if n.uid == amp)
actual_amp = next(n for n in network.nodes() if n.uid == amp)
expected_gain = expected_amp.pout_db - expected_amp.pin_db
actual_gain = actual_amp.pout_db - actual_amp.pin_db
print(actual_amp)
if amp in boosters:
assert expected_gain + deltap == pytest.approx(actual_gain, rel=1e-3)
if amp in ila_preamps:
assert expected_gain == pytest.approx(actual_gain, rel=1e-3)
@pytest.mark.parametrize('case', ['SI', 'nodes'])
@pytest.mark.parametrize('deltap', [0, +2, -0.5])
@pytest.mark.parametrize('target', [-20, -21, -18])
@pytest.mark.parametrize('mode, spacing', (['mode 1', 50e9], ['mode 2', 75e9]))
def test_equalization(case, deltap, target, mode, spacing):
"""check that power target on roadm is correct for these cases; check on booster
- SI : target_pch_out_db / target_psd_out_mWperGHz
- node : target_pch_out_db / target_psd_out_mWperGHz
- per degree : target_pch_out_db / target_psd_out_mWperGHz
for these cases with and without power from user
"""
equipment = load_equipment(EQPT_FILENAME)
setattr(equipment['Roadm']['default'], 'target_pch_out_db', target)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Rennes_STA', False,
['east edfa in Brest_KLA to Quimper', 'roadm Lannion_CAS', 'trx Rennes_STA'],
['STRICT', 'STRICT', 'STRICT'],
mode, spacing, deltap)
roadms = ['roadm Brest_KLA', 'roadm Lorient_KMA', 'roadm Lannion_CAS', 'roadm Rennes_STA']
# degree = {'roadm Brest_KLA': 'east edfa in Brest_KLA to Quimper',
# 'roadm Lorient_KMA': 'east edfa in Lorient_KMA to Loudeac'}
# boosters = ['east edfa in Brest_KLA to Quimper', 'east edfa in Lorient_KMA to Loudeac',
# 'east edfa in Lannion_CAS to Stbrieuc']
target_psd = powerdbm2psdmwperghz(target, 32e9)
ref = ref_carrier(req.power, equipment)
if case == 'SI':
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz',
target_psd)
network = net_setup(equipment)
elif case == 'nodes':
json_data = load_json(NETWORK_FILENAME)
for el in json_data['elements']:
if el['uid'] in roadms:
el['params'] = {'target_psd_out_mWperGHz': target_psd}
network = network_from_json(json_data, equipment)
spectrum = equipment['SI']['default']
p_db = spectrum.power_dbm
p_total_db = p_db + lin2db(automatic_nch(spectrum.f_min, spectrum.f_max, spectrum.spacing))
build_network(network, equipment, p_db, p_total_db)
# check that nodes not in roadms have target_pch_out_db not None
pw_roadms = [r for r in network.nodes() if r.uid not in roadms and isinstance(r, Roadm)]
for roadm in pw_roadms:
assert roadm.target_psd_out_mWperGHz is None
assert roadm.target_pch_out_dbm == target
path = compute_constrained_path(network, req)
si = create_input_spectral_information(
req.f_min, req.f_max, req.roll_off, req.baud_rate, req.power, req.spacing, ref_carrier=ref)
for i, el in enumerate(path):
if isinstance(el, Roadm):
si = el(si, degree=path[i+1].uid)
if case in ['SI', 'nodes', 'degrees']:
assert_allclose(powerdbm2psdmwperghz(watt2dbm(si.signal + si.ase + si.nli), si.baud_rate),
target_psd, rtol=1e-3)
else:
si = el(si)
print(el.uid)
@pytest.mark.parametrize('req_power', [0, 2, -1.5])
def test_power_option(req_power):
"""check that --po option adds correctly power with spectral information
"""
equipment = load_equipment(EQPT_FILENAME)
setattr(equipment['Roadm']['default'], 'target_pch_out_db', None)
setattr(equipment['Roadm']['default'], 'target_psd_out_mWperGHz', powerdbm2psdmwperghz(-20, 32e9))
network = net_setup(equipment)
req = create_voyager_req(equipment, 'trx Brest_KLA', 'trx Vannes_KBE', False, ['trx Vannes_KBE'], ['STRICT'],
'mode 1', 50e9, req_power)
path = compute_constrained_path(network, req)
infos_expected = propagate(path, req, equipment)
temp = [{
"f_min": 191.35e12, # align f_min , f_max on Voyager f_min, f_max and not SI !
"f_max": 196.1e12,
"baud_rate": req.baud_rate,
"spacing": 50e9,
"roll_off": 0.15,
"tx_osnr": 40
}]
req.initial_spectrum = _spectrum_from_json(temp, equipment)
update_spectrum_power(req)
network2 = net_setup(equipment)
path2 = compute_constrained_path(network2, req)
infos_actual = propagate(path2, req, equipment)
assert_array_equal(infos_expected.baud_rate, infos_actual.baud_rate)
assert_array_equal(infos_expected.slot_width, infos_actual.slot_width)
assert_array_equal(infos_expected.signal, infos_actual.signal)
assert_array_equal(infos_expected.nli, infos_actual.nli)
assert_array_equal(infos_expected.ase, infos_actual.ase)
assert_array_equal(infos_expected.roll_off, infos_actual.roll_off)
assert_array_equal(infos_expected.chromatic_dispersion, infos_actual.chromatic_dispersion)
assert_array_equal(infos_expected.pmd, infos_actual.pmd)
assert_array_equal(infos_expected.channel_number, infos_actual.channel_number)
assert_array_equal(infos_expected.number_of_channels, infos_actual.number_of_channels)

53
tests/test_info.py Normal file
View File

@@ -0,0 +1,53 @@
#!/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, Pref
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],
ref_power=Pref(1, 1, array([1, 1, 1]), None))
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]),
ref_power=Pref(1, 1, array([1, 2, 3]), None))
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,
ref_power=Pref(1, 1, 1, None))
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, ref_power=Pref(1, 1, 1, None))
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, ref_power=Pref(1, 1, 1, None))
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,
ref_power=Pref(1, 1, [1, 2], None))

View File

@@ -20,7 +20,15 @@ SRC_ROOT = Path(__file__).parent.parent
['-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', ]),
))
('transmission_main_example_long', transmission_main_example,
['-e', 'tests/data/eqpt_config.json', 'tests/data/test_long_network.json']),
('spectrum1_transmission_main_example', transmission_main_example,
['-spectrum', 'gnpy/example-data/initial_spectrum1.json', 'gnpy/example-data/meshTopologyExampleV2.xls', ]),
('spectrum2_transmission_main_example', transmission_main_example,
['-spectrum', 'gnpy/example-data/initial_spectrum2.json', 'gnpy/example-data/meshTopologyExampleV2.xls', ]),
))
def test_example_invocation(capfd, output, handler, args):
'''Make sure that our examples produce useful output'''
os.chdir(SRC_ROOT)

View File

@@ -1,26 +1,32 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
"""
Checks that the class SimParams behaves as a mutable Singleton.
"""
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'
import pytest
from gnpy.core.parameters import SimParams, NLIParams, RamanParams
def test_sim_parameters():
j = load_json(DATA_DIR / 'sim_params.json')
sim_params = SimParams(**j)
Simulation.set_params(sim_params)
s1 = Simulation.get_simulation()
assert s1.sim_params.raman_params.flag_raman
s2 = Simulation.get_simulation()
assert s2.sim_params.raman_params.flag_raman
j['raman_parameters']['flag_raman'] = False
sim_params = SimParams(**j)
Simulation.set_params(sim_params)
assert not s2.sim_params.raman_params.flag_raman
assert not s1.sim_params.raman_params.flag_raman
class MockSimParams(SimParams):
"""Mock simulation parameters for monkey patch"""
_shared_dict = {'nli_params': NLIParams(), 'raman_params': RamanParams()}
@pytest.fixture
def set_sim_params(monkeypatch):
monkeypatch.setattr(SimParams, '_shared_dict', MockSimParams._shared_dict)
def test_sim_parameters(set_sim_params):
sim_params = {'nli_params': {}, 'raman_params': {}}
MockSimParams.set_params(sim_params)
s1 = SimParams.get()
assert s1.nli_params.method == 'gn_model_analytic'
s2 = SimParams.get()
assert not s1.raman_params.flag
sim_params['raman_params']['flag'] = True
MockSimParams.set_params(sim_params)
assert s2.raman_params.flag
assert s1.raman_params.flag

View File

@@ -12,12 +12,14 @@ checks that restrictions in roadms are correctly applied during autodesign
from pathlib import Path
import pytest
from numpy.testing import assert_allclose
from gnpy.core.utils import lin2db, automatic_nch
from gnpy.core.elements import Fused, Roadm, Edfa
from gnpy.core.network import build_network
from gnpy.tools.json_io import network_from_json, load_equipment, load_json, Amp
from gnpy.core.equipment import trx_mode_params
from gnpy.topology.request import PathRequest, compute_constrained_path
from gnpy.topology.request import PathRequest, compute_constrained_path, ref_carrier
from gnpy.core.info import create_input_spectral_information
from gnpy.core.utils import db2lin
@@ -251,38 +253,26 @@ def test_roadm_target_power(prev_node_type, effective_pch_out_db, power_dbm):
path = compute_constrained_path(network, req)
si = create_input_spectral_information(
req.f_min, req.f_max, req.roll_off, req.baud_rate,
req.power, req.spacing)
req.power, req.spacing, ref_carrier(req.power, equipment))
for i, el in enumerate(path):
if isinstance(el, Roadm):
carriers_power_in_roadm = min([c.power.signal + c.power.nli + c.power.ase for c in si.carriers])
si = el(si, degree=path[i + 1].uid)
min_power_in_roadm = min(si.signal + si.ase + si.nli)
si = el(si, degree=path[i+1].uid)
power_out_roadm = si.signal + si.ase + si.nli
if el.uid == 'roadm node B':
print('input', carriers_power_in_roadm)
# if previous was an EDFA, power level at ROADM input is enough for the ROADM to apply its
# target power (as specified in equipment ie -20 dBm)
# if it is a Fused, the input power to the ROADM is smaller than the target power, and the
# 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 !
print('input', min_power_in_roadm)
if prev_node_type == 'edfa':
assert el.effective_pch_out_db == effective_pch_out_db
if prev_node_type == 'fused':
# then output power == input_power == effective_pch_out_db + power_dbm
assert effective_pch_out_db + power_dbm == \
pytest.approx(lin2db(carriers_power_in_roadm * 1e3), rel=1e-3)
assert el.effective_pch_out_db == effective_pch_out_db + power_dbm
for carrier in si.carriers:
print(carrier.power.signal + carrier.power.nli + carrier.power.ase)
power = carrier.power.signal + carrier.power.nli + carrier.power.ase
if prev_node_type == 'edfa':
# edfa prev_node sets input power to roadm to a high enough value:
# Check that egress power of roadm is equal to target power
assert power == pytest.approx(db2lin(effective_pch_out_db - 30), rel=1e-3)
elif prev_node_type == 'fused':
# fused prev_node does reamplfy power after fiber propagation, so input power
# to roadm is low.
# 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)
# 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.ref_pch_out_dbm, effective_pch_out_db, rtol=1e-3)
# Check that egress power of roadm is equal to target power
assert_allclose(power_out_roadm, db2lin(effective_pch_out_db - 30), rtol=1e-3)
elif prev_node_type == 'fused':
# fused prev_node does reamplfy power after fiber propagation, so input power
# to roadm is low.
# check that target power correctly reports power_dbm from previous propagation
assert_allclose(el.ref_pch_out_dbm, effective_pch_out_db + power_dbm, rtol=1e-3)
# Check that egress power of roadm is equalized to the min carrier input power.
assert_allclose(power_out_roadm, min_power_in_roadm, rtol=1e-3)
else:
si = el(si)

View File

@@ -1,48 +1,128 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: Alessio Ferrari
"""
Checks that RamanFiber propagates properly the spectral information. In this way, also the RamanSolver and the NliSolver
are tested.
"""
import pytest
from pathlib import Path
from pandas import read_csv
from numpy.testing import assert_allclose
from numpy import array, load
from gnpy.core.info import create_input_spectral_information
from gnpy.core.elements import RamanFiber
from gnpy.core.parameters import SimParams
from gnpy.core.science_utils import Simulation
from gnpy.core.info import create_input_spectral_information, create_arbitrary_spectral_information, Pref
from gnpy.core.elements import Fiber, RamanFiber
from gnpy.tools.json_io import load_json
from gnpy.core.exceptions import NetworkTopologyError
from gnpy.core.science_utils import RamanSolver
from tests.test_parameters import MockSimParams, set_sim_params
TEST_DIR = Path(__file__).parent
def test_raman_fiber():
""" Test the accuracy of propagating the RamanFiber."""
# spectral information generation
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)
def test_fiber():
""" Test the accuracy of propagating the Fiber."""
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_science_utils_fiber_config.json'))
sim_params = SimParams(**load_json(TEST_DIR / 'data' / 'sim_params.json'))
Simulation.set_params(sim_params)
fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'raman_fiber_config.json'))
# fix grid 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)
# 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])
pref = Pref(p_span0=0, p_spani=0, p_span0_per_channel=list(signal), ref_carrier=None)
spectral_info_input = create_arbitrary_spectral_information(frequency=frequency, slot_width=slot_width,
signal=signal, baud_rate=baud_rate, roll_off=0.15,
ref_power=pref)
# propagation
spectral_info_out = fiber(spectral_info_input)
p_signal = [carrier.power.signal for carrier in spectral_info_out.carriers]
p_ase = [carrier.power.ase for carrier in spectral_info_out.carriers]
p_nli = [carrier.power.nli for carrier in spectral_info_out.carriers]
p_signal = spectral_info_out.signal
p_nli = spectral_info_out.nli
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)
def test_raman_fiber(set_sim_params):
""" 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)
MockSimParams.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_ase, expected_results['ase'], rtol=1e-3)
assert_allclose(p_nli, expected_results['nli'], rtol=1e-3)
@pytest.mark.parametrize("loss, position, errmsg", (
(0.5, -2, f"Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded."),
(0.5, 81, f"Lumped loss positions must be between 0 and the fiber length (80.0 km), boundaries excluded.")))
def test_fiber_lumped_losses(loss, position, errmsg, set_sim_params):
""" Check on Fiber with lumped losses."""
MockSimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
fiber_dict = load_json(TEST_DIR / 'data' / 'test_lumped_losses_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
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)
MockSimParams.set_params(load_json(TEST_DIR / 'data' / 'sim_params.json'))
sim_params = MockSimParams.get()
fiber = Fiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_fiber_config.json'))
raman_fiber = RamanFiber(**load_json(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber_config.json'))
# propagation
# without Raman pumps
expected_power_profile = load(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_pumps.npy')
stimulated_raman_scattering = RamanSolver.calculate_stimulated_raman_scattering(
spectral_info_input, fiber)
power_profile = stimulated_raman_scattering.power_profile
assert_allclose(power_profile, expected_power_profile, rtol=1e-3)
# with Raman pumps
expected_power_profile = load(TEST_DIR / 'data' / 'test_lumped_losses_raman_fiber.npy')
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 = load(TEST_DIR / 'data' / 'test_lumped_losses_fiber_no_raman.npy')
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)