Source code for MDI.Generator.GeneratorEquations

"""
Generator Equations Module
==========================
EELT7030 — Operation and Expansion Planning of Electric Power Systems  
Federal University of Paraná (UFPR)

Author
------
Augusto Mathias Adams <augusto.adams@ufpr.br>

Summary
-------
This module defines the objective-related expressions for the generation
subsystem in the MDI framework. It formulates both the **operational cost**
and **energy balance** expressions, which are later aggregated into the
system-level optimization model.

Description
-----------
The functions in this module generate symbolic expressions that represent
the two principal aspects of the generation subproblem:

1. **Operational and investment cost function** —  
   Represents the total cost of operation and expansion over the planning
   horizon, including both variable and fixed investment terms.

   \[
   C_{gen} = 
   \sum_{g,t,p} h_p \, c^{op}_g \, P_{g,t,p}
   \;+\;
   \sum_{g,t} c^{inv}_g \, x_{g,t}
   \]

   where  
   - \(h_p\) denotes the duration (hours) of load level \(p\),  
   - \(c^{op}_g\) is the operational cost of generator \(g\),  
   - \(c^{inv}_g\) is the investment cost per MW of capacity,  
   - \(P_{g,t,p}\) is the power generation level,  
   - \(x_{g,t}\) indicates if the unit is available at time \(t\).

2. **Generation balance expression** —  
   Computes the total available generation for each time period and load
   level, serving as input to system-level energy balance constraints:

   \[
   G_{bal}(t,p) = \sum_{g} P_{g,t,p}
   \]

Functions
---------
add_generator_cost_expression(m, cost_array)
    Builds and appends the generator cost expression to the provided array.

add_generator_balance_expression(m, t, p, balance_array)
    Builds and appends the generation balance expression for a given time
    period and load level to the provided array.

Notes
-----
- Both expressions are appended to lists (``cost_array`` or ``balance_array``)
  to allow modular composition of objectives and constraints in composite models.
- Missing attributes silently skip expression creation to maintain model integrity.
- This design enables dynamic integration of subsystems (e.g., storage, hydro,
  or renewable modules) under a unified optimization framework.

References
----------
[1] CEPEL. *DESSEM — Manual de Metodologia*, 2023.  
[2] Unsihuay Vila, C. *Introdução aos Sistemas de Energia Elétrica*, Lecture Notes,
    EELT7030/UFPR, 2023.

Module Dependencies
-------------------
- **Internal:** ``MDI.GeneratorVars``, ``MDI.GeneratorConstraints``  
- **External:** ``pyomo.environ (ConcreteModel)``, ``typing``
"""

from typing import List, Any
from pyomo.environ import ConcreteModel


[docs] def add_generator_cost_expression( m: ConcreteModel, cost_array: List[Any] ) -> List[Any]: """ Build and append the generator cost expression to the provided list. This function constructs the total cost expression, including both operational and investment components, over all generators, time periods, and demand levels. The expression is appended to ``cost_array`` to allow aggregation with other subsystem costs. Parameters ---------- m : pyomo.environ.ConcreteModel Pyomo model containing generator-related sets, variables, and parameters. cost_array : list of pyomo expressions List to which the total generator cost expression will be appended. Returns ------- list of pyomo expressions The same list, extended with the generator cost expression. Notes ----- The total generation cost is defined as: .. math:: C_{gen} = \\sum_{g,t,p} h_p \\, c^{op}_g \\, P_{g,t,p} + \\sum_{g,t} c^{inv}_g \\, x_{g,t} where: - :math:`h_p` is the duration (hours) of load level :math:`p`; - :math:`c^{op}_g` is the operational cost per MWh; - :math:`c^{inv}_g` is the investment cost per MW; - :math:`P_{g,t,p}` and :math:`x_{g,t}` are decision variables. The resulting expression is symbolic and compatible with Pyomo objectives. """ required = [ 'GU', 'T', 'P', 'gen_P', 'gen_c_op', 'gen_c_inv', 'gen_y', 'gen_x', 'level_hours' ] if all(hasattr(m, attr) for attr in required): if m.parcel_investment: expr = sum( # Operational cost (proportional to energy generated) m.level_hours[p] * m.gen_c_op[g] * m.gen_P[g, t, p] for g in m.GU for t in m.T for p in m.P ) + sum( # Investment cost (proportional to installed capacity) m.gen_c_inv[g] * m.gen_x[g, t] for g in m.GU for t in m.T ) else: expr = sum( # Operational cost (proportional to energy generated) m.level_hours[p] * m.gen_c_op[g] * m.gen_P[g, t, p] for g in m.GU for t in m.T for p in m.P ) + sum( # Investment cost (proportional to installed capacity) m.gen_c_inv[g] * m.gen_y[g, t] for g in m.GU for t in m.T ) cost_array.append(expr) return cost_array
[docs] def add_generator_capacity_expression( m: ConcreteModel, t: Any, p: Any, capacity_array: List[Any] ) -> List[Any]: """ Build and append the generation capacity expression for a given time and level. Computes the total generation capacity across all units for the specified time period and demand level, and appends it to ``capacity_array``. The result serves as the left-hand side of the system-level generation capacity constraint. Parameters ---------- m : pyomo.environ.ConcreteModel Pyomo model containing generator sets and variables. t : Any Time period index. p : Any Load level index. capacity_array : list of pyomo expressions List to which the generation capacity expression will be appended. Returns ------- list of pyomo expressions The same list, extended with the generation capacity expression. Notes ----- The capacity expression is defined as: .. math:: G_{bal}(t,p) = \\sum_{g} P_{g,t,p} representing the total available generation at each period and load level. """ required = [ 'GU', 'T', 'P', 'gen_pmax' ] if all(hasattr(m, attr) for attr in required): expr = sum( # Net power generation by unit and load level m.gen_pmax[g] * m.gen_x[g, t] for g in m.GU if m.gen_include_cap[g] == True ) capacity_array.append(expr) return capacity_array
[docs] def add_generator_balance_expression( m: ConcreteModel, t: Any, p: Any, balance_array: List[Any] ) -> List[Any]: """ Build and append the generation balance expression for a given time and level. Computes the total power generated across all units for the specified time period and demand level, and appends it to ``balance_array``. The result serves as the left-hand side of the system-level energy balance constraint. Parameters ---------- m : pyomo.environ.ConcreteModel Pyomo model containing generator sets and variables. t : Any Time period index. p : Any Load level index. balance_array : list of pyomo expressions List to which the generation balance expression will be appended. Returns ------- list of pyomo expressions The same list, extended with the generation balance expression. Notes ----- The balance expression is defined as: .. math:: G_{bal}(t,p) = \\sum_{g} P_{g,t,p} representing the total available generation at each period and load level. """ required = [ 'GU', 'T', 'P', 'gen_P' ] if all(hasattr(m, attr) for attr in required): expr = sum( # Net power generation by unit and load level m.gen_P[g, t, p] for g in m.GU ) balance_array.append(expr) return balance_array