dual stage

Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
This commit is contained in:
Jean-Luc Auge
2019-02-07 17:55:10 +01:00
parent bf943f1347
commit 7b9647a063
3 changed files with 117 additions and 38 deletions

View File

@@ -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,

View File

@@ -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:

View File

@@ -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