示例#1
0
def test_verify_state_of_charge_soc_above_zero(caplog):
    """Test case: The SoC value are all above 0.00 and thus, physically infeasible
    Test to check if the WARNING log messages are logged"""

    # Create a list of floats greater than 1.00
    list_floats = [1.23, 1.0001, 2.05]
    data = np.array(list_floats)

    # Generate a date-time index
    index = pd.date_range(start="1/1/2018", periods=3, tz="Asia/Kolkata")

    # Create a SoC time series from above floats and date-time data
    soc_series = pd.Series(data=data, index=index)

    storage = "storage_01"

    # Add the SoC time series to the result JSON nested-dict
    dict_values = {ENERGY_STORAGE: {storage: {TIMESERIES_SOC: soc_series}}}

    # Test the function with the present case
    with caplog.at_level(logging.WARNING):
        E4.verify_state_of_charge(dict_values=dict_values)
    assert (
        f"SoC of {storage} has at least one time step where its value is greater than 1. This is a physically impossible value!"
        in caplog.text
    ), f"A WARNING message is not logged even though the SoC values are all above 1."
示例#2
0
def test_minimal_constraint_test_passes():
    # No minimal renewable factor
    dict_values = {CONSTRAINTS: {MINIMAL_RENEWABLE_FACTOR: {VALUE: 0}}}
    return_value = E4.minimal_constraint_test(dict_values,
                                              MINIMAL_RENEWABLE_FACTOR,
                                              RENEWABLE_FACTOR)
    assert (
        return_value == None
    ), f"When no minimal renewable factor is set, this test should not fail."
    # Min res < res
    dict_values = {
        CONSTRAINTS: {
            MINIMAL_RENEWABLE_FACTOR: {
                VALUE: 0.2
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                RENEWABLE_FACTOR: 0.3
            }
        },
    }
    return_value = E4.minimal_constraint_test(dict_values,
                                              MINIMAL_RENEWABLE_FACTOR,
                                              RENEWABLE_FACTOR)
    assert (
        return_value == None
    ), f"When minimal renewable factor < res, this test should not fail."
    # Min res < res, minimal deviation
    dict_values = {
        CONSTRAINTS: {
            MINIMAL_RENEWABLE_FACTOR: {
                VALUE: 0.2
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                RENEWABLE_FACTOR: 0.2 - 10**(-7)
            }
        },
    }
    return_value = E4.minimal_constraint_test(dict_values,
                                              MINIMAL_RENEWABLE_FACTOR,
                                              RENEWABLE_FACTOR)
    assert (
        return_value == None
    ), f"When minimal renewable factor is missed by < e6, this test should not fail."
示例#3
0
def test_verify_state_of_charge_feasible(caplog):
    """Two cases are tested here
    Case 1 is no storage components in the energy system, hence no verification carried out
    Case 2 is that all the SoC values are physically feasible, so no WARNING log messages"""

    # Test case: No storage components present in the system, so function is exited before any verification
    # Make an empty energyStorage dict signifying that there are no storage components in the energy system
    dict_values = {"energyStorage": {}}
    return_value = E4.verify_state_of_charge(dict_values=dict_values)
    assert (
        return_value is None
    ), f"When there are no storage components in the energy system, this test should not fail"

    # Test case: All physically possible values and no WARNING message is logged
    # Create a series of SoC values with three physically feasible values

    # Generate a list of 50 floats between 0 and 1
    list_floats = np.random.uniform(low=00.00, high=01.00, size=(50, ))
    data = np.array(list_floats)

    # Generate a date-time index
    index = pd.date_range(start="1/1/2018", periods=50, tz="Asia/Tokyo")

    # Create a SoC time series from above floats and date-time data
    soc_series = pd.Series(data=data, index=index)

    storage = "storage_01"
    # Add the SoC time series to the result JSON nested-dict
    dict_values = {
        ENERGY_STORAGE: {
            storage: {
                TIMESERIES_SOC: soc_series
            },
        }
    }
    # Test for the function's behavior with the current case
    with caplog.at_level(logging.WARNING):
        E4.verify_state_of_charge(dict_values=dict_values)
    assert (
        f"greater than 1. This is a physically impossible value!"
        not in caplog.text
    ), f"A WARNING message is logged even though the SoC values are all below 1."
    assert (
        f"is less than 0. This is a physically impossible value!"
        not in caplog.text
    ), f"A WARNING message is logged even though the SoC values are all above 0."
示例#4
0
def test_detect_excessive_excess_generation_in_bus_no_excess(caplog):
    """No excessive excess generation takes place. """
    bus_label = "Test_bus"
    dict_values = {
        "optimizedFlows": {
            bus_label:
            pd.DataFrame({
                "inflow": [1, 2, 3],
                "outflow": [-1, -1.9, -2.5],
                "excess": [0, 0.1, 0.5],
            })
        }
    }
    with caplog.at_level(logging.WARNING):
        E4.detect_excessive_excess_generation_in_bus(dict_values=dict_values)
    assert (
        caplog.text == ""
    ), f"A warning is logged although there is no excessive excess generation."
示例#5
0
def test_detect_excessive_excess_generation_in_bus_warning_is_logged(caplog):
    """A logging.warning is printed due to excessive excess generation. """
    bus_label = "Test_bus"
    dict_values = {
        "optimizedFlows": {
            bus_label:
            pd.DataFrame({
                "inflow": [1, 2, 3],
                "outflow": [-1, -1, -2],
                "excess": [0, 1, 1]
            })
        }
    }
    with caplog.at_level(logging.WARNING):
        E4.detect_excessive_excess_generation_in_bus(dict_values=dict_values)
    assert (
        f"Attention, on bus {bus_label} there is excessive excess generation"
        in caplog.text
    ), f"An intended warning is not logged although there is excessive excess generation."
示例#6
0
def test_maximum_emissions_test_passes():
    # No maximum emissions constraint
    dict_values = {CONSTRAINTS: {MAXIMUM_EMISSIONS: {VALUE: None}}}
    return_value = E4.maximum_emissions_test(dict_values)
    assert (
        return_value == None
    ), f"When no maximum emissions constraint is set, this test should not fail."
    # Total emissions < maximum emissions constraint
    dict_values = {
        CONSTRAINTS: {
            MAXIMUM_EMISSIONS: {
                VALUE: 1000
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                TOTAL_EMISSIONS: 999
            }
        },
    }
    return_value = E4.maximum_emissions_test(dict_values)
    assert (
        return_value == None
    ), f"When the maximum emissions constraint is met, this test should not fail."
    # Total emissions > maximum emissions constraint, minimal diff
    dict_values = {
        CONSTRAINTS: {
            MAXIMUM_EMISSIONS: {
                VALUE: 1000
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                TOTAL_EMISSIONS: 1000 + 1e-6
            }
        },
    }
    return_value = E4.maximum_emissions_test(dict_values)
    assert (
        return_value == None
    ), f"At a minimal exceeding of the maximum emission constraint of < e6, this test should not fail."
示例#7
0
def test_net_zero_energy_constraint_test_passes():
    # No nze constraint
    dict_values = {CONSTRAINTS: {NET_ZERO_ENERGY: {VALUE: False}}}
    return_value = E4.net_zero_energy_constraint_test(dict_values)
    assert (
        return_value == None
    ), f"When no net zero energy constraint is set, this test should not fail."
    # Degree of NZE >= 1
    dict_values = {
        CONSTRAINTS: {
            NET_ZERO_ENERGY: {
                VALUE: True
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                DEGREE_OF_NZE: 1
            }
        },
    }
    return_value = E4.net_zero_energy_constraint_test(dict_values)
    assert (
        return_value == None
    ), f"When the net zero energy constraint is met, this test should not fail."
    # Total emissions > maximum emissions constraint, minimal diff
    dict_values = {
        CONSTRAINTS: {
            NET_ZERO_ENERGY: {
                VALUE: True
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                DEGREE_OF_NZE: 1 - 10**(-7)
            }
        },
    }
    return_value = E4.net_zero_energy_constraint_test(dict_values)
    assert (
        return_value == None
    ), f"At a minimal exceeding of the net zero energy constraint of < e6, this test should not fail."
示例#8
0
def test_minimal_renewable_share_test_passes():
    # No minimal renewable factor
    dict_values = {CONSTRAINTS: {MINIMAL_RENEWABLE_FACTOR: {VALUE: 0}}}
    E4.minimal_renewable_share_test(dict_values)
    # Min res < res
    dict_values = {
        CONSTRAINTS: {
            MINIMAL_RENEWABLE_FACTOR: {
                VALUE: 0.2
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                RENEWABLE_FACTOR: 0.3
            }
        },
    }
    E4.minimal_renewable_share_test(dict_values)
    # Min res < res, minimal deviation
    dict_values = {
        CONSTRAINTS: {
            MINIMAL_RENEWABLE_FACTOR: {
                VALUE: 0.2
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                RENEWABLE_FACTOR: 0.2 - 10**(-7)
            }
        },
    }
    E4.minimal_renewable_share_test(dict_values)
示例#9
0
def test_detect_excessive_excess_generation_in_bus_several_busses_two_warnings(
        caplog):
    """Excessive excess generation takes place in two busses. """
    excessive_excess_bus_1, excessive_excess_bus_2 = (
        "Bus_excessive_excess_1",
        "Bus_excessive_excess_2",
    )
    dict_values = {
        "optimizedFlows": {
            "Bus_no_excessive_excess":
            pd.DataFrame({
                "inflow": [1, 2, 3],
                "outflow": [-1, -1.9, -2.5],
                "excess": [0, 0.1, 0.5],
            }),
            excessive_excess_bus_1:
            pd.DataFrame({
                "inflow": [1, 2, 3],
                "outflow": [-1, -1, -2],
                "excess": [0, 1, 1],
            }),
            excessive_excess_bus_2:
            pd.DataFrame({
                "inflow": [1, 2, 3],
                "outflow": [-1, -1, -1],
                "excess": [0, 1, 2],
            }),
        }
    }
    with caplog.at_level(logging.WARNING):
        E4.detect_excessive_excess_generation_in_bus(dict_values=dict_values)
    assert (
        f"Attention, on bus {excessive_excess_bus_1} there is excessive excess generation"
        in caplog.text and
        f"Attention, on bus {excessive_excess_bus_2} there is excessive excess generation"
        in caplog.text
    ), f"One or two intended warnings are missing although there is excessive excess generation in two busses."
示例#10
0
def test_minimal_renewable_share_test_fails():
    dict_values = {
        CONSTRAINTS: {
            MINIMAL_RENEWABLE_FACTOR: {
                VALUE: 0.2
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                RENEWABLE_FACTOR: 0.2 - 10**(-5)
            }
        },
    }
    return_value = E4.minimal_renewable_share_test(dict_values)
    assert return_value is False
示例#11
0
def test_net_zero_energy_constraint_test_fails():
    dict_values = {
        CONSTRAINTS: {
            NET_ZERO_ENERGY: {
                VALUE: True
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                DEGREE_OF_NZE: 1 - 10**(-6)
            }
        },
    }
    return_value = E4.net_zero_energy_constraint_test(dict_values)
    assert (
        return_value == False
    ), f"When the net zero energy constraint is not met by a difference of >= e6 this test should fail."
示例#12
0
def test_maximum_emissions_test_fails():
    dict_values = {
        CONSTRAINTS: {
            MAXIMUM_EMISSIONS: {
                VALUE: 1000
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                TOTAL_EMISSIONS: 1000.00001
            }
        },
    }
    return_value = E4.maximum_emissions_test(dict_values)
    assert (
        return_value == False
    ), f"When the maximum emissions constraint is not met by a difference of >= e6 this test should fail."
示例#13
0
def test_minimal_constraint_test_fails():
    dict_values = {
        CONSTRAINTS: {
            MINIMAL_RENEWABLE_FACTOR: {
                VALUE: 0.2
            }
        },
        KPI: {
            KPI_SCALARS_DICT: {
                RENEWABLE_FACTOR: 0.2 - 10**(-5)
            }
        },
    }
    return_value = E4.minimal_constraint_test(dict_values,
                                              MINIMAL_RENEWABLE_FACTOR,
                                              RENEWABLE_FACTOR)
    assert (
        return_value is False
    ), f"When the minimal renewable share constraint is not met (allowed deviation: < e6), this test should fail."
def evaluate_dict(dict_values, results_main, results_meta):
    """

    Parameters
    ----------
    dict_values: dict
        simulation parameters
    results_main: DataFrame
        oemof simulation results as output by processing.results()
    results_meta: DataFrame
        oemof simulation meta information as output by processing.meta_results()

    Returns
    -------

    """

    dict_values.update(
        {
            KPI: {
                KPI_COST_MATRIX: pd.DataFrame(columns=KPI_COST_MATRIX_ENTRIES),
                KPI_SCALAR_MATRIX: pd.DataFrame(columns=KPI_SCALAR_MATRIX_ENTRIES),
                KPI_SCALARS_DICT: {},
            }
        }
    )

    bus_data = {}
    # Store all information related to busses in bus_data
    for bus in dict_values[ENERGY_BUSSES]:
        # Read all energy flows from busses
        bus_data.update({bus: solph.views.node(results_main, bus)})

    logging.info("Evaluating optimized capacities and dispatch.")
    # Evaluate timeseries and store to a large DataFrame for each bus:
    E1.get_timeseries_per_bus(dict_values, bus_data)

    # Store all information related to storages in bus_data, as storage capacity acts as a bus
    for storage in dict_values[ENERGY_STORAGE]:
        bus_data.update(
            {
                dict_values[ENERGY_STORAGE][storage][LABEL]: solph.views.node(
                    results_main, dict_values[ENERGY_STORAGE][storage][LABEL],
                )
            }
        )
        E1.get_storage_results(
            dict_values[SIMULATION_SETTINGS],
            bus_data[dict_values[ENERGY_STORAGE][storage][LABEL]],
            dict_values[ENERGY_STORAGE][storage],
        )

        for storage_item in [STORAGE_CAPACITY, INPUT_POWER, OUTPUT_POWER]:
            E2.get_costs(
                dict_values[ENERGY_STORAGE][storage][storage_item],
                dict_values[ECONOMIC_DATA],
            )

        E2.lcoe_assets(dict_values[ENERGY_STORAGE][storage], ENERGY_STORAGE)
        for storage_item in [STORAGE_CAPACITY, INPUT_POWER, OUTPUT_POWER]:
            store_result_matrix(
                dict_values[KPI], dict_values[ENERGY_STORAGE][storage][storage_item]
            )

        if (
            dict_values[ENERGY_STORAGE][storage][INPUT_BUS_NAME]
            in dict_values[OPTIMIZED_FLOWS].keys()
        ) or (
            dict_values[ENERGY_STORAGE][storage][OUTPUT_BUS_NAME]
            in dict_values[OPTIMIZED_FLOWS].keys()
        ):
            bus_name = dict_values[ENERGY_STORAGE][storage][INPUT_BUS_NAME]
            timeseries_name = (
                dict_values[ENERGY_STORAGE][storage][LABEL]
                + " ("
                + str(
                    round(
                        dict_values[ENERGY_STORAGE][storage][STORAGE_CAPACITY][
                            OPTIMIZED_ADD_CAP
                        ][VALUE],
                        1,
                    )
                )
                + dict_values[ENERGY_STORAGE][storage][STORAGE_CAPACITY][
                    OPTIMIZED_ADD_CAP
                ][UNIT]
                + ") SOC"
            )

            dict_values[OPTIMIZED_FLOWS][bus_name][timeseries_name] = dict_values[
                ENERGY_STORAGE
            ][storage]["timeseries_soc"]

    for group in [ENERGY_CONVERSION, ENERGY_PRODUCTION, ENERGY_CONSUMPTION]:
        for asset in dict_values[group]:
            E1.get_results(
                settings=dict_values[SIMULATION_SETTINGS],
                bus_data=bus_data,
                dict_asset=dict_values[group][asset],
                asset_group=group,
            )
            E2.get_costs(dict_values[group][asset], dict_values[ECONOMIC_DATA])
            E2.lcoe_assets(dict_values[group][asset], group)
            store_result_matrix(dict_values[KPI], dict_values[group][asset])

    logging.info("Evaluating key performance indicators of the system")
    E3.all_totals(dict_values)
    E3.total_demand_and_excess_each_sector(dict_values)
    E3.add_total_feedin_electricity_equivaluent(dict_values)
    E3.add_levelized_cost_of_energy_carriers(dict_values)
    E3.add_total_renewable_and_non_renewable_energy_origin(dict_values)
    E3.add_renewable_share_of_local_generation(dict_values)
    E3.add_renewable_factor(dict_values)
    # E3.add_degree_of_sector_coupling(dict_values) feature not finished
    E3.add_onsite_energy_fraction(dict_values)
    E3.add_onsite_energy_matching(dict_values)
    E3.add_degree_of_autonomy(dict_values)

    # Tests and checks
    logging.info("Running validity checks.")
    E4.minimal_renewable_share_test(dict_values)
    E4.detect_excessive_excess_generation_in_bus(dict_values)