Source code for denspp.offline.analog.dev_load

import numpy as np
from .dev_noise import SettingsNoise
from .dev_handler import ElectricalLoadHandler, SettingsDevice



DefaultSettingsDEVResistor = SettingsDevice(
    type='R',
    fs_ana=50e3,
    noise_en=False,
    params_use={'r': 100e3},
    temp=300,
    use_poly=False
)


DefaultSettingsDEVResistiveDiodeSingle = SettingsDevice(
    type='RDs',
    fs_ana=50e3,
    noise_en=False,
    params_use={'i_sat': 10e-12, 'n_eff': 2.8, 'uth0': 0.1, 'r_sh': 20e3},
    temp=300,
    use_poly=False
)


DefaultSettingsDEVResistiveDiodeDouble = SettingsDevice(
    type='RDd',
    fs_ana=50e3,
    noise_en=False,
    params_use={'i_sat': 1e-12, 'n_eff': 2.8, 'uth0': 0.1, 'r_sh': 20e3},
    temp=300,
    use_poly=False
)


RecommendedSettingsNoise = SettingsNoise(
    temp=300,
    wgn_dB=-120,
    Fc=10,
    slope=0.6
)

[docs] class ElectricalLoad(ElectricalLoadHandler): def __init__(self, settings_dev: SettingsDevice, settings_noise=RecommendedSettingsNoise): ElectricalLoadHandler.__init__(self, settings_dev) # --- Registering electrical devices self.register_device( short_label='R', description='Resistor', func_equa=self._equation_resistor, func_reg=self._func2reg_resistor, func_fit=self._func2cur_resistor ) self.register_device( short_label='RDs', description='Resistive diode (single)', func_equa=self._equation_resistive_diode_single, func_reg=self._func2reg_resistive_diode, func_fit=self._func2cur_resistive_diode ) self.register_device( short_label='RDd', description='Resistive diode (anti-parallel)', func_equa=self._equation_resistive_diode_antiparallel, func_reg=self._func2reg_resistive_diode, func_fit=self._func2cur_resistive_diode ) def _equation_resistor(self, u_inp: np.ndarray, u_inn: np.ndarray | float, params: dict) -> np.ndarray: """Performing the behaviour of an electrical resistor :param u_inp: Positive input voltage [V] :param u_inn: Negative input voltage [V] :param params: Dictionary with device parameters :return: Corresponding current signal """ du = u_inp - u_inn i_out = du / params['r'] if self._settings_device.noise_en: i_out += self.gen_noise_awgn_curr(du.size, params['r']) return i_out def _func2cur_resistor(self, i_device: np.ndarray, r: float) -> np.ndarray: """Function for fitting the electrical inputs (voltage/ current) to model parameters for a resistor :param i_device: Numpy array with current parameters :param r: Resistance :return: Numpy array with extracted voltage """ return r * i_device def _func2reg_resistor(self, i_path: np.ndarray, xd: np.ndarray, params: dict) -> np.ndarray: """Function for do least_squared regression :param i_path: Input current sample (--> output value) :param xd: Input difference voltage sample :param params: Dictionary with device parameters :return: Numpy value with corresponding difference voltage (goes to zero with further optimization) """ v1 = self._func2cur_resistor(i_path, **params) return xd - v1 def _equation_resistive_diode_single(self, u_inp: np.ndarray, u_inn: np.ndarray | float, params: dict) -> np.ndarray: """Performing the behaviour of a series connection of resistor and a diode :param u_inp: Positive input voltage [V] :param u_inn: Negative input voltage [V] :param params: Dictionary with device parameters :return: Corresponding current signal """ i_fit = self._get_current_resistive_diode(u_inp, u_inn, params, False) xpos_neg = np.argwhere(u_inp-u_inn < 0.0).flatten() if not xpos_neg.size == 0: i_fit[xpos_neg] = 0.0 return i_fit def _equation_resistive_diode_antiparallel(self, u_inp: np.ndarray, u_inn: np.ndarray | float, params: dict) -> np.ndarray: """Performing the behaviour of a series connection of resistor and a diode :param u_inp: Positive input voltage [V] :param u_inn: Negative input voltage [V] :param params: Dictionary with device parameters :return: Corresponding current signal """ i_fit = self._get_current_resistive_diode(u_inp, u_inn, params, True) xpos_neg = np.argwhere(u_inp-u_inn < 0.0).flatten() if not xpos_neg.size == 0: i_fit[xpos_neg] = (-1) * i_fit[xpos_neg] return i_fit def _func2cur_resistive_diode(self, i_path: np.ndarray, uth0: float, r_sh: float, n_eff: float, i_sat: float) -> np.ndarray: """Function for performing curve fitting for resistive diode behaviour :param i_path: Numpy array with current signal [A] :param uth0: Threshold voltage of device :param r_sh: Shunt resistance :param n_eff: Effective emission coefficient :param i_sat: Saturation current :return: Corresponding voltage signal """ return uth0 + r_sh * i_path + n_eff * self._settings_device.temperature_voltage * np.log(i_path / i_sat + 1) def _func2reg_resistive_diode(self, i_path: np.ndarray, xd: np.ndarray, params: dict) -> np.ndarray: """Function for do least_squared regression :param i_path: Input current sample (--> output value) :param xd: Input difference voltage sample :return: Numpy value with corresponding difference voltage (goes to zero with further optimization) """ v1 = self._func2cur_resistive_diode(i_path, **params) return xd - v1 def _get_current_resistive_diode(self, u_inp: np.ndarray, u_inn: np.ndarray | float, params: dict, mode: bool) -> np.ndarray: """Performing the behaviour of a series connection of resistor and a diode :param u_inp: Positive input voltage [V] :parma u_inn: Negative input voltage [V] :param params: Dictionary with device parameters :param mode: Single side Connection (False) or antiparallel Connection (True) :return: Corresponding current signal """ du = u_inp - u_inn if not mode else np.abs(u_inp - u_inn) if isinstance(du, float): du = np.zeros(shape=(1,)) du[0] = u_inp - u_inn i_fit = self._do_regression(u_inp=u_inp, u_inn=u_inn, params=params, disable_print=True) # --- Checking if voltage limits or current limits are reached xpos_uth = np.argwhere(du < 0.0).flatten() if not xpos_uth.size == 0: i_fit[xpos_uth] = params['i_sat'] xpos_i0 = np.argwhere(i_fit < 0.0).flatten() if not xpos_i0.size == 0: i_fit[xpos_i0] = params['i_sat'] # --- Adding noise if self._settings_device.noise_en: i_fit += self.gen_noise_awgn_curr(du.size, params['r_sh']) return i_fit