mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-11-03 19:47:46 +00:00 
			
		
		
		
	Develop (#14)
* adding rrc filter, temporarily putting it in utilities.py * added some docstring stuff * added a simple loss class for fiber and cleaned up some duplicate convenience access properties * Changed Carrier to Channel to reflect correct nomenclature for multi-carrier/superchannels * in process fixes for main.py. adding in amp spacings and spans to convert to start adding additional noded to Coronet network * some simple additions to utilites * adding stand alone edfa model
This commit is contained in:
		@@ -10,6 +10,17 @@ from networkx import (draw_networkx_nodes, draw_networkx_edges,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from . import network_from_json
 | 
					from . import network_from_json
 | 
				
			||||||
from .elements import Transceiver, Fiber
 | 
					from .elements import Transceiver, Fiber
 | 
				
			||||||
 | 
					from .info import SpectralInformation, Channel, Power
 | 
				
			||||||
 | 
					from .algorithms import closed_paths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logger = getLogger(__package__ or __file__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def format_si(spectral_infos):
 | 
				
			||||||
 | 
					    return '\n'.join([
 | 
				
			||||||
 | 
					        f'#{idx} Carrier(frequency={c.frequency},\n  power=Power(signal={c.power.signal}, nli={c.power.nli}, ase={c.power.ase}))'
 | 
				
			||||||
 | 
					        for idx, si in sorted(set(spectral_infos))
 | 
				
			||||||
 | 
					        for c in set(si.carriers)
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger = getLogger('gnpy.core')
 | 
					logger = getLogger('gnpy.core')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,9 +36,38 @@ def main(args):
 | 
				
			|||||||
              for n in network.nodes()]
 | 
					              for n in network.nodes()]
 | 
				
			||||||
    labels = {n: n.location.city if isinstance(n, Transceiver) else ''
 | 
					    labels = {n: n.location.city if isinstance(n, Transceiver) else ''
 | 
				
			||||||
              for n in network.nodes()}
 | 
					              for n in network.nodes()}
 | 
				
			||||||
    draw_networkx_nodes(network, pos=pos, node_size=size, node_color=color)
 | 
					
 | 
				
			||||||
    draw_networkx_edges(network, pos=pos)
 | 
					    si = SpectralInformation(
 | 
				
			||||||
    draw_networkx_labels(network, pos=labels_pos, labels=labels, font_size=14)
 | 
					        Channel(1, 193.95e12, '16-qam', 32e9, 0,  # 193.95 THz, 32 Gbaud
 | 
				
			||||||
 | 
					            Power(1e-3, 1e-6, 1e-6)),             # 1 mW, 1uW, 1uW
 | 
				
			||||||
 | 
					        Channel(1, 195.95e12, '16-qam', 32e9, 0,  # 195.95 THz, 32 Gbaud
 | 
				
			||||||
 | 
					            Power(1.2e-3, 1e-6, 1e-6)),           # 1.2 mW, 1uW, 1uW
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nodes = [n for n in network.nodes() if isinstance(n, Transceiver)]
 | 
				
			||||||
 | 
					    source, sink = choice(nodes), choice(nodes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    results = list(islice(closed_paths(network, source, sink, si), 3))
 | 
				
			||||||
 | 
					    paths = [[n for _, n, _ in r] for r in results]
 | 
				
			||||||
 | 
					    infos = {}
 | 
				
			||||||
 | 
					    for idx, r in enumerate(results):
 | 
				
			||||||
 | 
					        for in_si, node, out_si in r:
 | 
				
			||||||
 | 
					            infos.setdefault(node, []).append((idx, out_si))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    node_color = ['#ff0000' if n is source or n is sink else
 | 
				
			||||||
 | 
					                  '#900000' if any(n in p for p in paths) else
 | 
				
			||||||
 | 
					                  '#ffdede' if isinstance(n, Transceiver) else '#dedeff'
 | 
				
			||||||
 | 
					                  for n in network.nodes()]
 | 
				
			||||||
 | 
					    edge_color = ['#ff9090' if any(u in p for p in paths) and
 | 
				
			||||||
 | 
					                               any(v in p for p in paths) else '#dedede'
 | 
				
			||||||
 | 
					                  for u, v in network.edges()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fig = figure()
 | 
				
			||||||
 | 
					    plot = draw_networkx_nodes(network, pos=pos, node_size=size, node_color=node_color, figure=fig)
 | 
				
			||||||
 | 
					    draw_networkx_edges(network, pos=pos, figure=fig, edge_color=edge_color)
 | 
				
			||||||
 | 
					    draw_networkx_labels(network, pos=labels_pos, labels=labels, font_size=14, figure=fig)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    title(f'Propagating from {source.loc.city} to {sink.loc.city}')
 | 
				
			||||||
    axis('off')
 | 
					    axis('off')
 | 
				
			||||||
    show()
 | 
					    show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,12 @@
 | 
				
			|||||||
#!/usr/bin/env python3
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					 | 
				
			||||||
from core.node import Node
 | 
					from core.node import Node
 | 
				
			||||||
from core.units import UNITS
 | 
					from core.units import UNITS
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
 | 
					from scipy.constants import c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# network elements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Transceiver(Node):
 | 
					class Transceiver(Node):
 | 
				
			||||||
    def __init__(self, config):
 | 
					    def __init__(self, config):
 | 
				
			||||||
        super().__init__(config)
 | 
					        super().__init__(config)
 | 
				
			||||||
@@ -11,7 +14,6 @@ class Transceiver(Node):
 | 
				
			|||||||
    def __call__(self, spectral_info):
 | 
					    def __call__(self, spectral_info):
 | 
				
			||||||
        return spectral_info
 | 
					        return spectral_info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
class Fiber(Node):
 | 
					class Fiber(Node):
 | 
				
			||||||
    def __init__(self, config):
 | 
					    def __init__(self, config):
 | 
				
			||||||
        super().__init__(config)
 | 
					        super().__init__(config)
 | 
				
			||||||
@@ -21,6 +23,51 @@ class Fiber(Node):
 | 
				
			|||||||
    def __repr__(self):
 | 
					    def __repr__(self):
 | 
				
			||||||
        return f'{type(self).__name__}(uid={self.uid}, length={self.length})'
 | 
					        return f'{type(self).__name__}(uid={self.uid}, length={self.length})'
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    def effective_length(self, loss_coef):
 | 
				
			||||||
 | 
					        alpha_dict = self.dbkm_2_lin(loss_coef)
 | 
				
			||||||
 | 
					        alpha = alpha_dict['alpha_acoef']
 | 
				
			||||||
 | 
					        leff = 1 - np.exp(-2 * alpha * self.span_length)
 | 
				
			||||||
 | 
					        return leff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def asymptotic_length(self, loss_coef):
 | 
				
			||||||
 | 
					        alpha_dict = self.dbkm_2_lin(loss_coef)
 | 
				
			||||||
 | 
					        alpha = alpha_dict['alpha_acoef']
 | 
				
			||||||
 | 
					        aleff = 1/(2 * alpha)
 | 
				
			||||||
 | 
					        return aleff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def dbkm_2_lin(self, loss_coef):
 | 
				
			||||||
 | 
					        """ calculates the linear loss coefficient
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        alpha_pcoef = loss_coef
 | 
				
			||||||
 | 
					        alpha_acoef = alpha_pcoef/(2*4.3429448190325184)
 | 
				
			||||||
 | 
					        s = 'alpha_pcoef is linear loss coefficient in [dB/km^-1] units'
 | 
				
			||||||
 | 
					        s = ''.join([s, "alpha_acoef is linear loss field amplitude \
 | 
				
			||||||
 | 
					                     coefficient in [km^-1] units"])
 | 
				
			||||||
 | 
					        d = {'alpha_pcoef': alpha_pcoef, 'alpha_acoef': alpha_acoef,
 | 
				
			||||||
 | 
					             'description:': s}
 | 
				
			||||||
 | 
					        return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def beta2(self, dispersion, ref_wavelength=None):
 | 
				
			||||||
 | 
					        """ Returns beta2 from dispersion parameter.  Dispersion is entered in
 | 
				
			||||||
 | 
					        ps/nm/km.  Disperion can be a numpy array or a single value.  If a
 | 
				
			||||||
 | 
					        value ref_wavelength is not entered 1550e-9m will be assumed.
 | 
				
			||||||
 | 
					        ref_wavelength can be a numpy array.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if ref_wavelength is None:
 | 
				
			||||||
 | 
					            ref_wavelength = 1550e-9
 | 
				
			||||||
 | 
					        wl = ref_wavelength
 | 
				
			||||||
 | 
					        D = np.abs(dispersion)
 | 
				
			||||||
 | 
					        b2 = (10**21) * (wl**2) * D / (2 * np.pi * c)
 | 
				
			||||||
 | 
					#       10^21 scales to ps^2/km
 | 
				
			||||||
 | 
					        return b2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # convenience access
 | 
				
			||||||
 | 
					    loss = property(lambda self: self.loss_.value)
 | 
				
			||||||
 | 
					    length = property(lambda self: self.length_.value)
 | 
				
			||||||
 | 
					    loc  = property(lambda self: self.location)
 | 
				
			||||||
 | 
					    lat  = property(lambda self: self.location.latitude)
 | 
				
			||||||
 | 
					    long = property(lambda self: self.location.longitude)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def propagate(self, *carriers):
 | 
					    def propagate(self, *carriers):
 | 
				
			||||||
        for carrier in carriers:
 | 
					        for carrier in carriers:
 | 
				
			||||||
            power = carrier.power
 | 
					            power = carrier.power
 | 
				
			||||||
@@ -32,3 +79,4 @@ class Fiber(Node):
 | 
				
			|||||||
    def __call__(self, spectral_info):
 | 
					    def __call__(self, spectral_info):
 | 
				
			||||||
        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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										42
									
								
								core/info.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								core/info.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from collections import namedtuple
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConvenienceAccess:
 | 
				
			||||||
 | 
					    def __init_subclass__(cls):
 | 
				
			||||||
 | 
					        for abbrev, field in getattr(cls, '_ABBREVS', {}).items():
 | 
				
			||||||
 | 
					            setattr(cls, abbrev, property(lambda self, f=field: getattr(self, f)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update(self, **kwargs):
 | 
				
			||||||
 | 
					        for abbrev, field in getattr(self, '_ABBREVS', {}).items():
 | 
				
			||||||
 | 
					            if abbrev in kwargs:
 | 
				
			||||||
 | 
					                kwargs[field] = kwargs.pop(abbrev)
 | 
				
			||||||
 | 
					        return self._replace(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Power(namedtuple('Power', 'signal nonlinear_interference amplified_spontaneous_emission'), ConvenienceAccess):
 | 
				
			||||||
 | 
					    _ABBREVS = {'nli': 'nonlinear_interference',
 | 
				
			||||||
 | 
					                'ase': 'amplified_spontaneous_emission',}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Channel(namedtuple('Channel', 'channel_number frequency modulation baud_rate alpha power'), ConvenienceAccess):
 | 
				
			||||||
 | 
					    _ABBREVS = {'channel': 'channel_number',
 | 
				
			||||||
 | 
					                'num_chan':      'channel_number',
 | 
				
			||||||
 | 
					                'num_carriers': 'num_carriers',
 | 
				
			||||||
 | 
					                'ffs':     'frequency',
 | 
				
			||||||
 | 
					                'freq':    'frequency',}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SpectralInformation(namedtuple('SpectralInformation', 'carriers'), ConvenienceAccess):
 | 
				
			||||||
 | 
					    def __new__(cls, *carriers):
 | 
				
			||||||
 | 
					        return super().__new__(cls, carriers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    si = SpectralInformation(
 | 
				
			||||||
 | 
					        Channel(1, 193.95e12, '16-qam', 32e9, 0,  # 193.95 THz, 32 Gbaud
 | 
				
			||||||
 | 
					            Power(1e-3, 1e-6, 1e-6)),             # 1 mW, 1uW, 1uW
 | 
				
			||||||
 | 
					        Channel(1, 195.95e12, '16-qam', 32e9, 0,  # 195.95 THz, 32 Gbaud
 | 
				
			||||||
 | 
					            Power(1.2e-3, 1e-6, 1e-6)),           # 1.2 mW, 1uW, 1uW
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    print(f'si = {si}')
 | 
				
			||||||
 | 
					    print(f'si = {si.carriers[0].power.nli}')
 | 
				
			||||||
 | 
					    si2 = si.update(carriers=tuple(c.update(power = c.power.update(nli = c.power.nli * 1e5))
 | 
				
			||||||
 | 
					                              for c in si.carriers))
 | 
				
			||||||
 | 
					    print(f'si2 = {si2}')
 | 
				
			||||||
@@ -10,12 +10,36 @@ from collections import namedtuple, Counter
 | 
				
			|||||||
from itertools import chain
 | 
					from itertools import chain
 | 
				
			||||||
from json import dumps
 | 
					from json import dumps
 | 
				
			||||||
from uuid import uuid4
 | 
					from uuid import uuid4
 | 
				
			||||||
 | 
					import math
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Node = namedtuple('Node', 'city state country region latitude longitude')
 | 
					Node = namedtuple('Node', 'city state country region latitude longitude')
 | 
				
			||||||
class Link(namedtuple('Link', 'from_city to_city distance distance_units')):
 | 
					class Link(namedtuple('Link', 'from_city to_city distance distance_units')):
 | 
				
			||||||
    def __new__(cls, from_city, to_city, distance, distance_units='km'):
 | 
					    def __new__(cls, from_city, to_city, distance, distance_units='km'):
 | 
				
			||||||
        return super().__new__(cls, from_city, to_city, distance, distance_units)
 | 
					        return super().__new__(cls, from_city, to_city, distance, distance_units)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def define_span_range(min_span, max_span, nspans):
 | 
				
			||||||
 | 
					    srange = (max_span - min_span) + min_span*np.random.rand(nspans)
 | 
				
			||||||
 | 
					    return srange
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def amp_spacings(min_span,max_span,length):
 | 
				
			||||||
 | 
					    nspans =  math.ceil(length/100)
 | 
				
			||||||
 | 
					    spans = define_span_range(min_span, max_span, nspans)
 | 
				
			||||||
 | 
					    tot = spans.sum()
 | 
				
			||||||
 | 
					    delta = length -tot
 | 
				
			||||||
 | 
					    if delta > 0 and delta < 25:
 | 
				
			||||||
 | 
					        ind  = np.where(np.min(spans))
 | 
				
			||||||
 | 
					        spans[ind] = spans[ind] + delta
 | 
				
			||||||
 | 
					    elif delta >= 25 and delta < 40:
 | 
				
			||||||
 | 
					        spans = spans + delta/float(nspans)
 | 
				
			||||||
 | 
					    elif delta > 40 and delta < 100:
 | 
				
			||||||
 | 
					        spans = np.append(spans,delta)
 | 
				
			||||||
 | 
					    elif delta > 100:
 | 
				
			||||||
 | 
					        spans  = np.append(spans, [delta/2, delta/2])
 | 
				
			||||||
 | 
					    elif delta < 0:
 | 
				
			||||||
 | 
					        spans = spans + delta/float(nspans)
 | 
				
			||||||
 | 
					    return list(spans)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def parse_excel(args):
 | 
					def parse_excel(args):
 | 
				
			||||||
    with open_workbook(args.workbook) as wb:
 | 
					    with open_workbook(args.workbook) as wb:
 | 
				
			||||||
        nodes_sheet = wb.sheet_by_name('Nodes')
 | 
					        nodes_sheet = wb.sheet_by_name('Nodes')
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								examples/edfa_model/DFG_96.txt
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								examples/edfa_model/DFG_96.txt
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					   2.5135969849999999e+01   2.5118228139999999e+01   2.5095421330000001e+01   2.5062457710000000e+01   2.5026027650000000e+01   2.4996379529999999e+01   2.4981672549999999e+01   2.4975306679999999e+01   2.4983207260000000e+01   2.4997185649999999e+01   2.5017572470000001e+01   2.5038327809999998e+01   2.5054955849999999e+01   2.5067071899999998e+01   2.5070914110000000e+01   2.5070943650000000e+01   2.5071143240000001e+01   2.5075336270000001e+01   2.5087310179999999e+01   2.5103139360000000e+01   2.5122762040000001e+01   2.5142394790000001e+01   2.5159456330000001e+01   2.5173927039999999e+01   2.5176737670000001e+01   2.5170371410000001e+01   2.5152162539999999e+01   2.5131143099999999e+01   2.5108023350000000e+01   2.5085487770000000e+01   2.5069166750000001e+01   2.5058481759999999e+01   2.5054473130000002e+01   2.5051544410000002e+01   2.5049460589999999e+01   2.5047178490000000e+01   2.5045516559999999e+01   2.5044676490000001e+01   2.5040729200000001e+01   2.5032854080000000e+01   2.5023488300000000e+01   2.5016592339999999e+01   2.5013321359999999e+01   2.5011234340000001e+01   2.5010300149999999e+01   2.5009365480000000e+01   2.5008739640000002e+01   2.5008425350000000e+01   2.5006964660000001e+01   2.5004043100000001e+01   2.5000709980000000e+01   2.4998423200000001e+01   2.4993063320000001e+01   2.4983524209999999e+01   2.4971251030000001e+01   2.4960381080000001e+01   2.4948887209999999e+01   2.4935314890000001e+01   2.4921319270000001e+01   2.4908986970000001e+01   2.4898965140000001e+01   2.4889584630000002e+01   2.4880838700000002e+01   2.4872100920000001e+01   2.4864620259999999e+01   2.4858397730000000e+01   2.4854458380000001e+01   2.4851554430000000e+01   2.4851766009999999e+01   2.4854080140000001e+01   2.4859096240000000e+01   2.4864744580000000e+01   2.4872034859999999e+01   2.4880365200000000e+01   2.4889106689999998e+01   2.4897213130000001e+01   2.4902826040000001e+01   2.4906566900000001e+01   2.4908650800000000e+01   2.4910939440000000e+01   2.4913430790000000e+01   2.4915923440000000e+01   2.4921553509999999e+01   2.4930318610000000e+01   2.4940528120000000e+01   2.4949046689999999e+01   2.4957571229999999e+01   2.4967818449999999e+01   2.4981800929999999e+01   2.4997826860000000e+01   2.5013931830000001e+01   2.5028098459999999e+01   2.5040325750000001e+01   2.5052569810000001e+01   2.5064797009999999e+01   2.5077046970000001e+01
 | 
				
			||||||
							
								
								
									
										1
									
								
								examples/edfa_model/DGT_96.txt
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								examples/edfa_model/DGT_96.txt
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					   2.7145266811316859e+00   2.7054438192385049e+00   2.6947834587664494e+00   2.6841217449620203e+00   2.6681935771243177e+00   2.6521732021128046e+00   2.6303964408153848e+00   2.6028603502864280e+00   2.5696460593920065e+00   2.5364027376452056e+00   2.4994462867966041e+00   2.4587748041127506e+00   2.4143984371852212e+00   2.3699990328716107e+00   2.3223736962293420e+00   2.2715207713712529e+00   2.2174389328192197e+00   2.1633756538423898e+00   2.1183028432496016e+00   2.0822250998736478e+00   2.0551007720052352e+00   2.0279625371819305e+00   2.0008103857988204e+00   1.9736443063300082e+00   1.9482128147680253e+00   1.9245345552113182e+00   1.9026104247588487e+00   1.8806927939516411e+00   1.8622356724442459e+00   1.8472755032011290e+00   1.8358140813807049e+00   1.8243814368429321e+00   1.8139629377087627e+00   1.8045606557581335e+00   1.7961751115773796e+00   1.7877868031023945e+00   1.7793941781790852e+00   1.7709972329654864e+00   1.7625959636196327e+00   1.7541903672600494e+00   1.7459181197626403e+00   1.7377807579136351e+00   1.7297783508684146e+00   1.7217732861435076e+00   1.7137640932265894e+00   1.7057507692361864e+00   1.6918150918099673e+00   1.6719047669939942e+00   1.6460167077689267e+00   1.6201194134191075e+00   1.5986915141218316e+00   1.5817353179379183e+00   1.5691997641843789e+00   1.5566577309558969e+00   1.5453741527614671e+00   1.5353620432989845e+00   1.5266220576235803e+00   1.5178910621476225e+00   1.5097346239790443e+00   1.5021530399096861e+00   1.4951454560626991e+00   1.4881342434792260e+00   1.4811193973568100e+00   1.4741004422522110e+00   1.4670307626366115e+00   1.4599103316162523e+00   1.4527395948591399e+00   1.4455651371583680e+00   1.4340878115214444e+00   1.4182738067303231e+00   1.3981208704326855e+00   1.3779439775587023e+00   1.3598972673004606e+00   1.3439818461440451e+00   1.3301807335621048e+00   1.3163839268630830e+00   1.3040618749785347e+00   1.2932153453410835e+00   1.2838336236692311e+00   1.2744470198196236e+00   1.2650555289898042e+00   1.2556591482982988e+00   1.2428104897182262e+00   1.2264996957264114e+00   1.2067249615595257e+00   1.1869318618366975e+00   1.1672278304018044e+00   1.1476135933863398e+00   1.1280891949729075e+00   1.1085552896156590e+00   1.0895983485572227e+00   1.0712204022764056e+00   1.0534217504465226e+00   1.0356155337864215e+00   1.0178077678537021e+00   1.0000000000000000e+00
 | 
				
			||||||
							
								
								
									
										1
									
								
								examples/edfa_model/NFR_96.txt
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								examples/edfa_model/NFR_96.txt
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					  -3.1537433199999998e-01  -3.1537433199999998e-01  -3.1540091571002721e-01  -3.1849146117510951e-01  -3.2158358425400546e-01  -3.2467728615499991e-01  -3.2762368641496226e-01  -3.2054138461232762e-01  -3.1345546385118733e-01  -3.0636592135697482e-01  -2.9920267890990127e-01  -2.7061972852631744e-01  -2.4202215770774693e-01  -2.1340995523361256e-01  -1.8478227130158695e-01  -1.4809761118389625e-01  -1.1139416731807622e-01  -7.4671925273579881e-02  -3.8026748965679924e-02  -1.9958469399422092e-02  -1.8809287980157928e-03   1.6205879960573561e-02   3.4301964005709673e-02   5.2407330474054062e-02   7.0521986509597359e-02   7.9578036683472006e-02   8.8546647361909522e-02   9.7519863231965306e-02   1.0649768784154924e-01   9.7741380449907406e-02   8.8803437172660038e-02   7.9860899732845866e-02   7.0913764587403796e-02   6.3335892740565308e-02   5.5756212252058776e-02   4.8172631747863209e-02   4.0585148217162359e-02   3.3381591675710129e-02   2.6178308595650738e-02   1.8971315351761126e-02   1.1760609076833628e-02   1.6950294922759991e-02   2.2274991357701439e-02   2.7602433189104329e-02   3.2932622540790261e-02   3.8265561538776145e-02   4.3601252311271169e-02   3.4856990743481552e-02   2.5991055149117932e-02   1.7120541224980364e-02   8.2757587359203223e-03   1.9423214065246042e-03  -4.3943890171043590e-03  -1.0734375072893196e-02  -1.7077639301414434e-02  -2.4679702899572852e-02  -3.2297970403821680e-02  -3.9920180090477250e-02  -4.7534566327530239e-02  -4.9234003141433724e-02  -5.0934320036547187e-02  -5.2635517696692252e-02  -5.4337596806402461e-02  -5.6040558050919301e-02  -5.7718452237076875e-02  -5.6840590379175944e-02  -5.5962273198734966e-02  -5.5083500341416583e-02  -5.4204271452516814e-02  -5.8396088726955113e-02  -6.2627330169715334e-02  -6.6860769089203700e-02  -7.0901736256069450e-02  -5.2096097309052243e-02  -3.3280684121412940e-02  -1.4455489070928059e-02   4.3150387579057158e-03   1.4839202394482527e-02   2.5368841662503576e-02   3.5903960836465652e-02   4.6444564195321399e-02   5.6990656022467459e-02   6.7542240605774059e-02   1.0002709623672751e-01   1.3258013095133617e-01   1.6515013362773309e-01   1.9773711753599391e-01   2.3194802687829724e-01   2.6618779883837107e-01   3.0044543658085349e-01   3.3472095409250663e-01   3.5929034770587287e-01   3.8384389188855605e-01   4.0841026111391787e-01   4.3298946543290784e-01   4.3298946543290784e-01
 | 
				
			||||||
							
								
								
									
										8
									
								
								examples/edfa_model/Pchan2D.txt
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								examples/edfa_model/Pchan2D.txt
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01
 | 
				
			||||||
 | 
					  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02
 | 
				
			||||||
 | 
					  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01  -2.0000000000000000e+01
 | 
				
			||||||
 | 
					  -2.0500000000000000e+01  -2.0489473680000000e+01  -2.0478947370000000e+01  -2.0468421050000000e+01  -2.0457894740000000e+01  -2.0447368420000000e+01  -2.0436842110000001e+01  -2.0426315790000000e+01  -2.0415789470000000e+01  -2.0405263160000001e+01  -2.0394736840000000e+01  -2.0384210530000001e+01  -2.0373684210000000e+01  -2.0363157890000000e+01  -2.0352631580000001e+01  -2.0342105260000000e+01  -2.0331578950000001e+01  -2.0321052630000001e+01  -2.0310526320000001e+01  -2.0300000000000001e+01  -2.0289473680000000e+01  -2.0278947370000001e+01  -2.0268421050000001e+01  -2.0257894740000001e+01  -2.0247368420000001e+01  -2.0236842110000001e+01  -2.0226315790000001e+01  -2.0215789470000001e+01  -2.0205263160000001e+01  -2.0194736840000001e+01  -2.0184210530000001e+01  -2.0173684210000001e+01  -2.0163157890000001e+01  -2.0152631580000001e+01  -2.0142105260000001e+01  -2.0131578950000002e+01  -2.0121052630000001e+01  -2.0110526320000002e+01  -2.0100000000000001e+01  -2.0089473680000001e+01  -2.0078947370000002e+01  -2.0068421050000001e+01  -2.0057894739999998e+01  -2.0047368420000002e+01  -2.0036842109999998e+01  -2.0026315790000002e+01  -2.0015789470000001e+01  -2.0005263159999998e+01  -1.9994736840000002e+01  -1.9984210529999999e+01  -1.9973684209999998e+01  -1.9963157890000002e+01  -1.9952631579999998e+01  -1.9942105260000002e+01  -1.9931578949999999e+01  -1.9921052629999998e+01  -1.9910526319999999e+01  -1.9899999999999999e+01  -1.9889473679999998e+01  -1.9878947369999999e+01  -1.9868421049999998e+01  -1.9857894739999999e+01  -1.9847368419999999e+01  -1.9836842109999999e+01  -1.9826315789999999e+01  -1.9815789469999999e+01  -1.9805263159999999e+01  -1.9794736839999999e+01  -1.9784210529999999e+01  -1.9773684209999999e+01  -1.9763157889999999e+01  -1.9752631579999999e+01  -1.9742105259999999e+01  -1.9731578949999999e+01  -1.9721052629999999e+01  -1.9710526320000000e+01  -1.9699999999999999e+01  -1.9689473679999999e+01  -1.9678947369999999e+01  -1.9668421049999999e+01  -1.9657894740000000e+01  -1.9647368419999999e+01  -1.9636842110000000e+01  -1.9626315790000000e+01  -1.9615789469999999e+01  -1.9605263160000000e+01  -1.9594736839999999e+01  -1.9584210530000000e+01  -1.9573684210000000e+01  -1.9563157889999999e+01  -1.9552631580000000e+01  -1.9542105260000000e+01  -1.9531578950000000e+01  -1.9521052630000000e+01  -1.9510526320000000e+01  -1.9500000000000000e+01
 | 
				
			||||||
 | 
					  -2.0500000000000000e+01  -2.0489473680000000e+01  -2.0478947370000000e+01  -2.0468421050000000e+01  -2.0457894740000000e+01  -2.0447368420000000e+01  -2.0436842110000001e+01  -2.0426315790000000e+01  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.9573684210000000e+01  -1.9563157889999999e+01  -1.9552631580000000e+01  -1.9542105260000000e+01  -1.9531578950000000e+01  -1.9521052630000000e+01  -1.9510526320000000e+01  -1.9500000000000000e+01
 | 
				
			||||||
 | 
					  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.4460000000000001e+01
 | 
				
			||||||
 | 
					  -1.4460000000000001e+01  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01  -1.4460000000000001e+01
 | 
				
			||||||
 | 
					  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.4460000000000001e+01  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02  -1.0000000000000000e+02
 | 
				
			||||||
							
								
								
									
										8
									
								
								examples/edfa_model/Pchan2DLegend.txt
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								examples/edfa_model/Pchan2DLegend.txt
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					   7.0000000000000000e+01	   1.1700000000000000e+02	   1.0800000000000000e+02	   1.0800000000000000e+02	   3.2000000000000000e+01	   7.0000000000000000e+01	   1.0800000000000000e+02	   9.7000000000000000e+01	   1.1600000000000000e+02	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	
 | 
				
			||||||
 | 
					   7.9000000000000000e+01	   1.1000000000000000e+02	   1.0100000000000000e+02	   3.2000000000000000e+01	   7.1000000000000000e+01	   1.1400000000000000e+02	   1.1100000000000000e+02	   1.1700000000000000e+02	   1.1200000000000000e+02	   3.2000000000000000e+01	   6.6000000000000000e+01	   1.0800000000000000e+02	   1.1700000000000000e+02	   1.0100000000000000e+02	   3.2000000000000000e+01	
 | 
				
			||||||
 | 
					   7.9000000000000000e+01	   1.1000000000000000e+02	   1.0100000000000000e+02	   3.2000000000000000e+01	   7.1000000000000000e+01	   1.1400000000000000e+02	   1.1100000000000000e+02	   1.1700000000000000e+02	   1.1200000000000000e+02	   3.2000000000000000e+01	   8.2000000000000000e+01	   1.0100000000000000e+02	   1.0000000000000000e+02	   3.2000000000000000e+01	   3.2000000000000000e+01	
 | 
				
			||||||
 | 
					   7.0000000000000000e+01	   1.1700000000000000e+02	   1.0800000000000000e+02	   1.0800000000000000e+02	   3.2000000000000000e+01	   1.1900000000000000e+02	   3.2000000000000000e+01	   8.3000000000000000e+01	   8.2000000000000000e+01	   8.3000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	
 | 
				
			||||||
 | 
					   6.6000000000000000e+01	   1.1100000000000000e+02	   1.1600000000000000e+02	   1.0400000000000000e+02	   3.2000000000000000e+01	   6.9000000000000000e+01	   1.1000000000000000e+02	   1.0000000000000000e+02	   1.1500000000000000e+02	   3.2000000000000000e+01	   1.1900000000000000e+02	   3.2000000000000000e+01	   8.3000000000000000e+01	   8.2000000000000000e+01	   8.3000000000000000e+01	
 | 
				
			||||||
 | 
					   1.0400000000000000e+02	   1.0100000000000000e+02	   9.7000000000000000e+01	   1.1800000000000000e+02	   1.2100000000000000e+02	   3.2000000000000000e+01	   9.8000000000000000e+01	   1.0800000000000000e+02	   1.1700000000000000e+02	   1.0100000000000000e+02	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	
 | 
				
			||||||
 | 
					   1.0400000000000000e+02	   1.0100000000000000e+02	   9.7000000000000000e+01	   1.1800000000000000e+02	   1.2100000000000000e+02	   3.2000000000000000e+01	   1.1400000000000000e+02	   1.0100000000000000e+02	   1.0000000000000000e+02	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	
 | 
				
			||||||
 | 
					   1.1900000000000000e+02	   1.1100000000000000e+02	   1.1400000000000000e+02	   1.1500000000000000e+02	   1.1600000000000000e+02	   3.2000000000000000e+01	   9.9000000000000000e+01	   9.7000000000000000e+01	   1.1500000000000000e+02	   1.0100000000000000e+02	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	   3.2000000000000000e+01	
 | 
				
			||||||
							
								
								
									
										300
									
								
								examples/edfa_model/amplifier.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								examples/edfa_model/amplifier.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,300 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Created on Mon Nov 27 12:32:04 2017
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@author: briantaylor
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
 | 
					from numpy import polyfit, polyval, mean
 | 
				
			||||||
 | 
					from utilities import lin2db, db2lin, itufs, freq2wavelength
 | 
				
			||||||
 | 
					import matplotlib.pyplot as plt
 | 
				
			||||||
 | 
					from scipy.constants import h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def noise_profile(nf, gain, ffs, df):    
 | 
				
			||||||
 | 
					    """ noise_profile(nf, gain, ffs, df) computes amplifier ase
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    :param nf: Noise figure in dB
 | 
				
			||||||
 | 
					    :param gain: Actual gain calculated for the EDFA in dB units
 | 
				
			||||||
 | 
					    :param ffs: A numpy array of frequencies
 | 
				
			||||||
 | 
					    :param df: the reference bw in THz
 | 
				
			||||||
 | 
					    :type nf: numpy.ndarray 
 | 
				
			||||||
 | 
					    :type gain: numpy.ndarray 
 | 
				
			||||||
 | 
					    :type ffs: numpy.ndarray 
 | 
				
			||||||
 | 
					    :type df: float
 | 
				
			||||||
 | 
					    :return: the asepower in dBm
 | 
				
			||||||
 | 
					    :rtype: numpy.ndarray
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ASE POWER USING PER CHANNEL GAIN PROFILE
 | 
				
			||||||
 | 
					    INPUTS:
 | 
				
			||||||
 | 
					    NF_dB - Noise figure in dB, vector of length number of channels or 
 | 
				
			||||||
 | 
					            spectral slices
 | 
				
			||||||
 | 
					    G_dB  - Actual gain calculated for the EDFA, vector of length number of 
 | 
				
			||||||
 | 
					            channels or spectral slices
 | 
				
			||||||
 | 
					    ffs     - Center frequency grid of the channels or spectral slices in THz,
 | 
				
			||||||
 | 
					            vector of length number of channels or spectral slices
 | 
				
			||||||
 | 
					    dF    - width of each channel or spectral slice in THz, 
 | 
				
			||||||
 | 
					            vector of length number of channels or spectral slices
 | 
				
			||||||
 | 
					    OUTPUT:
 | 
				
			||||||
 | 
					        ase_dBm - ase in dBm per channel or spectral slice
 | 
				
			||||||
 | 
					    NOTE: the output is the total ASE in the channel or spectral slice. For 
 | 
				
			||||||
 | 
					    50GHz channels the ASE BW is effectively 0.4nm. To get to noise power in
 | 
				
			||||||
 | 
					    0.1nm, subtract 6dB.
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    ONSR is usually quoted as channel power divided by
 | 
				
			||||||
 | 
					    the ASE power in 0.1nm RBW, regardless of the width of the actual
 | 
				
			||||||
 | 
					    channel.  This is a historical convention from the days when optical
 | 
				
			||||||
 | 
					    signals were much smaller (155Mbps, 2.5Gbps, ... 10Gbps) than the
 | 
				
			||||||
 | 
					    resolution of the OSAs that were used to measure spectral power which
 | 
				
			||||||
 | 
					    were set to 0.1nm resolution for convenience.  Moving forward into
 | 
				
			||||||
 | 
					    flexible grid and high baud rate signals, it may be convenient to begin
 | 
				
			||||||
 | 
					    quoting power spectral density in the same BW for both signal and ASE,
 | 
				
			||||||
 | 
					    e.g. 12.5GHz."""
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    h_mWThz = 1e-3*h*(1e14)**2 
 | 
				
			||||||
 | 
					    nf_lin = db2lin(nf)
 | 
				
			||||||
 | 
					    g_lin = db2lin(gain)
 | 
				
			||||||
 | 
					    ase = h_mWThz*df*ffs*(nf_lin*g_lin - 1)
 | 
				
			||||||
 | 
					    asedb = lin2db(ase)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return asedb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def gain_profile(dfg, dgt, Pin , gp , gtp):
 | 
				
			||||||
 | 
					    """ 
 | 
				
			||||||
 | 
					    :param dfg: design flat gain
 | 
				
			||||||
 | 
					    :param dgt: design gain tilt
 | 
				
			||||||
 | 
					    :param Pin: channing input power profile
 | 
				
			||||||
 | 
					    :param gp: Average gain setpoint in dB units
 | 
				
			||||||
 | 
					    :param gtp: gain tilt setting
 | 
				
			||||||
 | 
					    :type dfg: numpy.ndarray 
 | 
				
			||||||
 | 
					    :type dgt: numpy.ndarray 
 | 
				
			||||||
 | 
					    :type Pin: numpy.ndarray 
 | 
				
			||||||
 | 
					    :type gp: float
 | 
				
			||||||
 | 
					    :type gtp: float
 | 
				
			||||||
 | 
					    :return: gain profile in dBm
 | 
				
			||||||
 | 
					    :rtype: numpy.ndarray
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    AMPLIFICATION USING INPUT PROFILE
 | 
				
			||||||
 | 
					    INPUTS:
 | 
				
			||||||
 | 
					        DFG - vector of length number of channels or spectral slices
 | 
				
			||||||
 | 
					        DGT - vector of length number of channels or spectral slices
 | 
				
			||||||
 | 
					        Pin - input powers vector of length number of channels or 
 | 
				
			||||||
 | 
					        spectral slices
 | 
				
			||||||
 | 
					        Gp  - provisioned gain length 1
 | 
				
			||||||
 | 
					        GTp - provisioned tilt length 1
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    OUTPUT:
 | 
				
			||||||
 | 
					        amp gain per channel or spectral slice
 | 
				
			||||||
 | 
					    NOTE: there is no checking done for violations of the total output power
 | 
				
			||||||
 | 
					        capability of the amp.
 | 
				
			||||||
 | 
					        Ported from Matlab version written by David Boerges at Ciena.  
 | 
				
			||||||
 | 
					    Based on:
 | 
				
			||||||
 | 
					        R. di Muro, "The Er3+ fiber gain coefficient derived from a dynamic 
 | 
				
			||||||
 | 
					        gain
 | 
				
			||||||
 | 
					        tilt technique", Journal of Lightwave Technology, Vol. 18, Iss. 3, 
 | 
				
			||||||
 | 
					        Pp. 343-347, 2000.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    err_tolerance = 1.0e-11
 | 
				
			||||||
 | 
					    simple_opt = True
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # TODO make all values linear unit and convert to dB units as needed within
 | 
				
			||||||
 | 
					    # this function.
 | 
				
			||||||
 | 
					    nchan = list(range(len(Pin)))
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # TODO find a way to use these or lose them.  Primarily we should have a
 | 
				
			||||||
 | 
					    # way to determine if exceeding the gain or output power of the amp
 | 
				
			||||||
 | 
					    tot_in_power_db = lin2db(np.sum(db2lin(Pin)))
 | 
				
			||||||
 | 
					    avg_gain_db = lin2db(mean(db2lin(dfg)))
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    #Linear fit to get the
 | 
				
			||||||
 | 
					    p = polyfit(nchan, dgt, 1)
 | 
				
			||||||
 | 
					    dgt_slope = p[0]
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Calculate the target slope-  Currently assumes equal spaced channels
 | 
				
			||||||
 | 
					    # TODO make it so that supports arbitrary channel spacing.
 | 
				
			||||||
 | 
					    targ_slope = gtp / (len(nchan)-1)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # 1st estimate of DGT scaling
 | 
				
			||||||
 | 
					    dgts1 = targ_slope / dgt_slope
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # when simple_opt is true code makes 2 attempts to compute gain and 
 | 
				
			||||||
 | 
					    # the internal voa value.  This is currently here to provide direct
 | 
				
			||||||
 | 
					    # comparison with original Matlab code.  Will be removed.
 | 
				
			||||||
 | 
					    # TODO replace with loop
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if simple_opt:
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 1st estimate of Er gain & voa loss
 | 
				
			||||||
 | 
					        g1st = dfg + dgt*dgts1
 | 
				
			||||||
 | 
					        voa = lin2db(mean(db2lin(g1st))) - gp
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # 2nd estimate of Amp ch gain using the channel input profile
 | 
				
			||||||
 | 
					        g2nd = g1st - voa
 | 
				
			||||||
 | 
					        pout_db = lin2db(np.sum(db2lin(Pin + g2nd)))
 | 
				
			||||||
 | 
					        dgts2 = gp - (pout_db - tot_in_power_db)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        #Center estimate of amp ch gain
 | 
				
			||||||
 | 
					        xcent = dgts2
 | 
				
			||||||
 | 
					        gcent = g1st - voa + dgt*xcent
 | 
				
			||||||
 | 
					        pout_db = lin2db(np.sum(db2lin(Pin + gcent)))
 | 
				
			||||||
 | 
					        gavg_cent = pout_db - tot_in_power_db
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Lower estimate of Amp ch gain
 | 
				
			||||||
 | 
					        deltax = np.max(g1st) - np.min(g1st)
 | 
				
			||||||
 | 
					        xlow = dgts2 - deltax
 | 
				
			||||||
 | 
					        glow = g1st - voa + xlow*dgt
 | 
				
			||||||
 | 
					        pout_db = lin2db(np.sum(db2lin(Pin + glow)))
 | 
				
			||||||
 | 
					        gavg_low = pout_db - tot_in_power_db
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        # Upper gain estimate
 | 
				
			||||||
 | 
					        xhigh =dgts2 + deltax
 | 
				
			||||||
 | 
					        ghigh = g1st - voa + xhigh*dgt
 | 
				
			||||||
 | 
					        pout_db = lin2db(np.sum(db2lin(Pin + ghigh)))
 | 
				
			||||||
 | 
					        gavg_high = pout_db - tot_in_power_db
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # compute slope
 | 
				
			||||||
 | 
					        slope1 = (gavg_low - gavg_cent)/(xlow - xcent)
 | 
				
			||||||
 | 
					        slope2 = (gavg_cent - gavg_high)/(xcent - xhigh)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if np.abs(gp - gavg_cent) <= err_tolerance:
 | 
				
			||||||
 | 
					            dgts3 = xcent
 | 
				
			||||||
 | 
					        elif gp < gavg_cent:
 | 
				
			||||||
 | 
					            dgts3 = xcent - (gavg_cent - gp)/slope1
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            dgts3 = xcent + (-gavg_cent + gp)/slope2
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        gprofile = g1st - voa +dgt*dgts3
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        gprofile = None
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    return gprofile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    plt.close('all')
 | 
				
			||||||
 | 
					    fc = itufs(0.05)
 | 
				
			||||||
 | 
					    lc = freq2wavelength(fc)/1000
 | 
				
			||||||
 | 
					    nchan = list(range(len(lc)))
 | 
				
			||||||
 | 
					    df = np.array([0.05]*(nchan[-1] + 1))
 | 
				
			||||||
 | 
					    # TODO remove path dependence
 | 
				
			||||||
 | 
					    path = ''
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    DFG_96:  Design flat gain at each wavelength in the 96 channel 50GHz ITU
 | 
				
			||||||
 | 
					    grid in dB.  This can be experimentally determined by measuring the gain 
 | 
				
			||||||
 | 
					    at each wavelength using a full, flat channel (or ASE) load at the input.
 | 
				
			||||||
 | 
					    The amplifier should be set to its maximum flat gain (tilt = 0dB).  This 
 | 
				
			||||||
 | 
					    measurement captures the ripple of the amplifier.  If the amplifier was 
 | 
				
			||||||
 | 
					    designed to be mimimum ripple at some other tilt value, then the ripple
 | 
				
			||||||
 | 
					    reflected in this measurement will not be that minimum.  However, when
 | 
				
			||||||
 | 
					    the DGT gets applied through the provisioning of tilt, the model should
 | 
				
			||||||
 | 
					    accurately reproduce the expected ripple at that tilt value.  One could
 | 
				
			||||||
 | 
					    also do the measurement at some expected tilt value and back-calculate
 | 
				
			||||||
 | 
					    this vector using the DGT method.  Alternatively, one could re-write the
 | 
				
			||||||
 | 
					    algorithm to accept a nominal tilt and a tiled version of this vector.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    dfg_96 =  np.loadtxt(path + 'DFG_96.txt')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """maximum gain for flat operation - the amp in the data file was designed
 | 
				
			||||||
 | 
					    for 25dB gain and has an internal VOA for setting the external gain
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    avg_dfg = dfg_96.mean()
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    DGT_96:  This is the so-called Dynamic Gain Tilt of the EDFA in dB/dB. It
 | 
				
			||||||
 | 
					    is the change in gain at each wavelength corresponding to a 1dB change at
 | 
				
			||||||
 | 
					    the longest wavelength supported.  The value can be obtained
 | 
				
			||||||
 | 
					    experimentally or through analysis of the cross sections or Giles
 | 
				
			||||||
 | 
					    parameters of the Er fibre.  This is experimentally measured by changing 
 | 
				
			||||||
 | 
					    the gain of the amplifier above the maximum flat gain while not changing 
 | 
				
			||||||
 | 
					    the internal VOA (i.e. the mid-stage VOA is set to minimum and does not 
 | 
				
			||||||
 | 
					    change during the measurement). Note that the measurement can change the 
 | 
				
			||||||
 | 
					    gain by an arbitrary amount and divide by the gain change (in dB) which
 | 
				
			||||||
 | 
					    is measured at the reference wavelength (the red end of the band).
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    dgt_96 = np.loadtxt(path + 'DGT_96.txt')
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    pNFfit3:  Cubic polynomial fit coefficients to noise figure in dB 
 | 
				
			||||||
 | 
					    averaged across wavelength as a function of gain change from design flat:  
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        NFavg = pNFfit3(1)*dG^3 + pNFfit3(2)*dG^2 pNFfit3(3)*dG + pNFfit3(4)
 | 
				
			||||||
 | 
					    where 
 | 
				
			||||||
 | 
					        dG = GainTarget - average(DFG_96)
 | 
				
			||||||
 | 
					    note that dG will normally be a negative value.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    nf_fitco = np.loadtxt(path + 'pNFfit3.txt')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """NFR_96:  Noise figure ripple in dB away from the average noise figure
 | 
				
			||||||
 | 
					    across the band.  This captures the wavelength dependence of the NF.  To
 | 
				
			||||||
 | 
					    calculate the NF across channels, one uses the cubic fit coefficients
 | 
				
			||||||
 | 
					    with the external gain target to get the average nosie figure, NFavg and 
 | 
				
			||||||
 | 
					    then adds this to NFR_96:
 | 
				
			||||||
 | 
					    NF_96 = NFR_96 + NFavg
 | 
				
			||||||
 | 
					    """ 
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    nf_ripple = np.loadtxt(path + 'NFR_96.txt')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # This is an example to set the provisionable gain and gain-tilt values
 | 
				
			||||||
 | 
					    # Tilt is in units of dB/THz
 | 
				
			||||||
 | 
					    gain_target = 20.0
 | 
				
			||||||
 | 
					    tilt_target = -0.7
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # calculate the NF for the EDFA at this gain setting
 | 
				
			||||||
 | 
					    dg = gain_target - avg_dfg
 | 
				
			||||||
 | 
					    nf_avg = polyval(nf_fitco, dg)
 | 
				
			||||||
 | 
					    nf_96 = nf_ripple + nf_avg
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # get the input power profiles to show
 | 
				
			||||||
 | 
					    pch2d =  np.loadtxt(path + 'Pchan2D.txt')
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Load legend and assemble legend text
 | 
				
			||||||
 | 
					    pch2d_legend_data = np.loadtxt(path + 'Pchan2DLegend.txt')
 | 
				
			||||||
 | 
					    pch2d_legend = []
 | 
				
			||||||
 | 
					    for ea in pch2d_legend_data:
 | 
				
			||||||
 | 
					        s = ''.join([chr(xx) for xx in ea.astype(dtype=int)]).strip()
 | 
				
			||||||
 | 
					        pch2d_legend.append(s)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    #assemble plot
 | 
				
			||||||
 | 
					    axis_font = {'fontname': 'Arial', 'size':'16', 'fontweight':'bold'}
 | 
				
			||||||
 | 
					    title_font = {'fontname': 'Arial', 'size':'17', 'fontweight':'bold'}
 | 
				
			||||||
 | 
					    tic_font = {'fontname': 'Arial', 'size':'12'} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    plt.rcParams["font.family"] = "Arial"
 | 
				
			||||||
 | 
					    plt.figure()
 | 
				
			||||||
 | 
					    plt.plot(nchan, pch2d.T, '.-', lw=2)
 | 
				
			||||||
 | 
					    plt.xlabel('Channel Number', **axis_font)
 | 
				
			||||||
 | 
					    plt.ylabel('Channel Power [dBm]', **axis_font)
 | 
				
			||||||
 | 
					    plt.title('Input Power Profiles for Different Channel Loading', 
 | 
				
			||||||
 | 
					              **title_font)
 | 
				
			||||||
 | 
					    plt.legend(pch2d_legend, loc=5)
 | 
				
			||||||
 | 
					    plt.grid()
 | 
				
			||||||
 | 
					    plt.ylim((-100, -10))
 | 
				
			||||||
 | 
					    plt.xlim((0,110))
 | 
				
			||||||
 | 
					    plt.xticks(np.arange(0,100,10), **tic_font)
 | 
				
			||||||
 | 
					    plt.yticks(np.arange(-110,-10,10), **tic_font)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    plt.figure()
 | 
				
			||||||
 | 
					    ea = pch2d[1,:]
 | 
				
			||||||
 | 
					    for ea in pch2d:
 | 
				
			||||||
 | 
					        chgain = gain_profile(dfg_96, dgt_96, ea, gain_target, tilt_target)
 | 
				
			||||||
 | 
					        pase = noise_profile(nf_96, chgain, fc, df)
 | 
				
			||||||
 | 
					        pout = lin2db(db2lin(ea + chgain) + db2lin(pase))
 | 
				
			||||||
 | 
					        plt.plot(nchan, pout, '.-', lw=2)
 | 
				
			||||||
 | 
					    plt.title('Output Power with ASE for Different Channel Loading', 
 | 
				
			||||||
 | 
					              **title_font)
 | 
				
			||||||
 | 
					    plt.xlabel('Channel Number', **axis_font)
 | 
				
			||||||
 | 
					    plt.ylabel('Channel Power [dBm]', **axis_font)
 | 
				
			||||||
 | 
					    plt.grid()
 | 
				
			||||||
 | 
					    plt.ylim((-50, 10))
 | 
				
			||||||
 | 
					    plt.xlim((0,100))
 | 
				
			||||||
 | 
					    plt.xticks(np.arange(0,100,10), **tic_font)
 | 
				
			||||||
 | 
					    plt.yticks(np.arange(-50,10,10), **tic_font)
 | 
				
			||||||
 | 
					    plt.legend(pch2d_legend, loc=5)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										1
									
								
								examples/edfa_model/pNFfit3.txt
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								examples/edfa_model/pNFfit3.txt
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					   1.6824099999999999e-04   4.6996099999999999e-02   3.5954899999999998e-02   5.8285099999999996e+00
 | 
				
			||||||
							
								
								
									
										120
									
								
								examples/edfa_model/utilities.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								examples/edfa_model/utilities.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Created on Fri Nov 10 17:50:46 2017
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@author: briantaylor
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
 | 
					from numpy import pi, cos, sqrt, log10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def c():
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Returns the speed of light in meters per second
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return 299792458.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def itufs(spacing, startf=191.35, stopf=196.10):
 | 
				
			||||||
 | 
					    """Creates an array of frequencies whose default range is
 | 
				
			||||||
 | 
					    191.35-196.10 THz
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    :param spacing: Frequency spacing in THz
 | 
				
			||||||
 | 
					    :param starf: Start frequency in THz
 | 
				
			||||||
 | 
					    :param stopf: Stop frequency in THz
 | 
				
			||||||
 | 
					    :type spacing: float
 | 
				
			||||||
 | 
					    :type startf: float
 | 
				
			||||||
 | 
					    :type stopf: float
 | 
				
			||||||
 | 
					    :return an array of frequnecies determined by the spacing parameter
 | 
				
			||||||
 | 
					    :rtype: numpy.ndarray
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return np.arange(startf, stopf + spacing/2, spacing)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def h():
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Returns plank's constant in J*s
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return 6.62607004e-34
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def lin2db(value):
 | 
				
			||||||
 | 
					    return 10*log10(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def db2lin(value):
 | 
				
			||||||
 | 
					    return 10**(value/10)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def wavelength2freq(value):
 | 
				
			||||||
 | 
					    """ Converts wavelength units to frequeuncy units.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return c()/value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def freq2wavelength(value):
 | 
				
			||||||
 | 
					    """ Converts frequency units to wavelength units.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return c()/value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def deltawl2deltaf(delta_wl, wavelength):
 | 
				
			||||||
 | 
					    """ deltawl2deltaf(delta_wl, wavelength):
 | 
				
			||||||
 | 
					    delta_wl is BW in wavelength units
 | 
				
			||||||
 | 
					    wavelength is the center wl
 | 
				
			||||||
 | 
					    units for delta_wl and wavelength must be same
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param delta_wl: delta wavelength BW in same units as wavelength
 | 
				
			||||||
 | 
					    :param wavelength: wavelength BW is relevant for
 | 
				
			||||||
 | 
					    :type delta_wl: float or numpy.ndarray
 | 
				
			||||||
 | 
					    :type wavelength: float
 | 
				
			||||||
 | 
					    :return: The BW in frequency units
 | 
				
			||||||
 | 
					    :rtype: float or ndarray
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """ 
 | 
				
			||||||
 | 
					    f = wavelength2freq(wavelength)
 | 
				
			||||||
 | 
					    return delta_wl*f/wavelength
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def deltaf2deltawl(delta_f, frequency):
 | 
				
			||||||
 | 
					    """ deltawl2deltaf(delta_f, frequency):
 | 
				
			||||||
 | 
					        converts delta frequency to delta wavelength
 | 
				
			||||||
 | 
					        units for delta_wl and wavelength must be same
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    :param delta_f: delta frequency in same units as frequency
 | 
				
			||||||
 | 
					    :param frequency: frequency BW is relevant for
 | 
				
			||||||
 | 
					    :type delta_f: float or numpy.ndarray
 | 
				
			||||||
 | 
					    :type frequency: float
 | 
				
			||||||
 | 
					    :return: The BW in wavelength units
 | 
				
			||||||
 | 
					    :rtype: float or ndarray
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    wl = freq2wavelength(frequency)
 | 
				
			||||||
 | 
					    return delta_f*wl/frequency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def rrc(ffs, baud_rate, alpha):
 | 
				
			||||||
 | 
					    """ rrc(ffs, baud_rate, alpha): computes the root-raised cosine filter 
 | 
				
			||||||
 | 
					    function.
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    :param ffs: A numpy array of frequencies
 | 
				
			||||||
 | 
					    :param baud_rate: The Baud Rate of the System
 | 
				
			||||||
 | 
					    :param alpha: The roll-off factor of the filter
 | 
				
			||||||
 | 
					    :type ffs: numpy.ndarray
 | 
				
			||||||
 | 
					    :type baud_rate: float
 | 
				
			||||||
 | 
					    :type alpha: float
 | 
				
			||||||
 | 
					    :return: hf a numpy array of the filter shape
 | 
				
			||||||
 | 
					    :rtype: numpy.ndarray
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Ts = 1/baud_rate
 | 
				
			||||||
 | 
					    l_lim = (1 - alpha)/(2 * Ts)
 | 
				
			||||||
 | 
					    r_lim = (1 + alpha)/(2 * Ts)
 | 
				
			||||||
 | 
					    hf = np.zeros(np.shape(ffs))
 | 
				
			||||||
 | 
					    slope_inds = np.where(
 | 
				
			||||||
 | 
					            np.logical_and(np.abs(ffs) > l_lim, np.abs(ffs) < r_lim))
 | 
				
			||||||
 | 
					    hf[slope_inds] = 0.5 * (1 + cos((pi * Ts / alpha) * 
 | 
				
			||||||
 | 
					            (np.abs(ffs[slope_inds]) - l_lim)))
 | 
				
			||||||
 | 
					    p_inds = np.where(np.logical_and(np.abs(ffs) > 0, np.abs(ffs) < l_lim))
 | 
				
			||||||
 | 
					    hf[p_inds] =  1
 | 
				
			||||||
 | 
					    return sqrt(hf)
 | 
				
			||||||
							
								
								
									
										120
									
								
								utilities.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								utilities.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Created on Fri Nov 10 17:50:46 2017
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@author: briantaylor
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
 | 
					from numpy import pi, cos, sqrt, log10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def c():
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Returns the speed of light in meters per second
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return 299792458.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def itufs(spacing, startf=191.35, stopf=196.10):
 | 
				
			||||||
 | 
					    """Creates an array of frequencies whose default range is
 | 
				
			||||||
 | 
					    191.35-196.10 THz
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    :param spacing: Frequency spacing in THz
 | 
				
			||||||
 | 
					    :param starf: Start frequency in THz
 | 
				
			||||||
 | 
					    :param stopf: Stop frequency in THz
 | 
				
			||||||
 | 
					    :type spacing: float
 | 
				
			||||||
 | 
					    :type startf: float
 | 
				
			||||||
 | 
					    :type stopf: float
 | 
				
			||||||
 | 
					    :return an array of frequnecies determined by the spacing parameter
 | 
				
			||||||
 | 
					    :rtype: numpy.ndarray
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return np.arange(startf, stopf + spacing/2, spacing)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def h():
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Returns plank's constant in J*s
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return 6.62607004e-34
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def lin2db(value):
 | 
				
			||||||
 | 
					    return 10*log10(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def db2lin(value):
 | 
				
			||||||
 | 
					    return 10**(value/10)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def wavelength2freq(value):
 | 
				
			||||||
 | 
					    """ Converts wavelength units to frequeuncy units.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return c()/value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def freq2wavelength(value):
 | 
				
			||||||
 | 
					    """ Converts frequency units to wavelength units.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return c()/value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def deltawl2deltaf(delta_wl, wavelength):
 | 
				
			||||||
 | 
					    """ deltawl2deltaf(delta_wl, wavelength):
 | 
				
			||||||
 | 
					    delta_wl is BW in wavelength units
 | 
				
			||||||
 | 
					    wavelength is the center wl
 | 
				
			||||||
 | 
					    units for delta_wl and wavelength must be same
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param delta_wl: delta wavelength BW in same units as wavelength
 | 
				
			||||||
 | 
					    :param wavelength: wavelength BW is relevant for
 | 
				
			||||||
 | 
					    :type delta_wl: float or numpy.ndarray
 | 
				
			||||||
 | 
					    :type wavelength: float
 | 
				
			||||||
 | 
					    :return: The BW in frequency units
 | 
				
			||||||
 | 
					    :rtype: float or ndarray
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """ 
 | 
				
			||||||
 | 
					    f = wavelength2freq(wavelength)
 | 
				
			||||||
 | 
					    return delta_wl*f/wavelength
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def deltaf2deltawl(delta_f, frequency):
 | 
				
			||||||
 | 
					    """ deltawl2deltaf(delta_f, frequency):
 | 
				
			||||||
 | 
					        converts delta frequency to delta wavelength
 | 
				
			||||||
 | 
					        units for delta_wl and wavelength must be same
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    :param delta_f: delta frequency in same units as frequency
 | 
				
			||||||
 | 
					    :param frequency: frequency BW is relevant for
 | 
				
			||||||
 | 
					    :type delta_f: float or numpy.ndarray
 | 
				
			||||||
 | 
					    :type frequency: float
 | 
				
			||||||
 | 
					    :return: The BW in wavelength units
 | 
				
			||||||
 | 
					    :rtype: float or ndarray
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    wl = freq2wavelength(frequency)
 | 
				
			||||||
 | 
					    return delta_f*wl/frequency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def rrc(ffs, baud_rate, alpha):
 | 
				
			||||||
 | 
					    """ rrc(ffs, baud_rate, alpha): computes the root-raised cosine filter 
 | 
				
			||||||
 | 
					    function.
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    :param ffs: A numpy array of frequencies
 | 
				
			||||||
 | 
					    :param baud_rate: The Baud Rate of the System
 | 
				
			||||||
 | 
					    :param alpha: The roll-off factor of the filter
 | 
				
			||||||
 | 
					    :type ffs: numpy.ndarray
 | 
				
			||||||
 | 
					    :type baud_rate: float
 | 
				
			||||||
 | 
					    :type alpha: float
 | 
				
			||||||
 | 
					    :return: hf a numpy array of the filter shape
 | 
				
			||||||
 | 
					    :rtype: numpy.ndarray
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Ts = 1/baud_rate
 | 
				
			||||||
 | 
					    l_lim = (1 - alpha)/(2 * Ts)
 | 
				
			||||||
 | 
					    r_lim = (1 + alpha)/(2 * Ts)
 | 
				
			||||||
 | 
					    hf = np.zeros(np.shape(ffs))
 | 
				
			||||||
 | 
					    slope_inds = np.where(
 | 
				
			||||||
 | 
					            np.logical_and(np.abs(ffs) > l_lim, np.abs(ffs) < r_lim))
 | 
				
			||||||
 | 
					    hf[slope_inds] = 0.5 * (1 + cos((pi * Ts / alpha) * 
 | 
				
			||||||
 | 
					            (np.abs(ffs[slope_inds]) - l_lim)))
 | 
				
			||||||
 | 
					    p_inds = np.where(np.logical_and(np.abs(ffs) > 0, np.abs(ffs) < l_lim))
 | 
				
			||||||
 | 
					    hf[p_inds] =  1
 | 
				
			||||||
 | 
					    return sqrt(hf)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user