mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-30 17:47:50 +00:00 
			
		
		
		
	fixed merge conflict
This commit is contained in:
		| @@ -205,7 +205,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -221,7 +223,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -237,7 +241,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -253,7 +259,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -269,7 +277,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -285,7 +295,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -301,7 +313,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -317,7 +331,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -333,7 +349,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -349,7 +367,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -365,7 +385,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -381,7 +403,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -397,7 +421,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -413,7 +439,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -429,7 +457,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -445,7 +475,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							| @@ -31,6 +31,7 @@ from gnpy.core.equipment import load_equipment | |||||||
| from gnpy.core.elements import Transceiver, Roadm, Edfa, Fused | from gnpy.core.elements import Transceiver, Roadm, Edfa, Fused | ||||||
| from gnpy.core.utils import db2lin, lin2db | from gnpy.core.utils import db2lin, lin2db | ||||||
| from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power | from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power | ||||||
|  | from gnpy.core.request import Path_request, Result_element, compute_constrained_path, propagate | ||||||
| from copy import copy, deepcopy | from copy import copy, deepcopy | ||||||
| from numpy import log10 | from numpy import log10 | ||||||
|  |  | ||||||
| @@ -46,125 +47,34 @@ parser.add_argument('-v', '--verbose', action='count') | |||||||
| parser.add_argument('-o', '--output', default=None) | parser.add_argument('-o', '--output', default=None) | ||||||
|  |  | ||||||
|  |  | ||||||
| class Path_request(): | def requests_from_json(json_data,equipment): | ||||||
|     def __init__(self,jsondata,tspjsondata): |  | ||||||
|         self.request_id = jsondata['request-id'] |  | ||||||
|         self.source = jsondata['src-tp-id'] |  | ||||||
|         self.destination = jsondata['dst-tp-id'] |  | ||||||
|         # retrieving baudrate out of transponder type and mode (format) |  | ||||||
|         self.tsp = jsondata['path-constraints']['te-bandwidth']['trx_type'] |  | ||||||
|         self.tsp_mode = jsondata['path-constraints']['te-bandwidth']['trx_mode'] |  | ||||||
|         # for debug |  | ||||||
|         # print(tsp) |  | ||||||
|         try: |  | ||||||
|             baudrate = next(m['baudrate']  |  | ||||||
|                 for t in  tspjsondata if t['type_variety'] == self.tsp |  | ||||||
|                 for m in t['mode']  if  m['format'] == self.tsp_mode) |  | ||||||
|         except StopIteration: |  | ||||||
|             msg = f'could not find tsp : {self.tsp} with mode: {self.tsp_mode} in eqpt library' |  | ||||||
|             logger.critical(msg) |  | ||||||
|             raise ValueError(msg) |  | ||||||
|         self.baudrate = baudrate |  | ||||||
|  |  | ||||||
|         nodes_list = jsondata['optimizations']['explicit-route-include-objects'] |  | ||||||
|         self.nodes_list = [n['unnumbered-hop']['node-id'] for n in nodes_list] |  | ||||||
|         # create a list for individual loose capability for each node ...  |  | ||||||
|         # even if convert_service_sheet fills it with the same value |  | ||||||
|         self.loose_list = [n['unnumbered-hop']['hop-type'] for n in nodes_list] |  | ||||||
|  |  | ||||||
|         self.spacing = jsondata['path-constraints']['te-bandwidth']['spacing'] |  | ||||||
|         self.power = jsondata['path-constraints']['te-bandwidth']['output-power'] |  | ||||||
|         self.nb_channel = jsondata['path-constraints']['te-bandwidth']['max-nb-of-channel'] |  | ||||||
|  |  | ||||||
|     def __str__(self): |  | ||||||
|         return '\n\t'.join([  f'{type(self).__name__} {self.request_id}', |  | ||||||
|                             f'source:       {self.source}', |  | ||||||
|                             f'destination:  {self.destination}']) |  | ||||||
|     def __repr__(self): |  | ||||||
|         return '\n\t'.join([  f'{type(self).__name__} {self.request_id}', |  | ||||||
|                             f'source:       {self.source}', |  | ||||||
|                             f'destination:  {self.destination}', |  | ||||||
|                             f'trx type:     {self.tsp}', |  | ||||||
|                             f'baudrate:     {self.baudrate}', |  | ||||||
|                             f'spacing:      {self.spacing}', |  | ||||||
|                             f'power:        {self.power}' |  | ||||||
|                             '\n']) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Result_element(Element): |  | ||||||
|     def __init__(self,path_request,computed_path): |  | ||||||
|         self.path_id = int(path_request.request_id) |  | ||||||
|         self.path_request = path_request |  | ||||||
|         self.computed_path = computed_path |  | ||||||
|         hop_type = [] |  | ||||||
|         for e in computed_path : |  | ||||||
|             if isinstance(e, Transceiver) :  |  | ||||||
|                 hop_type.append(' - '.join([path_request.tsp,path_request.tsp_mode]))  |  | ||||||
|             else: |  | ||||||
|                 hop_type.append('not recorded') |  | ||||||
|         self.hop_type = hop_type |  | ||||||
|     uid = property(lambda self: repr(self)) |  | ||||||
|     @property |  | ||||||
|     def pathresult(self): |  | ||||||
|         return { |  | ||||||
|                'path-id': self.path_id, |  | ||||||
|                'path-properties':{ |  | ||||||
|                    'path-metric': [ |  | ||||||
|                        { |  | ||||||
|                        'metric-type': 'SNR@bandwidth', |  | ||||||
|                        'accumulative-value': round(mean(self.computed_path[-1].snr),2) |  | ||||||
|                        }, |  | ||||||
|                        { |  | ||||||
|                        'metric-type': 'SNR@0.1nm', |  | ||||||
|                        'accumulative-value': round(mean(self.computed_path[-1].snr+10*log10(self.path_request.baudrate/12.5)),2) |  | ||||||
|                        } |  | ||||||
|                     ], |  | ||||||
|                     'path-srlgs': { |  | ||||||
|                         'usage': 'not used yet', |  | ||||||
|                         'values': 'not used yet' |  | ||||||
|                     }, |  | ||||||
|                     'path-route-objects': [ |  | ||||||
|                         { |  | ||||||
|                         'path-route-object': { |  | ||||||
|                             'index': self.computed_path.index(n), |  | ||||||
|                             'unnumbered-hop': { |  | ||||||
|                                 'node-id': n.uid, |  | ||||||
|                                 'link-tp-id': n.uid, |  | ||||||
|                                 'hop-type': self.hop_type[self.computed_path.index(n)], |  | ||||||
|                                 'direction': 'not used' |  | ||||||
|                             }, |  | ||||||
|                             'label-hop': { |  | ||||||
|                                 'te-label': { |  | ||||||
|                                     'generic': 'not used yet', |  | ||||||
|                                     'direction': 'not used yet' |  | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
|                             } |  | ||||||
|                         } for n in self.computed_path |  | ||||||
|                         ] |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|                      |  | ||||||
|     @property |  | ||||||
|     def json(self): |  | ||||||
|         return self.pathresult  |  | ||||||
|  |  | ||||||
| def load_SI(filename): |  | ||||||
|     with open(filename) as f: |  | ||||||
|         json_data = loads(f.read()) |  | ||||||
|         return json_data['SI'][0] |  | ||||||
|  |  | ||||||
| def load_Transceiver(filename): |  | ||||||
|     with open(filename) as f: |  | ||||||
|         json_data = loads(f.read()) |  | ||||||
|         return json_data['Transceiver'] |  | ||||||
|  |  | ||||||
| def requests_from_json(json_data,eqpt_filename): |  | ||||||
|     requests_list = [] |     requests_list = [] | ||||||
|     tspjsondata = load_Transceiver(eqpt_filename) |     tsp_lib = equipment['Transceiver'] | ||||||
|  |  | ||||||
|     for req in json_data['path-request']: |     for req in json_data['path-request']: | ||||||
|         #print(f'{req}') |         #print(f'{req}') | ||||||
|         requests_list.append(Path_request(req,tspjsondata)) |         params = {} | ||||||
|  |         params['request_id'] = req['request-id'] | ||||||
|  |         params['source'] = req['src-tp-id'] | ||||||
|  |         params['destination'] = req['dst-tp-id'] | ||||||
|  |         params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type'] | ||||||
|  |         params['trx_mode'] = req['path-constraints']['te-bandwidth']['trx_mode'] | ||||||
|  |         params['frequency'] = tsp_lib[params['trx_type']].frequency | ||||||
|  |         try: | ||||||
|  |             extra_params =  next(m  | ||||||
|  |                 for m in tsp_lib[params['trx_type']].mode if  m['format'] == params['trx_mode']) | ||||||
|  |         except StopIteration : | ||||||
|  |             msg = f'could not find tsp : {params["trx_type"]} with mode: {params["trx_mode"]} in eqpt library' | ||||||
|  |             raise ValueError(msg) | ||||||
|  |         nd_list = req['optimizations']['explicit-route-include-objects'] | ||||||
|  |         params['nodes_list'] = [n['unnumbered-hop']['node-id'] for n in nd_list] | ||||||
|  |         params['loose_list'] = [n['unnumbered-hop']['hop-type'] for n in nd_list] | ||||||
|  |         params['spacing'] = req['path-constraints']['te-bandwidth']['spacing'] | ||||||
|  |         params['power'] = req['path-constraints']['te-bandwidth']['output-power'] | ||||||
|  |         params['nb_channel'] = req['path-constraints']['te-bandwidth']['max-nb-of-channel'] | ||||||
|  |  | ||||||
|  |         params.update(extra_params) | ||||||
|  |         requests_list.append(Path_request(**params)) | ||||||
|  |  | ||||||
|     return requests_list |     return requests_list | ||||||
|  |  | ||||||
| @@ -179,65 +89,22 @@ def load_requests(filename,eqpt_filename): | |||||||
|     return json_data |     return json_data | ||||||
|  |  | ||||||
| def compute_path(network, pathreqlist): | def compute_path(network, pathreqlist): | ||||||
|     # temporary : repeats calls from transmission_main_example |  | ||||||
|     # to be merged when ready |  | ||||||
|      |      | ||||||
|     path_res_list = [] |     path_res_list = [] | ||||||
|     trx = [n for n in network.nodes() if isinstance(n, Transceiver)] |  | ||||||
|     roadm = [n for n in network.nodes() if isinstance(n, Roadm)] |  | ||||||
|     edfa = [n for n in network.nodes() if isinstance(n, Edfa)] |  | ||||||
|     # TODO include also fused in the element check : too difficult because of direction |  | ||||||
|     # fused = [n for n in network.nodes() if isinstance(n, Fused)] |  | ||||||
|     sidata = load_SI(args.eqpt_filename) |  | ||||||
|     for pathreq in pathreqlist: |     for pathreq in pathreqlist: | ||||||
|         pathreq.nodes_list.append(pathreq.destination) |         pathreq.nodes_list.append(pathreq.destination) | ||||||
|         #we assume that the destination is a strict constraint |         #we assume that the destination is a strict constraint | ||||||
|         pathreq.loose_list.append('strict') |         pathreq.loose_list.append('strict') | ||||||
|         print(f'Computing path from {pathreq.source} to {pathreq.destination}') |         print(f'Computing path from {pathreq.source} to {pathreq.destination}') | ||||||
|         print(f'with explicit path: {pathreq.nodes_list}') |         print(f'with explicit path: {pathreq.nodes_list}') | ||||||
|  |         total_path = compute_constrained_path(network, pathreq) | ||||||
|         source = next(el for el in trx if el.uid == pathreq.source) |          | ||||||
|         # start the path with its source |  | ||||||
|         total_path = [source] |  | ||||||
|         for n in pathreq.nodes_list: |  | ||||||
|             # print(n) |  | ||||||
|             try : |  | ||||||
|                 node = next(el for el in trx if el.uid == n) |  | ||||||
|             except StopIteration: |  | ||||||
|                 try: |  | ||||||
|                     node = next(el for el in roadm if el.uid == f'roadm {n}') |  | ||||||
|                 except StopIteration: |  | ||||||
|                     try: |  | ||||||
|                         node = next(el for el in edfa  |  | ||||||
|                             if el.uid.startswith(f'egress edfa in {n}')) |  | ||||||
|                     except StopIteration: |  | ||||||
|                         msg = f'could not find node : {n} in network topology: \ |  | ||||||
|                             not a trx, roadm, edfa or fused element' |  | ||||||
|                         logger.critical(msg) |  | ||||||
|                         raise ValueError(msg) |  | ||||||
|             # extend path list without repeating source -> skip first element in the list |  | ||||||
|             try: |  | ||||||
|                 total_path.extend(dijkstra_path(network, source, node)[1:]) |  | ||||||
|                 source = node |  | ||||||
|             except NetworkXNoPath: |  | ||||||
|             	# for debug |  | ||||||
|                 # print(pathreq.loose_list) |  | ||||||
|                 # print(pathreq.nodes_list.index(n)) |  | ||||||
|                 if pathreq.loose_list[pathreq.nodes_list.index(n)] == 'loose': |  | ||||||
|                     print(f'could not find a path from {source.uid} to loose node : {n} in network topology') |  | ||||||
|                     print(f'node  {n} is skipped') |  | ||||||
|                 else: |  | ||||||
|                     msg = f'could not find a path from {source.uid} to node : {n} in network topology' |  | ||||||
|                     logger.critical(msg) |  | ||||||
|                     raise ValueError(msg) |  | ||||||
|         # for debug |         # for debug | ||||||
|         # print(f'{pathreq.baudrate}   {pathreq.power}   {pathreq.spacing}   {pathreq.nb_channel}') |         # print(f'{pathreq.baudrate}   {pathreq.power}   {pathreq.spacing}   {pathreq.nb_channel}') | ||||||
|         si = create_input_spectral_information( |          | ||||||
|             sidata['f_min'], sidata['roll_off'], |         total_path = propagate(total_path,pathreq,equipment, show=False) | ||||||
|             pathreq.baudrate, pathreq.power, pathreq.spacing, pathreq.nb_channel) |  | ||||||
|         for el in total_path: |  | ||||||
|             si = el(si) |  | ||||||
|             # print(el) |  | ||||||
|         # we record the last tranceiver object in order to have th whole  |         # we record the last tranceiver object in order to have th whole  | ||||||
|         # information about spectrum. Important Note: since transceivers  |         # information about spectrum. Important Note: since transceivers  | ||||||
|         # attached to roadms are actually logical elements to simulate |         # attached to roadms are actually logical elements to simulate | ||||||
| @@ -246,7 +113,6 @@ def compute_path(network, pathreqlist): | |||||||
|         # we use deepcopy: to ensure each propagation is recorded and not  |         # we use deepcopy: to ensure each propagation is recorded and not  | ||||||
|         # overwritten  |         # overwritten  | ||||||
|          |          | ||||||
|         # path_res_list.append(deepcopy(destination)) |  | ||||||
|         path_res_list.append(deepcopy(total_path)) |         path_res_list.append(deepcopy(total_path)) | ||||||
|     return path_res_list |     return path_res_list | ||||||
|  |  | ||||||
| @@ -267,7 +133,7 @@ if __name__ == '__main__': | |||||||
|     equipment = load_equipment(args.eqpt_filename) |     equipment = load_equipment(args.eqpt_filename) | ||||||
|     network = load_network(args.network_filename,equipment) |     network = load_network(args.network_filename,equipment) | ||||||
|     build_network(network, equipment=equipment) |     build_network(network, equipment=equipment) | ||||||
|     pths = requests_from_json(data, args.eqpt_filename) |     pths = requests_from_json(data, equipment) | ||||||
|     print(pths) |     print(pths) | ||||||
|     test = compute_path(network,pths) |     test = compute_path(network,pths) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,7 +20,8 @@ from networkx import (draw_networkx_nodes, draw_networkx_edges, | |||||||
|  |  | ||||||
| from gnpy.core import load_network, build_network | from gnpy.core import load_network, build_network | ||||||
| from gnpy.core.elements import Transceiver, Fiber, Edfa, Roadm | from gnpy.core.elements import Transceiver, Fiber, Edfa, Roadm | ||||||
| from gnpy.core.info import SpectralInformation, Channel, Power | from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power | ||||||
|  | from gnpy.core.request import Path_request, RequestParams, compute_constrained_path, propagate | ||||||
|  |  | ||||||
| logger = getLogger(__name__) | logger = getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -48,26 +49,19 @@ def plot_results(network, path, source, sink): | |||||||
|     show() |     show() | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(network, equipment, source, sink): | def main(network, equipment, source, sink, req = None): | ||||||
|     build_network(network, equipment=equipment) |     build_network(network, equipment=equipment) | ||||||
|     path = dijkstra_path(network, source, sink) |      | ||||||
|  |     path = compute_constrained_path(network,req) | ||||||
|     spans = [s.length for s in path if isinstance(s, Fiber)] |     spans = [s.length for s in path if isinstance(s, Fiber)] | ||||||
|     print(f'\nThere are {len(spans)} fiber spans over {sum(spans):.0f}m between {source.uid} and {sink.uid}') |     print(f'\nThere are {len(spans)} fiber spans over {sum(spans):.0f}m between {source.uid} and {sink.uid}') | ||||||
|     print(f'\nNow propagating between {source.uid} and {sink.uid}:') |     print(f'\nNow propagating between {source.uid} and {sink.uid}:') | ||||||
|  |      | ||||||
|     for p in range(0, 1): #change range to sweep results across several powers in dBm |     for p in range(0, 1): #change range to sweep results across several powers in dBm | ||||||
|         p=db2lin(p)*1e-3 |         req.power = db2lin(p)*1e-3 | ||||||
|         spacing = 0.05 # THz |         print(f'\nPropagating with input power = {lin2db(req.power*1e3):.2f}dBm :') | ||||||
|         si = SpectralInformation() # SI units: W, Hz |         propagate(path,req,equipment,show=True) | ||||||
|         si = si.update(carriers=[ |         print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f}dBm :') | ||||||
|             Channel(f, (191.3 + spacing * f) * 1e12, 32e9, 0.15, Power(p, 0, 0)) |  | ||||||
|             for f in range(1,97) |  | ||||||
|         ]) |  | ||||||
|         print(f'\nPorpagating with input power = {lin2db(p*1e3):.2f}dBm :') |  | ||||||
|         for el in path: |  | ||||||
|             si = el(si) |  | ||||||
|             print(el) #remove this line when sweeping across several powers |  | ||||||
|         print(f'\nTransmission result for input power = {lin2db(p*1e3):.2f}dBm :') |  | ||||||
|         print(sink) |         print(sink) | ||||||
|  |  | ||||||
|     return path |     return path | ||||||
| @@ -91,7 +85,7 @@ if __name__ == '__main__': | |||||||
|     # logger.info(equipment) |     # logger.info(equipment) | ||||||
|  |  | ||||||
|     network = load_network(args.filename, equipment) |     network = load_network(args.filename, equipment) | ||||||
|     print(network) |     # print(network) | ||||||
|  |  | ||||||
|     transceivers = {n.uid: n for n in network.nodes() if isinstance(n, Transceiver)} |     transceivers = {n.uid: n for n in network.nodes() if isinstance(n, Transceiver)} | ||||||
|      |      | ||||||
| @@ -135,7 +129,29 @@ if __name__ == '__main__': | |||||||
|  |  | ||||||
|     logger.info(f'source = {args.source!r}') |     logger.info(f'source = {args.source!r}') | ||||||
|     logger.info(f'sink = {args.sink!r}') |     logger.info(f'sink = {args.sink!r}') | ||||||
|     path = main(network, equipment, source, sink) |  | ||||||
|  |     params = {} | ||||||
|  |     params['request_id'] = 0 | ||||||
|  |     params['source'] = source.uid | ||||||
|  |     params['destination'] = sink.uid | ||||||
|  |     params['trx_type'] = 'vendorA_trx-type1' | ||||||
|  |     params['trx_mode'] = 'PS_SP64_1' | ||||||
|  |     params['nodes_list'] = [sink.uid] | ||||||
|  |     params['loose_list'] = ['strict'] | ||||||
|  |     params['spacing'] = 50e9 | ||||||
|  |     params['power'] = 0 | ||||||
|  |     params['nb_channel'] = 97 | ||||||
|  |     params['frequency'] = equipment['Transceiver'][params['trx_type']].frequency | ||||||
|  |     try: | ||||||
|  |         extra_params = next(m  | ||||||
|  |             for m in equipment['Transceiver'][params['trx_type']].mode  | ||||||
|  |                 if  m['format'] == params['trx_mode']) | ||||||
|  |     except StopIteration : | ||||||
|  |         msg = f'could not find tsp : {params} with mode: {params} in eqpt library' | ||||||
|  |         raise ValueError(msg) | ||||||
|  |     params.update(extra_params) | ||||||
|  |     req = Path_request(**params) | ||||||
|  |     path = main(network, equipment, source, sink,req) | ||||||
|  |  | ||||||
|     if args.plot: |     if args.plot: | ||||||
|         plot_results(network, path, source, sink) |         plot_results(network, path, source, sink) | ||||||
|   | |||||||
| @@ -156,7 +156,9 @@ def convert_file(input_filename, filter_region=[]): | |||||||
|               'type_variety': x.east_fiber, |               'type_variety': x.east_fiber, | ||||||
|               'params': {'length':   round(x.east_distance, 3), |               'params': {'length':   round(x.east_distance, 3), | ||||||
|                          'length_units':    x.distance_units, |                          'length_units':    x.distance_units, | ||||||
|                          'loss_coef': x.east_lineic} |                          'loss_coef': x.east_lineic, | ||||||
|  |                          'connector_loss_in':x.east_con_in, | ||||||
|  |                          'connector_loss_out':x.east_con_out} | ||||||
|             } |             } | ||||||
|               for x in links] + |               for x in links] + | ||||||
|             [{'uid': f'fiber ({x.to_city} → {x.from_city})-{x.west_cable}', |             [{'uid': f'fiber ({x.to_city} → {x.from_city})-{x.west_cable}', | ||||||
| @@ -166,7 +168,9 @@ def convert_file(input_filename, filter_region=[]): | |||||||
|               'type_variety': x.west_fiber, |               'type_variety': x.west_fiber, | ||||||
|               'params': {'length':   round(x.west_distance, 3), |               'params': {'length':   round(x.west_distance, 3), | ||||||
|                          'length_units':    x.distance_units, |                          'length_units':    x.distance_units, | ||||||
|                          'loss_coef': x.west_lineic} |                          'loss_coef': x.west_lineic, | ||||||
|  |                          'connector_loss_in':x.west_con_in, | ||||||
|  |                          'connector_loss_out':x.west_con_out} | ||||||
|             } # missing ILA construction  |             } # missing ILA construction  | ||||||
|               for x in links] + |               for x in links] + | ||||||
|             [{'uid': f'egress edfa in {e.from_city} to {e.to_city}', |             [{'uid': f'egress edfa in {e.from_city} to {e.to_city}', | ||||||
|   | |||||||
| @@ -143,17 +143,23 @@ class Fused(Node): | |||||||
|         carriers = tuple(self.propagate(*spectral_info.carriers)) |         carriers = tuple(self.propagate(*spectral_info.carriers)) | ||||||
|         return spectral_info.update(carriers=carriers) |         return spectral_info.update(carriers=carriers) | ||||||
|  |  | ||||||
| FiberParams = namedtuple('FiberParams', 'type_variety length loss_coef length_units dispersion gamma') | FiberParams = namedtuple('FiberParams', 'type_variety length loss_coef length_units connector_loss_in connector_loss_out dispersion gamma') | ||||||
|  |  | ||||||
| class Fiber(Node): | class Fiber(Node): | ||||||
|     def __init__(self, *args, params=None, **kwargs): |     def __init__(self, *args, params=None, **kwargs): | ||||||
|         if params is None: |         if params is None: | ||||||
|             params = {} |             params = {} | ||||||
|  |         if 'connector_loss_in' not in params : | ||||||
|  |             # test added to ensure backward compatibility in case loss was not in the json | ||||||
|  |             params['connector_loss_in'] = 0.0 | ||||||
|  |             params['connector_loss_out'] = 0.0 | ||||||
|         super().__init__(*args, params=FiberParams(**params), **kwargs) |         super().__init__(*args, params=FiberParams(**params), **kwargs) | ||||||
|         self.type_variety = self.params.type_variety |         self.type_variety = self.params.type_variety | ||||||
|         self.length = self.params.length * UNITS[self.params.length_units] # in m |         self.length = self.params.length * UNITS[self.params.length_units] # in m | ||||||
|         self.loss_coef = self.params.loss_coef * 1e-3 # lineic loss dB/m |         self.loss_coef = self.params.loss_coef * 1e-3 # lineic loss dB/m | ||||||
|         self.lin_loss_coef = self.params.loss_coef / (20 * log10(exp(1))) |         self.lin_loss_coef = self.params.loss_coef / (20 * log10(exp(1))) | ||||||
|  |         self.connector_loss_in = self.params.connector_loss_in | ||||||
|  |         self.connector_loss_out = self.params.connector_loss_out | ||||||
|         self.dispersion = self.params.dispersion  # s/m/m |         self.dispersion = self.params.dispersion  # s/m/m | ||||||
|         self.gamma = self.params.gamma # 1/W/m        |         self.gamma = self.params.gamma # 1/W/m        | ||||||
|         # TODO|jla: discuss factor 2 in the linear lineic attenuation |         # TODO|jla: discuss factor 2 in the linear lineic attenuation | ||||||
| @@ -166,12 +172,13 @@ class Fiber(Node): | |||||||
|         return '\n'.join([f'{type(self).__name__} {self.uid}', |         return '\n'.join([f'{type(self).__name__} {self.uid}', | ||||||
|                           f'  type_variety: {self.type_variety}', |                           f'  type_variety: {self.type_variety}', | ||||||
|                           f'  length (m):   {self.length:.2f}', |                           f'  length (m):   {self.length:.2f}', | ||||||
|                           f'  loss (dB):    {self.loss:.2f}']) |                           f'  loss (dB):    {self.loss:.2f}', | ||||||
|  |                           f'  (includes conn loss (dB) in: {self.connector_loss_in:.2f} out: {self.connector_loss_out:.2f})']) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def loss(self): |     def loss(self): | ||||||
|         # dB loss: useful for polymorphism (roadm, fiber, att) |         # dB loss: useful for polymorphism (roadm, fiber, att) | ||||||
|         return self.loss_coef * self.length |         return self.loss_coef * self.length + self.connector_loss_in + self.connector_loss_out | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def passive(self): |     def passive(self): | ||||||
| @@ -251,12 +258,29 @@ class Fiber(Node): | |||||||
|         return carrier_nli |         return carrier_nli | ||||||
|  |  | ||||||
|     def propagate(self, *carriers): |     def propagate(self, *carriers): | ||||||
|  |  | ||||||
|  |         # apply connector_att_in on all carriers before computing gn analytics  premiere partie pas bonne | ||||||
|  |         attenuation = db2lin(self.connector_loss_in) | ||||||
|  |  | ||||||
|  |         chan = [] | ||||||
|  |         for carrier in carriers: | ||||||
|  |             pwr = carrier.power | ||||||
|  |             pwr = pwr._replace(signal=pwr.signal/attenuation, | ||||||
|  |                                nonlinear_interference=pwr.nli/attenuation, | ||||||
|  |                                amplified_spontaneous_emission=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.connector_loss_out) | ||||||
|         for carrier in carriers: |         for carrier in carriers: | ||||||
|             pwr = carrier.power |             pwr = carrier.power | ||||||
|             carrier_nli = self._gn_analytic(carrier, *carriers) |             carrier_nli = self._gn_analytic(carrier, *carriers) | ||||||
|             pwr = pwr._replace(signal=pwr.signal/self.lin_attenuation, |             pwr = pwr._replace(signal=pwr.signal/self.lin_attenuation/attenuation, | ||||||
|                                nonlinear_interference=(pwr.nli+carrier_nli)/self.lin_attenuation, |                                nonlinear_interference=(pwr.nli+carrier_nli)/self.lin_attenuation/attenuation, | ||||||
|                                amplified_spontaneous_emission=pwr.ase/self.lin_attenuation) |                                amplified_spontaneous_emission=pwr.ase/self.lin_attenuation/attenuation) | ||||||
|             yield carrier._replace(power=pwr) |             yield carrier._replace(power=pwr) | ||||||
|  |  | ||||||
|     def __call__(self, spectral_info): |     def __call__(self, spectral_info): | ||||||
|   | |||||||
| @@ -11,6 +11,8 @@ This module contains classes for modelling SpectralInformation. | |||||||
| from collections import namedtuple | from collections import namedtuple | ||||||
| from numpy import array | from numpy import array | ||||||
| from gnpy.core.utils import lin2db | from gnpy.core.utils import lin2db | ||||||
|  | from json import loads | ||||||
|  | from gnpy.core.utils import load_json | ||||||
|  |  | ||||||
| class ConvenienceAccess: | class ConvenienceAccess: | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										183
									
								
								gnpy/core/request.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								gnpy/core/request.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | # TelecomInfraProject/gnpy/examples | ||||||
|  | # Module name : path_requests_run.py | ||||||
|  | # Version :  | ||||||
|  | # License : BSD 3-Clause Licence | ||||||
|  | # Copyright (c) 2018, Telecom Infra Project | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | @author: esther.lerouzic | ||||||
|  | @author: jeanluc-auge | ||||||
|  | read json request file in accordance with: | ||||||
|  |     Yang model for requesting Path Computation | ||||||
|  |     draft-ietf-teas-yang-path-computation-01.txt.  | ||||||
|  | and returns path results in terms of path and feasibility | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | from sys import exit | ||||||
|  | from argparse import ArgumentParser | ||||||
|  | from pathlib import Path | ||||||
|  | from collections import namedtuple | ||||||
|  | from logging import getLogger, basicConfig, CRITICAL, DEBUG, INFO | ||||||
|  | from json import dumps, loads | ||||||
|  | from networkx import (draw_networkx_nodes, draw_networkx_edges, | ||||||
|  |                       draw_networkx_labels, dijkstra_path, NetworkXNoPath) | ||||||
|  | from numpy import mean | ||||||
|  | from examples.convert_service_sheet import convert_service_sheet, Request_element, Element | ||||||
|  | from gnpy.core.utils import load_json | ||||||
|  | from gnpy.core.network import load_network, build_network | ||||||
|  | from gnpy.core.equipment import load_equipment | ||||||
|  | from gnpy.core.elements import Transceiver, Roadm, Edfa, Fused | ||||||
|  | from gnpy.core.utils import db2lin, lin2db | ||||||
|  | from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power | ||||||
|  | from copy import copy, deepcopy | ||||||
|  | from numpy import log10 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | RequestParams = namedtuple('RequestParams','request_id source destination trx_type'+ | ||||||
|  | ' trx_mode nodes_list loose_list spacing power nb_channel frequency format baudrate OSNR bit_rate') | ||||||
|  |  | ||||||
|  | class Path_request: | ||||||
|  |     def __init__(self, *args, **params): | ||||||
|  |         params = RequestParams(**params) | ||||||
|  |         self.request_id = params.request_id | ||||||
|  |         self.source     = params.source | ||||||
|  |         self.destination = params.destination | ||||||
|  |         self.tsp        = params.trx_type | ||||||
|  |         self.tsp_mode   = params.trx_mode | ||||||
|  |         self.baudrate   = params.baudrate | ||||||
|  |         self.nodes_list = params.nodes_list | ||||||
|  |         self.loose_list = params.loose_list | ||||||
|  |         self.spacing    = params.spacing | ||||||
|  |         self.power      = params.power | ||||||
|  |         self.nb_channel = params.nb_channel | ||||||
|  |         self.frequency  = params.frequency | ||||||
|  |         self.format     = params.format | ||||||
|  |         self.OSNR       = params.OSNR | ||||||
|  |         self.bit_rate   = params.bit_rate | ||||||
|  |          | ||||||
|  |  | ||||||
|  |     def __str__(self): | ||||||
|  |         return '\n\t'.join([  f'{type(self).__name__} {self.request_id}', | ||||||
|  |                             f'source:       {self.source}', | ||||||
|  |                             f'destination:  {self.destination}']) | ||||||
|  |     def __repr__(self): | ||||||
|  |         return '\n\t'.join([  f'{type(self).__name__} {self.request_id}', | ||||||
|  |                             f'source:       {self.source}', | ||||||
|  |                             f'destination:  {self.destination}', | ||||||
|  |                             f'trx type:     {self.tsp}', | ||||||
|  |                             f'baudrate:     {self.baudrate}', | ||||||
|  |                             f'spacing:      {self.spacing}', | ||||||
|  |                             f'power:        {self.power}' | ||||||
|  |                             '\n']) | ||||||
|  |  | ||||||
|  | class Result_element(Element): | ||||||
|  |     def __init__(self,path_request,computed_path): | ||||||
|  |         self.path_id = int(path_request.request_id) | ||||||
|  |         self.path_request = path_request | ||||||
|  |         self.computed_path = computed_path | ||||||
|  |         hop_type = [] | ||||||
|  |         for e in computed_path : | ||||||
|  |             if isinstance(e, Transceiver) :  | ||||||
|  |                 hop_type.append(' - '.join([path_request.tsp,path_request.tsp_mode]))  | ||||||
|  |             else: | ||||||
|  |                 hop_type.append('not recorded') | ||||||
|  |         self.hop_type = hop_type | ||||||
|  |     uid = property(lambda self: repr(self)) | ||||||
|  |     @property | ||||||
|  |     def pathresult(self): | ||||||
|  |         return { | ||||||
|  |                'path-id': self.path_id, | ||||||
|  |                'path-properties':{ | ||||||
|  |                    'path-metric': [ | ||||||
|  |                        { | ||||||
|  |                        'metric-type': 'SNR@bandwidth', | ||||||
|  |                        'accumulative-value': round(mean(self.computed_path[-1].snr),2) | ||||||
|  |                        }, | ||||||
|  |                        { | ||||||
|  |                        'metric-type': 'SNR@0.1nm', | ||||||
|  |                        'accumulative-value': round(mean(self.computed_path[-1].snr+10*log10(self.path_request.baudrate/12.5)),2) | ||||||
|  |                        } | ||||||
|  |                     ], | ||||||
|  |                     'path-srlgs': { | ||||||
|  |                         'usage': 'not used yet', | ||||||
|  |                         'values': 'not used yet' | ||||||
|  |                     }, | ||||||
|  |                     'path-route-objects': [ | ||||||
|  |                         { | ||||||
|  |                         'path-route-object': { | ||||||
|  |                             'index': self.computed_path.index(n), | ||||||
|  |                             'unnumbered-hop': { | ||||||
|  |                                 'node-id': n.uid, | ||||||
|  |                                 'link-tp-id': n.uid, | ||||||
|  |                                 'hop-type': self.hop_type[self.computed_path.index(n)], | ||||||
|  |                                 'direction': 'not used' | ||||||
|  |                             }, | ||||||
|  |                             'label-hop': { | ||||||
|  |                                 'te-label': { | ||||||
|  |                                     'generic': 'not used yet', | ||||||
|  |                                     'direction': 'not used yet' | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                         } for n in self.computed_path | ||||||
|  |                         ] | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |                      | ||||||
|  |     @property | ||||||
|  |     def json(self): | ||||||
|  |         return self.pathresult  | ||||||
|  |  | ||||||
|  | def compute_constrained_path(network, req): | ||||||
|  |     trx = [n for n in network.nodes() if isinstance(n, Transceiver)] | ||||||
|  |     roadm = [n for n in network.nodes() if isinstance(n, Roadm)] | ||||||
|  |     edfa = [n for n in network.nodes() if isinstance(n, Edfa)] | ||||||
|  |  | ||||||
|  |     source = next(el for el in trx if el.uid == req.source) | ||||||
|  |     # start the path with its source | ||||||
|  |     total_path = [source] | ||||||
|  |     for n in req.nodes_list: | ||||||
|  |         # print(n) | ||||||
|  |         try : | ||||||
|  |             node = next(el for el in trx if el.uid == n) | ||||||
|  |         except StopIteration: | ||||||
|  |             try: | ||||||
|  |                 node = next(el for el in roadm if el.uid == f'roadm {n}') | ||||||
|  |             except StopIteration: | ||||||
|  |                 try: | ||||||
|  |                     node = next(el for el in edfa  | ||||||
|  |                         if el.uid.startswith(f'egress edfa in {n}')) | ||||||
|  |                 except StopIteration: | ||||||
|  |                     msg = f'could not find node : {n} in network topology: \ | ||||||
|  |                         not a trx, roadm, edfa or fused element' | ||||||
|  |                     logger.critical(msg) | ||||||
|  |                     raise ValueError(msg) | ||||||
|  |         # extend path list without repeating source -> skip first element in the list | ||||||
|  |         try: | ||||||
|  |             total_path.extend(dijkstra_path(network, source, node)[1:]) | ||||||
|  |             source = node | ||||||
|  |         except NetworkXNoPath: | ||||||
|  |             # for debug | ||||||
|  |             # print(req.loose_list) | ||||||
|  |             # print(req.nodes_list.index(n)) | ||||||
|  |             if req.loose_list[req.nodes_list.index(n)] == 'loose': | ||||||
|  |                 print(f'could not find a path from {source.uid} to loose node : {n} in network topology') | ||||||
|  |                 print(f'node  {n} is skipped') | ||||||
|  |             else: | ||||||
|  |                 msg = f'could not find a path from {source.uid} to node : {n} in network topology' | ||||||
|  |                 logger.critical(msg) | ||||||
|  |                 raise ValueError(msg) | ||||||
|  |     return total_path  | ||||||
|  |  | ||||||
|  | def propagate(path,req,equipment, show=False): | ||||||
|  |     default_si_data = equipment['SI']['default'] | ||||||
|  |     si = create_input_spectral_information( | ||||||
|  |         req.frequency['min'], default_si_data.roll_off, | ||||||
|  |         req.baudrate, req.power, req.spacing, req.nb_channel) | ||||||
|  |     for el in path: | ||||||
|  |         si = el(si) | ||||||
|  |         if show : | ||||||
|  |             print(el) | ||||||
|  |     return path     | ||||||
							
								
								
									
										261
									
								
								tests/LinkforTest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								tests/LinkforTest.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,261 @@ | |||||||
|  | { | ||||||
|  |   "elements": [ | ||||||
|  |     { | ||||||
|  |       "uid": "trx A", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "city": "A", | ||||||
|  |           "region": "", | ||||||
|  |           "latitude": 0, | ||||||
|  |           "longitude": 0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Transceiver" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "trx B", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "city": "B", | ||||||
|  |           "region": "", | ||||||
|  |           "latitude": 0, | ||||||
|  |           "longitude": 0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Transceiver" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "trx F", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "city": "F", | ||||||
|  |           "region": "", | ||||||
|  |           "latitude": 0, | ||||||
|  |           "longitude": 0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Transceiver" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "fiber (A \u2192 B)-", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "latitude": 0.0, | ||||||
|  |           "longitude": 0.0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Fiber", | ||||||
|  |       "type_variety": "SSMF", | ||||||
|  |       "params": { | ||||||
|  |         "length": 80.0, | ||||||
|  |         "length_units": "km", | ||||||
|  |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 1.00, | ||||||
|  |         "connector_loss_out": 1.00 | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "fiber (B \u2192 C)-", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "latitude": 0.0, | ||||||
|  |           "longitude": 0.0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Fiber", | ||||||
|  |       "type_variety": "SSMF", | ||||||
|  |       "params": { | ||||||
|  |         "length": 80.0, | ||||||
|  |         "length_units": "km", | ||||||
|  |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 1.00, | ||||||
|  |         "connector_loss_out": 1.00 | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "fiber (C \u2192 D)-", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "latitude": 0.0, | ||||||
|  |           "longitude": 0.0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Fiber", | ||||||
|  |       "type_variety": "SSMF", | ||||||
|  |       "params": { | ||||||
|  |         "length": 80.0, | ||||||
|  |         "length_units": "km", | ||||||
|  |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 1.00, | ||||||
|  |         "connector_loss_out": 1.00 | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "fiber (D \u2192 E)-", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "latitude": 0.0, | ||||||
|  |           "longitude": 0.0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Fiber", | ||||||
|  |       "type_variety": "SSMF", | ||||||
|  |       "params": { | ||||||
|  |         "length": 80.0, | ||||||
|  |         "length_units": "km", | ||||||
|  |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 1.00, | ||||||
|  |         "connector_loss_out": 1.00 | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "uid": "fiber (E \u2192 F)-", | ||||||
|  |       "metadata": { | ||||||
|  |         "location": { | ||||||
|  |           "latitude": 0.0, | ||||||
|  |           "longitude": 0.0 | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "type": "Fiber", | ||||||
|  |       "type_variety": "SSMF", | ||||||
|  |       "params": { | ||||||
|  |         "length": 80.0, | ||||||
|  |         "length_units": "km", | ||||||
|  |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 1.00, | ||||||
|  |         "connector_loss_out": 1.00 | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |         { | ||||||
|  |             "uid": "Edfa1", | ||||||
|  |             "type": "Edfa", | ||||||
|  |             "type_variety": "std_medium_gain",             | ||||||
|  |             "operational": { | ||||||
|  |                 "gain_target": 18, | ||||||
|  |                 "tilt_target": 0 | ||||||
|  |             }, | ||||||
|  |             "metadata": { | ||||||
|  |                 "location": { | ||||||
|  |                     "region": "", | ||||||
|  |                     "latitude": 2, | ||||||
|  |                     "longitude": 0 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "uid": "Edfa2", | ||||||
|  |             "type": "Edfa", | ||||||
|  |             "type_variety": "std_medium_gain",             | ||||||
|  |             "operational": { | ||||||
|  |                 "gain_target": 18, | ||||||
|  |                 "tilt_target": 0 | ||||||
|  |             }, | ||||||
|  |             "metadata": { | ||||||
|  |                 "location": { | ||||||
|  |                     "region": "", | ||||||
|  |                     "latitude": 2, | ||||||
|  |                     "longitude": 0 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "uid": "Edfa3", | ||||||
|  |             "type": "Edfa", | ||||||
|  |             "type_variety": "std_medium_gain",             | ||||||
|  |             "operational": { | ||||||
|  |                 "gain_target": 18, | ||||||
|  |                 "tilt_target": 0 | ||||||
|  |             }, | ||||||
|  |             "metadata": { | ||||||
|  |                 "location": { | ||||||
|  |                     "region": "", | ||||||
|  |                     "latitude": 2, | ||||||
|  |                     "longitude": 0 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "uid": "Edfa4", | ||||||
|  |             "type": "Edfa", | ||||||
|  |             "type_variety": "std_medium_gain",             | ||||||
|  |             "operational": { | ||||||
|  |                 "gain_target": 18, | ||||||
|  |                 "tilt_target": 0 | ||||||
|  |             }, | ||||||
|  |             "metadata": { | ||||||
|  |                 "location": { | ||||||
|  |                     "region": "", | ||||||
|  |                     "latitude": 2, | ||||||
|  |                     "longitude": 0 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "uid": "Edfa5", | ||||||
|  |             "type": "Edfa", | ||||||
|  |             "type_variety": "std_medium_gain",             | ||||||
|  |             "operational": { | ||||||
|  |                 "gain_target": 18, | ||||||
|  |                 "tilt_target": 0 | ||||||
|  |             }, | ||||||
|  |             "metadata": { | ||||||
|  |                 "location": { | ||||||
|  |                     "region": "", | ||||||
|  |                     "latitude": 2, | ||||||
|  |                     "longitude": 0 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |   ], | ||||||
|  |   "connections": [ | ||||||
|  |     { | ||||||
|  |       "from_node": "fiber (A \u2192 B)-", | ||||||
|  |       "to_node": "Edfa1" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "Edfa1", | ||||||
|  |       "to_node": "fiber (B \u2192 C)-" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "fiber (B \u2192 C)-", | ||||||
|  |       "to_node": "Edfa2" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "Edfa2", | ||||||
|  |       "to_node": "fiber (C \u2192 D)-" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "fiber (C \u2192 D)-", | ||||||
|  |       "to_node": "Edfa3" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "Edfa3", | ||||||
|  |       "to_node": "fiber (D \u2192 E)-" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "fiber (D \u2192 E)-", | ||||||
|  |       "to_node": "Edfa4" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "Edfa4", | ||||||
|  |       "to_node": "fiber (E \u2192 F)-" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "fiber (E \u2192 F)-", | ||||||
|  |       "to_node": "Edfa5" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "Edfa5", | ||||||
|  |       "to_node": "trx F" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "trx A", | ||||||
|  |       "to_node": "fiber (A \u2192 B)-" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "from_node": "Edfa1", | ||||||
|  |       "to_node": "trx B" | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -181,7 +181,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -197,7 +199,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -213,7 +217,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -229,7 +235,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -245,7 +253,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -261,7 +271,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -277,7 +289,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -293,7 +307,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -309,7 +325,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -325,7 +343,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -341,7 +361,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -357,7 +379,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -373,7 +397,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -389,7 +415,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -405,7 +433,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -421,7 +451,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -253,7 +253,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -269,7 +271,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -285,7 +289,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -301,7 +307,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -317,7 +325,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -333,7 +343,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -349,7 +361,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -365,7 +379,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -381,7 +397,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 80.0, |         "length": 80.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -397,7 +415,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -413,7 +433,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -429,7 +451,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -445,7 +469,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -461,7 +487,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -477,7 +505,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -493,7 +523,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -509,7 +541,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -525,7 +559,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 80.0, |         "length": 80.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -253,7 +253,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -269,7 +271,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -285,7 +289,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -301,7 +307,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -317,7 +325,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -333,7 +343,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -349,7 +361,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -365,7 +379,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -381,7 +397,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 80.0, |         "length": 80.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -397,7 +415,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 20.0, |         "length": 20.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -413,7 +433,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 50.0, |         "length": 50.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -429,7 +451,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -445,7 +469,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 10.0, |         "length": 10.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -461,7 +487,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 60.0, |         "length": 60.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -477,7 +505,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 65.0, |         "length": 65.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -493,7 +523,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 40.0, |         "length": 40.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -509,7 +541,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 35.0, |         "length": 35.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -525,7 +559,9 @@ | |||||||
|       "params": { |       "params": { | ||||||
|         "length": 80.0, |         "length": 80.0, | ||||||
|         "length_units": "km", |         "length_units": "km", | ||||||
|         "loss_coef": 0.2 |         "loss_coef": 0.2, | ||||||
|  |         "connector_loss_in": 0.5, | ||||||
|  |         "connector_loss_out": 0.5 | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 James Powell
					James Powell