def test_add_constraints_net_zero_energy_requirement_is_false(self):
        """Checks that the nze constraint is not added if user provides the value False"""
        dict_values = self.dict_values.copy()
        dict_values.update({
            CONSTRAINTS: {
                MAXIMUM_EMISSIONS: {
                    VALUE: None
                },
                MINIMAL_RENEWABLE_FACTOR: {
                    VALUE: 0
                },
                MINIMAL_DEGREE_OF_AUTONOMY: {
                    VALUE: 0
                },
                NET_ZERO_ENERGY: {
                    VALUE: False
                },
            }
        })

        model = D2.add_constraints(
            local_energy_system=solph.Model(self.model),
            dict_values=dict_values,
            dict_model=self.dict_model,
        )

        assert (
            hasattr(model, "constraint_net_zero_energy") == False
        ), f"When the net_zero_energy constraint is deactivated (False), no constraint should be added"
 def test_add_constraints_maximum_emissions_None(self):
     """Verifies if the max emissions constraint was not added, in case the user does not provide a value"""
     dict_values = self.dict_values.copy()
     dict_values.update({
         CONSTRAINTS: {
             MAXIMUM_EMISSIONS: {
                 VALUE: None
             },
             MINIMAL_RENEWABLE_FACTOR: {
                 VALUE: 0
             },
             MINIMAL_DEGREE_OF_AUTONOMY: {
                 VALUE: 0
             },
             NET_ZERO_ENERGY: {
                 VALUE: False
             },
         }
     })
     model = D2.add_constraints(
         local_energy_system=solph.Model(self.model),
         dict_values=dict_values,
         dict_model=self.dict_model,
     )
     assert (
         hasattr(model, "integral_limit_emission_factor") == False
     ), f"When maximum_emission is None, no emission constraint should be added to the ESM."
    def test_add_constraints_minimal_renewable_share_is_0(self):
        """Checks that the minimal renewable share constraint is not added if user provides a minimal share of 0"""
        dict_values = self.dict_values.copy()
        dict_values.update({
            CONSTRAINTS: {
                MAXIMUM_EMISSIONS: {
                    VALUE: None
                },
                MINIMAL_RENEWABLE_FACTOR: {
                    VALUE: 0
                },
                MINIMAL_DEGREE_OF_AUTONOMY: {
                    VALUE: 0
                },
                NET_ZERO_ENERGY: {
                    VALUE: False
                },
            }
        })

        model = D2.add_constraints(
            local_energy_system=solph.Model(self.model),
            dict_values=dict_values,
            dict_model=self.dict_model,
        )

        assert (
            hasattr(model, "constraint_minimal_renewable_share") == False
        ), f"When the minimal_renewable_share is 0, no constraint should be added"
def test_prepare_demand_assets():
    asset = "asset"
    demand_profiles = "demand"
    electricity = "Electricity"
    dict_values = {
        ENERGY_CONSUMPTION: {
            asset + AUTO_SINK: {},
            asset + EXCESS: {},
            asset + EXCESS_SINK_POSTFIX: {},
            demand_profiles: {
                LABEL: demand_profiles,
                INFLOW_DIRECTION: electricity,
                ENERGY_VECTOR: electricity,
            },
        },
    }
    dict_model = {
        OEMOF_SINK: {
            demand_profiles: demand_profiles
        },
        OEMOF_BUSSES: {
            electricity: electricity
        },
    }
    oemof_solph_object_asset = "object"
    weighting_factor_energy_carrier = "weighting_factor_energy_carrier"
    oemof_solph_object_bus = "oemof_solph_object_bus"

    demands = D2.prepare_demand_assets(
        dict_values,
        dict_model,
        oemof_solph_object_asset,
        weighting_factor_energy_carrier,
        oemof_solph_object_bus,
    )

    assert (
        demand_profiles in demands
    ), f"Demand asset {demand_profiles} should be in the demands taken into account for the constraints, but is not included in it ({demands.keys()})."
    exp = {
        oemof_solph_object_asset:
        dict_model[OEMOF_SINK][dict_values[ENERGY_CONSUMPTION][demand_profiles]
                               [LABEL]],
        oemof_solph_object_bus:
        dict_model[OEMOF_BUSSES][dict_values[ENERGY_CONSUMPTION]
                                 [demand_profiles][INFLOW_DIRECTION]],
        weighting_factor_energy_carrier:
        DEFAULT_WEIGHTS_ENERGY_CARRIERS[dict_values[ENERGY_CONSUMPTION][
            demand_profiles][ENERGY_VECTOR]][VALUE],
    }

    for key in exp.keys():
        assert (
            key in demands[demand_profiles]
        ), f"The parameter {key} for demand {demand_profiles} not is not added for demand asset processing for the constraints."
        assert (
            demands[demand_profiles][key] == exp[key]
        ), f"The expected value (exp[key]) of {key} for {demand_profiles} is not met, but is of value {demands[demand_profiles][key]}."
    def test_add_constraints_minimal_renewable_share(self):
        """Checks if the constraint minimal renewable share value provided by the user is being applied or not"""
        model = D2.add_constraints(
            local_energy_system=solph.Model(self.model),
            dict_values=self.dict_values,
            dict_model=self.dict_model,
        )

        assert (
            hasattr(model, "constraint_minimal_renewable_share") == True
        ), f"The minimal renewable share has not been added, something has failed."
 def test_constraint_maximum_emissions(self):
     """Checks if maximum emissions limit is properly added as a constraint"""
     # Create a solph model using the input values (especially the constraints setup as class variables above)
     model = D2.constraint_maximum_emissions(
         model=solph.Model(self.model),
         dict_values=self.dict_values,
     )
     assert (
         model.integral_limit_emission_factor.NoConstraint[0] ==
         self.exp_emission_limit
     ), f"Either the maximum emission constraint has not been added or the wrong limit has been added; limit is {model.integral_limit_emission_factor.NoConstraint[0]}."
def run_oemof(dict_values, save_energy_system_graph=False):
    """
    Creates and solves energy system model generated from excel template inputs.
    Each component is included by calling its constructor function in D1_model_components.

    Parameters
    ----------
    dict values: dict
        Includes all dictionary values describing the whole project, including costs,
        technical parameters and components. In C0_data_processing, each component was attributed
        with a certain in/output bus.

    Returns
    -------
    saves and returns oemof simulation results
    """

    start = timer.initalize()

    model, dict_model = model_building.initialize(dict_values)

    model = model_building.adding_assets_to_energysystem_model(
        dict_values, dict_model, model)

    model_building.plot_networkx_graph(
        dict_values, model, save_energy_system_graph=save_energy_system_graph)

    logging.debug(
        "Creating oemof model based on created components and busses...")
    local_energy_system = solph.Model(model)
    logging.debug(
        "Created oemof model based on created components and busses.")

    local_energy_system = D2.add_constraints(local_energy_system, dict_values,
                                             dict_model)

    model_building.store_lp_file(dict_values, local_energy_system)

    model, results_main, results_meta = model_building.simulating(
        dict_values, model, local_energy_system)

    model_building.store_oemof_results(dict_values, model)

    timer.stop(dict_values, start)

    return results_meta, results_main
 def test_add_constraints_maximum_emissions(self):
     """Checks if maximum emissions constraint works as intended"""
     dict_values = self.dict_values.copy()
     # Modify the minimum renewable factor constraint to be 0, otherwise this constraint will also be added
     dict_values.update({
         MINIMAL_RENEWABLE_FACTOR: {
             VALUE: 0
         },
         MINIMAL_DEGREE_OF_AUTONOMY: {
             VALUE: 0
         },
         NET_ZERO_ENERGY: {
             VALUE: False
         },
     })
     model = D2.add_constraints(
         local_energy_system=solph.Model(self.model),
         dict_values=dict_values,
         dict_model=self.dict_model,
     )
     assert (
         model.integral_limit_emission_factor.NoConstraint[0] ==
         self.exp_emission_limit
     ), f"Either the maximum emission constraint has not been added or the wrong limit has been added; limit is {model.integral_limit_emission_factor.NoConstraint[0]}."
def test_prepare_constraint_minimal_renewable_share():
    pv_plant = "PV"
    diesel = "Diesel"
    electricity = "Electricity"
    fuel = "Fuel"
    dso_1 = "DSO_1"
    dso_2 = "DSO_2"
    dict_values = {
        ENERGY_PROVIDERS: {
            dso_1: {
                LABEL: dso_1,
                RENEWABLE_SHARE_DSO: {
                    VALUE: 0.3
                }
            },
            dso_2: {
                LABEL: dso_2,
                RENEWABLE_SHARE_DSO: {
                    VALUE: 0.7
                }
            },
        },
        ENERGY_PRODUCTION: {
            pv_plant: {
                RENEWABLE_ASSET_BOOL: {
                    VALUE: True
                },
                LABEL: pv_plant,
                OUTPUT_BUS_NAME: electricity,
                ENERGY_VECTOR: electricity,
            },
            diesel: {
                RENEWABLE_ASSET_BOOL: {
                    VALUE: False
                },
                LABEL: diesel,
                OUTPUT_BUS_NAME: fuel,
                ENERGY_VECTOR: electricity,
            },
            dso_1 + DSO_CONSUMPTION: {
                LABEL: dso_1 + DSO_CONSUMPTION,
                OUTPUT_BUS_NAME: electricity,
                ENERGY_VECTOR: electricity,
            },
            dso_2 + DSO_CONSUMPTION: {
                LABEL: dso_2 + DSO_CONSUMPTION,
                OUTPUT_BUS_NAME: electricity,
                ENERGY_VECTOR: electricity,
            },
        },
    }
    dict_model = {
        OEMOF_SOURCE: {
            pv_plant: pv_plant,
            diesel: diesel,
            dso_1 + DSO_CONSUMPTION: dso_1 + DSO_CONSUMPTION,
            dso_2 + DSO_CONSUMPTION: dso_2 + DSO_CONSUMPTION,
        },
        OEMOF_BUSSES: {
            electricity: electricity,
            fuel: fuel
        },
    }
    oemof_solph_object_asset = "object"
    weighting_factor_energy_carrier = "weighting_factor_energy_carrier"
    renewable_share_asset_flow = "renewable_share_asset_flow"
    oemof_solph_object_bus = "oemof_solph_object_bus"

    (
        renewable_assets,
        non_renewable_assets,
    ) = D2.prepare_constraint_minimal_renewable_share(
        dict_values=dict_values,
        dict_model=dict_model,
        oemof_solph_object_asset=oemof_solph_object_asset,
        weighting_factor_energy_carrier=weighting_factor_energy_carrier,
        renewable_share_asset_flow=renewable_share_asset_flow,
        oemof_solph_object_bus=oemof_solph_object_bus,
    )

    assert (pv_plant in renewable_assets
            ), f"The {pv_plant} is not added to the renewable assets."
    assert (pv_plant not in non_renewable_assets
            ), f"The {pv_plant} is not added to the renewable assets."
    assert (renewable_assets[pv_plant][renewable_share_asset_flow] == 1
            ), f"The renewable share of asset {pv_plant} is added incorrectly."

    assert (diesel in non_renewable_assets
            ), f"The {diesel} is added to the renewable assets."
    assert (diesel not in renewable_assets
            ), f"The {diesel} is not added to the non-renewable assets."
    assert (non_renewable_assets[diesel][renewable_share_asset_flow] == 0
            ), f"The renewable share of asset {diesel} is added incorrectly."

    assert (
        dso_1 + DSO_CONSUMPTION in renewable_assets
    ), f"The {dso_1 + DSO_CONSUMPTION} is not added as a renewable source."
    assert (
        renewable_assets[dso_1 +
                         DSO_CONSUMPTION][renewable_share_asset_flow] == 0.3
    ), f"The renewable share of asset {dso_1 + DSO_CONSUMPTION} is added incorrectly."

    assert (
        dso_1 + DSO_CONSUMPTION in non_renewable_assets
    ), f"The {dso_1 + DSO_CONSUMPTION} is not added as a non-renewable source."
    assert (
        non_renewable_assets[
            dso_1 + DSO_CONSUMPTION][renewable_share_asset_flow] == 0.3
    ), f"The renewable share of asset {dso_1 + DSO_CONSUMPTION} is added incorrectly."

    assert (
        dso_2 + DSO_CONSUMPTION in renewable_assets
    ), f"The {dso_2 + DSO_CONSUMPTION} is not added as a renewable source."
    assert (
        renewable_assets[dso_2 +
                         DSO_CONSUMPTION][renewable_share_asset_flow] == 0.7
    ), f"The renewable share of asset {dso_2 + DSO_CONSUMPTION} is added incorrectly."

    assert (
        dso_2 + DSO_CONSUMPTION in non_renewable_assets
    ), f"The {dso_2 + DSO_CONSUMPTION} is not added as a non-renewable source."
    assert (
        non_renewable_assets[
            dso_2 + DSO_CONSUMPTION][renewable_share_asset_flow] == 0.7
    ), f"The renewable share of asset {dso_2 + DSO_CONSUMPTION} is added incorrectly."
def test_prepare_energy_provider_feedin_sinks():
    electricity = "Electricity"
    dso = "DSO"
    dict_values = {
        ENERGY_PROVIDERS: {
            dso: {
                LABEL: dso
            },
        },
        ENERGY_CONSUMPTION: {
            dso + DSO_FEEDIN + AUTO_SINK: {
                LABEL: dso + DSO_FEEDIN,
                INFLOW_DIRECTION: electricity,
                ENERGY_VECTOR: electricity,
            }
        },
    }
    dict_model = {
        OEMOF_SINK: {
            dso + DSO_FEEDIN: dso + DSO_FEEDIN,
        },
        OEMOF_BUSSES: {
            electricity: electricity
        },
    }
    oemof_solph_object_asset = "object"
    weighting_factor_energy_carrier = "weighting_factor_energy_carrier"
    oemof_solph_object_bus = "oemof_solph_object_bus"

    energy_provider_feedin_sinks = D2.prepare_energy_provider_feedin_sinks(
        dict_values,
        dict_model,
        oemof_solph_object_asset,
        weighting_factor_energy_carrier,
        oemof_solph_object_bus,
    )

    DSO_sink_name = dict_values[ENERGY_PROVIDERS][dso][
        LABEL] + DSO_FEEDIN + AUTO_SINK

    assert (
        DSO_sink_name in energy_provider_feedin_sinks
    ), f"DSO sink asset {DSO_sink_name} should be in the energy provider sink list taken into account for the constraints, but is not included in it ({energy_provider_feedin_sinks.keys()})."

    exp = {
        oemof_solph_object_asset:
        dict_model[OEMOF_SINK][dict_values[ENERGY_CONSUMPTION][DSO_sink_name]
                               [LABEL]],
        oemof_solph_object_bus:
        dict_model[OEMOF_BUSSES][dict_values[ENERGY_CONSUMPTION][DSO_sink_name]
                                 [INFLOW_DIRECTION]],
        weighting_factor_energy_carrier:
        DEFAULT_WEIGHTS_ENERGY_CARRIERS[dict_values[ENERGY_CONSUMPTION]
                                        [DSO_sink_name][ENERGY_VECTOR]][VALUE],
    }

    for key in exp.keys():
        assert (
            key in energy_provider_feedin_sinks[DSO_sink_name]
        ), f"The parameter {key} for DSO {DSO_sink_name} not is not added for energy provider sinks processing for constraints."
        assert (
            energy_provider_feedin_sinks[DSO_sink_name][key] == exp[key]
        ), f"The expected value (exp[key]) of {key} for {DSO_sink_name} is not met, but is of value {energy_provider_feedin_sinks[DSO_sink_name][key]}."