Skip to content
Snippets Groups Projects
Select Git revision
  • 401b3338ce8a2771667a2059f01ba80dd814c4ec
  • main default protected
2 results

setup.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    test_esipp_converter.py 8.35 KiB
    # imports
    
    # standard
    
    import random
    
    # local, external
    
    import numpy as np
    
    # local, internal
    
    import src.topupopt.problems.esipp.dynsys as dynsys
    
    import src.topupopt.problems.esipp.converter as cvn
    
    import src.topupopt.problems.esipp.signal as sgn
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    class TestConverter:
        # **************************************************************************
        # **************************************************************************
    
        # test converters
        # 1) regular and irregular time steps
        # 2) time invariant and time varying models
        # 3) integrate and do not integrate outputs
        # 4) generate coefficients
    
        # test creating a stateless converter without outputs
    
        # test creating a stateless converter with 1 output
    
        # test creating a stateless converter with 2 output
    
        # test creating a converter based on a single ODE system without outputs
    
        # test creating a converter based on a single ODE system with 1 output
    
        # test creating a converter based on a single ODE system with 2 output
    
        # test creating a converter based on a multiple ODE system without outputs
    
        # test creating a converter based on a multiple ODE system with 1 output
    
        # test creating a converter based on a multiple ODE multi-output system
    
        # **************************************************************************
        # **************************************************************************
    
        def test_full_converter_regular(self):
            time_step_durations = [1, 1, 1, 1]
            method_full_converter(time_step_durations)
    
        # **************************************************************************
        # **************************************************************************
    
        def test_full_converter_irregular(self):
            time_step_durations = [1, 1.5, 0.5, 1]
            method_full_converter(time_step_durations)
    
        # **************************************************************************
        # **************************************************************************
    
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    def get_stateless_model_data(relative_amplitude_variation: float = 0.0):
        mrh_deviation = random.random() - 0.5
    
        Aw = 6.22  # original: 6.22 m2
    
        min_rel_heat = 0.2 * (1 + relative_amplitude_variation * mrh_deviation)
    
        return Aw, min_rel_heat
    
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    def get_single_ode_model_data(relative_amplitude_variation: float = 0.0):
        # define how the coefficients change
    
        Ria_deviation = random.random() - 0.5
    
        # define the (A, B, C and D) matrices
        # A: n*n
        # B: n*m
        # C: r*n
        # D: r*m
    
        Ci = 1.360 * 3600000
        Ria = (1 + relative_amplitude_variation * Ria_deviation) * 5.31 / 3600000
        Aw = 6.22
    
        min_rel_heat = 0.2
    
        x0 = np.array([20])
    
        return Ci, Ria, Aw, min_rel_heat, x0
    
    
    # *****************************************************************************
    # *****************************************************************************
    
    
    def get_multi_ode_model_data(relative_amplitude_variation: float = 0.0):
        # define how the coefficients change
    
        Rih_deviation = random.random() - 0.5
    
        Ria_deviation = random.random() - 0.5
    
        # define the (A, B, C and D) matrices
        # A: n*n
        # B: n*m
        # C: r*n
        # D: r*m
    
        # from Bacher and Madsen (2011): model TiTh
    
        Ci = 1.360 * 3600000  # original: 1.36 kWh/ºC
        Ch = 0.309 * 3600000  # original: 0.309 kWh/ºC
        Ria = (
            (1 + relative_amplitude_variation * Ria_deviation) * 5.31 / 3600000
        )  # original: 5.31 ºC/kWh
        Rih = (
            (1 + relative_amplitude_variation * Rih_deviation) * 0.639 / 3600000
        )  # original: 0.639 ºC/kWh
        Aw = 6.22  # original: 6.22 m2
    
        Pw = 5000  # 5 kW
    
        min_rel_heat = 0.2
    
        x0 = np.array([20, 20])
    
        return Ci, Ch, Ria, Rih, Aw, min_rel_heat, Pw, x0
    
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    def stateless_model(Aw, min_rel_heat):
        # inputs: Ta, phi_s, phi_h above the minimum, phi_h status
        # outputs: solar irradiance, heat
    
        d = np.array([[0, Aw, 0, 0], [0, 0, (1 - min_rel_heat), min_rel_heat]])
    
        return None, None, None, d
    
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    def single_node_model(Ci, Ria, Aw, min_rel_heat, Pw):
        # states: Ti and Th
        # inputs: Ta, phi_s, phi_h above the minimum, phi_h status
        # outputs: solar irradiance, heat
    
        a = np.array([[-1 / (Ria * Ci)]])
        b = np.array(
            [
                [
                    1 / (Ci * Ria),
                    Aw / Ci,
                    Pw * (1 - min_rel_heat) / Ci,
                    Pw * min_rel_heat / Ci,
                ]
            ]
        )
        c = np.array([[0], [0]])
        d = np.array([[0, Aw, 0, 0], [0, 0, Pw * (1 - min_rel_heat), Pw * min_rel_heat]])
    
        return a, b, c, d
    
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    def two_node_model(Ci, Ch, Ria, Rih, Aw, min_rel_heat, Pw):
        # states: Ti and Th
        # inputs: Ta, phi_s, phi_h above the minimum, phi_h status
        # outputs: solar irradiance, heat
    
        a = np.array(
            [[-(1 / Rih + 1 / Ria) / Ci, 1 / (Ci * Rih)], [1 / (Ch * Rih), -1 / (Ch * Rih)]]
        )
        b = np.array(
            [
                [1 / (Ci * Ria), Aw / Ci, 0, 0],
                [0, 0, Pw * (1 - min_rel_heat) / Ch, Pw * min_rel_heat / Ch],
            ]
        )
        c = np.array([[0, 0], [0, 0]])
        d = np.array([[0, Aw, 0, 0], [0, 0, Pw * (1 - min_rel_heat), Pw * min_rel_heat]])
    
        return a, b, c, d
    
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    def get_two_node_model_signals(number_samples):
        # signals
    
        # inputs:
        # 1) ambient temperature (real, can be fixed later)
        # 2) solar irradiation (real, can be fixed later)
        # 3) relative heat above minimum (nnr)
        # 4) heater status (binary)
    
        list_inputs = [
            sgn.FreeUnboundedSignal(number_samples),
            sgn.FreeUnboundedSignal(number_samples),
            sgn.NonNegativeRealSignal(number_samples),
            sgn.BinarySignal(number_samples),
        ]
    
        # states
        # 1) indoor temperature (real)
        # 2) heater temperature (real)
    
        list_states = [
            sgn.FreeUnboundedSignal(number_samples),
            sgn.FreeUnboundedSignal(number_samples),
        ]
    
        # outputs:
        # 1) solar gain (nnr)
        # 2) heat input (nnr)
    
        list_outputs = [
            sgn.NonNegativeRealSignal(number_samples),
            sgn.NonNegativeRealSignal(number_samples),
        ]
    
        return list_inputs, list_states, list_outputs
    
    
    # ******************************************************************************
    # ******************************************************************************
    
    
    def method_full_converter(time_step_durations: list):
        # number of samples
        number_time_steps = len(time_step_durations)
    
        # get the coefficients
        Ci, Ch, Ria, Rih, Aw, min_rel_heat, Pw, x0 = get_multi_ode_model_data()
    
        # get the model
        a, b, c, d = two_node_model(Ci, Ch, Ria, Rih, Aw, min_rel_heat, Pw)
    
        # get the signals
        inputs, states, outputs = get_two_node_model_signals(number_time_steps)
    
        # create a dynamic system
        ds = dynsys.DynamicSystem(
            time_interval_durations=time_step_durations, A=a, B=b, C=c, D=d
        )
    
        # create a converter
        cvn1 = cvn.Converter(
            sys=ds,
            time_frame=None,
            initial_states=x0,
            turn_key_cost=3,
            inputs=inputs,
            states=states,
            outputs=outputs,
        )
    
        # get the dictionaries
        (a_innk, b_inmk, c_irnk, d_irmk, e_x_ink, e_y_irk) = cvn1.matrix_dictionaries()
    
        # TODO: check the dicts
    
    
    # ******************************************************************************
    # ******************************************************************************