annular.market_model ==================== .. py:module:: annular.market_model Attributes ---------- .. autoapisummary:: annular.market_model.logger annular.market_model.ALL_BID_COLUMNS annular.market_model.BID_IDX_COLUMNS annular.market_model.BID_COLUMN_NAMES Functions --------- .. autoapisummary:: annular.market_model.create_market_model annular.market_model.encode_block_bids_into_model annular.market_model.constrain_power_balance annular.market_model.create_generation_cost_expression annular.market_model.set_objective_as_social_welfare_maximization annular.market_model.get_market_clearing_price_as_dual annular.market_model.fix_integer_variables annular.market_model.run_market_model annular.market_model.extract_scheduled_bids annular.market_model.extract_generator_dispatch annular.market_model.market_results_to_df annular.market_model.validate_bids annular.market_model._validate_acceptance_ratio annular.market_model._validate_nonnegative_quantity annular.market_model._validate_sense annular.market_model._validate_dataframe_format annular.market_model._validate_single_price_per_profile Module Contents --------------- .. py:data:: logger .. py:data:: ALL_BID_COLUMNS :type: tuple :value: ('satellite', 'exclusive_group_id', 'profile_block_id', 'sense', 'timestamp', 'quantity',... .. py:data:: BID_IDX_COLUMNS :value: ('satellite', 'exclusive_group_id', 'profile_block_id', 'sense', 'timestamp') .. py:data:: BID_COLUMN_NAMES :value: ('quantity', 'acceptance_ratio', 'price') .. py:function:: create_market_model(satellite_bids: pandas.DataFrame, generator_configs: dict[str, dict], timeseries_data: pandas.DataFrame, snapshots: Iterable[pandas.Timestamp]) -> pyomo.environ.AbstractModel Create the central market clearing model. :param satellite_bids: MultiIndex DataFrame of bids for all satellites. :param generator_configs: dict of configurations defining of all generators. :param timeseries_data: DataFrame containing all timeseries_data. :param snapshots: snapshots/timesteps for which the market model is created. :returns: Pyomo model representing the market-clearing optimization problem. .. py:function:: encode_block_bids_into_model(model: pyomo.environ.Model, satellite_bids: pandas.DataFrame) -> None Create gross surplus expression and set mutual exclusivity constraint. This takes bids in the following format: +-----------+--------------------+------------------+-------+-----------+----------+------------------+-------+ | satellite | exclusive_group_id | profile_block_id | sense | timestamp | quantity | acceptance_ratio | price | +-----------+--------------------+------------------+-------+-----------+----------+------------------+-------+ | ... | ... | ... | ... | ... | ... | ... | ... | +-----------+--------------------+------------------+-------+-----------+----------+------------------+-------+ where: - `satellite`: indicates which satellite this bid originates from - `exclusive_group_id`: ID of which exclusive group this bid belongs to - `profile_block_id`: ID of which profile block this bid belongs to - `sense`: indicates whether the bid is a demand or a supply bid - `timestamp`: timestamp for this bid - `quantity`: quantity for this bid - `acceptance_ratio`: minimum acceptance ratio between 0 and 1 - `price`: price for this bid and (satellite, exclusive_group_id, profile_block_id, sense, timestamp) are its Index. Multiple bids sharing the same `profile_block_id` will be encoded to be met together, i.e., all-or-none. If multiple profiles share the same `exclusive_group_id`, at most one of them will be satisfied. Every bid must have a `profile_block_id` and `exclusive_group_id`. If a bid does not make use of profile block or exclusive group functionality, the `exclusive_group_id` must be unique, while `profile_block_id` can be any value. :param model: Pyomo model to which the gross surplus expression is added. :param satellite_bids: MultiIndex DataFrame of bids for all satellites. .. py:function:: constrain_power_balance(model) Constrain that total demand must equal total supply at all times. Assumes `model.gen_power`, `model.demand_met`, and `model.supply_used` have been defined. :param model: Pyomo model to which the power balance constraint is added. .. py:function:: create_generation_cost_expression(model: pyomo.environ.AbstractModel) -> None Create generation cost expression to be used in the objective function. :param model: Pyomo model to which the generation cost expression is added. .. py:function:: set_objective_as_social_welfare_maximization(model: pyomo.environ.AbstractModel) -> None Set the objective function as social welfare maximization. Social welfare is defined as: gross surplus - generation cost. :param model: Pyomo model to which the objective is added. .. py:function:: get_market_clearing_price_as_dual(model_instance: pyomo.environ.ConcreteModel) -> pandas.DataFrame Get market price as the dual of the power balance constraint. Note: Market price might be determined by satellite bids. :param model_instance: Solved pyomo instance of the market model (LP) :returns: DataFrame representing the market clearing price for each timestamp. .. py:function:: fix_integer_variables(model_instance: pyomo.environ.Model) -> pyomo.environ.ConcreteModel Fix all integer variables of the solved model instance to their current values. :param model_instance: Solved pyomo instance of the market model (MILP). :returns: Pyomo model instance with integer/binary variables fixed to their current values from the solved MILP instance (making it an LP). .. py:function:: run_market_model(model: pyomo.environ.AbstractModel, output_path: pathlib.Path) -> tuple[numpy.ndarray, numpy.ndarray] Run market model and return market_price and scheduled_bids. :param model: Pyomo model to run/solve. :param output_path: path to save the results to. :returns: market clearing price and bids scheduled by the market. :rtype: tuple :raises RuntimeError: if the optimization problem is infeasible or unbounded. .. py:function:: extract_scheduled_bids(model_instance: pyomo.environ.ConcreteModel) -> pandas.DataFrame Extract scheduled bids from market model. :param model_instance: solved market-clearning pyomo model. :returns: amount of scheduled amount, per row of bids. .. py:function:: extract_generator_dispatch(model_instance: pyomo.environ.ConcreteModel) -> pandas.DataFrame Extract generator dispatch from market model. :param model_instance: solved market-clearing pyomo model. :returns: amount of generator dispatch per timestamp. .. py:function:: market_results_to_df(generator_dispatch: pandas.DataFrame, market_price: pandas.DataFrame, scheduled_bids: pandas.DataFrame) -> pandas.DataFrame Prepare the relevant market clearing results that should be logged. The market results are returned as one row per timestamp. Columns are market price, dispatch per generator, and scheduled bids per satellite. I.e., +-----------+--------------+-------------+-------------+-----+-------------+-------------+-----+ | timestamp | market_price | Generator 1 | Generator 2 | ... | Satellite 1 | Satellite 2 | ... | +-----------+--------------+-------------+-------------+-----+-------------+-------------+-----+ | ... | ... | ... | ... | | ... | ... | | +-----------+--------------+-------------+-------------+-----+-------------+-------------+-----+ with 'Generator N' and 'Satellite N' replaced by their actual provided names. :param generator_dispatch: dataframe of generator dispatch per generator and timestamp. :param market_price: dataframe of market clearing price per timestamp. :param scheduled_bids: dataframe of scheduled amount per bid table entry. :returns: combined table of market price, generator dispatch and quantity supplied/consumed by satellite, per timestamp. .. py:function:: validate_bids(bids: pandas.DataFrame) -> None Validate that bids have format in line with assumptions in market model. :param bids: data frame with bids. :raises Errors depending on validation check.: .. py:function:: _validate_acceptance_ratio(bids: pandas.DataFrame) .. py:function:: _validate_nonnegative_quantity(quantity: pandas.Series | numpy.ndarray) .. py:function:: _validate_sense(sense: numpy.ndarray) .. py:function:: _validate_dataframe_format(bids) .. py:function:: _validate_single_price_per_profile(bids)