cronian.validate

Script to validate the configurations describing prosumers and generators.

It currently contains the following functions:
  • validate_all_agents: validates uniqueness of generator and prosumer IDs.

  • validate_prosumer: validates the prosumer dict.

  • get_prosumer_id: gets the prosumer ID from its configuration.

  • validate_required_entries: validates required entries in config.

  • validate_fields: recursively checks for empty key fields in config.

  • validate_asset_outputs: ensures assets produce outputs that match demand

    carriers or electricity.

  • validate_assets_input_output_efficiency_relationship: ensures that the set

    of asset’s in(out)puts is the same as the set of efficiencies.

  • validate_asset_behavior: ensures that an asset has a valid behavior.

  • validate_asset_behavior_attributes: ensures that an asset has valid

    behavior attributes.

  • validate_base_or_flexible_demand: ensures prosumer has at least a base or

    flex demand.

  • validate_satisfiable_demand: ensures each demand can be satisfied by at

    least one asset.

  • validate_battery_operator: ensures battery operators have at least a

    battery asset & only VRE gens as other asset.

  • validate_irrelevant_prosumer: ensures prosumer with no electric demand or

    battery is not allowed (since it is irrelevant to the simulation).

  • validate_prosumer_potential_feasibility: validates that the prosumer’s

    optimization problem is potentially feasible.

Attributes

VALID_ASSET_BEHAVIORS

GENERATOR_ATTRIBUTES

CONVERTER_ATTRIBUTES

STORAGE_ATTRIBUTES

Functions

validate_all_agents(→ tuple[list[str], list[str]])

Validate agents' IDs and configs before building the optimization model.

validate_prosumer(→ bool)

Perform some validation checks on prosumer dict.

validate_required_entries(→ set[str])

Validate required entries for a prosumer.

validate_fields(→ None)

Recursively check for empty entries in prosumer's configuration file.

validate_asset_outputs(→ None)

Ensure assets produce outputs that match electricity or demand carriers.

validate_assets_input_output_efficiency_relationship(→ None)

Ensure that the set of asset's in(out)puts is the same as efficiencies.

validate_asset_behavior(→ None)

Ensure that an asset has a valid behavior.

validate_asset_behavior_attributes(→ None)

Ensure that an asset has valid behavior attributes.

validate_base_or_flexible_demand(→ None)

Ensure that a prosumer has a base or flexible demand for each demand key.

validate_satisfiable_demand(→ None)

Ensure that each demand can be satisfied by at least one asset.

validate_battery_operator_assets(→ None)

Ensure all assets of battery operator agent have electricity as output.

validate_prosumer_relevance(→ None)

Ensure that a prosumer with no electric demand or asset is not allowed.

validate_prosumer_potential_feasibility(→ None)

Validate that the prosumer's optimization problem is potentially feasible.

calculate_capacity_of_current_assets(→ float)

Calculate the combined capacity of converter assets for a given prosumer.

asset_supplies_demand_carrier(→ bool)

Check if an asset supplies a given demand carrier.

get_asset_efficiency(→ float)

Get the efficiency of an asset for a given demand carrier.

calculate_max_demand_for_a_given_demand_carrier(→ float)

Calculate the max demand of a given demand carrier of the prosumer.

Module Contents

cronian.validate.VALID_ASSET_BEHAVIORS
cronian.validate.GENERATOR_ATTRIBUTES
cronian.validate.CONVERTER_ATTRIBUTES
cronian.validate.STORAGE_ATTRIBUTES
cronian.validate.validate_all_agents(configurations: dict[str, dict], timeseries_data: pandas.DataFrame) tuple[list[str], list[str]]

Validate agents’ IDs and configs before building the optimization model.

Args:
configurations: Nested dictionary containing the configurations defining

generators, prosumers, and general parameters of the simulation.

timeseries_data: Timeseries data containing the availability factors for

VRE generators and EVs doing V2G, demand profiles for prosumers, …

Returns:

prosumer_ids: A list of unique prosumer IDs. generator_ids: A list of unique generator IDs.

Raises:
ValueError: If duplicate IDs exist among prosumers/generators, or if

prosumers & generators have the same ID.

Example usage:

>>> from pyprojroot import here
>>> from configuration import load_configurations
...
>>> config_folder = here("tests/test_data/demo_configurations")
>>> configurations = load_configurations(config_folder)
>>> validate_all_agents(configurations)
cronian.validate.validate_prosumer(prosumer: dict, timeseries_data: pandas.DataFrame) bool

Perform some validation checks on prosumer dict.

Args:

prosumer: Dictionary containing prosumer details. timeseries_data: Timeseries data containing the availability factors for

VRE generators and EVs doing V2G, demand profiles for prosumers, …

Returns:

True if all validations for this prosumer are successful.

Raises:

ValueError: If any validation check fails.

cronian.validate.validate_required_entries(prosumer: dict, prosumer_id: str) set[str]

Validate required entries for a prosumer.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID.

Returns:

demand_carriers: Set of carriers for all demands of the prosumer.

Raises:

ValueError: If any required key is missing in the prosumer dict.

cronian.validate.validate_fields(agent: any, agent_id: str, key_path: str = '') None

Recursively check for empty entries in prosumer’s configuration file.

Args:

agent: Dictionary containing the agent’s details. agent_id: The prosumer or generator agent’s unique ID. key_path: String representing path to the current key for error report.

Raises:

ValueError: If any entry or subentry is empty.

cronian.validate.validate_asset_outputs(prosumer: dict, prosumer_id: str) None

Ensure assets produce outputs that match electricity or demand carriers.

That is, for each asset, its output must be a subset of the prosumer’s demand carriers and electricity. We do not allow assets to produce carriers they don’t consume except for electricity since electricity can be exchanged with other prosumers at the market bus where they interact.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID.

Raises:

ValueError: If an asset has invalid outputs.

cronian.validate.validate_assets_input_output_efficiency_relationship(prosumer: dict, prosumer_id: str) None

Ensure that the set of asset’s in(out)puts is the same as efficiencies.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID.

Raises:

ValueError: If set of asset’s in(out)puts is not same as efficiencies. NotImplementedError: If the asset has multiple inputs and outputs.

cronian.validate.validate_asset_behavior(prosumer: dict, prosumer_id: str) None

Ensure that an asset has a valid behavior.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID.

Raises:

ValueError: If an asset has an invalid behavior.

cronian.validate.validate_asset_behavior_attributes(prosumer: dict, prosumer_id: str) None

Ensure that an asset has valid behavior attributes.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID.

Raises:

ValueError: If an asset has an invalid behavior attribute.

cronian.validate.validate_base_or_flexible_demand(prosumer: dict, prosumer_id: str) None

Ensure that a prosumer has a base or flexible demand for each demand key.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID.

Raises:
ValueError: If the prosumer has no base or flexible demand for each for

any listed demand key.

cronian.validate.validate_satisfiable_demand(prosumer: dict, prosumer_id: str, demand_carriers: set) None

Ensure that each demand can be satisfied by at least one asset.

This function checks that each demand listed can be satisfied by at least one of the prosumer’s assets. This is done by creating by creating a a set of output of all assets, and then checking that the difference between this set and the demand_carriers set is an empty set.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID. demand_carriers: Set of carriers for all demands of the prosumer.

Raises:

ValueError: If a demand cannot be satisfied by at least one asset.

cronian.validate.validate_battery_operator_assets(prosumer: dict) None

Ensure all assets of battery operator agent have electricity as output.

Args:

prosumer: Dictionary containing prosumer details.

Raises:
ValueError: If any asset of the battery operator does not have

electricity as output.

cronian.validate.validate_prosumer_relevance(prosumer: dict, prosumer_id: str) None

Ensure that a prosumer with no electric demand or asset is not allowed.

Such a prosumer is irrelevant to the simulation since it does not interact with the market bus and hence, does not interact with other prosumers.

Args:

prosumer: Dictionary containing prosumer details. prosumer_id: The prosumer’s unique ID.

Raises:

ValueError: If prosumer has no electric demand or electric asset.

cronian.validate.validate_prosumer_potential_feasibility(prosumer: dict, timeseries_data: pandas.DataFrame) None

Validate that the prosumer’s optimization problem is potentially feasible.

Validate that for each demand carrier, the combined capacity of all assets that can satisfy the demand, multiplied by their respective efficiency is greater than the maximum demand for that carrier. This is to ensure that the optimization problem of the prosumer is feasible. Since the check can be a little tricky if storage is present, and hence, we cannot for sure say that it is infeasible, we do not immediately crash the simulation but instead, we raise a warning for a potential infeasibility in the prosumer’s optimization problem.

NOTE: This is done only for non-electric demands since electric demand can be directly satisfied at the market bus even without prosumer’s own assets.

Args:

prosumer: Dictionary containing prosumer details. timeseries_data: Timeseries data containing the availability factors for

VRE generators and EVs doing V2G, demand profiles for prosumers, …

cronian.validate.calculate_capacity_of_current_assets(prosumer: dict, demand_carrier: str) float

Calculate the combined capacity of converter assets for a given prosumer.

The combined capacity is the sum of the product of the capacity of each converter asset and its efficiency.

Args:

prosumer: dictionary containing the prosumer’s details. demand_carrier: carrier for which the capacity of converter assets is

calculated.

Returns:

combined capacity of converter assets supplying the demand carrier.

cronian.validate.asset_supplies_demand_carrier(asset_data: dict, demand_carrier) bool

Check if an asset supplies a given demand carrier.

Args:

asset_data: Dictionary containing asset details. demand_carrier: Carrier for which the asset supplies power.

cronian.validate.get_asset_efficiency(asset_data: dict, demand_carrier) float

Get the efficiency of an asset for a given demand carrier.

For multiple-inputs-single-output assets, simply set this value to 1.0 For example, a hybrid boiler has input: [methane, electricity] and output: heat. Although it produces heat, heat does not appear in its efficiency dict: {methane: 0.9, electricity: 0.9}. So, we set the efficiency to 1.0.

Args:

asset_data: Dictionary containing asset details. demand_carrier: Carrier for which the asset supplies power.

Returns:

Efficiency of the asset for the given demand carrier.

cronian.validate.calculate_max_demand_for_a_given_demand_carrier(prosumer: dict, timeseries_data: pandas.DataFrame, demand_carrier: str) float

Calculate the max demand of a given demand carrier of the prosumer.

Args:

prosumer: dictionary containing the prosumer’s details. timeseries_data: Timeseries data containing the availability factors for

VRE generators and EVs doing V2G, demand profiles for prosumers, …

demand_carrier: carrier for which the maximum demand power is calculated.

Returns:

Max value in the timeseries for a given demand carrier of the prosumer.