mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-30 01:32:21 +00:00 
			
		
		
		
	fixed merge conflict
This commit is contained in:
		| @@ -205,7 +205,9 @@ | ||||
|       "params": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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.utils import db2lin, lin2db | ||||
| 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 numpy import log10 | ||||
|  | ||||
| @@ -46,125 +47,34 @@ parser.add_argument('-v', '--verbose', action='count') | ||||
| parser.add_argument('-o', '--output', default=None) | ||||
|  | ||||
|  | ||||
| class Path_request(): | ||||
|     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): | ||||
| def requests_from_json(json_data,equipment): | ||||
|     requests_list = [] | ||||
|     tspjsondata = load_Transceiver(eqpt_filename) | ||||
|     tsp_lib = equipment['Transceiver'] | ||||
|  | ||||
|     for req in json_data['path-request']: | ||||
|         #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 | ||||
|  | ||||
| @@ -179,65 +89,22 @@ def load_requests(filename,eqpt_filename): | ||||
|     return json_data | ||||
|  | ||||
| def compute_path(network, pathreqlist): | ||||
|     # temporary : repeats calls from transmission_main_example | ||||
|     # to be merged when ready | ||||
|      | ||||
|     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: | ||||
|         pathreq.nodes_list.append(pathreq.destination) | ||||
|         #we assume that the destination is a strict constraint | ||||
|         pathreq.loose_list.append('strict') | ||||
|         print(f'Computing path from {pathreq.source} to {pathreq.destination}') | ||||
|         print(f'with explicit path: {pathreq.nodes_list}') | ||||
|  | ||||
|         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) | ||||
|         total_path = compute_constrained_path(network, pathreq) | ||||
|          | ||||
|         # for debug | ||||
|         # print(f'{pathreq.baudrate}   {pathreq.power}   {pathreq.spacing}   {pathreq.nb_channel}') | ||||
|         si = create_input_spectral_information( | ||||
|             sidata['f_min'], sidata['roll_off'], | ||||
|             pathreq.baudrate, pathreq.power, pathreq.spacing, pathreq.nb_channel) | ||||
|         for el in total_path: | ||||
|             si = el(si) | ||||
|             # print(el) | ||||
|          | ||||
|         total_path = propagate(total_path,pathreq,equipment, show=False) | ||||
|  | ||||
|         # we record the last tranceiver object in order to have th whole  | ||||
|         # information about spectrum. Important Note: since transceivers  | ||||
|         # 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  | ||||
|         # overwritten  | ||||
|          | ||||
|         # path_res_list.append(deepcopy(destination)) | ||||
|         path_res_list.append(deepcopy(total_path)) | ||||
|     return path_res_list | ||||
|  | ||||
| @@ -267,7 +133,7 @@ if __name__ == '__main__': | ||||
|     equipment = load_equipment(args.eqpt_filename) | ||||
|     network = load_network(args.network_filename,equipment) | ||||
|     build_network(network, equipment=equipment) | ||||
|     pths = requests_from_json(data, args.eqpt_filename) | ||||
|     pths = requests_from_json(data, equipment) | ||||
|     print(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.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__) | ||||
|  | ||||
| @@ -48,26 +49,19 @@ def plot_results(network, path, source, sink): | ||||
|     show() | ||||
|  | ||||
|  | ||||
| def main(network, equipment, source, sink): | ||||
| def main(network, equipment, source, sink, req = None): | ||||
|     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)] | ||||
|     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}:') | ||||
|  | ||||
|      | ||||
|     for p in range(0, 1): #change range to sweep results across several powers in dBm | ||||
|         p=db2lin(p)*1e-3 | ||||
|         spacing = 0.05 # THz | ||||
|         si = SpectralInformation() # SI units: W, Hz | ||||
|         si = si.update(carriers=[ | ||||
|             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 :') | ||||
|         req.power = db2lin(p)*1e-3 | ||||
|         print(f'\nPropagating with input power = {lin2db(req.power*1e3):.2f}dBm :') | ||||
|         propagate(path,req,equipment,show=True) | ||||
|         print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f}dBm :') | ||||
|         print(sink) | ||||
|  | ||||
|     return path | ||||
| @@ -91,7 +85,7 @@ if __name__ == '__main__': | ||||
|     # logger.info(equipment) | ||||
|  | ||||
|     network = load_network(args.filename, equipment) | ||||
|     print(network) | ||||
|     # print(network) | ||||
|  | ||||
|     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'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: | ||||
|         plot_results(network, path, source, sink) | ||||
|   | ||||
| @@ -156,7 +156,9 @@ def convert_file(input_filename, filter_region=[]): | ||||
|               'type_variety': x.east_fiber, | ||||
|               'params': {'length':   round(x.east_distance, 3), | ||||
|                          '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] + | ||||
|             [{'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, | ||||
|               'params': {'length':   round(x.west_distance, 3), | ||||
|                          '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  | ||||
|               for x in links] + | ||||
|             [{'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)) | ||||
|         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): | ||||
|     def __init__(self, *args, params=None, **kwargs): | ||||
|         if params is None: | ||||
|             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) | ||||
|         self.type_variety = self.params.type_variety | ||||
|         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.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.gamma = self.params.gamma # 1/W/m        | ||||
|         # 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}', | ||||
|                           f'  type_variety: {self.type_variety}', | ||||
|                           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 | ||||
|     def loss(self): | ||||
|         # 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 | ||||
|     def passive(self): | ||||
| @@ -251,12 +258,29 @@ class Fiber(Node): | ||||
|         return carrier_nli | ||||
|  | ||||
|     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: | ||||
|             pwr = carrier.power | ||||
|             carrier_nli = self._gn_analytic(carrier, *carriers) | ||||
|             pwr = pwr._replace(signal=pwr.signal/self.lin_attenuation, | ||||
|                                nonlinear_interference=(pwr.nli+carrier_nli)/self.lin_attenuation, | ||||
|                                amplified_spontaneous_emission=pwr.ase/self.lin_attenuation) | ||||
|             pwr = pwr._replace(signal=pwr.signal/self.lin_attenuation/attenuation, | ||||
|                                nonlinear_interference=(pwr.nli+carrier_nli)/self.lin_attenuation/attenuation, | ||||
|                                amplified_spontaneous_emission=pwr.ase/self.lin_attenuation/attenuation) | ||||
|             yield carrier._replace(power=pwr) | ||||
|  | ||||
|     def __call__(self, spectral_info): | ||||
|   | ||||
| @@ -11,6 +11,8 @@ This module contains classes for modelling SpectralInformation. | ||||
| from collections import namedtuple | ||||
| from numpy import array | ||||
| from gnpy.core.utils import lin2db | ||||
| from json import loads | ||||
| from gnpy.core.utils import load_json | ||||
|  | ||||
| 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": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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": { | ||||
|         "length": 80.0, | ||||
|         "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": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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": { | ||||
|         "length": 80.0, | ||||
|         "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": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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": { | ||||
|         "length": 80.0, | ||||
|         "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": { | ||||
|         "length": 20.0, | ||||
|         "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": { | ||||
|         "length": 50.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 10.0, | ||||
|         "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": { | ||||
|         "length": 60.0, | ||||
|         "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": { | ||||
|         "length": 65.0, | ||||
|         "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": { | ||||
|         "length": 40.0, | ||||
|         "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": { | ||||
|         "length": 35.0, | ||||
|         "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": { | ||||
|         "length": 80.0, | ||||
|         "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