mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-11-02 02:57:52 +00:00
@@ -1,5 +1,6 @@
|
|||||||
{ "Edfa":[{
|
{ "Edfa":[{
|
||||||
"type_variety": "high_detail_model_example",
|
"type_variety": "high_detail_model_example",
|
||||||
|
"type_def": "advanced_model",
|
||||||
"gain_flatmax": 25,
|
"gain_flatmax": 25,
|
||||||
"gain_min": 15,
|
"gain_min": 15,
|
||||||
"p_max": 21,
|
"p_max": 21,
|
||||||
@@ -84,7 +85,15 @@
|
|||||||
"p_max": 21,
|
"p_max": 21,
|
||||||
"nf0": 5.5,
|
"nf0": 5.5,
|
||||||
"allowed_for_design": false
|
"allowed_for_design": false
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"type_variety": "a+b",
|
||||||
|
"type_def": "dual_stage",
|
||||||
|
"gain_min": 20,
|
||||||
|
"preamp_variety": "std_medium_gain",
|
||||||
|
"booster_variety": "std_low_gain",
|
||||||
|
"allowed_for_design": true
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"Fiber":[{
|
"Fiber":[{
|
||||||
"type_variety": "SSMF",
|
"type_variety": "SSMF",
|
||||||
@@ -117,7 +126,11 @@
|
|||||||
"Roadms":[{
|
"Roadms":[{
|
||||||
"gain_mode_default_loss": 20,
|
"gain_mode_default_loss": 20,
|
||||||
"power_mode_pout_target": -20,
|
"power_mode_pout_target": -20,
|
||||||
"add_drop_osnr": 38
|
"add_drop_osnr": 38,
|
||||||
|
"restrictions": {
|
||||||
|
"preamp_variety_list":["low_gain_preamp", "high_gain_preamp"],
|
||||||
|
"booster_variety_list":["std_booster"]
|
||||||
|
}
|
||||||
}],
|
}],
|
||||||
"SI":[{
|
"SI":[{
|
||||||
"f_min": 191.3e12,
|
"f_min": 191.3e12,
|
||||||
|
|||||||
@@ -588,12 +588,29 @@ class Edfa(Node):
|
|||||||
# ase & nli are only calculated in signal bandwidth
|
# ase & nli are only calculated in signal bandwidth
|
||||||
# pout_db is not the absolute full output power (negligible if sufficient channels)
|
# pout_db is not the absolute full output power (negligible if sufficient channels)
|
||||||
|
|
||||||
def _nf_variable_gain(self, params, gain_target):
|
def _nf(self, type_def, nf_model, nf_fit_coef, gain_flatmax, gain_target):
|
||||||
#if hybrid raman, use edfa_gain_flatmax attribute, else use gain_flatmax
|
#if hybrid raman, use edfa_gain_flatmax attribute, else use gain_flatmax
|
||||||
gain_flatmax = getattr(params, 'edfa_gain_flatmax', params.gain_flatmax)
|
#gain_flatmax = getattr(params, 'edfa_gain_flatmax', params.gain_flatmax)
|
||||||
dg = max(gain_flatmax - gain_target, 0)
|
dg = max(gain_flatmax - gain_target, 0)
|
||||||
g1a = gain_target - params.nf_model.delta_p - dg
|
if type_def == 'variable_gain':
|
||||||
nf_avg = lin2db(db2lin(params.nf_model.nf1) + db2lin(params.nf_model.nf2)/db2lin(g1a))
|
g1a = gain_target - nf_model.delta_p - dg
|
||||||
|
nf_avg = lin2db(db2lin(nf_model.nf1) + db2lin(nf_model.nf2)/db2lin(g1a))
|
||||||
|
elif type_def == 'fixed_gain':
|
||||||
|
nf_avg = nf_model.nf0
|
||||||
|
elif type_def == 'openroadm':
|
||||||
|
pin_ch = self.pin_db - lin2db(self.nch)
|
||||||
|
# model OSNR = f(Pin)
|
||||||
|
nf_avg = pin_ch - polyval(nf_model.nf_coef, pin_ch) + 58
|
||||||
|
elif type_def == 'advanced_model':
|
||||||
|
nf_avg = polyval(nf_fit_coeff, -dg)
|
||||||
|
else :
|
||||||
|
print(
|
||||||
|
f'\x1b[1;31;40m'\
|
||||||
|
+ f'CRITICAL: unrecognized type def _{self.params.type_def}_\n\
|
||||||
|
=> please check eqpt_config.json'\
|
||||||
|
+ '\x1b[0m'
|
||||||
|
)
|
||||||
|
exit()
|
||||||
return nf_avg
|
return nf_avg
|
||||||
|
|
||||||
def _calc_nf(self, avg = False):
|
def _calc_nf(self, avg = False):
|
||||||
@@ -602,23 +619,19 @@ class Edfa(Node):
|
|||||||
False => polynomial fit based on self.params.nf_fit_coeff"""
|
False => polynomial fit based on self.params.nf_fit_coeff"""
|
||||||
# TODO|jla: TBD alarm rising or input VOA padding in case
|
# TODO|jla: TBD alarm rising or input VOA padding in case
|
||||||
# gain_min > gain_target TBD:
|
# gain_min > gain_target TBD:
|
||||||
pad = max(self.params.gain_min - self.effective_gain, 0)
|
|
||||||
gain_target = self.effective_gain + pad
|
|
||||||
|
|
||||||
if self.params.type_def == 'variable_gain':
|
|
||||||
nf_avg = self._nf_variable_gain(self.params, gain_target)
|
if self.params.type_def == 'hybrid':
|
||||||
elif self.params.type_def == 'fixed_gain':
|
#pas de padding en raman, sauf implem specifique entre le raman et l'edfa: non supportée
|
||||||
nf_avg = self.params.nf_model.nf0
|
|
||||||
elif self.params.type_def == 'openroadm':
|
|
||||||
pin_ch = self.pin_db - lin2db(self.nch)
|
|
||||||
# model OSNR = f(Pin)
|
|
||||||
nf_avg = pin_ch - polyval(self.params.nf_model.nf_coef, pin_ch) + 58
|
|
||||||
elif self.params.type_def == 'hybrid':
|
|
||||||
#pas de padding en raman, sauf implem specifique entre le raman et l'edfa, non supporté
|
|
||||||
pad = 0
|
pad = 0
|
||||||
|
|
||||||
# update gain_target with ramnan gain
|
# update gain_target with ramnan gain
|
||||||
gain_target = self.effective_gain - self.params.raman_model.gain_ram
|
gain_target = self.effective_gain - self.params.raman_model.gain_ram
|
||||||
nf_edfa_avg = self._nf_variable_gain(self.params, gain_target)
|
nf_edfa_avg = self._nf( 'variable_gain',
|
||||||
|
self.params.nf_model,
|
||||||
|
None,
|
||||||
|
self.params.edfa_gain_flatmax,
|
||||||
|
gain_target)
|
||||||
#DEBUG/CHECK:
|
#DEBUG/CHECK:
|
||||||
#print('gain total', self.effective_gain )
|
#print('gain total', self.effective_gain )
|
||||||
#print('gain', gain_target)
|
#print('gain', gain_target)
|
||||||
@@ -628,10 +641,30 @@ class Edfa(Node):
|
|||||||
+ db2lin(nf_edfa_avg)
|
+ db2lin(nf_edfa_avg)
|
||||||
/ db2lin(self.params.raman_model.gain_ram)\
|
/ db2lin(self.params.raman_model.gain_ram)\
|
||||||
)
|
)
|
||||||
print('hybrid',nf_avg)
|
elif self.params.type_def == 'dual_stage':
|
||||||
else: #use polynomial model
|
pad = 0
|
||||||
dg = max(self.params.gain_flatmax - gain_target, 0)
|
g1 = self.params.preamp_gain_flatmax
|
||||||
nf_avg = polyval(self.params.nf_fit_coeff, -dg)
|
g2 = self.effective_gain - g1
|
||||||
|
nf1_avg = self._nf( self.params.preamp_type_def,
|
||||||
|
self.params.preamp_nf_model,
|
||||||
|
self.params.preamp_nf_fit_coeff,
|
||||||
|
self.params.preamp_gain_flatmax,
|
||||||
|
g1)
|
||||||
|
nf2_avg = self._nf( self.params.booster_type_def,
|
||||||
|
self.params.booster_nf_model,
|
||||||
|
self.params.booster_nf_fit_coeff,
|
||||||
|
self.params.booster_gain_flatmax,
|
||||||
|
g2)
|
||||||
|
nf_avg = lin2db(db2lin(nf1_avg) + db2lin(nf2_avg-g1))
|
||||||
|
else:
|
||||||
|
pad = max(self.params.gain_min - self.effective_gain, 0)
|
||||||
|
gain_target = self.effective_gain + pad
|
||||||
|
|
||||||
|
nf_avg = self._nf( self.params.type_def,
|
||||||
|
self.params.nf_model,
|
||||||
|
self.params.nf_fit_coeff,
|
||||||
|
self.params.gain_flatmax,
|
||||||
|
gain_target)
|
||||||
|
|
||||||
self.att_in = pad
|
self.att_in = pad
|
||||||
if avg:
|
if avg:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ Model_vg = namedtuple('Model_vg', 'nf1 nf2 delta_p')
|
|||||||
Model_fg = namedtuple('Model_fg', 'nf0')
|
Model_fg = namedtuple('Model_fg', 'nf0')
|
||||||
Model_openroadm = namedtuple('Model_openroadm', 'nf_coef')
|
Model_openroadm = namedtuple('Model_openroadm', 'nf_coef')
|
||||||
Model_hybrid = namedtuple('Model_hybrid', 'nf_ram gain_ram edfa_variety')
|
Model_hybrid = namedtuple('Model_hybrid', 'nf_ram gain_ram edfa_variety')
|
||||||
|
Model_dual_stage = namedtuple('Model_dual_stage', 'preamp_variety booster_variety')
|
||||||
|
|
||||||
class common:
|
class common:
|
||||||
def update_attr(self, default_values, kwargs):
|
def update_attr(self, default_values, kwargs):
|
||||||
@@ -107,6 +108,7 @@ class Amp(common):
|
|||||||
'p_max': None,
|
'p_max': None,
|
||||||
'nf_model': None,
|
'nf_model': None,
|
||||||
'raman_model': None,
|
'raman_model': None,
|
||||||
|
'dual_stage_model': None,
|
||||||
'nf_fit_coeff': None,
|
'nf_fit_coeff': None,
|
||||||
'nf_ripple': None,
|
'nf_ripple': None,
|
||||||
'dgt': None,
|
'dgt': None,
|
||||||
@@ -119,19 +121,14 @@ class Amp(common):
|
|||||||
self.update_attr(self.default_values, kwargs)
|
self.update_attr(self.default_values, kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_advanced_json(cls, filename, **kwargs):
|
def from_json(cls, filename, **kwargs):
|
||||||
with open(filename, encoding='utf-8') as f:
|
config = Path(filename).parent / 'default_edfa_config.json'
|
||||||
json_data = load(f)
|
|
||||||
return cls(**{**kwargs, **json_data, 'type_def':None, 'nf_model':None})
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_default_json(cls, filename, **kwargs):
|
|
||||||
with open(filename, encoding='utf-8') as f:
|
|
||||||
json_data = load(f)
|
|
||||||
type_variety = kwargs['type_variety']
|
type_variety = kwargs['type_variety']
|
||||||
type_def = kwargs.get('type_def', 'variable_gain') #default compatibility with older json eqpt files
|
type_def = kwargs.get('type_def', 'variable_gain') #default compatibility with older json eqpt files
|
||||||
nf_def = None
|
nf_def = None
|
||||||
raman_def = None
|
raman_def = None
|
||||||
|
dual_stage_def = None
|
||||||
|
|
||||||
if type_def == 'fixed_gain':
|
if type_def == 'fixed_gain':
|
||||||
try:
|
try:
|
||||||
@@ -144,6 +141,8 @@ class Amp(common):
|
|||||||
del kwargs['nf_max']
|
del kwargs['nf_max']
|
||||||
except KeyError: pass #nf_min and nf_max are not needed for fixed gain amp
|
except KeyError: pass #nf_min and nf_max are not needed for fixed gain amp
|
||||||
nf_def = Model_fg(nf0)
|
nf_def = Model_fg(nf0)
|
||||||
|
elif type_def == 'advanced_model':
|
||||||
|
config = Path(filename).parent / kwargs.pop('advanced_config_from_json')
|
||||||
elif type_def == 'variable_gain':
|
elif type_def == 'variable_gain':
|
||||||
gain_min, gain_max = kwargs['gain_min'], kwargs['gain_flatmax']
|
gain_min, gain_max = kwargs['gain_min'], kwargs['gain_flatmax']
|
||||||
try: #nf_min and nf_max are expected for a variable gain amp
|
try: #nf_min and nf_max are expected for a variable gain amp
|
||||||
@@ -173,7 +172,20 @@ class Amp(common):
|
|||||||
print(f'missing nf_ram/gain_ram values input for amplifier: {type_variety} in eqpt_config.json')
|
print(f'missing nf_ram/gain_ram values input for amplifier: {type_variety} in eqpt_config.json')
|
||||||
exit()
|
exit()
|
||||||
raman_def = Model_hybrid(nf_ram, gain_ram, edfa_variety)
|
raman_def = Model_hybrid(nf_ram, gain_ram, edfa_variety)
|
||||||
return cls(**{**kwargs, **json_data, 'nf_model': nf_def, 'raman_model' : raman_def})
|
elif type_def == 'dual_stage':
|
||||||
|
try: #nf_ram and gain_ram are expected for a hybrid amp
|
||||||
|
preamp_variety = kwargs.pop('preamp_variety')
|
||||||
|
booster_variety = kwargs.pop('booster_variety')
|
||||||
|
except KeyError:
|
||||||
|
print(f'missing preamp/booster variety input for amplifier: {type_variety} in eqpt_config.json')
|
||||||
|
exit()
|
||||||
|
dual_stage_def = Model_dual_stage(preamp_variety, booster_variety)
|
||||||
|
|
||||||
|
with open(config, encoding='utf-8') as f:
|
||||||
|
json_data = load(f)
|
||||||
|
|
||||||
|
return cls(**{**kwargs, **json_data,
|
||||||
|
'nf_model': nf_def, 'raman_model' : raman_def, 'dual_stage_model': dual_stage_def})
|
||||||
|
|
||||||
|
|
||||||
def nf_model(type_variety, gain_min, gain_max, nf_min, nf_max):
|
def nf_model(type_variety, gain_min, gain_max, nf_min, nf_max):
|
||||||
@@ -341,6 +353,31 @@ def update_hybrid(equipment):
|
|||||||
edfa.edfa_gain_flatmax = edfa_booster.gain_flatmax
|
edfa.edfa_gain_flatmax = edfa_booster.gain_flatmax
|
||||||
return equipment
|
return equipment
|
||||||
|
|
||||||
|
def update_dual_stage(equipment):
|
||||||
|
edfa_dict = equipment['Edfa']
|
||||||
|
for edfa in edfa_dict.values():
|
||||||
|
if edfa.type_def == 'dual_stage':
|
||||||
|
edfa_preamp = edfa_dict[edfa.dual_stage_model.preamp_variety]
|
||||||
|
edfa_booster = edfa_dict[edfa.dual_stage_model.booster_variety]
|
||||||
|
for k,v in edfa_preamp.__dict__.items():
|
||||||
|
attr_k = 'preamp_'+k
|
||||||
|
setattr(edfa, attr_k, v)
|
||||||
|
for k,v in edfa_booster.__dict__.items():
|
||||||
|
attr_k = 'booster_'+k
|
||||||
|
setattr(edfa, attr_k, v)
|
||||||
|
edfa.p_max = edfa_booster.p_max
|
||||||
|
edfa.gain_flatmax = edfa_booster.gain_flatmax + edfa_preamp.gain_flatmax
|
||||||
|
if edfa.gain_min < edfa_preamp.gain_min:
|
||||||
|
print(
|
||||||
|
f'\x1b[1;31;40m'\
|
||||||
|
+ f'CRITICAL: dual stage {edfa.type_variety} min gain is lower than its preamp min gain\
|
||||||
|
=> please increase its min gain in eqpt_config.json'\
|
||||||
|
+ '\x1b[0m'
|
||||||
|
)
|
||||||
|
exit()
|
||||||
|
return equipment
|
||||||
|
|
||||||
|
|
||||||
def equipment_from_json(json_data, filename):
|
def equipment_from_json(json_data, filename):
|
||||||
"""build global dictionnary eqpt_library that stores all eqpt characteristics:
|
"""build global dictionnary eqpt_library that stores all eqpt characteristics:
|
||||||
edfa type type_variety, fiber type_variety
|
edfa type type_variety, fiber type_variety
|
||||||
@@ -357,14 +394,10 @@ def equipment_from_json(json_data, filename):
|
|||||||
for entry in entries:
|
for entry in entries:
|
||||||
subkey = entry.get('type_variety', 'default')
|
subkey = entry.get('type_variety', 'default')
|
||||||
if key == 'Edfa':
|
if key == 'Edfa':
|
||||||
if 'advanced_config_from_json' in entry:
|
equipment[key][subkey] = Amp.from_json(filename, **entry)
|
||||||
config = Path(filename).parent / entry.pop('advanced_config_from_json')
|
|
||||||
equipment[key][subkey] = Amp.from_advanced_json(config, **entry)
|
|
||||||
else:
|
|
||||||
config = Path(filename).parent / 'default_edfa_config.json'
|
|
||||||
equipment[key][subkey] = Amp.from_default_json(config, **entry)
|
|
||||||
else:
|
else:
|
||||||
equipment[key][subkey] = typ(**entry)
|
equipment[key][subkey] = typ(**entry)
|
||||||
equipment = update_trx_osnr(equipment)
|
equipment = update_trx_osnr(equipment)
|
||||||
equipment = update_hybrid(equipment)
|
equipment = update_hybrid(equipment)
|
||||||
|
equipment = update_dual_stage(equipment)
|
||||||
return equipment
|
return equipment
|
||||||
|
|||||||
Reference in New Issue
Block a user