From e6442cd3902bed9132f7849ee38c8304e38abfb9 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:20:53 +0200 Subject: [PATCH 01/29] Reorganize documentation of mathematical fdormulations --- docs/SUMMARY.md | 18 ++ docs/user-guide/Mathematical Notation/Bus.md | 34 ++ docs/user-guide/Mathematical Notation/Flow.md | 47 +++ .../Mathematical Notation/InvestParameters.md | 300 ++++++++++++++++- .../Mathematical Notation/LinearConverter.md | 36 +++ .../Mathematical Notation/OnOffParameters.md | 306 +++++++++++++++++- .../Mathematical Notation/Storage.md | 48 +++ flixopt/components.py | 14 + 8 files changed, 801 insertions(+), 2 deletions(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index f66c4e5e5..d29fd406f 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,6 +1,24 @@ - [Home](index.md) - [Getting Started](getting-started.md) - [User Guide](user-guide/) + - [Mathematical Notation](user-guide/Mathematical Notation/) + - [Overview](user-guide/Mathematical Notation/index.md) + - Components + - [Flow](user-guide/Mathematical Notation/Flow.md) + - [Bus](user-guide/Mathematical Notation/Bus.md) + - [Storage](user-guide/Mathematical Notation/Storage.md) + - [LinearConverter](user-guide/Mathematical Notation/LinearConverter.md) + - Features + - [InvestParameters](user-guide/Mathematical Notation/InvestParameters.md) + - [OnOffParameters](user-guide/Mathematical Notation/OnOffParameters.md) + - [Piecewise](user-guide/Mathematical Notation/Piecewise.md) + - System-Level + - [Effects, Penalty & Objective](user-guide/Mathematical Notation/Effects, Penalty & Objective.md) + - [Modeling Patterns](user-guide/Mathematical Notation/modeling-patterns/) + - [Overview](user-guide/Mathematical Notation/modeling-patterns/index.md) + - [Bounds and States](user-guide/Mathematical Notation/modeling-patterns/bounds-and-states.md) + - [Duration Tracking](user-guide/Mathematical Notation/modeling-patterns/duration-tracking.md) + - [State Transitions](user-guide/Mathematical Notation/modeling-patterns/state-transitions.md) - [Examples](examples/) - [Contribute](contribute.md) - [API Reference](api-reference/) diff --git a/docs/user-guide/Mathematical Notation/Bus.md b/docs/user-guide/Mathematical Notation/Bus.md index 6ba17eede..2cfd300c3 100644 --- a/docs/user-guide/Mathematical Notation/Bus.md +++ b/docs/user-guide/Mathematical Notation/Bus.md @@ -31,3 +31,37 @@ With: - $\text{t}_i$ being the time step - $s_{b \rightarrow \Phi}(\text{t}_i)$ being the penalty term - $\text a_{b \rightarrow \Phi}(\text{t}_i)$ being the penalty coefficient (`excess_penalty_per_flow_hour`) + +--- + +## Implementation + +**Class:** [`Bus`][flixopt.elements.Bus] + +**Location:** `flixopt/elements.py:120` + +**Model Class:** [`BusModel`][flixopt.elements.BusModel] + +**Location:** `flixopt/elements.py:736` + +**Key Constraints:** +- Bus balance equation (eq. $\eqref{eq:bus_balance}$ or $\eqref{eq:bus_balance-excess}$): `flixopt/elements.py:751` +- Excess/deficit bounds (when applicable): `flixopt/elements.py:763` + +**Variables Created:** +- No additional variables for strict balance +- `excess_input`, `excess_output`: Excess/deficit variables $\phi_\text{in}(\text{t}_i), \phi_\text{out}(\text{t}_i)$ (when penalty is specified) + +**Parameters:** +- `excess_penalty_per_flow_hour`: Penalty coefficient $\text{a}_{b \rightarrow \Phi}$ for balance violations + +**Penalty Contribution:** +When excess is allowed, the penalty term $s_{b \rightarrow \Phi}(\text{t}_i)$ contributes to the overall system penalty $\Phi$ as described in [Effects, Penalty & Objective](Effects,%20Penalty%20&%20Objective.md#penalty). + +--- + +## See Also + +- [Flow](Flow.md) - Definition of flow rates in the balance +- [Effects, Penalty & Objective](Effects,%20Penalty%20&%20Objective.md) - How penalties are included in the objective function +- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/Mathematical Notation/Flow.md b/docs/user-guide/Mathematical Notation/Flow.md index 78135e822..d90188020 100644 --- a/docs/user-guide/Mathematical Notation/Flow.md +++ b/docs/user-guide/Mathematical Notation/Flow.md @@ -24,3 +24,50 @@ $$ This mathematical formulation can be extended by using [OnOffParameters](./OnOffParameters.md) to define the on/off state of the Flow, or by using [InvestParameters](./InvestParameters.md) to change the size of the Flow from a constant to an optimization variable. + +--- + +## Mathematical Patterns Used + +Flow formulation uses the following modeling patterns: + +- **[Scaled Bounds](modeling-patterns/bounds-and-states.md#scaled-bounds)** - Basic flow rate bounds (equation $\eqref{eq:flow_rate}$) +- **[Scaled Bounds with State](modeling-patterns/bounds-and-states.md#scaled-bounds-with-state)** - When combined with [OnOffParameters](OnOffParameters.md) +- **[Bounds with State](modeling-patterns/bounds-and-states.md#bounds-with-state)** - Investment decisions with [InvestParameters](InvestParameters.md) + +--- + +## Implementation + +**Class:** [`Flow`][flixopt.elements.Flow] + +**Location:** `flixopt/elements.py:175` + +**Model Class:** [`FlowModel`][flixopt.elements.FlowModel] + +**Location:** `flixopt/elements.py:350` + +**Key Constraints:** +- Flow rate bounds (eq. $\eqref{eq:flow_rate}$): Created in `FlowModel._do_modeling()` + +**Variables Created:** +- `flow_rate`: Flow rate variable $p(\text{t}_i)$ +- Additional variables when using [OnOffParameters](OnOffParameters.md) or [InvestParameters](InvestParameters.md) + +**Parameters:** +- `size`: Flow size $\text{P}$ (can be fixed or variable with InvestParameters) +- `relative_minimum`, `relative_maximum`: Relative bounds $\text{p}^{\text{L}}_{\text{rel}}, \text{p}^{\text{U}}_{\text{rel}}$ +- `effects_per_flow_hour`: Operational effects (costs, emissions, etc.) +- `invest_parameters`: Optional investment modeling (see [InvestParameters](InvestParameters.md)) +- `on_off_parameters`: Optional on/off operation (see [OnOffParameters](OnOffParameters.md)) + +--- + +## See Also + +- [OnOffParameters](OnOffParameters.md) - Binary on/off operation +- [InvestParameters](InvestParameters.md) - Variable flow sizing +- [Bus](Bus.md) - Flow balance constraints +- [LinearConverter](LinearConverter.md) - Flow ratio constraints +- [Storage](Storage.md) - Flow integration over time +- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/Mathematical Notation/InvestParameters.md b/docs/user-guide/Mathematical Notation/InvestParameters.md index d3cd4f81e..f9a91beae 100644 --- a/docs/user-guide/Mathematical Notation/InvestParameters.md +++ b/docs/user-guide/Mathematical Notation/InvestParameters.md @@ -1,3 +1,301 @@ # InvestParameters -This is a work in progress. +[`InvestParameters`][flixopt.interface.InvestParameters] model investment decisions in optimization problems, enabling both binary (invest/don't invest) and continuous sizing choices with comprehensive cost modeling. + +## Investment Decision Types + +FlixOpt supports two main types of investment decisions: + +### Binary Investment + +Fixed-size investment creating a yes/no decision (e.g., install a 100 kW generator): + +$$\label{eq:invest_binary} +v_\text{invest} = s_\text{invest} \cdot \text{size}_\text{fixed} +$$ + +With: +- $v_\text{invest}$ being the resulting investment size +- $s_\text{invest} \in \{0, 1\}$ being the binary investment decision +- $\text{size}_\text{fixed}$ being the predefined component size + +**Behavior:** +- $s_\text{invest} = 0$: no investment ($v_\text{invest} = 0$) +- $s_\text{invest} = 1$: invest at fixed size ($v_\text{invest} = \text{size}_\text{fixed}$) + +--- + +### Continuous Sizing + +Variable-size investment with bounds (e.g., battery capacity from 10-1000 kWh): + +$$\label{eq:invest_continuous} +s_\text{invest} \cdot \text{size}_\text{min} \leq v_\text{invest} \leq s_\text{invest} \cdot \text{size}_\text{max} +$$ + +With: +- $v_\text{invest}$ being the investment size variable (continuous) +- $s_\text{invest} \in \{0, 1\}$ being the binary investment decision +- $\text{size}_\text{min}$ being the minimum investment size (if investing) +- $\text{size}_\text{max}$ being the maximum investment size + +**Behavior:** +- $s_\text{invest} = 0$: no investment ($v_\text{invest} = 0$) +- $s_\text{invest} = 1$: invest with size in $[\text{size}_\text{min}, \text{size}_\text{max}]$ + +This uses the **bounds with state** pattern described in [Bounds and States](modeling-patterns/bounds-and-states.md#bounds-with-state). + +--- + +### Optional vs. Mandatory Investment + +The `optional` parameter controls whether investment is required: + +**Optional Investment** (`optional=True`): +$$\label{eq:invest_optional} +s_\text{invest} \in \{0, 1\} +$$ + +The optimization can freely choose to invest or not. + +**Mandatory Investment** (`optional=False`): +$$\label{eq:invest_mandatory} +s_\text{invest} = 1 +$$ + +The investment must occur (useful for mandatory upgrades or replacements). + +--- + +## Effect Modeling + +Investment effects (costs, emissions, etc.) are modeled using three components: + +### Fixed Effects + +One-time effects incurred if investment is made, independent of size: + +$$\label{eq:invest_fixed_effects} +E_{e,\text{fix}} = s_\text{invest} \cdot \text{fix}_e +$$ + +With: +- $E_{e,\text{fix}}$ being the fixed contribution to effect $e$ +- $\text{fix}_e$ being the fixed effect value (e.g., fixed installation cost) + +**Examples:** +- Fixed installation costs (permits, grid connection) +- One-time environmental impacts (land preparation) +- Fixed labor or administrative costs + +--- + +### Specific Effects + +Effects proportional to investment size (per-unit costs): + +$$\label{eq:invest_specific_effects} +E_{e,\text{spec}} = v_\text{invest} \cdot \text{spec}_e +$$ + +With: +- $E_{e,\text{spec}}$ being the size-dependent contribution to effect $e$ +- $\text{spec}_e$ being the specific effect value per unit size (e.g., €/kW) + +**Examples:** +- Equipment costs (€/kW) +- Material requirements (kg steel/kW) +- Recurring costs (€/kW/year maintenance) + +--- + +### Piecewise Effects + +Non-linear effect relationships using piecewise linear approximations: + +$$\label{eq:invest_piecewise_effects} +E_{e,\text{pw}} = \sum_{k=1}^{K} \lambda_k \cdot r_{e,k} +$$ + +Subject to: +$$ +v_\text{invest} = \sum_{k=1}^{K} \lambda_k \cdot v_k +$$ + +With: +- $E_{e,\text{pw}}$ being the piecewise contribution to effect $e$ +- $\lambda_k$ being the piecewise lambda variables (see [Piecewise](Piecewise.md)) +- $r_{e,k}$ being the effect rate at piece $k$ +- $v_k$ being the size points defining the pieces + +**Use cases:** +- Economies of scale (bulk discounts) +- Technology learning curves +- Threshold effects (capacity tiers with different costs) + +See [Piecewise](Piecewise.md) for detailed mathematical formulation. + +--- + +### Divestment Effects + +Costs incurred if investment is NOT made: + +$$\label{eq:invest_divest_effects} +E_{e,\text{divest}} = (1 - s_\text{invest}) \cdot \text{divest}_e +$$ + +With: +- $E_{e,\text{divest}}$ being the divestment contribution to effect $e$ +- $\text{divest}_e$ being the divestment effect value + +**Behavior:** +- $s_\text{invest} = 0$: divestment effects are incurred +- $s_\text{invest} = 1$: no divestment effects + +**Examples:** +- Demolition or disposal costs +- Contractual penalties for not investing +- Opportunity costs or lost revenues + +--- + +### Total Investment Effects + +The total contribution to effect $e$ from an investment is: + +$$\label{eq:invest_total_effects} +E_{e,\text{invest}} = E_{e,\text{fix}} + E_{e,\text{spec}} + E_{e,\text{pw}} + E_{e,\text{divest}} +$$ + +Effects integrate into the overall system effects as described in [Effects, Penalty & Objective](Effects,%20Penalty%20&%20Objective.md). + +--- + +## Integration with Components + +Investment parameters modify component sizing: + +### Without Investment +Component size is a fixed parameter: +$$ +\text{size} = \text{size}_\text{nominal} +$$ + +### With Investment +Component size becomes a variable: +$$ +\text{size} = v_\text{invest} +$$ + +This size variable then appears in component constraints. For example, flow rate bounds become: + +$$ +v_\text{invest} \cdot \text{rel}_\text{lower} \leq p(t) \leq v_\text{invest} \cdot \text{rel}_\text{upper} +$$ + +Using the **scaled bounds** pattern from [Bounds and States](modeling-patterns/bounds-and-states.md#scaled-bounds). + +--- + +## Cost Annualization + +**Important:** All investment cost values must be properly weighted to match the optimization model's time horizon. + +For long-term investments, costs should be annualized: + +$$\label{eq:annualization} +\text{cost}_\text{annual} = \frac{\text{cost}_\text{capital} \cdot r}{1 - (1 + r)^{-n}} +$$ + +With: +- $\text{cost}_\text{capital}$ being the upfront investment cost +- $r$ being the discount rate +- $n$ being the equipment lifetime in years + +**Example:** €1,000,000 equipment with 20-year life and 5% discount rate +$$ +\text{cost}_\text{annual} = \frac{1{,}000{,}000 \cdot 0.05}{1 - (1.05)^{-20}} \approx €80{,}243/\text{year} +$$ + +--- + +## Implementation + +**Class:** [`InvestParameters`][flixopt.interface.InvestParameters] + +**Location:** `flixopt/interface.py:663` + +**Key Parameters:** +- `fixed_size`: For binary investments (mutually exclusive with continuous sizing) +- `minimum_size`, `maximum_size`: For continuous sizing +- `optional`: Whether investment can be skipped +- `fix_effects`: Fixed costs dictionary +- `specific_effects`: Per-unit costs dictionary +- `piecewise_effects`: Non-linear cost modeling +- `divest_effects`: Costs for not investing + +**Used in:** +- [`Flow`][flixopt.elements.Flow] - Flexible capacity decisions +- [`Storage`][flixopt.components.Storage] - Storage sizing optimization +- [`LinearConverter`][flixopt.components.LinearConverter] - Converter capacity planning +- All components supporting investment decisions + +--- + +## Examples + +### Binary Investment (Solar Panels) +```python +solar_investment = InvestParameters( + fixed_size=100, # 100 kW system + optional=True, + fix_effects={'cost': 25000}, # Installation costs + specific_effects={'cost': 1200}, # €1200/kW +) +``` + +### Continuous Sizing (Battery) +```python +battery_investment = InvestParameters( + minimum_size=10, # kWh + maximum_size=1000, + optional=True, + fix_effects={'cost': 5000}, # Grid connection + specific_effects={'cost': 600}, # €600/kWh +) +``` + +### With Divestment Costs (Replacement) +```python +boiler_replacement = InvestParameters( + minimum_size=50, # kW + maximum_size=200, + optional=True, + fix_effects={'cost': 15000}, + specific_effects={'cost': 400}, + divest_effects={'cost': 8000}, # Demolition if not replaced +) +``` + +### Economies of Scale (Piecewise) +```python +battery_investment = InvestParameters( + minimum_size=10, + maximum_size=1000, + piecewise_effects=PiecewiseEffects( + piecewise_origin=Piecewise([ + Piece(0, 100), # Small + Piece(100, 500), # Medium + Piece(500, 1000), # Large + ]), + piecewise_shares={ + 'cost': Piecewise([ + Piece(800, 750), # €800-750/kWh + Piece(750, 600), # €750-600/kWh + Piece(600, 500), # €600-500/kWh (bulk discount) + ]) + }, + ), +) +``` diff --git a/docs/user-guide/Mathematical Notation/LinearConverter.md b/docs/user-guide/Mathematical Notation/LinearConverter.md index bf1279c32..147dcaf6a 100644 --- a/docs/user-guide/Mathematical Notation/LinearConverter.md +++ b/docs/user-guide/Mathematical Notation/LinearConverter.md @@ -17,5 +17,41 @@ $$ \label{eq:Linear-Transformer-Ratio-simple} $$ where $\text a$ can be interpreted as the conversion efficiency of the **LinearConverter**. + #### Piecewise Conversion factors The conversion efficiency can be defined as a piecewise linear approximation. See [Piecewise](Piecewise.md) for more details. + +--- + +## Implementation + +**Class:** [`LinearConverter`][flixopt.components.LinearConverter] + +**Location:** `flixopt/components.py:37` + +**Key Constraints:** +- Linear conversion equation (eq. $\eqref{eq:Linear-Transformer-Ratio}$): Created in component-specific modeling methods + +**Parameters:** +- Conversion factors $\text{a}_{f_\text{in}}$ and $\text{b}_{f_\text{out}}$ are defined through flow connections +- For simple converters with one input and one output, efficiency $\text{a}$ is specified + +**Specialized Linear Converters:** + +FlixOpt provides specialized linear converter classes for common applications: + +- **[`HeatPump`][flixopt.linear_converters.HeatPump]** - Coefficient of Performance (COP) based conversion +- **[`Power2Heat`][flixopt.linear_converters.Power2Heat]** - Electric heating with efficiency ≤ 1 +- **[`CHP`][flixopt.linear_converters.CHP]** - Combined heat and power generation +- **[`Boiler`][flixopt.linear_converters.Boiler]** - Fuel to heat conversion + +These classes handle the mathematical formulation automatically based on physical relationships. + +--- + +## See Also + +- [Flow](Flow.md) - Definition of flow rates +- [Piecewise](Piecewise.md) - Non-linear conversion efficiency modeling +- [InvestParameters](InvestParameters.md) - Variable converter sizing +- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/Mathematical Notation/OnOffParameters.md b/docs/user-guide/Mathematical Notation/OnOffParameters.md index ca22d7d33..3fde93eda 100644 --- a/docs/user-guide/Mathematical Notation/OnOffParameters.md +++ b/docs/user-guide/Mathematical Notation/OnOffParameters.md @@ -1,3 +1,307 @@ # OnOffParameters -This is a work in progress. +[`OnOffParameters`][flixopt.interface.OnOffParameters] model equipment that operates in discrete on/off states rather than continuous operation. This captures realistic operational constraints including startup costs, minimum run times, cycling limitations, and maintenance scheduling. + +## Binary State Variable + +Equipment operation is modeled using a binary state variable: + +$$\label{eq:onoff_state} +s(t) \in \{0, 1\} \quad \forall t +$$ + +With: +- $s(t) = 1$: equipment is operating (on state) +- $s(t) = 0$: equipment is shutdown (off state) + +This state variable controls the equipment's operational constraints and modifies flow bounds using the **bounds with state** pattern from [Bounds and States](modeling-patterns/bounds-and-states.md#bounds-with-state). + +--- + +## State Transitions and Switching + +State transitions are tracked using switch variables (see [State Transitions](modeling-patterns/state-transitions.md#binary-state-transitions)): + +$$\label{eq:onoff_transitions} +s^\text{on}(t) - s^\text{off}(t) = s(t) - s(t-1) \quad \forall t > 0 +$$ + +$$\label{eq:onoff_switch_exclusivity} +s^\text{on}(t) + s^\text{off}(t) \leq 1 \quad \forall t +$$ + +With: +- $s^\text{on}(t) \in \{0, 1\}$: equals 1 when switching from off to on (startup) +- $s^\text{off}(t) \in \{0, 1\}$: equals 1 when switching from on to off (shutdown) + +**Behavior:** +- Off → On: $s^\text{on}(t) = 1, s^\text{off}(t) = 0$ +- On → Off: $s^\text{on}(t) = 0, s^\text{off}(t) = 1$ +- No change: $s^\text{on}(t) = 0, s^\text{off}(t) = 0$ + +--- + +## Effects and Costs + +### Switching Effects + +Effects incurred when equipment starts up: + +$$\label{eq:onoff_switch_effects} +E_{e,\text{switch}} = \sum_{t} s^\text{on}(t) \cdot \text{effect}_{e,\text{switch}} +$$ + +With: +- $\text{effect}_{e,\text{switch}}$ being the effect value per startup event + +**Examples:** +- Startup fuel consumption +- Wear and tear costs +- Labor costs for startup procedures +- Inrush power demands + +--- + +### Running Effects + +Effects incurred while equipment is operating: + +$$\label{eq:onoff_running_effects} +E_{e,\text{run}} = \sum_{t} s(t) \cdot \Delta t \cdot \text{effect}_{e,\text{run}} +$$ + +With: +- $\text{effect}_{e,\text{run}}$ being the effect rate per operating hour +- $\Delta t$ being the time step duration + +**Examples:** +- Fixed operating and maintenance costs +- Auxiliary power consumption +- Consumable materials +- Emissions while running + +--- + +## Operating Hour Constraints + +### Total Operating Hours + +Bounds on total operating time across the planning horizon: + +$$\label{eq:onoff_total_hours} +h_\text{min} \leq \sum_{t} s(t) \cdot \Delta t \leq h_\text{max} +$$ + +With: +- $h_\text{min}$ being the minimum total operating hours +- $h_\text{max}$ being the maximum total operating hours + +**Use cases:** +- Minimum runtime requirements (contracts, maintenance) +- Maximum runtime limits (fuel availability, permits, equipment life) + +--- + +### Consecutive Operating Hours + +**Minimum Consecutive On-Time:** + +Enforces minimum runtime once started using duration tracking (see [Duration Tracking](modeling-patterns/duration-tracking.md#minimum-duration-constraints)): + +$$\label{eq:onoff_min_on_duration} +d^\text{on}(t) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min} \quad \forall t > 0 +$$ + +With: +- $d^\text{on}(t)$ being the consecutive on-time duration +- $h^\text{on}_\text{min}$ being the minimum required on-time + +**Behavior:** +- When shutting down: enforces equipment was on for at least $h^\text{on}_\text{min}$ +- Prevents short cycling and frequent startups + +**Maximum Consecutive On-Time:** + +Limits continuous operation before requiring shutdown: + +$$\label{eq:onoff_max_on_duration} +d^\text{on}(t) \leq h^\text{on}_\text{max} \quad \forall t +$$ + +**Use cases:** +- Mandatory maintenance intervals +- Process batch time limits +- Thermal cycling requirements + +--- + +### Consecutive Shutdown Hours + +**Minimum Consecutive Off-Time:** + +Enforces minimum shutdown duration before restarting: + +$$\label{eq:onoff_min_off_duration} +d^\text{off}(t) \geq (s(t) - s(t-1)) \cdot h^\text{off}_\text{min} \quad \forall t > 0 +$$ + +With: +- $d^\text{off}(t)$ being the consecutive off-time duration +- $h^\text{off}_\text{min}$ being the minimum required off-time + +**Use cases:** +- Cooling periods +- Maintenance requirements +- Process stabilization + +**Maximum Consecutive Off-Time:** + +Limits shutdown duration before mandatory restart: + +$$\label{eq:onoff_max_off_duration} +d^\text{off}(t) \leq h^\text{off}_\text{max} \quad \forall t +$$ + +**Use cases:** +- Equipment preservation requirements +- Process stability needs +- Contractual minimum activity levels + +--- + +## Cycling Limits + +Maximum number of startups across the planning horizon: + +$$\label{eq:onoff_max_switches} +\sum_{t} s^\text{on}(t) \leq n_\text{max} +$$ + +With: +- $n_\text{max}$ being the maximum allowed number of startups + +**Use cases:** +- Preventing excessive equipment wear +- Grid stability requirements +- Operational complexity limits +- Maintenance budget constraints + +--- + +## Integration with Flow Bounds + +OnOffParameters modify flow rate bounds by coupling them to the on/off state. + +**Without OnOffParameters** (continuous operation): +$$ +P \cdot \text{rel}_\text{lower} \leq p(t) \leq P \cdot \text{rel}_\text{upper} +$$ + +**With OnOffParameters** (binary operation): +$$ +s(t) \cdot P \cdot \max(\varepsilon, \text{rel}_\text{lower}) \leq p(t) \leq s(t) \cdot P \cdot \text{rel}_\text{upper} +$$ + +Using the **bounds with state** pattern from [Bounds and States](modeling-patterns/bounds-and-states.md#bounds-with-state). + +**Behavior:** +- When $s(t) = 0$: flow is forced to zero +- When $s(t) = 1$: flow follows normal bounds + +--- + +## Complete Formulation Summary + +For equipment with OnOffParameters, the complete constraint system includes: + +1. **State variable:** $s(t) \in \{0, 1\}$ +2. **Switch tracking:** $s^\text{on}(t) - s^\text{off}(t) = s(t) - s(t-1)$ +3. **Switch exclusivity:** $s^\text{on}(t) + s^\text{off}(t) \leq 1$ +4. **Duration tracking:** + - On-duration: $d^\text{on}(t)$ following duration tracking pattern + - Off-duration: $d^\text{off}(t)$ following duration tracking pattern +5. **Minimum on-time:** $d^\text{on}(t) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min}$ +6. **Maximum on-time:** $d^\text{on}(t) \leq h^\text{on}_\text{max}$ +7. **Minimum off-time:** $d^\text{off}(t) \geq (s(t) - s(t-1)) \cdot h^\text{off}_\text{min}$ +8. **Maximum off-time:** $d^\text{off}(t) \leq h^\text{off}_\text{max}$ +9. **Total hours:** $h_\text{min} \leq \sum_t s(t) \cdot \Delta t \leq h_\text{max}$ +10. **Cycling limit:** $\sum_t s^\text{on}(t) \leq n_\text{max}$ +11. **Flow bounds:** $s(t) \cdot P \cdot \text{rel}_\text{lower} \leq p(t) \leq s(t) \cdot P \cdot \text{rel}_\text{upper}$ + +--- + +## Implementation + +**Class:** [`OnOffParameters`][flixopt.interface.OnOffParameters] + +**Location:** `flixopt/interface.py:918` + +**Key Parameters:** +- `effects_per_switch_on`: Costs per startup event +- `effects_per_running_hour`: Costs per hour of operation +- `on_hours_total_min`, `on_hours_total_max`: Total runtime bounds +- `consecutive_on_hours_min`, `consecutive_on_hours_max`: Consecutive runtime bounds +- `consecutive_off_hours_min`, `consecutive_off_hours_max`: Consecutive shutdown bounds +- `switch_on_total_max`: Maximum number of startups +- `force_switch_on`: Create switch variables even without limits (for tracking) + +**Mathematical Patterns Used:** +- [State Transitions](modeling-patterns/state-transitions.md#binary-state-transitions) - Switch tracking +- [Duration Tracking](modeling-patterns/duration-tracking.md) - Consecutive time constraints +- [Bounds with State](modeling-patterns/bounds-and-states.md#bounds-with-state) - Flow control + +**Used in:** +- [`Flow`][flixopt.elements.Flow] - On/off operation for flows +- All components supporting discrete operational states + +--- + +## Examples + +### Power Plant with Startup Costs +```python +power_plant = OnOffParameters( + effects_per_switch_on={'startup_cost': 25000}, # €25k per startup + effects_per_running_hour={'fixed_om': 125}, # €125/hour while running + consecutive_on_hours_min=8, # Minimum 8-hour run + consecutive_off_hours_min=4, # 4-hour cooling period + on_hours_total_max=6000, # Annual limit +) +``` + +### Batch Process with Cycling Limits +```python +batch_reactor = OnOffParameters( + effects_per_switch_on={'setup_cost': 1500}, + consecutive_on_hours_min=12, # 12-hour minimum batch + consecutive_on_hours_max=24, # 24-hour maximum batch + consecutive_off_hours_min=6, # Cleaning time + switch_on_total_max=200, # Max 200 batches +) +``` + +### HVAC with Cycle Prevention +```python +hvac = OnOffParameters( + effects_per_switch_on={'compressor_wear': 0.5}, + consecutive_on_hours_min=1, # Prevent short cycling + consecutive_off_hours_min=0.5, # 30-min minimum off + switch_on_total_max=2000, # Limit compressor starts +) +``` + +### Backup Generator with Testing Requirements +```python +backup_gen = OnOffParameters( + effects_per_switch_on={'fuel_priming': 50}, # L diesel + consecutive_on_hours_min=0.5, # 30-min test duration + consecutive_off_hours_max=720, # Test every 30 days + on_hours_total_min=26, # Weekly testing requirement +) +``` + +--- + +## Notes + +**Time Series Boundary:** The final time period constraints for consecutive_on_hours_min/max and consecutive_off_hours_min/max are not enforced at the end of the planning horizon. This allows optimization to end with ongoing campaigns that may be shorter/longer than specified, as they extend beyond the modeled period. diff --git a/docs/user-guide/Mathematical Notation/Storage.md b/docs/user-guide/Mathematical Notation/Storage.md index 63f01d198..99deb3d29 100644 --- a/docs/user-guide/Mathematical Notation/Storage.md +++ b/docs/user-guide/Mathematical Notation/Storage.md @@ -42,3 +42,51 @@ Where: - $\eta_\text{in}(\text{t}_i)$ is the charging efficiency at time $\text{t}_i$ - $p_{f_\text{out}}(\text{t}_i)$ is the output flow rate at time $\text{t}_i$ - $\eta_\text{out}(\text{t}_i)$ is the discharging efficiency at time $\text{t}_i$ + +--- + +## Mathematical Patterns Used + +Storage formulation uses the following modeling patterns: + +- **[Basic Bounds](modeling-patterns/bounds-and-states.md#basic-bounds)** - For charge state bounds (equation $\eqref{eq:Storage_Bounds}$) +- **[Scaled Bounds](modeling-patterns/bounds-and-states.md#scaled-bounds)** - For flow rate bounds relative to storage size + +When combined with investment parameters, storage can use: +- **[Bounds with State](modeling-patterns/bounds-and-states.md#bounds-with-state)** - Investment decisions (see [InvestParameters](InvestParameters.md)) + +--- + +## Implementation + +**Class:** [`Storage`][flixopt.components.Storage] + +**Location:** `flixopt/components.py:237` + +**Model Class:** [`StorageModel`][flixopt.components.StorageModel] + +**Location:** `flixopt/components.py:800` + +**Key Constraints:** +- Charge state bounds: `flixopt/components.py:~820` +- Storage balance equation (eq. 3): `flixopt/components.py:838-842` + +**Variables Created:** +- `charge_state`: State of charge $c(\text{t}_i)$ +- `charge_flow`: Input flow rate $p_{f_\text{in}}(\text{t}_i)$ +- `discharge_flow`: Output flow rate $p_{f_\text{out}}(\text{t}_i)$ + +**Parameters:** +- `size`: Storage capacity $\text{C}$ +- `relative_loss_per_hour`: Self-discharge rate $\dot{\text{c}}_\text{rel,loss}$ +- `charge_state_start`: Initial charge $c(\text{t}_0)$ +- `charge_state_end`: Final charge target $c(\text{t}_\text{end})$ (optional) +- `eta_charge`, `eta_discharge`: Charging/discharging efficiencies $\eta_\text{in}, \eta_\text{out}$ + +--- + +## See Also + +- [Flow](Flow.md) - Input and output flow definitions +- [InvestParameters](InvestParameters.md) - Variable storage sizing +- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks diff --git a/flixopt/components.py b/flixopt/components.py index 01b6864e3..e8fcdf8b2 100644 --- a/flixopt/components.py +++ b/flixopt/components.py @@ -247,6 +247,20 @@ class Storage(Component): final state constraints, and time-varying parameters. It supports both fixed-size and investment-optimized storage systems with comprehensive techno-economic modeling. + Mathematical Formulation: + See the complete mathematical model in the documentation: + `Storage.md `_ + + - Equation (1): Charge state bounds + - Equation (3): Storage balance (charge state evolution) + + Variable Mapping: + - ``capacity_in_flow_hours`` → C (storage capacity) + - ``charge_state`` → c(t_i) (state of charge at time t_i) + - ``relative_loss_per_hour`` → ċ_rel,loss (self-discharge rate) + - ``eta_charge`` → η_in (charging efficiency) + - ``eta_discharge`` → η_out (discharging efficiency) + Args: label: The label of the Element. Used to identify it in the FlowSystem. charging: Incoming flow for loading the storage. Represents energy or material From d1c411da8a6c2c34c6a2ea4100e72c89afa83526 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:24:06 +0200 Subject: [PATCH 02/29] Fix mkdocs --- docs/SUMMARY.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index d29fd406f..f66c4e5e5 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,24 +1,6 @@ - [Home](index.md) - [Getting Started](getting-started.md) - [User Guide](user-guide/) - - [Mathematical Notation](user-guide/Mathematical Notation/) - - [Overview](user-guide/Mathematical Notation/index.md) - - Components - - [Flow](user-guide/Mathematical Notation/Flow.md) - - [Bus](user-guide/Mathematical Notation/Bus.md) - - [Storage](user-guide/Mathematical Notation/Storage.md) - - [LinearConverter](user-guide/Mathematical Notation/LinearConverter.md) - - Features - - [InvestParameters](user-guide/Mathematical Notation/InvestParameters.md) - - [OnOffParameters](user-guide/Mathematical Notation/OnOffParameters.md) - - [Piecewise](user-guide/Mathematical Notation/Piecewise.md) - - System-Level - - [Effects, Penalty & Objective](user-guide/Mathematical Notation/Effects, Penalty & Objective.md) - - [Modeling Patterns](user-guide/Mathematical Notation/modeling-patterns/) - - [Overview](user-guide/Mathematical Notation/modeling-patterns/index.md) - - [Bounds and States](user-guide/Mathematical Notation/modeling-patterns/bounds-and-states.md) - - [Duration Tracking](user-guide/Mathematical Notation/modeling-patterns/duration-tracking.md) - - [State Transitions](user-guide/Mathematical Notation/modeling-patterns/state-transitions.md) - [Examples](examples/) - [Contribute](contribute.md) - [API Reference](api-reference/) From a2f46954d5c60837d0711d721289b0393a59d699 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:24:17 +0200 Subject: [PATCH 03/29] Revert "Fix mkdocs" This reverts commit d1c411da8a6c2c34c6a2ea4100e72c89afa83526. --- docs/SUMMARY.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index f66c4e5e5..d29fd406f 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,6 +1,24 @@ - [Home](index.md) - [Getting Started](getting-started.md) - [User Guide](user-guide/) + - [Mathematical Notation](user-guide/Mathematical Notation/) + - [Overview](user-guide/Mathematical Notation/index.md) + - Components + - [Flow](user-guide/Mathematical Notation/Flow.md) + - [Bus](user-guide/Mathematical Notation/Bus.md) + - [Storage](user-guide/Mathematical Notation/Storage.md) + - [LinearConverter](user-guide/Mathematical Notation/LinearConverter.md) + - Features + - [InvestParameters](user-guide/Mathematical Notation/InvestParameters.md) + - [OnOffParameters](user-guide/Mathematical Notation/OnOffParameters.md) + - [Piecewise](user-guide/Mathematical Notation/Piecewise.md) + - System-Level + - [Effects, Penalty & Objective](user-guide/Mathematical Notation/Effects, Penalty & Objective.md) + - [Modeling Patterns](user-guide/Mathematical Notation/modeling-patterns/) + - [Overview](user-guide/Mathematical Notation/modeling-patterns/index.md) + - [Bounds and States](user-guide/Mathematical Notation/modeling-patterns/bounds-and-states.md) + - [Duration Tracking](user-guide/Mathematical Notation/modeling-patterns/duration-tracking.md) + - [State Transitions](user-guide/Mathematical Notation/modeling-patterns/state-transitions.md) - [Examples](examples/) - [Contribute](contribute.md) - [API Reference](api-reference/) From 9d452b5feda0ca008c7802cf29785a007bf3e895 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:42:07 +0200 Subject: [PATCH 04/29] Temp --- docs/SUMMARY.md | 34 +++++++++---------- .../effects-penalty-objective.md} | 0 .../elements}/Bus.md | 0 .../elements}/Flow.md | 0 .../elements}/LinearConverter.md | 0 .../elements}/Storage.md | 0 .../features}/InvestParameters.md | 0 .../features}/OnOffParameters.md | 0 .../features}/Piecewise.md | 0 .../index.md | 0 .../others.md | 0 11 files changed, 16 insertions(+), 18 deletions(-) rename docs/user-guide/{Mathematical Notation/Effects, Penalty & Objective.md => mathematical-notation/effects-penalty-objective.md} (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation/elements}/Bus.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation/elements}/Flow.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation/elements}/LinearConverter.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation/elements}/Storage.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation/features}/InvestParameters.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation/features}/OnOffParameters.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation/features}/Piecewise.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation}/index.md (100%) rename docs/user-guide/{Mathematical Notation => mathematical-notation}/others.md (100%) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index d29fd406f..ca8a6696f 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,24 +1,22 @@ - [Home](index.md) - [Getting Started](getting-started.md) - [User Guide](user-guide/) - - [Mathematical Notation](user-guide/Mathematical Notation/) - - [Overview](user-guide/Mathematical Notation/index.md) - - Components - - [Flow](user-guide/Mathematical Notation/Flow.md) - - [Bus](user-guide/Mathematical Notation/Bus.md) - - [Storage](user-guide/Mathematical Notation/Storage.md) - - [LinearConverter](user-guide/Mathematical Notation/LinearConverter.md) - - Features - - [InvestParameters](user-guide/Mathematical Notation/InvestParameters.md) - - [OnOffParameters](user-guide/Mathematical Notation/OnOffParameters.md) - - [Piecewise](user-guide/Mathematical Notation/Piecewise.md) - - System-Level - - [Effects, Penalty & Objective](user-guide/Mathematical Notation/Effects, Penalty & Objective.md) - - [Modeling Patterns](user-guide/Mathematical Notation/modeling-patterns/) - - [Overview](user-guide/Mathematical Notation/modeling-patterns/index.md) - - [Bounds and States](user-guide/Mathematical Notation/modeling-patterns/bounds-and-states.md) - - [Duration Tracking](user-guide/Mathematical Notation/modeling-patterns/duration-tracking.md) - - [State Transitions](user-guide/Mathematical Notation/modeling-patterns/state-transitions.md) + - [Overview](user-guide/mathematical-notation/index.md) + - [Elements](user-guide/mathematical-notation/elements/) + - [Flow](user-guide/mathematical-notation/elements/Flow.md) + - [Bus](user-guide/mathematical-notation/elements/Bus.md) + - [Storage](user-guide/mathematical-notation/elements/Storage.md) + - [LinearConverter](user-guide/mathematical-notation/elements/LinearConverter.md) + - [Features](user-guide/mathematical-notation/features/) + - [InvestParameters](user-guide/mathematical-notation/features/InvestParameters.md) + - [OnOffParameters](user-guide/mathematical-notation/features/OnOffParameters.md) + - [Piecewise](user-guide/mathematical-notation/features/Piecewise.md) + - [Effects, Penalty & Objective](user-guide/mathematical-notation/effects-penalty-objective.md) + - [Modeling Patterns](user-guide/mathematical-notation/modeling-patterns/) + - [Overview](user-guide/mathematical-notation/modeling-patterns/index.md) + - [Bounds and States](user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md) + - [Duration Tracking](user-guide/mathematical-notation/modeling-patterns/duration-tracking.md) + - [State Transitions](user-guide/mathematical-notation/modeling-patterns/state-transitions.md) - [Examples](examples/) - [Contribute](contribute.md) - [API Reference](api-reference/) diff --git a/docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md b/docs/user-guide/mathematical-notation/effects-penalty-objective.md similarity index 100% rename from docs/user-guide/Mathematical Notation/Effects, Penalty & Objective.md rename to docs/user-guide/mathematical-notation/effects-penalty-objective.md diff --git a/docs/user-guide/Mathematical Notation/Bus.md b/docs/user-guide/mathematical-notation/elements/Bus.md similarity index 100% rename from docs/user-guide/Mathematical Notation/Bus.md rename to docs/user-guide/mathematical-notation/elements/Bus.md diff --git a/docs/user-guide/Mathematical Notation/Flow.md b/docs/user-guide/mathematical-notation/elements/Flow.md similarity index 100% rename from docs/user-guide/Mathematical Notation/Flow.md rename to docs/user-guide/mathematical-notation/elements/Flow.md diff --git a/docs/user-guide/Mathematical Notation/LinearConverter.md b/docs/user-guide/mathematical-notation/elements/LinearConverter.md similarity index 100% rename from docs/user-guide/Mathematical Notation/LinearConverter.md rename to docs/user-guide/mathematical-notation/elements/LinearConverter.md diff --git a/docs/user-guide/Mathematical Notation/Storage.md b/docs/user-guide/mathematical-notation/elements/Storage.md similarity index 100% rename from docs/user-guide/Mathematical Notation/Storage.md rename to docs/user-guide/mathematical-notation/elements/Storage.md diff --git a/docs/user-guide/Mathematical Notation/InvestParameters.md b/docs/user-guide/mathematical-notation/features/InvestParameters.md similarity index 100% rename from docs/user-guide/Mathematical Notation/InvestParameters.md rename to docs/user-guide/mathematical-notation/features/InvestParameters.md diff --git a/docs/user-guide/Mathematical Notation/OnOffParameters.md b/docs/user-guide/mathematical-notation/features/OnOffParameters.md similarity index 100% rename from docs/user-guide/Mathematical Notation/OnOffParameters.md rename to docs/user-guide/mathematical-notation/features/OnOffParameters.md diff --git a/docs/user-guide/Mathematical Notation/Piecewise.md b/docs/user-guide/mathematical-notation/features/Piecewise.md similarity index 100% rename from docs/user-guide/Mathematical Notation/Piecewise.md rename to docs/user-guide/mathematical-notation/features/Piecewise.md diff --git a/docs/user-guide/Mathematical Notation/index.md b/docs/user-guide/mathematical-notation/index.md similarity index 100% rename from docs/user-guide/Mathematical Notation/index.md rename to docs/user-guide/mathematical-notation/index.md diff --git a/docs/user-guide/Mathematical Notation/others.md b/docs/user-guide/mathematical-notation/others.md similarity index 100% rename from docs/user-guide/Mathematical Notation/others.md rename to docs/user-guide/mathematical-notation/others.md From cc9692a3304b09430eb28628f28321f4c5c1cb93 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:45:55 +0200 Subject: [PATCH 05/29] Temp --- docs/SUMMARY.md | 10 ++++---- .../effects-penalty-objective.md | 4 ++-- .../mathematical-notation/elements/Bus.md | 4 ++-- .../mathematical-notation/elements/Flow.md | 24 +++++++++---------- .../elements/LinearConverter.md | 12 +++++----- .../mathematical-notation/elements/Storage.md | 14 +++++------ .../features/InvestParameters.md | 8 +++---- .../features/OnOffParameters.md | 14 +++++------ 8 files changed, 45 insertions(+), 45 deletions(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index ca8a6696f..44b3bf83b 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,22 +1,22 @@ - [Home](index.md) - [Getting Started](getting-started.md) - [User Guide](user-guide/) - - [Overview](user-guide/mathematical-notation/index.md) - - [Elements](user-guide/mathematical-notation/elements/) +- [Mathematical Notation](user-guide/mathematical-notation/index.md) + - [Elements](user-guide/mathematical-notation/elements/index.md) - [Flow](user-guide/mathematical-notation/elements/Flow.md) - [Bus](user-guide/mathematical-notation/elements/Bus.md) - [Storage](user-guide/mathematical-notation/elements/Storage.md) - [LinearConverter](user-guide/mathematical-notation/elements/LinearConverter.md) - - [Features](user-guide/mathematical-notation/features/) + - [Features](user-guide/mathematical-notation/features/index.md) - [InvestParameters](user-guide/mathematical-notation/features/InvestParameters.md) - [OnOffParameters](user-guide/mathematical-notation/features/OnOffParameters.md) - [Piecewise](user-guide/mathematical-notation/features/Piecewise.md) - [Effects, Penalty & Objective](user-guide/mathematical-notation/effects-penalty-objective.md) - - [Modeling Patterns](user-guide/mathematical-notation/modeling-patterns/) - - [Overview](user-guide/mathematical-notation/modeling-patterns/index.md) + - [Modeling Patterns](user-guide/mathematical-notation/modeling-patterns/index.md) - [Bounds and States](user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md) - [Duration Tracking](user-guide/mathematical-notation/modeling-patterns/duration-tracking.md) - [State Transitions](user-guide/mathematical-notation/modeling-patterns/state-transitions.md) + - [Cross-Reference](user-guide/mathematical-notation/cross-reference.md) - [Examples](examples/) - [Contribute](contribute.md) - [API Reference](api-reference/) diff --git a/docs/user-guide/mathematical-notation/effects-penalty-objective.md b/docs/user-guide/mathematical-notation/effects-penalty-objective.md index 7da311c37..7801e10ab 100644 --- a/docs/user-guide/mathematical-notation/effects-penalty-objective.md +++ b/docs/user-guide/mathematical-notation/effects-penalty-objective.md @@ -1,6 +1,6 @@ ## Effects [`Effects`][flixopt.effects.Effect] are used to allocate things like costs, emissions, or other "effects" occurring in the system. -These arise from so called **Shares**, which originate from **Elements** like [Flows](Flow.md). +These arise from so called **Shares**, which originate from **Elements** like [Flows](../elements/Flow.md). **Example:** @@ -113,7 +113,7 @@ With: - $\mathcal{T}$ being the set of all timesteps - $s_{l \rightarrow \Phi}$ being the share of element $l$ to the penalty -At the moment, penalties only occur in [Buses](Bus.md) +At the moment, penalties only occur in [Buses](../elements/Bus.md) ## Objective diff --git a/docs/user-guide/mathematical-notation/elements/Bus.md b/docs/user-guide/mathematical-notation/elements/Bus.md index 2cfd300c3..c7cea3faf 100644 --- a/docs/user-guide/mathematical-notation/elements/Bus.md +++ b/docs/user-guide/mathematical-notation/elements/Bus.md @@ -62,6 +62,6 @@ When excess is allowed, the penalty term $s_{b \rightarrow \Phi}(\text{t}_i)$ co ## See Also -- [Flow](Flow.md) - Definition of flow rates in the balance +- [Flow](../elements/Flow.md) - Definition of flow rates in the balance - [Effects, Penalty & Objective](Effects,%20Penalty%20&%20Objective.md) - How penalties are included in the objective function -- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks +- [Modeling Patterns](../modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/mathematical-notation/elements/Flow.md b/docs/user-guide/mathematical-notation/elements/Flow.md index d90188020..e1fe3d81f 100644 --- a/docs/user-guide/mathematical-notation/elements/Flow.md +++ b/docs/user-guide/mathematical-notation/elements/Flow.md @@ -31,9 +31,9 @@ to change the size of the Flow from a constant to an optimization variable. Flow formulation uses the following modeling patterns: -- **[Scaled Bounds](modeling-patterns/bounds-and-states.md#scaled-bounds)** - Basic flow rate bounds (equation $\eqref{eq:flow_rate}$) -- **[Scaled Bounds with State](modeling-patterns/bounds-and-states.md#scaled-bounds-with-state)** - When combined with [OnOffParameters](OnOffParameters.md) -- **[Bounds with State](modeling-patterns/bounds-and-states.md#bounds-with-state)** - Investment decisions with [InvestParameters](InvestParameters.md) +- **[Scaled Bounds](../modeling-patterns/bounds-and-states.md#scaled-bounds)** - Basic flow rate bounds (equation $\eqref{eq:flow_rate}$) +- **[Scaled Bounds with State](../modeling-patterns/bounds-and-states.md#scaled-bounds-with-state)** - When combined with [OnOffParameters](../features/OnOffParameters.md) +- **[Bounds with State](../modeling-patterns/bounds-and-states.md#bounds-with-state)** - Investment decisions with [InvestParameters](../features/InvestParameters.md) --- @@ -52,22 +52,22 @@ Flow formulation uses the following modeling patterns: **Variables Created:** - `flow_rate`: Flow rate variable $p(\text{t}_i)$ -- Additional variables when using [OnOffParameters](OnOffParameters.md) or [InvestParameters](InvestParameters.md) +- Additional variables when using [OnOffParameters](../features/OnOffParameters.md) or [InvestParameters](../features/InvestParameters.md) **Parameters:** - `size`: Flow size $\text{P}$ (can be fixed or variable with InvestParameters) - `relative_minimum`, `relative_maximum`: Relative bounds $\text{p}^{\text{L}}_{\text{rel}}, \text{p}^{\text{U}}_{\text{rel}}$ - `effects_per_flow_hour`: Operational effects (costs, emissions, etc.) -- `invest_parameters`: Optional investment modeling (see [InvestParameters](InvestParameters.md)) -- `on_off_parameters`: Optional on/off operation (see [OnOffParameters](OnOffParameters.md)) +- `invest_parameters`: Optional investment modeling (see [InvestParameters](../features/InvestParameters.md)) +- `on_off_parameters`: Optional on/off operation (see [OnOffParameters](../features/OnOffParameters.md)) --- ## See Also -- [OnOffParameters](OnOffParameters.md) - Binary on/off operation -- [InvestParameters](InvestParameters.md) - Variable flow sizing -- [Bus](Bus.md) - Flow balance constraints -- [LinearConverter](LinearConverter.md) - Flow ratio constraints -- [Storage](Storage.md) - Flow integration over time -- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks +- [OnOffParameters](../features/OnOffParameters.md) - Binary on/off operation +- [InvestParameters](../features/InvestParameters.md) - Variable flow sizing +- [Bus](../elements/Bus.md) - Flow balance constraints +- [LinearConverter](../elements/LinearConverter.md) - Flow ratio constraints +- [Storage](../elements/Storage.md) - Flow integration over time +- [Modeling Patterns](../modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/mathematical-notation/elements/LinearConverter.md b/docs/user-guide/mathematical-notation/elements/LinearConverter.md index 147dcaf6a..9a684b61f 100644 --- a/docs/user-guide/mathematical-notation/elements/LinearConverter.md +++ b/docs/user-guide/mathematical-notation/elements/LinearConverter.md @@ -1,4 +1,4 @@ -[`LinearConverters`][flixopt.components.LinearConverter] define a ratio between incoming and outgoing [Flows](Flow.md). +[`LinearConverters`][flixopt.components.LinearConverter] define a ratio between incoming and outgoing [Flows](../elements/Flow.md). $$ \label{eq:Linear-Transformer-Ratio} \sum_{f_{\text{in}} \in \mathcal F_{in}} \text a_{f_{\text{in}}}(\text{t}_i) \cdot p_{f_\text{in}}(\text{t}_i) = \sum_{f_{\text{out}} \in \mathcal F_{out}} \text b_{f_\text{out}}(\text{t}_i) \cdot p_{f_\text{out}}(\text{t}_i) @@ -19,7 +19,7 @@ $$ where $\text a$ can be interpreted as the conversion efficiency of the **LinearConverter**. #### Piecewise Conversion factors -The conversion efficiency can be defined as a piecewise linear approximation. See [Piecewise](Piecewise.md) for more details. +The conversion efficiency can be defined as a piecewise linear approximation. See [Piecewise](../features/Piecewise.md) for more details. --- @@ -51,7 +51,7 @@ These classes handle the mathematical formulation automatically based on physica ## See Also -- [Flow](Flow.md) - Definition of flow rates -- [Piecewise](Piecewise.md) - Non-linear conversion efficiency modeling -- [InvestParameters](InvestParameters.md) - Variable converter sizing -- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks +- [Flow](../elements/Flow.md) - Definition of flow rates +- [Piecewise](../features/Piecewise.md) - Non-linear conversion efficiency modeling +- [InvestParameters](../features/InvestParameters.md) - Variable converter sizing +- [Modeling Patterns](../modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/mathematical-notation/elements/Storage.md b/docs/user-guide/mathematical-notation/elements/Storage.md index 99deb3d29..8c7726f4a 100644 --- a/docs/user-guide/mathematical-notation/elements/Storage.md +++ b/docs/user-guide/mathematical-notation/elements/Storage.md @@ -1,5 +1,5 @@ # Storages -**Storages** have one incoming and one outgoing **[Flow](Flow.md)** with a charging and discharging efficiency. +**Storages** have one incoming and one outgoing **[Flow](../elements/Flow.md)** with a charging and discharging efficiency. A storage has a state of charge $c(\text{t}_i)$ which is limited by its `size` $\text C$ and relative bounds $\eqref{eq:Storage_Bounds}$. $$ \label{eq:Storage_Bounds} @@ -49,11 +49,11 @@ Where: Storage formulation uses the following modeling patterns: -- **[Basic Bounds](modeling-patterns/bounds-and-states.md#basic-bounds)** - For charge state bounds (equation $\eqref{eq:Storage_Bounds}$) -- **[Scaled Bounds](modeling-patterns/bounds-and-states.md#scaled-bounds)** - For flow rate bounds relative to storage size +- **[Basic Bounds](../modeling-patterns/bounds-and-states.md#basic-bounds)** - For charge state bounds (equation $\eqref{eq:Storage_Bounds}$) +- **[Scaled Bounds](../modeling-patterns/bounds-and-states.md#scaled-bounds)** - For flow rate bounds relative to storage size When combined with investment parameters, storage can use: -- **[Bounds with State](modeling-patterns/bounds-and-states.md#bounds-with-state)** - Investment decisions (see [InvestParameters](InvestParameters.md)) +- **[Bounds with State](../modeling-patterns/bounds-and-states.md#bounds-with-state)** - Investment decisions (see [InvestParameters](../features/InvestParameters.md)) --- @@ -87,6 +87,6 @@ When combined with investment parameters, storage can use: ## See Also -- [Flow](Flow.md) - Input and output flow definitions -- [InvestParameters](InvestParameters.md) - Variable storage sizing -- [Modeling Patterns](modeling-patterns/index.md) - Mathematical building blocks +- [Flow](../elements/Flow.md) - Input and output flow definitions +- [InvestParameters](../features/InvestParameters.md) - Variable storage sizing +- [Modeling Patterns](../modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/mathematical-notation/features/InvestParameters.md b/docs/user-guide/mathematical-notation/features/InvestParameters.md index f9a91beae..0161ee066 100644 --- a/docs/user-guide/mathematical-notation/features/InvestParameters.md +++ b/docs/user-guide/mathematical-notation/features/InvestParameters.md @@ -43,7 +43,7 @@ With: - $s_\text{invest} = 0$: no investment ($v_\text{invest} = 0$) - $s_\text{invest} = 1$: invest with size in $[\text{size}_\text{min}, \text{size}_\text{max}]$ -This uses the **bounds with state** pattern described in [Bounds and States](modeling-patterns/bounds-and-states.md#bounds-with-state). +This uses the **bounds with state** pattern described in [Bounds and States](../modeling-patterns/bounds-and-states.md#bounds-with-state). --- @@ -124,7 +124,7 @@ $$ With: - $E_{e,\text{pw}}$ being the piecewise contribution to effect $e$ -- $\lambda_k$ being the piecewise lambda variables (see [Piecewise](Piecewise.md)) +- $\lambda_k$ being the piecewise lambda variables (see [Piecewise](../features/Piecewise.md)) - $r_{e,k}$ being the effect rate at piece $k$ - $v_k$ being the size points defining the pieces @@ -133,7 +133,7 @@ With: - Technology learning curves - Threshold effects (capacity tiers with different costs) -See [Piecewise](Piecewise.md) for detailed mathematical formulation. +See [Piecewise](../features/Piecewise.md) for detailed mathematical formulation. --- @@ -194,7 +194,7 @@ $$ v_\text{invest} \cdot \text{rel}_\text{lower} \leq p(t) \leq v_\text{invest} \cdot \text{rel}_\text{upper} $$ -Using the **scaled bounds** pattern from [Bounds and States](modeling-patterns/bounds-and-states.md#scaled-bounds). +Using the **scaled bounds** pattern from [Bounds and States](../modeling-patterns/bounds-and-states.md#scaled-bounds). --- diff --git a/docs/user-guide/mathematical-notation/features/OnOffParameters.md b/docs/user-guide/mathematical-notation/features/OnOffParameters.md index 3fde93eda..55b3ef300 100644 --- a/docs/user-guide/mathematical-notation/features/OnOffParameters.md +++ b/docs/user-guide/mathematical-notation/features/OnOffParameters.md @@ -14,13 +14,13 @@ With: - $s(t) = 1$: equipment is operating (on state) - $s(t) = 0$: equipment is shutdown (off state) -This state variable controls the equipment's operational constraints and modifies flow bounds using the **bounds with state** pattern from [Bounds and States](modeling-patterns/bounds-and-states.md#bounds-with-state). +This state variable controls the equipment's operational constraints and modifies flow bounds using the **bounds with state** pattern from [Bounds and States](../modeling-patterns/bounds-and-states.md#bounds-with-state). --- ## State Transitions and Switching -State transitions are tracked using switch variables (see [State Transitions](modeling-patterns/state-transitions.md#binary-state-transitions)): +State transitions are tracked using switch variables (see [State Transitions](../modeling-patterns/state-transitions.md#binary-state-transitions)): $$\label{eq:onoff_transitions} s^\text{on}(t) - s^\text{off}(t) = s(t) - s(t-1) \quad \forall t > 0 @@ -106,7 +106,7 @@ With: **Minimum Consecutive On-Time:** -Enforces minimum runtime once started using duration tracking (see [Duration Tracking](modeling-patterns/duration-tracking.md#minimum-duration-constraints)): +Enforces minimum runtime once started using duration tracking (see [Duration Tracking](../modeling-patterns/duration-tracking.md#minimum-duration-constraints)): $$\label{eq:onoff_min_on_duration} d^\text{on}(t) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min} \quad \forall t > 0 @@ -202,7 +202,7 @@ $$ s(t) \cdot P \cdot \max(\varepsilon, \text{rel}_\text{lower}) \leq p(t) \leq s(t) \cdot P \cdot \text{rel}_\text{upper} $$ -Using the **bounds with state** pattern from [Bounds and States](modeling-patterns/bounds-and-states.md#bounds-with-state). +Using the **bounds with state** pattern from [Bounds and States](../modeling-patterns/bounds-and-states.md#bounds-with-state). **Behavior:** - When $s(t) = 0$: flow is forced to zero @@ -246,9 +246,9 @@ For equipment with OnOffParameters, the complete constraint system includes: - `force_switch_on`: Create switch variables even without limits (for tracking) **Mathematical Patterns Used:** -- [State Transitions](modeling-patterns/state-transitions.md#binary-state-transitions) - Switch tracking -- [Duration Tracking](modeling-patterns/duration-tracking.md) - Consecutive time constraints -- [Bounds with State](modeling-patterns/bounds-and-states.md#bounds-with-state) - Flow control +- [State Transitions](../modeling-patterns/state-transitions.md#binary-state-transitions) - Switch tracking +- [Duration Tracking](../modeling-patterns/duration-tracking.md) - Consecutive time constraints +- [Bounds with State](../modeling-patterns/bounds-and-states.md#bounds-with-state) - Flow control **Used in:** - [`Flow`][flixopt.elements.Flow] - On/off operation for flows From 055c45612e1c3840c8a68f9b2b128d673c9dc064 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:50:10 +0200 Subject: [PATCH 06/29] Switch to mkdocs.yml navigation --- mkdocs.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 98747d987..6fab852c1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,6 +8,33 @@ site_url: https://flixopt.github.io/flixopt/ repo_url: https://github.com/flixOpt/flixopt repo_name: flixOpt/flixopt +nav: + - Home: index.md + - Getting Started: getting-started.md + - User Guide: + - user-guide/index.md + - Mathematical Notation: + - Overview: user-guide/mathematical-notation/index.md + - Elements: + - Flow: user-guide/mathematical-notation/elements/Flow.md + - Bus: user-guide/mathematical-notation/elements/Bus.md + - Storage: user-guide/mathematical-notation/elements/Storage.md + - LinearConverter: user-guide/mathematical-notation/elements/LinearConverter.md + - Features: + - InvestParameters: user-guide/mathematical-notation/features/InvestParameters.md + - OnOffParameters: user-guide/mathematical-notation/features/OnOffParameters.md + - Piecewise: user-guide/mathematical-notation/features/Piecewise.md + - Effects, Penalty & Objective: user-guide/mathematical-notation/effects-penalty-objective.md + - Modeling Patterns: + - Overview: user-guide/mathematical-notation/modeling-patterns/index.md + - Bounds and States: user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md + - Duration Tracking: user-guide/mathematical-notation/modeling-patterns/duration-tracking.md + - State Transitions: user-guide/mathematical-notation/modeling-patterns/state-transitions.md + - Examples: examples/ + - Contribute: contribute.md + - API Reference: api-reference/ + - Release Notes: changelog/ + theme: name: material @@ -88,9 +115,6 @@ plugins: - gen-files: scripts: - scripts/gen_ref_pages.py - - literate-nav: - nav_file: SUMMARY.md - implicit_index: true # This makes index.md the default landing page - mkdocstrings: # Handles automatic API documentation generation default_handler: python # Sets Python as the default language handlers: From d008ec412541004f7cbe6892549f1adbf0474eb0 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:51:49 +0200 Subject: [PATCH 07/29] Added files to docs --- docs/SUMMARY.md | 23 -- .../mathematical-notation/cross-reference.md | 112 +++++++++ .../modeling-patterns/bounds-and-states.md | 165 +++++++++++++ .../modeling-patterns/duration-tracking.md | 169 +++++++++++++ .../modeling-patterns/index.md | 54 +++++ .../modeling-patterns/state-transitions.md | 227 ++++++++++++++++++ 6 files changed, 727 insertions(+), 23 deletions(-) delete mode 100644 docs/SUMMARY.md create mode 100644 docs/user-guide/mathematical-notation/cross-reference.md create mode 100644 docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md create mode 100644 docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md create mode 100644 docs/user-guide/mathematical-notation/modeling-patterns/index.md create mode 100644 docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md deleted file mode 100644 index 44b3bf83b..000000000 --- a/docs/SUMMARY.md +++ /dev/null @@ -1,23 +0,0 @@ -- [Home](index.md) -- [Getting Started](getting-started.md) -- [User Guide](user-guide/) -- [Mathematical Notation](user-guide/mathematical-notation/index.md) - - [Elements](user-guide/mathematical-notation/elements/index.md) - - [Flow](user-guide/mathematical-notation/elements/Flow.md) - - [Bus](user-guide/mathematical-notation/elements/Bus.md) - - [Storage](user-guide/mathematical-notation/elements/Storage.md) - - [LinearConverter](user-guide/mathematical-notation/elements/LinearConverter.md) - - [Features](user-guide/mathematical-notation/features/index.md) - - [InvestParameters](user-guide/mathematical-notation/features/InvestParameters.md) - - [OnOffParameters](user-guide/mathematical-notation/features/OnOffParameters.md) - - [Piecewise](user-guide/mathematical-notation/features/Piecewise.md) - - [Effects, Penalty & Objective](user-guide/mathematical-notation/effects-penalty-objective.md) - - [Modeling Patterns](user-guide/mathematical-notation/modeling-patterns/index.md) - - [Bounds and States](user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md) - - [Duration Tracking](user-guide/mathematical-notation/modeling-patterns/duration-tracking.md) - - [State Transitions](user-guide/mathematical-notation/modeling-patterns/state-transitions.md) - - [Cross-Reference](user-guide/mathematical-notation/cross-reference.md) -- [Examples](examples/) -- [Contribute](contribute.md) -- [API Reference](api-reference/) -- [Release Notes](changelog/) diff --git a/docs/user-guide/mathematical-notation/cross-reference.md b/docs/user-guide/mathematical-notation/cross-reference.md new file mode 100644 index 000000000..a539a0987 --- /dev/null +++ b/docs/user-guide/mathematical-notation/cross-reference.md @@ -0,0 +1,112 @@ +# Mathematical Documentation Cross-Reference + +This document provides a comprehensive mapping between mathematical concepts, their documentation, implementation, and tests. Use this to quickly locate where specific mathematical formulations are defined and implemented. + +## Components + +| Concept | Documentation | Equations | Implementation | Key Location | +|---------|---------------|-----------|----------------|--------------| +| **Flow rate bounds** | [Flow.md](../elements/Flow.md) | eq. (1) | `FlowModel._do_modeling()` | `flixopt/elements.py:350+` | +| **Bus balance** | [Bus.md](../elements/Bus.md) | eq. (1), (2) | `BusModel._do_modeling()` | `flixopt/elements.py:751` | +| **Bus excess/deficit** | [Bus.md](../elements/Bus.md) | eq. (3), (4) | `BusModel._do_modeling()` | `flixopt/elements.py:763` | +| **Storage charge bounds** | [Storage.md](../elements/Storage.md) | eq. (1) | `StorageModel._do_modeling()` | `flixopt/components.py:~820` | +| **Storage balance** | [Storage.md](../elements/Storage.md) | eq. (3) | `StorageModel._do_modeling()` | `flixopt/components.py:838-842` | +| **Linear conversion** | [LinearConverter.md](../elements/LinearConverter.md) | eq. (1), (2) | Component-specific | `flixopt/components.py:37+` | + +## Features + +| Concept | Documentation | Equations | Implementation | Key Location | +|---------|---------------|-----------|----------------|--------------| +| **Binary investment** | [InvestParameters.md](../features/InvestParameters.md) | eq. (1) | `InvestParametersFeature` | `flixopt/interface.py:663+` | +| **Continuous investment sizing** | [InvestParameters.md](../features/InvestParameters.md) | eq. (2) | `InvestParametersFeature` | `flixopt/interface.py:663+` | +| **Investment fixed effects** | [InvestParameters.md](../features/InvestParameters.md) | eq. (4) | Effect calculation | `flixopt/features.py` | +| **Investment specific effects** | [InvestParameters.md](../features/InvestParameters.md) | eq. (5) | Effect calculation | `flixopt/features.py` | +| **Investment divestment effects** | [InvestParameters.md](../features/InvestParameters.md) | eq. (8) | Effect calculation | `flixopt/features.py` | +| **On/off state variable** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (1) | `OnOffFeature` | `flixopt/interface.py:918+` | +| **State transitions** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (2), (3) | `OnOffFeature` | Uses `state_transition_bounds()` | +| **Switching effects** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (4) | Effect calculation | `flixopt/features.py` | +| **Running effects** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (5) | Effect calculation | `flixopt/features.py` | +| **Minimum on-time** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (8) | Duration tracking | Uses `consecutive_duration_tracking()` | +| **Piecewise segments** | [Piecewise.md](../features/Piecewise.md) | eq. (1)-(4) | `PiecewiseModel` | `flixopt/features.py:382+` | + +## Modeling Patterns + +| Pattern | Documentation | Equations | Implementation | Key Location | +|---------|---------------|-----------|----------------|--------------| +| **Basic bounds** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#basic-bounds) | eq. (1) | `BoundingPatterns.basic_bounds()` | `flixopt/modeling.py:393` | +| **Bounds with state** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#bounds-with-state) | eq. (2) | `BoundingPatterns.bounds_with_state()` | `flixopt/modeling.py:427` | +| **Scaled bounds** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#scaled-bounds) | eq. (3) | `BoundingPatterns.scaled_bounds()` | `flixopt/modeling.py:473` | +| **Scaled bounds with state** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#scaled-bounds-with-state) | eq. (4), (5) | `BoundingPatterns.scaled_bounds_with_state()` | `flixopt/modeling.py:516` | +| **Expression tracking** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#expression-tracking) | eq. (6), (7) | `ModelingPrimitives.expression_tracking_variable()` | `flixopt/modeling.py:201` | +| **Mutual exclusivity** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#mutual-exclusivity) | eq. (8) | `ModelingPrimitives.mutual_exclusivity_constraint()` | `flixopt/modeling.py:345` | +| **Duration tracking** | [duration-tracking.md](../modeling-patterns/duration-tracking.md) | eq. (1)-(4) | `ModelingPrimitives.consecutive_duration_tracking()` | `flixopt/modeling.py:240` | +| **Minimum duration** | [duration-tracking.md](../modeling-patterns/duration-tracking.md#minimum-duration-constraints) | eq. (5) | Part of `consecutive_duration_tracking()` | `flixopt/modeling.py:240` | +| **State transitions** | [state-transitions.md](../modeling-patterns/state-transitions.md#binary-state-transitions) | eq. (1)-(4) | `BoundingPatterns.state_transition_bounds()` | `flixopt/modeling.py:573` | +| **Continuous transitions** | [state-transitions.md](../modeling-patterns/state-transitions.md#continuous-transitions) | eq. (5), (6) | `BoundingPatterns.continuous_transition_bounds()` | `flixopt/modeling.py:618` | +| **Level changes with binaries** | [state-transitions.md](../modeling-patterns/state-transitions.md#level-changes-with-binaries) | eq. (7)-(12) | `BoundingPatterns.link_changes_to_level_with_binaries()` | `flixopt/modeling.py:684` | + +## Effects System + +| Concept | Documentation | Equations | Implementation | Key Location | +|---------|---------------|-----------|----------------|--------------| +| **Share to effect (invest)** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (1) | Effect aggregation | `flixopt/effects.py` | +| **Share to effect (operation)** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (2) | Effect aggregation | `flixopt/effects.py` | +| **Cross-effect contribution** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (3), (4) | Effect cross-links | `flixopt/effects.py` | +| **Total effect** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (6) | Effect total calculation | `flixopt/effects.py` | +| **Effect bounds** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (7), (8) | Effect constraints | `flixopt/effects.py` | +| **Penalty** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (9) | Penalty aggregation | `flixopt/effects.py` | +| **Objective function** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (10) | Objective creation | `flixopt/flow_system.py` | + +## Quick Lookup by Python Class + +| Python Class | Mathematical Documentation | Location | +|--------------|---------------------------|----------| +| `Flow` | [Flow.md](../elements/Flow.md) | `flixopt/elements.py:175` | +| `Bus` | [Bus.md](../elements/Bus.md) | `flixopt/elements.py:120` | +| `Storage` | [Storage.md](../elements/Storage.md) | `flixopt/components.py:237` | +| `LinearConverter` | [LinearConverter.md](../elements/LinearConverter.md) | `flixopt/components.py:37` | +| `InvestParameters` | [InvestParameters.md](../features/InvestParameters.md) | `flixopt/interface.py:663` | +| `OnOffParameters` | [OnOffParameters.md](../features/OnOffParameters.md) | `flixopt/interface.py:918` | +| `Piecewise` | [Piecewise.md](../features/Piecewise.md) | `flixopt/interface.py:83` | +| `Effect` | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | `flixopt/effects.py:32` | +| `ModelingPrimitives` | [modeling-patterns/](../modeling-patterns/index.md) | `flixopt/modeling.py:178` | +| `BoundingPatterns` | [modeling-patterns/](../modeling-patterns/index.md) | `flixopt/modeling.py:390` | + +## Quick Lookup by Mathematical Concept + +| Mathematical Concept | Documentation | Implementation Function | +|---------------------|---------------|------------------------| +| Variable bounds | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md) | `basic_bounds()`, `bounds_with_state()`, `scaled_bounds()`, `scaled_bounds_with_state()` | +| Binary state control | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#bounds-with-state) | `bounds_with_state()`, `scaled_bounds_with_state()` | +| Consecutive time periods | [duration-tracking.md](../modeling-patterns/duration-tracking.md) | `consecutive_duration_tracking()` | +| Switching between states | [state-transitions.md](../modeling-patterns/state-transitions.md) | `state_transition_bounds()`, `continuous_transition_bounds()` | +| Linear equality constraints | [LinearConverter.md](../elements/LinearConverter.md) | Component-specific implementations | +| Energy balance | [Storage.md](../elements/Storage.md), [Bus.md](../elements/Bus.md) | Component-specific implementations | +| Piecewise linear functions | [Piecewise.md](../features/Piecewise.md) | `PiecewiseModel._do_modeling()` | +| Investment decisions | [InvestParameters.md](../features/InvestParameters.md) | `InvestParametersFeature` | +| On/off operation | [OnOffParameters.md](../features/OnOffParameters.md) | `OnOffFeature` | +| Cost/effect allocation | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | Effect system in `flixopt/effects.py` | + +## Navigation Tips + +### Finding Documentation from Code +1. Find the class name in Python (e.g., `Storage`) +2. Look up the class in "Quick Lookup by Python Class" table +3. Follow the link to the mathematical documentation + +### Finding Implementation from Docs +1. Find the equation number in documentation (e.g., Storage eq. 3) +2. Look up in the corresponding section in the cross-reference tables +3. Navigate to the implementation location + +### Understanding a Mathematical Pattern +1. Identify the pattern type (bounds, transitions, duration, etc.) +2. Read the pattern documentation in [modeling-patterns/](../modeling-patterns/index.md) +3. See usage examples in component documentation +4. Find implementation in `flixopt/modeling.py` + +## See Also + +- [Mathematical Notation Overview](index.md) - Naming conventions and fundamentals +- [Modeling Patterns](../modeling-patterns/index.md) - Reusable mathematical building blocks +- [Effects, Penalty & Objective](../effects-penalty-objective.md) - System-level formulation diff --git a/docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md b/docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md new file mode 100644 index 000000000..122ae14a7 --- /dev/null +++ b/docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md @@ -0,0 +1,165 @@ +# Bounds and States + +This document describes the mathematical formulations for variable bounding patterns used throughout FlixOpt. These patterns define how optimization variables are constrained, both with and without state control. + +## Basic Bounds + +The simplest bounding pattern constrains a variable between lower and upper bounds. + +$$\label{eq:basic_bounds} +\text{lower} \leq v \leq \text{upper} +$$ + +With: +- $v$ being the optimization variable +- $\text{lower}$ being the lower bound (constant or time-dependent) +- $\text{upper}$ being the upper bound (constant or time-dependent) + +**Implementation:** [`BoundingPatterns.basic_bounds()`][flixopt.modeling.BoundingPatterns.basic_bounds] in `flixopt/modeling.py:393` + +**Used in:** +- Storage charge state bounds (see [Storage](../Storage.md)) +- Flow rate absolute bounds + +--- + +## Bounds with State + +When a variable should only be non-zero if a binary state variable is active (e.g., on/off operation, investment decisions), the bounds are controlled by the state: + +$$\label{eq:bounds_with_state} +s \cdot \max(\varepsilon, \text{lower}) \leq v \leq s \cdot \text{upper} +$$ + +With: +- $v$ being the optimization variable +- $s \in \{0, 1\}$ being the binary state variable +- $\text{lower}$ being the lower bound when active +- $\text{upper}$ being the upper bound when active +- $\varepsilon$ being a small positive number to ensure numerical stability + +**Behavior:** +- When $s = 0$: variable is forced to zero ($0 \leq v \leq 0$) +- When $s = 1$: variable can take values in $[\text{lower}, \text{upper}]$ + +**Implementation:** [`BoundingPatterns.bounds_with_state()`][flixopt.modeling.BoundingPatterns.bounds_with_state] in `flixopt/modeling.py:427` + +**Used in:** +- Flow rates with on/off operation (see [OnOffParameters](../features/OnOffParameters.md)) +- Investment size decisions (see [InvestParameters](../features/InvestParameters.md)) + +--- + +## Scaled Bounds + +When a variable's bounds depend on another variable (e.g., flow rate scaled by component size), scaled bounds are used: + +$$\label{eq:scaled_bounds} +v_\text{scale} \cdot \text{rel}_\text{lower} \leq v \leq v_\text{scale} \cdot \text{rel}_\text{upper} +$$ + +With: +- $v$ being the optimization variable (e.g., flow rate) +- $v_\text{scale}$ being the scaling variable (e.g., component size) +- $\text{rel}_\text{lower}$ being the relative lower bound factor (typically 0) +- $\text{rel}_\text{upper}$ being the relative upper bound factor (typically 1) + +**Example:** Flow rate bounds +- If $v_\text{scale} = P$ (flow size) and $\text{rel}_\text{upper} = 1$ +- Then: $0 \leq p(t_i) \leq P$ (see [Flow](../Flow.md)) + +**Implementation:** [`BoundingPatterns.scaled_bounds()`][flixopt.modeling.BoundingPatterns.scaled_bounds] in `flixopt/modeling.py:473` + +**Used in:** +- Flow rate constraints (see [Flow](../Flow.md) equation 1) +- Storage charge state constraints (see [Storage](../Storage.md) equation 1) + +--- + +## Scaled Bounds with State + +Combining scaled bounds with binary state control requires a Big-M formulation to handle both the scaling and the on/off behavior: + +$$\label{eq:scaled_bounds_with_state_1} +(s - 1) \cdot M_\text{misc} + v_\text{scale} \cdot \text{rel}_\text{lower} \leq v \leq v_\text{scale} \cdot \text{rel}_\text{upper} +$$ + +$$\label{eq:scaled_bounds_with_state_2} +s \cdot M_\text{lower} \leq v \leq s \cdot M_\text{upper} +$$ + +With: +- $v$ being the optimization variable +- $v_\text{scale}$ being the scaling variable +- $s \in \{0, 1\}$ being the binary state variable +- $\text{rel}_\text{lower}$ being the relative lower bound factor +- $\text{rel}_\text{upper}$ being the relative upper bound factor +- $M_\text{misc} = v_\text{scale,max} \cdot \text{rel}_\text{lower}$ +- $M_\text{upper} = v_\text{scale,max} \cdot \text{rel}_\text{upper}$ +- $M_\text{lower} = \max(\varepsilon, v_\text{scale,min} \cdot \text{rel}_\text{lower})$ + +Where $v_\text{scale,max}$ and $v_\text{scale,min}$ are the maximum and minimum possible values of the scaling variable. + +**Behavior:** +- When $s = 0$: variable is forced to zero +- When $s = 1$: variable follows scaled bounds $v_\text{scale} \cdot \text{rel}_\text{lower} \leq v \leq v_\text{scale} \cdot \text{rel}_\text{upper}$ + +**Implementation:** [`BoundingPatterns.scaled_bounds_with_state()`][flixopt.modeling.BoundingPatterns.scaled_bounds_with_state] in `flixopt/modeling.py:516` + +**Used in:** +- Flow rates with on/off operation and investment sizing +- Components combining [OnOffParameters](../features/OnOffParameters.md) and [InvestParameters](../features/InvestParameters.md) + +--- + +## Expression Tracking + +Sometimes it's necessary to create an auxiliary variable that equals an expression: + +$$\label{eq:expression_tracking} +v_\text{tracker} = \text{expression} +$$ + +With optional bounds: + +$$\label{eq:expression_tracking_bounds} +\text{lower} \leq v_\text{tracker} \leq \text{upper} +$$ + +With: +- $v_\text{tracker}$ being the auxiliary tracking variable +- $\text{expression}$ being a linear expression of other variables +- $\text{lower}, \text{upper}$ being optional bounds on the tracker + +**Use cases:** +- Creating named variables for complex expressions +- Bounding intermediate results +- Simplifying constraint formulations + +**Implementation:** [`ModelingPrimitives.expression_tracking_variable()`][flixopt.modeling.ModelingPrimitives.expression_tracking_variable] in `flixopt/modeling.py:201` + +--- + +## Mutual Exclusivity + +When multiple binary variables should not be active simultaneously (at most one can be 1): + +$$\label{eq:mutual_exclusivity} +\sum_{i} s_i(t) \leq \text{tolerance} \quad \forall t +$$ + +With: +- $s_i(t) \in \{0, 1\}$ being binary state variables +- $\text{tolerance}$ being the maximum number of simultaneously active states (typically 1) +- $t$ being the time index + +**Use cases:** +- Ensuring only one operating mode is active +- Mutual exclusion of operation and maintenance states +- Enforcing single-choice decisions + +**Implementation:** [`ModelingPrimitives.mutual_exclusivity_constraint()`][flixopt.modeling.ModelingPrimitives.mutual_exclusivity_constraint] in `flixopt/modeling.py:345` + +**Used in:** +- Operating mode selection +- Piecewise linear function segments (see [Piecewise](../features/Piecewise.md)) diff --git a/docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md b/docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md new file mode 100644 index 000000000..da5220134 --- /dev/null +++ b/docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md @@ -0,0 +1,169 @@ +# Duration Tracking + +Duration tracking allows monitoring how long a binary state has been consecutively active. This is essential for modeling minimum run times, ramp-up periods, and similar time-dependent constraints. + +## Consecutive Duration Tracking + +For a binary state variable $s(t) \in \{0, 1\}$, the consecutive duration $d(t)$ tracks how long the state has been continuously active. + +### Duration Upper Bound + +The duration cannot exceed zero when the state is inactive: + +$$\label{eq:duration_upper} +d(t) \leq s(t) \cdot M \quad \forall t +$$ + +With: +- $d(t)$ being the duration variable (continuous, non-negative) +- $s(t) \in \{0, 1\}$ being the binary state variable +- $M$ being a sufficiently large constant (big-M) + +**Behavior:** +- When $s(t) = 0$: forces $d(t) \leq 0$, thus $d(t) = 0$ +- When $s(t) = 1$: allows $d(t)$ to be positive + +--- + +### Duration Accumulation + +While the state is active, the duration increases by the time step size: + +$$\label{eq:duration_accumulation_upper} +d(t+1) \leq d(t) + \Delta d(t) \quad \forall t +$$ + +$$\label{eq:duration_accumulation_lower} +d(t+1) \geq d(t) + \Delta d(t) + (s(t+1) - 1) \cdot M \quad \forall t +$$ + +With: +- $\Delta d(t)$ being the duration increment for time step $t$ (typically $\Delta t_i$ from the time series) +- $M$ being a sufficiently large constant + +**Behavior:** +- When $s(t+1) = 1$: both inequalities enforce $d(t+1) = d(t) + \Delta d(t)$ +- When $s(t+1) = 0$: only the upper bound applies, and $d(t+1) = 0$ (from equation $\eqref{eq:duration_upper}$) + +--- + +### Initial Duration + +The duration at the first time step depends on both the state and any previous duration: + +$$\label{eq:duration_initial} +d(0) = (\Delta d(0) + d_\text{prev}) \cdot s(0) +$$ + +With: +- $d_\text{prev}$ being the duration from before the optimization period +- $\Delta d(0)$ being the duration increment for the first time step + +**Behavior:** +- When $s(0) = 1$: duration continues from previous period +- When $s(0) = 0$: duration resets to zero + +--- + +### Complete Formulation + +Combining all constraints: + +$$ +\begin{align} +d(t) &\leq s(t) \cdot M && \forall t \label{eq:duration_complete_1} \\ +d(t+1) &\leq d(t) + \Delta d(t) && \forall t \label{eq:duration_complete_2} \\ +d(t+1) &\geq d(t) + \Delta d(t) + (s(t+1) - 1) \cdot M && \forall t \label{eq:duration_complete_3} \\ +d(0) &= (\Delta d(0) + d_\text{prev}) \cdot s(0) && \label{eq:duration_complete_4} +\end{align} +$$ + +--- + +## Minimum Duration Constraints + +To enforce a minimum consecutive duration (e.g., minimum run time), an additional constraint links the duration to state changes: + +$$\label{eq:minimum_duration} +d(t) \geq (s(t-1) - s(t)) \cdot d_\text{min}(t-1) \quad \forall t > 0 +$$ + +With: +- $d_\text{min}(t)$ being the required minimum duration at time $t$ + +**Behavior:** +- When shutting down ($s(t-1) = 1, s(t) = 0$): enforces $d(t-1) \geq d_\text{min}(t-1)$ +- This ensures the state was active for at least $d_\text{min}$ before turning off +- When state is constant or turning on: constraint is non-binding + +--- + +## Implementation + +**Function:** [`ModelingPrimitives.consecutive_duration_tracking()`][flixopt.modeling.ModelingPrimitives.consecutive_duration_tracking] + +**Location:** `flixopt/modeling.py:240` + +**Parameters:** +- `state_variable`: Binary state variable $s(t)$ +- `duration_per_step`: Duration increment per time step $\Delta d(t)$ +- `previous_duration`: Initial duration from before optimization period $d_\text{prev}$ +- `minimum_duration` (optional): Minimum required duration $d_\text{min}(t)$ + +**Returns:** +- Duration variable $d(t)$ +- Created constraints + +--- + +## Use Cases + +### Minimum Run Time + +Ensuring equipment runs for a minimum duration once started: + +```python +# State: 1 when running, 0 when off +# Require at least 2 hours of operation +duration = modeling.consecutive_duration_tracking( + state_variable=on_state, + duration_per_step=time_step_hours, + minimum_duration=2.0 +) +``` + +### Ramp-Up Tracking + +Tracking time since startup for gradual ramp-up constraints: + +```python +# Track startup duration +startup_duration = modeling.consecutive_duration_tracking( + state_variable=on_state, + duration_per_step=time_step_hours +) +# Constrain output based on startup duration +# (additional constraints would link output to startup_duration) +``` + +### Cooldown Requirements + +Tracking time in a state before allowing transitions: + +```python +# Track maintenance duration +maintenance_duration = modeling.consecutive_duration_tracking( + state_variable=maintenance_state, + duration_per_step=time_step_hours, + minimum_duration=scheduled_maintenance_hours +) +``` + +--- + +## Used In + +This pattern is used in: +- [`OnOffParameters`](../features/OnOffParameters.md) - Minimum on/off times +- Operating mode constraints with minimum durations +- Startup/shutdown sequence modeling diff --git a/docs/user-guide/mathematical-notation/modeling-patterns/index.md b/docs/user-guide/mathematical-notation/modeling-patterns/index.md new file mode 100644 index 000000000..15ff8dbd2 --- /dev/null +++ b/docs/user-guide/mathematical-notation/modeling-patterns/index.md @@ -0,0 +1,54 @@ +# Modeling Patterns + +This section documents the fundamental mathematical patterns used throughout FlixOpt for constructing optimization models. These patterns are implemented in `flixopt.modeling` and provide reusable building blocks for creating constraints. + +## Overview + +The modeling patterns are organized into three categories: + +1. **[Bounds and States](bounds-and-states.md)** - Variable bounding with optional state control +2. **[Duration Tracking](duration-tracking.md)** - Tracking consecutive durations of states +3. **[State Transitions](state-transitions.md)** - Modeling state changes and transitions + +## Pattern Categories + +### Bounding Patterns + +These patterns define how optimization variables are constrained within bounds: + +- **Basic Bounds** - Simple upper and lower bounds on variables +- **Bounds with State** - Binary-controlled bounds (on/off states) +- **Scaled Bounds** - Bounds dependent on another variable (e.g., size) +- **Scaled Bounds with State** - Combination of scaling and binary control + +### Tracking Patterns + +These patterns track properties over time: + +- **Expression Tracking** - Creating auxiliary variables that track expressions +- **Consecutive Duration Tracking** - Tracking how long a state has been active +- **Mutual Exclusivity** - Ensuring only one of multiple options is active + +### Transition Patterns + +These patterns model changes between states: + +- **State Transitions** - Tracking switches between binary states (on→off, off→on) +- **Continuous Transitions** - Linking continuous variable changes to switches +- **Level Changes with Binaries** - Controlled increases/decreases in levels + +## Usage in Components + +These patterns are used throughout FlixOpt components: + +- [`Flow`][flixopt.elements.Flow] uses **scaled bounds with state** for flow rate constraints +- [`Storage`][flixopt.components.Storage] uses **basic bounds** for charge state +- [`OnOffParameters`](../features/OnOffParameters.md) uses **state transitions** for startup/shutdown +- [`InvestParameters`](../features/InvestParameters.md) uses **bounds with state** for investment decisions + +## Implementation + +All patterns are implemented in [`flixopt.modeling`][flixopt.modeling] module: + +- [`ModelingPrimitives`][flixopt.modeling.ModelingPrimitives] - Core constraint patterns +- [`BoundingPatterns`][flixopt.modeling.BoundingPatterns] - Specialized bounding patterns diff --git a/docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md b/docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md new file mode 100644 index 000000000..b0225c629 --- /dev/null +++ b/docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md @@ -0,0 +1,227 @@ +# State Transitions + +State transition patterns model changes between discrete states and link them to continuous variables. These patterns are essential for modeling startup/shutdown events, switching behavior, and controlled changes in system operation. + +## Binary State Transitions + +For a binary state variable $s(t) \in \{0, 1\}$, state transitions track when the state switches on or off. + +### Switch Variables + +Two binary variables track the transitions: +- $s^\text{on}(t) \in \{0, 1\}$: equals 1 when switching from off to on +- $s^\text{off}(t) \in \{0, 1\}$: equals 1 when switching from on to off + +### Transition Tracking + +The state change equals the difference between switch-on and switch-off: + +$$\label{eq:state_transition} +s^\text{on}(t) - s^\text{off}(t) = s(t) - s(t-1) \quad \forall t > 0 +$$ + +$$\label{eq:state_transition_initial} +s^\text{on}(0) - s^\text{off}(0) = s(0) - s_\text{prev} +$$ + +With: +- $s(t)$ being the binary state variable +- $s_\text{prev}$ being the state before the optimization period +- $s^\text{on}(t), s^\text{off}(t)$ being the switch variables + +**Behavior:** +- Off → On ($s(t-1)=0, s(t)=1$): $s^\text{on}(t)=1, s^\text{off}(t)=0$ +- On → Off ($s(t-1)=1, s(t)=0$): $s^\text{on}(t)=0, s^\text{off}(t)=1$ +- No change: $s^\text{on}(t)=0, s^\text{off}(t)=0$ + +--- + +### Mutual Exclusivity of Switches + +A state cannot switch on and off simultaneously: + +$$\label{eq:switch_exclusivity} +s^\text{on}(t) + s^\text{off}(t) \leq 1 \quad \forall t +$$ + +This ensures: +- At most one switch event per time step +- No simultaneous on/off switching + +--- + +### Complete State Transition Formulation + +$$ +\begin{align} +s^\text{on}(t) - s^\text{off}(t) &= s(t) - s(t-1) && \forall t > 0 \label{eq:transition_complete_1} \\ +s^\text{on}(0) - s^\text{off}(0) &= s(0) - s_\text{prev} && \label{eq:transition_complete_2} \\ +s^\text{on}(t) + s^\text{off}(t) &\leq 1 && \forall t \label{eq:transition_complete_3} \\ +s^\text{on}(t), s^\text{off}(t) &\in \{0, 1\} && \forall t \label{eq:transition_complete_4} +\end{align} +$$ + +**Implementation:** [`BoundingPatterns.state_transition_bounds()`][flixopt.modeling.BoundingPatterns.state_transition_bounds] in `flixopt/modeling.py:573` + +--- + +## Continuous Transitions + +When a continuous variable should only change when certain switch events occur, continuous transition bounds link the variable changes to binary switches. + +### Change Bounds with Switches + +$$\label{eq:continuous_transition} +-\Delta v^\text{max} \cdot (s^\text{on}(t) + s^\text{off}(t)) \leq v(t) - v(t-1) \leq \Delta v^\text{max} \cdot (s^\text{on}(t) + s^\text{off}(t)) \quad \forall t > 0 +$$ + +$$\label{eq:continuous_transition_initial} +-\Delta v^\text{max} \cdot (s^\text{on}(0) + s^\text{off}(0)) \leq v(0) - v_\text{prev} \leq \Delta v^\text{max} \cdot (s^\text{on}(0) + s^\text{off}(0)) +$$ + +With: +- $v(t)$ being the continuous variable +- $v_\text{prev}$ being the value before the optimization period +- $\Delta v^\text{max}$ being the maximum allowed change +- $s^\text{on}(t), s^\text{off}(t) \in \{0, 1\}$ being switch binary variables + +**Behavior:** +- When $s^\text{on}(t) = 0$ and $s^\text{off}(t) = 0$: forces $v(t) = v(t-1)$ (no change) +- When $s^\text{on}(t) = 1$ or $s^\text{off}(t) = 1$: allows change up to $\pm \Delta v^\text{max}$ + +**Implementation:** [`BoundingPatterns.continuous_transition_bounds()`][flixopt.modeling.BoundingPatterns.continuous_transition_bounds] in `flixopt/modeling.py:618` + +--- + +## Level Changes with Binaries + +This pattern models a level variable that can increase or decrease, with changes controlled by binary variables. This is useful for inventory management, capacity adjustments, or gradual state changes. + +### Level Evolution + +The level evolves based on increases and decreases: + +$$\label{eq:level_initial} +\ell(0) = \ell_\text{init} + \ell^\text{inc}(0) - \ell^\text{dec}(0) +$$ + +$$\label{eq:level_evolution} +\ell(t) = \ell(t-1) + \ell^\text{inc}(t) - \ell^\text{dec}(t) \quad \forall t > 0 +$$ + +With: +- $\ell(t)$ being the level variable +- $\ell_\text{init}$ being the initial level +- $\ell^\text{inc}(t)$ being the increase in level at time $t$ (non-negative) +- $\ell^\text{dec}(t)$ being the decrease in level at time $t$ (non-negative) + +--- + +### Change Bounds with Binary Control + +Changes are bounded and controlled by binary variables: + +$$\label{eq:increase_bound} +\ell^\text{inc}(t) \leq \Delta \ell^\text{max} \cdot b^\text{inc}(t) \quad \forall t +$$ + +$$\label{eq:decrease_bound} +\ell^\text{dec}(t) \leq \Delta \ell^\text{max} \cdot b^\text{dec}(t) \quad \forall t +$$ + +With: +- $\Delta \ell^\text{max}$ being the maximum change per time step +- $b^\text{inc}(t), b^\text{dec}(t) \in \{0, 1\}$ being binary control variables + +--- + +### Mutual Exclusivity of Changes + +Simultaneous increase and decrease are prevented: + +$$\label{eq:change_exclusivity} +b^\text{inc}(t) + b^\text{dec}(t) \leq 1 \quad \forall t +$$ + +This ensures: +- Level can only increase OR decrease (or stay constant) in each time step +- No simultaneous contradictory changes + +--- + +### Complete Level Change Formulation + +$$ +\begin{align} +\ell(0) &= \ell_\text{init} + \ell^\text{inc}(0) - \ell^\text{dec}(0) && \label{eq:level_complete_1} \\ +\ell(t) &= \ell(t-1) + \ell^\text{inc}(t) - \ell^\text{dec}(t) && \forall t > 0 \label{eq:level_complete_2} \\ +\ell^\text{inc}(t) &\leq \Delta \ell^\text{max} \cdot b^\text{inc}(t) && \forall t \label{eq:level_complete_3} \\ +\ell^\text{dec}(t) &\leq \Delta \ell^\text{max} \cdot b^\text{dec}(t) && \forall t \label{eq:level_complete_4} \\ +b^\text{inc}(t) + b^\text{dec}(t) &\leq 1 && \forall t \label{eq:level_complete_5} \\ +b^\text{inc}(t), b^\text{dec}(t) &\in \{0, 1\} && \forall t \label{eq:level_complete_6} +\end{align} +$$ + +**Implementation:** [`BoundingPatterns.link_changes_to_level_with_binaries()`][flixopt.modeling.BoundingPatterns.link_changes_to_level_with_binaries] in `flixopt/modeling.py:684` + +--- + +## Use Cases + +### Startup/Shutdown Costs + +Track startup and shutdown events to apply costs: + +```python +# Create switch variables +switch_on, switch_off = modeling.state_transition_bounds( + state_variable=on_state, + previous_state=previous_on_state +) + +# Apply costs to switches +startup_cost = switch_on * startup_cost_per_event +shutdown_cost = switch_off * shutdown_cost_per_event +``` + +### Limited Switching + +Restrict the number of state changes: + +```python +# Track all switches +switch_on, switch_off = modeling.state_transition_bounds( + state_variable=on_state +) + +# Limit total switches +model.add_constraint( + (switch_on + switch_off).sum() <= max_switches +) +``` + +### Gradual Capacity Changes + +Model systems where capacity can be incrementally adjusted: + +```python +# Level represents installed capacity +level_var, increase, decrease, inc_binary, dec_binary = \ + modeling.link_changes_to_level_with_binaries( + initial_level=current_capacity, + max_change=max_capacity_change_per_period + ) + +# Constrain total increases +model.add_constraint(increase.sum() <= max_total_expansion) +``` + +--- + +## Used In + +These patterns are used in: +- [`OnOffParameters`](../features/OnOffParameters.md) - Startup/shutdown tracking and costs +- Operating mode switching with transition costs +- Investment planning with staged capacity additions +- Inventory management with controlled stock changes From 564ad0567c6cf204454c1dee3eb79a47c4572ba5 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:54:18 +0200 Subject: [PATCH 08/29] Moved cross-reference.md --- .../mathematical-notation/cross-reference.md | 112 ------------------ .../user-guide/mathematical-notation/index.md | 71 +++++++++++ 2 files changed, 71 insertions(+), 112 deletions(-) delete mode 100644 docs/user-guide/mathematical-notation/cross-reference.md diff --git a/docs/user-guide/mathematical-notation/cross-reference.md b/docs/user-guide/mathematical-notation/cross-reference.md deleted file mode 100644 index a539a0987..000000000 --- a/docs/user-guide/mathematical-notation/cross-reference.md +++ /dev/null @@ -1,112 +0,0 @@ -# Mathematical Documentation Cross-Reference - -This document provides a comprehensive mapping between mathematical concepts, their documentation, implementation, and tests. Use this to quickly locate where specific mathematical formulations are defined and implemented. - -## Components - -| Concept | Documentation | Equations | Implementation | Key Location | -|---------|---------------|-----------|----------------|--------------| -| **Flow rate bounds** | [Flow.md](../elements/Flow.md) | eq. (1) | `FlowModel._do_modeling()` | `flixopt/elements.py:350+` | -| **Bus balance** | [Bus.md](../elements/Bus.md) | eq. (1), (2) | `BusModel._do_modeling()` | `flixopt/elements.py:751` | -| **Bus excess/deficit** | [Bus.md](../elements/Bus.md) | eq. (3), (4) | `BusModel._do_modeling()` | `flixopt/elements.py:763` | -| **Storage charge bounds** | [Storage.md](../elements/Storage.md) | eq. (1) | `StorageModel._do_modeling()` | `flixopt/components.py:~820` | -| **Storage balance** | [Storage.md](../elements/Storage.md) | eq. (3) | `StorageModel._do_modeling()` | `flixopt/components.py:838-842` | -| **Linear conversion** | [LinearConverter.md](../elements/LinearConverter.md) | eq. (1), (2) | Component-specific | `flixopt/components.py:37+` | - -## Features - -| Concept | Documentation | Equations | Implementation | Key Location | -|---------|---------------|-----------|----------------|--------------| -| **Binary investment** | [InvestParameters.md](../features/InvestParameters.md) | eq. (1) | `InvestParametersFeature` | `flixopt/interface.py:663+` | -| **Continuous investment sizing** | [InvestParameters.md](../features/InvestParameters.md) | eq. (2) | `InvestParametersFeature` | `flixopt/interface.py:663+` | -| **Investment fixed effects** | [InvestParameters.md](../features/InvestParameters.md) | eq. (4) | Effect calculation | `flixopt/features.py` | -| **Investment specific effects** | [InvestParameters.md](../features/InvestParameters.md) | eq. (5) | Effect calculation | `flixopt/features.py` | -| **Investment divestment effects** | [InvestParameters.md](../features/InvestParameters.md) | eq. (8) | Effect calculation | `flixopt/features.py` | -| **On/off state variable** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (1) | `OnOffFeature` | `flixopt/interface.py:918+` | -| **State transitions** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (2), (3) | `OnOffFeature` | Uses `state_transition_bounds()` | -| **Switching effects** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (4) | Effect calculation | `flixopt/features.py` | -| **Running effects** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (5) | Effect calculation | `flixopt/features.py` | -| **Minimum on-time** | [OnOffParameters.md](../features/OnOffParameters.md) | eq. (8) | Duration tracking | Uses `consecutive_duration_tracking()` | -| **Piecewise segments** | [Piecewise.md](../features/Piecewise.md) | eq. (1)-(4) | `PiecewiseModel` | `flixopt/features.py:382+` | - -## Modeling Patterns - -| Pattern | Documentation | Equations | Implementation | Key Location | -|---------|---------------|-----------|----------------|--------------| -| **Basic bounds** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#basic-bounds) | eq. (1) | `BoundingPatterns.basic_bounds()` | `flixopt/modeling.py:393` | -| **Bounds with state** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#bounds-with-state) | eq. (2) | `BoundingPatterns.bounds_with_state()` | `flixopt/modeling.py:427` | -| **Scaled bounds** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#scaled-bounds) | eq. (3) | `BoundingPatterns.scaled_bounds()` | `flixopt/modeling.py:473` | -| **Scaled bounds with state** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#scaled-bounds-with-state) | eq. (4), (5) | `BoundingPatterns.scaled_bounds_with_state()` | `flixopt/modeling.py:516` | -| **Expression tracking** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#expression-tracking) | eq. (6), (7) | `ModelingPrimitives.expression_tracking_variable()` | `flixopt/modeling.py:201` | -| **Mutual exclusivity** | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#mutual-exclusivity) | eq. (8) | `ModelingPrimitives.mutual_exclusivity_constraint()` | `flixopt/modeling.py:345` | -| **Duration tracking** | [duration-tracking.md](../modeling-patterns/duration-tracking.md) | eq. (1)-(4) | `ModelingPrimitives.consecutive_duration_tracking()` | `flixopt/modeling.py:240` | -| **Minimum duration** | [duration-tracking.md](../modeling-patterns/duration-tracking.md#minimum-duration-constraints) | eq. (5) | Part of `consecutive_duration_tracking()` | `flixopt/modeling.py:240` | -| **State transitions** | [state-transitions.md](../modeling-patterns/state-transitions.md#binary-state-transitions) | eq. (1)-(4) | `BoundingPatterns.state_transition_bounds()` | `flixopt/modeling.py:573` | -| **Continuous transitions** | [state-transitions.md](../modeling-patterns/state-transitions.md#continuous-transitions) | eq. (5), (6) | `BoundingPatterns.continuous_transition_bounds()` | `flixopt/modeling.py:618` | -| **Level changes with binaries** | [state-transitions.md](../modeling-patterns/state-transitions.md#level-changes-with-binaries) | eq. (7)-(12) | `BoundingPatterns.link_changes_to_level_with_binaries()` | `flixopt/modeling.py:684` | - -## Effects System - -| Concept | Documentation | Equations | Implementation | Key Location | -|---------|---------------|-----------|----------------|--------------| -| **Share to effect (invest)** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (1) | Effect aggregation | `flixopt/effects.py` | -| **Share to effect (operation)** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (2) | Effect aggregation | `flixopt/effects.py` | -| **Cross-effect contribution** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (3), (4) | Effect cross-links | `flixopt/effects.py` | -| **Total effect** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (6) | Effect total calculation | `flixopt/effects.py` | -| **Effect bounds** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (7), (8) | Effect constraints | `flixopt/effects.py` | -| **Penalty** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (9) | Penalty aggregation | `flixopt/effects.py` | -| **Objective function** | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | eq. (10) | Objective creation | `flixopt/flow_system.py` | - -## Quick Lookup by Python Class - -| Python Class | Mathematical Documentation | Location | -|--------------|---------------------------|----------| -| `Flow` | [Flow.md](../elements/Flow.md) | `flixopt/elements.py:175` | -| `Bus` | [Bus.md](../elements/Bus.md) | `flixopt/elements.py:120` | -| `Storage` | [Storage.md](../elements/Storage.md) | `flixopt/components.py:237` | -| `LinearConverter` | [LinearConverter.md](../elements/LinearConverter.md) | `flixopt/components.py:37` | -| `InvestParameters` | [InvestParameters.md](../features/InvestParameters.md) | `flixopt/interface.py:663` | -| `OnOffParameters` | [OnOffParameters.md](../features/OnOffParameters.md) | `flixopt/interface.py:918` | -| `Piecewise` | [Piecewise.md](../features/Piecewise.md) | `flixopt/interface.py:83` | -| `Effect` | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | `flixopt/effects.py:32` | -| `ModelingPrimitives` | [modeling-patterns/](../modeling-patterns/index.md) | `flixopt/modeling.py:178` | -| `BoundingPatterns` | [modeling-patterns/](../modeling-patterns/index.md) | `flixopt/modeling.py:390` | - -## Quick Lookup by Mathematical Concept - -| Mathematical Concept | Documentation | Implementation Function | -|---------------------|---------------|------------------------| -| Variable bounds | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md) | `basic_bounds()`, `bounds_with_state()`, `scaled_bounds()`, `scaled_bounds_with_state()` | -| Binary state control | [bounds-and-states.md](../modeling-patterns/bounds-and-states.md#bounds-with-state) | `bounds_with_state()`, `scaled_bounds_with_state()` | -| Consecutive time periods | [duration-tracking.md](../modeling-patterns/duration-tracking.md) | `consecutive_duration_tracking()` | -| Switching between states | [state-transitions.md](../modeling-patterns/state-transitions.md) | `state_transition_bounds()`, `continuous_transition_bounds()` | -| Linear equality constraints | [LinearConverter.md](../elements/LinearConverter.md) | Component-specific implementations | -| Energy balance | [Storage.md](../elements/Storage.md), [Bus.md](../elements/Bus.md) | Component-specific implementations | -| Piecewise linear functions | [Piecewise.md](../features/Piecewise.md) | `PiecewiseModel._do_modeling()` | -| Investment decisions | [InvestParameters.md](../features/InvestParameters.md) | `InvestParametersFeature` | -| On/off operation | [OnOffParameters.md](../features/OnOffParameters.md) | `OnOffFeature` | -| Cost/effect allocation | [Effects, Penalty & Objective.md](../effects-penalty-objective.md) | Effect system in `flixopt/effects.py` | - -## Navigation Tips - -### Finding Documentation from Code -1. Find the class name in Python (e.g., `Storage`) -2. Look up the class in "Quick Lookup by Python Class" table -3. Follow the link to the mathematical documentation - -### Finding Implementation from Docs -1. Find the equation number in documentation (e.g., Storage eq. 3) -2. Look up in the corresponding section in the cross-reference tables -3. Navigate to the implementation location - -### Understanding a Mathematical Pattern -1. Identify the pattern type (bounds, transitions, duration, etc.) -2. Read the pattern documentation in [modeling-patterns/](../modeling-patterns/index.md) -3. See usage examples in component documentation -4. Find implementation in `flixopt/modeling.py` - -## See Also - -- [Mathematical Notation Overview](index.md) - Naming conventions and fundamentals -- [Modeling Patterns](../modeling-patterns/index.md) - Reusable mathematical building blocks -- [Effects, Penalty & Objective](../effects-penalty-objective.md) - System-level formulation diff --git a/docs/user-guide/mathematical-notation/index.md b/docs/user-guide/mathematical-notation/index.md index b76a1ba1f..126ea52e1 100644 --- a/docs/user-guide/mathematical-notation/index.md +++ b/docs/user-guide/mathematical-notation/index.md @@ -20,3 +20,74 @@ $$\Delta \text{t}_i = \text{t}_{i+1} - \text{t}_i \quad \text{for} \quad i \in \ The final time interval $\Delta \text{t}_\text n$ defaults to $\Delta \text{t}_\text n = \Delta \text{t}_{\text n-1}$, but is of course customizable. Non-equidistant time steps are also supported. + +--- + +## Documentation Structure + +This mathematical notation guide is organized into the following sections: + +### Elements +Core building blocks of energy system models: +- [Flow](elements/Flow.md) - Flow rate constraints and bounds +- [Bus](elements/Bus.md) - Nodal balance equations +- [Storage](elements/Storage.md) - Storage balance and charge state evolution +- [LinearConverter](elements/LinearConverter.md) - Linear conversion relationships + +### Features +Optional modeling capabilities: +- [InvestParameters](features/InvestParameters.md) - Investment decision modeling +- [OnOffParameters](features/OnOffParameters.md) - Binary on/off operation +- [Piecewise](features/Piecewise.md) - Piecewise linear approximations + +### System-Level +- [Effects, Penalty & Objective](effects-penalty-objective.md) - Cost allocation and objective function + +### Modeling Patterns +Reusable mathematical building blocks: +- [Bounds and States](modeling-patterns/bounds-and-states.md) - Variable bounding patterns +- [Duration Tracking](modeling-patterns/duration-tracking.md) - Consecutive time period tracking +- [State Transitions](modeling-patterns/state-transitions.md) - State change modeling + +--- + +## Quick Reference + +### Components Cross-Reference + +| Concept | Documentation | Equations | Implementation | Location | +|---------|---------------|-----------|----------------|----------| +| **Flow rate bounds** | [Flow](elements/Flow.md) | eq. (1) | `FlowModel._do_modeling()` | `elements.py:350+` | +| **Bus balance** | [Bus](elements/Bus.md) | eq. (1), (2) | `BusModel._do_modeling()` | `elements.py:751` | +| **Storage balance** | [Storage](elements/Storage.md) | eq. (3) | `StorageModel._do_modeling()` | `components.py:838-842` | +| **Linear conversion** | [LinearConverter](elements/LinearConverter.md) | eq. (1), (2) | Component-specific | `components.py:37+` | + +### Features Cross-Reference + +| Concept | Documentation | Equations | Implementation | +|---------|---------------|-----------|----------------| +| **Binary investment** | [InvestParameters](features/InvestParameters.md) | eq. (1) | `InvestParametersFeature` | +| **On/off operation** | [OnOffParameters](features/OnOffParameters.md) | eq. (1)-(11) | `OnOffFeature` | +| **Piecewise segments** | [Piecewise](features/Piecewise.md) | eq. (1)-(4) | `PiecewiseModel` | + +### Modeling Patterns Cross-Reference + +| Pattern | Documentation | Implementation | +|---------|---------------|----------------| +| **Basic bounds** | [bounds-and-states](modeling-patterns/bounds-and-states.md#basic-bounds) | `BoundingPatterns.basic_bounds()` | +| **Bounds with state** | [bounds-and-states](modeling-patterns/bounds-and-states.md#bounds-with-state) | `BoundingPatterns.bounds_with_state()` | +| **Scaled bounds** | [bounds-and-states](modeling-patterns/bounds-and-states.md#scaled-bounds) | `BoundingPatterns.scaled_bounds()` | +| **Duration tracking** | [duration-tracking](modeling-patterns/duration-tracking.md) | `ModelingPrimitives.consecutive_duration_tracking()` | +| **State transitions** | [state-transitions](modeling-patterns/state-transitions.md) | `BoundingPatterns.state_transition_bounds()` | + +### Python Class Lookup + +| Class | Documentation | Location | +|-------|---------------|----------| +| `Flow` | [Flow](elements/Flow.md) | `flixopt/elements.py:175` | +| `Bus` | [Bus](elements/Bus.md) | `flixopt/elements.py:120` | +| `Storage` | [Storage](elements/Storage.md) | `flixopt/components.py:237` | +| `LinearConverter` | [LinearConverter](elements/LinearConverter.md) | `flixopt/components.py:37` | +| `InvestParameters` | [InvestParameters](features/InvestParameters.md) | `flixopt/interface.py:663` | +| `OnOffParameters` | [OnOffParameters](features/OnOffParameters.md) | `flixopt/interface.py:918` | +| `Piecewise` | [Piecewise](features/Piecewise.md) | `flixopt/interface.py:83` | From dbd2dfcf2c2ea63abd49a982fd9c3c542b8cba38 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:56:43 +0200 Subject: [PATCH 09/29] Reformulate --- docs/user-guide/mathematical-notation/index.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/user-guide/mathematical-notation/index.md b/docs/user-guide/mathematical-notation/index.md index 126ea52e1..27391b272 100644 --- a/docs/user-guide/mathematical-notation/index.md +++ b/docs/user-guide/mathematical-notation/index.md @@ -44,10 +44,13 @@ Optional modeling capabilities: - [Effects, Penalty & Objective](effects-penalty-objective.md) - Cost allocation and objective function ### Modeling Patterns -Reusable mathematical building blocks: -- [Bounds and States](modeling-patterns/bounds-and-states.md) - Variable bounding patterns -- [Duration Tracking](modeling-patterns/duration-tracking.md) - Consecutive time period tracking -- [State Transitions](modeling-patterns/state-transitions.md) - State change modeling +**Low-level mathematical building blocks** - These patterns are internal implementation details used exclusively within the high-level interfaces (Elements and Features). **Users do not interact with these patterns directly**; they are automatically applied when using Elements and Features: + +- [Bounds and States](modeling-patterns/bounds-and-states.md) - Variable bounding patterns (used internally) +- [Duration Tracking](modeling-patterns/duration-tracking.md) - Consecutive time period tracking (used internally) +- [State Transitions](modeling-patterns/state-transitions.md) - State change modeling (used internally) + +**Note:** These patterns are documented for developers and advanced users who want to understand the underlying mathematical formulations. Normal users should focus on the Elements and Features sections above. --- From b9047e1b9d19dbacc2b29a83c6ca190b8a03dd9c Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:58:38 +0200 Subject: [PATCH 10/29] Reformulate --- .../user-guide/mathematical-notation/index.md | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/user-guide/mathematical-notation/index.md b/docs/user-guide/mathematical-notation/index.md index 27391b272..e604cf032 100644 --- a/docs/user-guide/mathematical-notation/index.md +++ b/docs/user-guide/mathematical-notation/index.md @@ -1,6 +1,12 @@ # Mathematical Notation +This section provides the **mathematical formulations** underlying FlixOpt's optimization models. It is intended as **reference documentation** for users who want to understand the mathematical details behind the high-level FlixOpt API described in the [FlixOpt Concepts](../index.md) guide. + +**For typical usage**, refer to the [FlixOpt Concepts](../index.md) guide, [Examples](../../examples/), and [API Reference](../../api-reference/) - you don't need to understand these mathematical formulations to use FlixOpt effectively. + +--- + ## Naming Conventions FlixOpt uses the following naming conventions: @@ -25,32 +31,44 @@ Non-equidistant time steps are also supported. ## Documentation Structure -This mathematical notation guide is organized into the following sections: +This reference is organized to match the FlixOpt API structure: ### Elements -Core building blocks of energy system models: +Mathematical formulations for core FlixOpt elements (corresponding to [`flixopt.elements`][flixopt.elements]): + - [Flow](elements/Flow.md) - Flow rate constraints and bounds - [Bus](elements/Bus.md) - Nodal balance equations - [Storage](elements/Storage.md) - Storage balance and charge state evolution - [LinearConverter](elements/LinearConverter.md) - Linear conversion relationships +**User API:** When you create a `Flow`, `Bus`, `Storage`, or `LinearConverter` in your FlixOpt model, these mathematical formulations are automatically applied. + ### Features -Optional modeling capabilities: +Mathematical formulations for optional features (corresponding to parameters in FlixOpt classes): + - [InvestParameters](features/InvestParameters.md) - Investment decision modeling - [OnOffParameters](features/OnOffParameters.md) - Binary on/off operation - [Piecewise](features/Piecewise.md) - Piecewise linear approximations +**User API:** When you pass `invest_parameters` or `on_off_parameters` to a `Flow` or component, these formulations are applied. + ### System-Level - [Effects, Penalty & Objective](effects-penalty-objective.md) - Cost allocation and objective function -### Modeling Patterns -**Low-level mathematical building blocks** - These patterns are internal implementation details used exclusively within the high-level interfaces (Elements and Features). **Users do not interact with these patterns directly**; they are automatically applied when using Elements and Features: +**User API:** When you create [`Effect`][flixopt.effects.Effect] objects and set `effects_per_flow_hour`, these formulations govern how costs are calculated. + +### Modeling Patterns (Advanced) +**Internal implementation details** - These low-level patterns are used internally by Elements and Features. They are documented here for: + +- Developers extending FlixOpt +- Advanced users debugging models or understanding solver behavior +- Researchers comparing mathematical formulations -- [Bounds and States](modeling-patterns/bounds-and-states.md) - Variable bounding patterns (used internally) -- [Duration Tracking](modeling-patterns/duration-tracking.md) - Consecutive time period tracking (used internally) -- [State Transitions](modeling-patterns/state-transitions.md) - State change modeling (used internally) +**Normal users do not need to read this section** - the patterns are automatically applied when you use Elements and Features: -**Note:** These patterns are documented for developers and advanced users who want to understand the underlying mathematical formulations. Normal users should focus on the Elements and Features sections above. +- [Bounds and States](modeling-patterns/bounds-and-states.md) - Variable bounding patterns +- [Duration Tracking](modeling-patterns/duration-tracking.md) - Consecutive time period tracking +- [State Transitions](modeling-patterns/state-transitions.md) - State change modeling --- From 7e0845fed1f52176cdb31806f2c99830b43a3445 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 16:41:17 +0200 Subject: [PATCH 11/29] Improve docs --- .../effects-penalty-objective.md | 4 +- .../mathematical-notation/elements/Bus.md | 24 ++------- .../mathematical-notation/elements/Flow.md | 23 +++------ .../elements/LinearConverter.md | 13 ++--- .../mathematical-notation/elements/Storage.md | 21 ++------ .../features/InvestParameters.md | 8 +-- .../features/OnOffParameters.md | 6 +-- .../user-guide/mathematical-notation/index.md | 50 +++++++++---------- .../modeling-patterns/bounds-and-states.md | 20 ++++---- .../modeling-patterns/duration-tracking.md | 12 +---- .../modeling-patterns/state-transitions.md | 6 +-- 11 files changed, 64 insertions(+), 123 deletions(-) diff --git a/docs/user-guide/mathematical-notation/effects-penalty-objective.md b/docs/user-guide/mathematical-notation/effects-penalty-objective.md index 7801e10ab..5fb3ff382 100644 --- a/docs/user-guide/mathematical-notation/effects-penalty-objective.md +++ b/docs/user-guide/mathematical-notation/effects-penalty-objective.md @@ -1,6 +1,6 @@ ## Effects [`Effects`][flixopt.effects.Effect] are used to allocate things like costs, emissions, or other "effects" occurring in the system. -These arise from so called **Shares**, which originate from **Elements** like [Flows](../elements/Flow.md). +These arise from so called **Shares**, which originate from **Elements** like [Flows](elements/Flow.md). **Example:** @@ -113,7 +113,7 @@ With: - $\mathcal{T}$ being the set of all timesteps - $s_{l \rightarrow \Phi}$ being the share of element $l$ to the penalty -At the moment, penalties only occur in [Buses](../elements/Bus.md) +At the moment, penalties only occur in [Buses](elements/Bus.md) ## Objective diff --git a/docs/user-guide/mathematical-notation/elements/Bus.md b/docs/user-guide/mathematical-notation/elements/Bus.md index c7cea3faf..bfe57d234 100644 --- a/docs/user-guide/mathematical-notation/elements/Bus.md +++ b/docs/user-guide/mathematical-notation/elements/Bus.md @@ -36,32 +36,14 @@ With: ## Implementation -**Class:** [`Bus`][flixopt.elements.Bus] +**Python Class:** [`Bus`][flixopt.elements.Bus] -**Location:** `flixopt/elements.py:120` - -**Model Class:** [`BusModel`][flixopt.elements.BusModel] - -**Location:** `flixopt/elements.py:736` - -**Key Constraints:** -- Bus balance equation (eq. $\eqref{eq:bus_balance}$ or $\eqref{eq:bus_balance-excess}$): `flixopt/elements.py:751` -- Excess/deficit bounds (when applicable): `flixopt/elements.py:763` - -**Variables Created:** -- No additional variables for strict balance -- `excess_input`, `excess_output`: Excess/deficit variables $\phi_\text{in}(\text{t}_i), \phi_\text{out}(\text{t}_i)$ (when penalty is specified) - -**Parameters:** -- `excess_penalty_per_flow_hour`: Penalty coefficient $\text{a}_{b \rightarrow \Phi}$ for balance violations - -**Penalty Contribution:** -When excess is allowed, the penalty term $s_{b \rightarrow \Phi}(\text{t}_i)$ contributes to the overall system penalty $\Phi$ as described in [Effects, Penalty & Objective](Effects,%20Penalty%20&%20Objective.md#penalty). +See the API documentation for implementation details and usage examples. --- ## See Also - [Flow](../elements/Flow.md) - Definition of flow rates in the balance -- [Effects, Penalty & Objective](Effects,%20Penalty%20&%20Objective.md) - How penalties are included in the objective function +- [Effects, Penalty & Objective](../effects-penalty-objective.md) - How penalties are included in the objective function - [Modeling Patterns](../modeling-patterns/index.md) - Mathematical building blocks diff --git a/docs/user-guide/mathematical-notation/elements/Flow.md b/docs/user-guide/mathematical-notation/elements/Flow.md index e1fe3d81f..6b03fa434 100644 --- a/docs/user-guide/mathematical-notation/elements/Flow.md +++ b/docs/user-guide/mathematical-notation/elements/Flow.md @@ -21,8 +21,8 @@ $$ $$ -This mathematical formulation can be extended by using [OnOffParameters](./OnOffParameters.md) -to define the on/off state of the Flow, or by using [InvestParameters](./InvestParameters.md) +This mathematical formulation can be extended by using [OnOffParameters](../features/OnOffParameters.md) +to define the on/off state of the Flow, or by using [InvestParameters](../features/InvestParameters.md) to change the size of the Flow from a constant to an optimization variable. --- @@ -39,28 +39,17 @@ Flow formulation uses the following modeling patterns: ## Implementation -**Class:** [`Flow`][flixopt.elements.Flow] +**Python Class:** [`Flow`][flixopt.elements.Flow] -**Location:** `flixopt/elements.py:175` - -**Model Class:** [`FlowModel`][flixopt.elements.FlowModel] - -**Location:** `flixopt/elements.py:350` - -**Key Constraints:** -- Flow rate bounds (eq. $\eqref{eq:flow_rate}$): Created in `FlowModel._do_modeling()` - -**Variables Created:** -- `flow_rate`: Flow rate variable $p(\text{t}_i)$ -- Additional variables when using [OnOffParameters](../features/OnOffParameters.md) or [InvestParameters](../features/InvestParameters.md) - -**Parameters:** +**Key Parameters:** - `size`: Flow size $\text{P}$ (can be fixed or variable with InvestParameters) - `relative_minimum`, `relative_maximum`: Relative bounds $\text{p}^{\text{L}}_{\text{rel}}, \text{p}^{\text{U}}_{\text{rel}}$ - `effects_per_flow_hour`: Operational effects (costs, emissions, etc.) - `invest_parameters`: Optional investment modeling (see [InvestParameters](../features/InvestParameters.md)) - `on_off_parameters`: Optional on/off operation (see [OnOffParameters](../features/OnOffParameters.md)) +See the [`Flow`][flixopt.elements.Flow] API documentation for complete parameter list and usage examples. + --- ## See Also diff --git a/docs/user-guide/mathematical-notation/elements/LinearConverter.md b/docs/user-guide/mathematical-notation/elements/LinearConverter.md index 9a684b61f..b007aa7f5 100644 --- a/docs/user-guide/mathematical-notation/elements/LinearConverter.md +++ b/docs/user-guide/mathematical-notation/elements/LinearConverter.md @@ -25,16 +25,7 @@ The conversion efficiency can be defined as a piecewise linear approximation. Se ## Implementation -**Class:** [`LinearConverter`][flixopt.components.LinearConverter] - -**Location:** `flixopt/components.py:37` - -**Key Constraints:** -- Linear conversion equation (eq. $\eqref{eq:Linear-Transformer-Ratio}$): Created in component-specific modeling methods - -**Parameters:** -- Conversion factors $\text{a}_{f_\text{in}}$ and $\text{b}_{f_\text{out}}$ are defined through flow connections -- For simple converters with one input and one output, efficiency $\text{a}$ is specified +**Python Class:** [`LinearConverter`][flixopt.components.LinearConverter] **Specialized Linear Converters:** @@ -47,6 +38,8 @@ FlixOpt provides specialized linear converter classes for common applications: These classes handle the mathematical formulation automatically based on physical relationships. +See the API documentation for implementation details and usage examples. + --- ## See Also diff --git a/docs/user-guide/mathematical-notation/elements/Storage.md b/docs/user-guide/mathematical-notation/elements/Storage.md index 8c7726f4a..259958798 100644 --- a/docs/user-guide/mathematical-notation/elements/Storage.md +++ b/docs/user-guide/mathematical-notation/elements/Storage.md @@ -59,30 +59,17 @@ When combined with investment parameters, storage can use: ## Implementation -**Class:** [`Storage`][flixopt.components.Storage] +**Python Class:** [`Storage`][flixopt.components.Storage] -**Location:** `flixopt/components.py:237` - -**Model Class:** [`StorageModel`][flixopt.components.StorageModel] - -**Location:** `flixopt/components.py:800` - -**Key Constraints:** -- Charge state bounds: `flixopt/components.py:~820` -- Storage balance equation (eq. 3): `flixopt/components.py:838-842` - -**Variables Created:** -- `charge_state`: State of charge $c(\text{t}_i)$ -- `charge_flow`: Input flow rate $p_{f_\text{in}}(\text{t}_i)$ -- `discharge_flow`: Output flow rate $p_{f_\text{out}}(\text{t}_i)$ - -**Parameters:** +**Key Parameters:** - `size`: Storage capacity $\text{C}$ - `relative_loss_per_hour`: Self-discharge rate $\dot{\text{c}}_\text{rel,loss}$ - `charge_state_start`: Initial charge $c(\text{t}_0)$ - `charge_state_end`: Final charge target $c(\text{t}_\text{end})$ (optional) - `eta_charge`, `eta_discharge`: Charging/discharging efficiencies $\eta_\text{in}, \eta_\text{out}$ +See the [`Storage`][flixopt.components.Storage] API documentation for complete parameter list and usage examples. + --- ## See Also diff --git a/docs/user-guide/mathematical-notation/features/InvestParameters.md b/docs/user-guide/mathematical-notation/features/InvestParameters.md index 0161ee066..45c338630 100644 --- a/docs/user-guide/mathematical-notation/features/InvestParameters.md +++ b/docs/user-guide/mathematical-notation/features/InvestParameters.md @@ -168,7 +168,7 @@ $$\label{eq:invest_total_effects} E_{e,\text{invest}} = E_{e,\text{fix}} + E_{e,\text{spec}} + E_{e,\text{pw}} + E_{e,\text{divest}} $$ -Effects integrate into the overall system effects as described in [Effects, Penalty & Objective](Effects,%20Penalty%20&%20Objective.md). +Effects integrate into the overall system effects as described in [Effects, Penalty & Objective](../effects-penalty-objective.md). --- @@ -222,9 +222,7 @@ $$ ## Implementation -**Class:** [`InvestParameters`][flixopt.interface.InvestParameters] - -**Location:** `flixopt/interface.py:663` +**Python Class:** [`InvestParameters`][flixopt.interface.InvestParameters] **Key Parameters:** - `fixed_size`: For binary investments (mutually exclusive with continuous sizing) @@ -235,6 +233,8 @@ $$ - `piecewise_effects`: Non-linear cost modeling - `divest_effects`: Costs for not investing +See the [`InvestParameters`][flixopt.interface.InvestParameters] API documentation for complete parameter list and usage examples. + **Used in:** - [`Flow`][flixopt.elements.Flow] - Flexible capacity decisions - [`Storage`][flixopt.components.Storage] - Storage sizing optimization diff --git a/docs/user-guide/mathematical-notation/features/OnOffParameters.md b/docs/user-guide/mathematical-notation/features/OnOffParameters.md index 55b3ef300..87835400a 100644 --- a/docs/user-guide/mathematical-notation/features/OnOffParameters.md +++ b/docs/user-guide/mathematical-notation/features/OnOffParameters.md @@ -232,9 +232,7 @@ For equipment with OnOffParameters, the complete constraint system includes: ## Implementation -**Class:** [`OnOffParameters`][flixopt.interface.OnOffParameters] - -**Location:** `flixopt/interface.py:918` +**Python Class:** [`OnOffParameters`][flixopt.interface.OnOffParameters] **Key Parameters:** - `effects_per_switch_on`: Costs per startup event @@ -245,6 +243,8 @@ For equipment with OnOffParameters, the complete constraint system includes: - `switch_on_total_max`: Maximum number of startups - `force_switch_on`: Create switch variables even without limits (for tracking) +See the [`OnOffParameters`][flixopt.interface.OnOffParameters] API documentation for complete parameter list and usage examples. + **Mathematical Patterns Used:** - [State Transitions](../modeling-patterns/state-transitions.md#binary-state-transitions) - Switch tracking - [Duration Tracking](../modeling-patterns/duration-tracking.md) - Consecutive time constraints diff --git a/docs/user-guide/mathematical-notation/index.md b/docs/user-guide/mathematical-notation/index.md index e604cf032..2cc44c879 100644 --- a/docs/user-guide/mathematical-notation/index.md +++ b/docs/user-guide/mathematical-notation/index.md @@ -76,39 +76,39 @@ Mathematical formulations for optional features (corresponding to parameters in ### Components Cross-Reference -| Concept | Documentation | Equations | Implementation | Location | -|---------|---------------|-----------|----------------|----------| -| **Flow rate bounds** | [Flow](elements/Flow.md) | eq. (1) | `FlowModel._do_modeling()` | `elements.py:350+` | -| **Bus balance** | [Bus](elements/Bus.md) | eq. (1), (2) | `BusModel._do_modeling()` | `elements.py:751` | -| **Storage balance** | [Storage](elements/Storage.md) | eq. (3) | `StorageModel._do_modeling()` | `components.py:838-842` | -| **Linear conversion** | [LinearConverter](elements/LinearConverter.md) | eq. (1), (2) | Component-specific | `components.py:37+` | +| Concept | Documentation | Python Class | +|---------|---------------|--------------| +| **Flow rate bounds** | [Flow](elements/Flow.md) | [`Flow`][flixopt.elements.Flow] | +| **Bus balance** | [Bus](elements/Bus.md) | [`Bus`][flixopt.elements.Bus] | +| **Storage balance** | [Storage](elements/Storage.md) | [`Storage`][flixopt.components.Storage] | +| **Linear conversion** | [LinearConverter](elements/LinearConverter.md) | [`LinearConverter`][flixopt.components.LinearConverter] | ### Features Cross-Reference -| Concept | Documentation | Equations | Implementation | -|---------|---------------|-----------|----------------| -| **Binary investment** | [InvestParameters](features/InvestParameters.md) | eq. (1) | `InvestParametersFeature` | -| **On/off operation** | [OnOffParameters](features/OnOffParameters.md) | eq. (1)-(11) | `OnOffFeature` | -| **Piecewise segments** | [Piecewise](features/Piecewise.md) | eq. (1)-(4) | `PiecewiseModel` | +| Concept | Documentation | Python Class | +|---------|---------------|--------------| +| **Binary investment** | [InvestParameters](features/InvestParameters.md) | [`InvestParameters`][flixopt.interface.InvestParameters] | +| **On/off operation** | [OnOffParameters](features/OnOffParameters.md) | [`OnOffParameters`][flixopt.interface.OnOffParameters] | +| **Piecewise segments** | [Piecewise](features/Piecewise.md) | [`Piecewise`][flixopt.interface.Piecewise] | ### Modeling Patterns Cross-Reference | Pattern | Documentation | Implementation | |---------|---------------|----------------| -| **Basic bounds** | [bounds-and-states](modeling-patterns/bounds-and-states.md#basic-bounds) | `BoundingPatterns.basic_bounds()` | -| **Bounds with state** | [bounds-and-states](modeling-patterns/bounds-and-states.md#bounds-with-state) | `BoundingPatterns.bounds_with_state()` | -| **Scaled bounds** | [bounds-and-states](modeling-patterns/bounds-and-states.md#scaled-bounds) | `BoundingPatterns.scaled_bounds()` | -| **Duration tracking** | [duration-tracking](modeling-patterns/duration-tracking.md) | `ModelingPrimitives.consecutive_duration_tracking()` | -| **State transitions** | [state-transitions](modeling-patterns/state-transitions.md) | `BoundingPatterns.state_transition_bounds()` | +| **Basic bounds** | [bounds-and-states](modeling-patterns/bounds-and-states.md#basic-bounds) | [`BoundingPatterns.basic_bounds()`][flixopt.modeling.BoundingPatterns.basic_bounds] | +| **Bounds with state** | [bounds-and-states](modeling-patterns/bounds-and-states.md#bounds-with-state) | [`BoundingPatterns.bounds_with_state()`][flixopt.modeling.BoundingPatterns.bounds_with_state] | +| **Scaled bounds** | [bounds-and-states](modeling-patterns/bounds-and-states.md#scaled-bounds) | [`BoundingPatterns.scaled_bounds()`][flixopt.modeling.BoundingPatterns.scaled_bounds] | +| **Duration tracking** | [duration-tracking](modeling-patterns/duration-tracking.md) | [`ModelingPrimitives.consecutive_duration_tracking()`][flixopt.modeling.ModelingPrimitives.consecutive_duration_tracking] | +| **State transitions** | [state-transitions](modeling-patterns/state-transitions.md) | [`BoundingPatterns.state_transition_bounds()`][flixopt.modeling.BoundingPatterns.state_transition_bounds] | ### Python Class Lookup -| Class | Documentation | Location | -|-------|---------------|----------| -| `Flow` | [Flow](elements/Flow.md) | `flixopt/elements.py:175` | -| `Bus` | [Bus](elements/Bus.md) | `flixopt/elements.py:120` | -| `Storage` | [Storage](elements/Storage.md) | `flixopt/components.py:237` | -| `LinearConverter` | [LinearConverter](elements/LinearConverter.md) | `flixopt/components.py:37` | -| `InvestParameters` | [InvestParameters](features/InvestParameters.md) | `flixopt/interface.py:663` | -| `OnOffParameters` | [OnOffParameters](features/OnOffParameters.md) | `flixopt/interface.py:918` | -| `Piecewise` | [Piecewise](features/Piecewise.md) | `flixopt/interface.py:83` | +| Class | Documentation | API Reference | +|-------|---------------|---------------| +| `Flow` | [Flow](elements/Flow.md) | [`Flow`][flixopt.elements.Flow] | +| `Bus` | [Bus](elements/Bus.md) | [`Bus`][flixopt.elements.Bus] | +| `Storage` | [Storage](elements/Storage.md) | [`Storage`][flixopt.components.Storage] | +| `LinearConverter` | [LinearConverter](elements/LinearConverter.md) | [`LinearConverter`][flixopt.components.LinearConverter] | +| `InvestParameters` | [InvestParameters](features/InvestParameters.md) | [`InvestParameters`][flixopt.interface.InvestParameters] | +| `OnOffParameters` | [OnOffParameters](features/OnOffParameters.md) | [`OnOffParameters`][flixopt.interface.OnOffParameters] | +| `Piecewise` | [Piecewise](features/Piecewise.md) | [`Piecewise`][flixopt.interface.Piecewise] | diff --git a/docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md b/docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md index 122ae14a7..d5821948f 100644 --- a/docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md +++ b/docs/user-guide/mathematical-notation/modeling-patterns/bounds-and-states.md @@ -15,10 +15,10 @@ With: - $\text{lower}$ being the lower bound (constant or time-dependent) - $\text{upper}$ being the upper bound (constant or time-dependent) -**Implementation:** [`BoundingPatterns.basic_bounds()`][flixopt.modeling.BoundingPatterns.basic_bounds] in `flixopt/modeling.py:393` +**Implementation:** [`BoundingPatterns.basic_bounds()`][flixopt.modeling.BoundingPatterns.basic_bounds] **Used in:** -- Storage charge state bounds (see [Storage](../Storage.md)) +- Storage charge state bounds (see [Storage](../elements/Storage.md)) - Flow rate absolute bounds --- @@ -42,7 +42,7 @@ With: - When $s = 0$: variable is forced to zero ($0 \leq v \leq 0$) - When $s = 1$: variable can take values in $[\text{lower}, \text{upper}]$ -**Implementation:** [`BoundingPatterns.bounds_with_state()`][flixopt.modeling.BoundingPatterns.bounds_with_state] in `flixopt/modeling.py:427` +**Implementation:** [`BoundingPatterns.bounds_with_state()`][flixopt.modeling.BoundingPatterns.bounds_with_state] **Used in:** - Flow rates with on/off operation (see [OnOffParameters](../features/OnOffParameters.md)) @@ -66,13 +66,13 @@ With: **Example:** Flow rate bounds - If $v_\text{scale} = P$ (flow size) and $\text{rel}_\text{upper} = 1$ -- Then: $0 \leq p(t_i) \leq P$ (see [Flow](../Flow.md)) +- Then: $0 \leq p(t_i) \leq P$ (see [Flow](../elements/Flow.md)) -**Implementation:** [`BoundingPatterns.scaled_bounds()`][flixopt.modeling.BoundingPatterns.scaled_bounds] in `flixopt/modeling.py:473` +**Implementation:** [`BoundingPatterns.scaled_bounds()`][flixopt.modeling.BoundingPatterns.scaled_bounds] **Used in:** -- Flow rate constraints (see [Flow](../Flow.md) equation 1) -- Storage charge state constraints (see [Storage](../Storage.md) equation 1) +- Flow rate constraints (see [Flow](../elements/Flow.md) equation 1) +- Storage charge state constraints (see [Storage](../elements/Storage.md) equation 1) --- @@ -104,7 +104,7 @@ Where $v_\text{scale,max}$ and $v_\text{scale,min}$ are the maximum and minimum - When $s = 0$: variable is forced to zero - When $s = 1$: variable follows scaled bounds $v_\text{scale} \cdot \text{rel}_\text{lower} \leq v \leq v_\text{scale} \cdot \text{rel}_\text{upper}$ -**Implementation:** [`BoundingPatterns.scaled_bounds_with_state()`][flixopt.modeling.BoundingPatterns.scaled_bounds_with_state] in `flixopt/modeling.py:516` +**Implementation:** [`BoundingPatterns.scaled_bounds_with_state()`][flixopt.modeling.BoundingPatterns.scaled_bounds_with_state] **Used in:** - Flow rates with on/off operation and investment sizing @@ -136,7 +136,7 @@ With: - Bounding intermediate results - Simplifying constraint formulations -**Implementation:** [`ModelingPrimitives.expression_tracking_variable()`][flixopt.modeling.ModelingPrimitives.expression_tracking_variable] in `flixopt/modeling.py:201` +**Implementation:** [`ModelingPrimitives.expression_tracking_variable()`][flixopt.modeling.ModelingPrimitives.expression_tracking_variable] --- @@ -158,7 +158,7 @@ With: - Mutual exclusion of operation and maintenance states - Enforcing single-choice decisions -**Implementation:** [`ModelingPrimitives.mutual_exclusivity_constraint()`][flixopt.modeling.ModelingPrimitives.mutual_exclusivity_constraint] in `flixopt/modeling.py:345` +**Implementation:** [`ModelingPrimitives.mutual_exclusivity_constraint()`][flixopt.modeling.ModelingPrimitives.mutual_exclusivity_constraint] **Used in:** - Operating mode selection diff --git a/docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md b/docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md index da5220134..5d430d28c 100644 --- a/docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md +++ b/docs/user-guide/mathematical-notation/modeling-patterns/duration-tracking.md @@ -102,17 +102,7 @@ With: **Function:** [`ModelingPrimitives.consecutive_duration_tracking()`][flixopt.modeling.ModelingPrimitives.consecutive_duration_tracking] -**Location:** `flixopt/modeling.py:240` - -**Parameters:** -- `state_variable`: Binary state variable $s(t)$ -- `duration_per_step`: Duration increment per time step $\Delta d(t)$ -- `previous_duration`: Initial duration from before optimization period $d_\text{prev}$ -- `minimum_duration` (optional): Minimum required duration $d_\text{min}(t)$ - -**Returns:** -- Duration variable $d(t)$ -- Created constraints +See the API documentation for complete parameter list and usage details. --- diff --git a/docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md b/docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md index b0225c629..dc75a8008 100644 --- a/docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md +++ b/docs/user-guide/mathematical-notation/modeling-patterns/state-transitions.md @@ -61,7 +61,7 @@ s^\text{on}(t), s^\text{off}(t) &\in \{0, 1\} && \forall t \label{eq:transition_ \end{align} $$ -**Implementation:** [`BoundingPatterns.state_transition_bounds()`][flixopt.modeling.BoundingPatterns.state_transition_bounds] in `flixopt/modeling.py:573` +**Implementation:** [`BoundingPatterns.state_transition_bounds()`][flixopt.modeling.BoundingPatterns.state_transition_bounds] --- @@ -89,7 +89,7 @@ With: - When $s^\text{on}(t) = 0$ and $s^\text{off}(t) = 0$: forces $v(t) = v(t-1)$ (no change) - When $s^\text{on}(t) = 1$ or $s^\text{off}(t) = 1$: allows change up to $\pm \Delta v^\text{max}$ -**Implementation:** [`BoundingPatterns.continuous_transition_bounds()`][flixopt.modeling.BoundingPatterns.continuous_transition_bounds] in `flixopt/modeling.py:618` +**Implementation:** [`BoundingPatterns.continuous_transition_bounds()`][flixopt.modeling.BoundingPatterns.continuous_transition_bounds] --- @@ -162,7 +162,7 @@ b^\text{inc}(t), b^\text{dec}(t) &\in \{0, 1\} && \forall t \label{eq:level_comp \end{align} $$ -**Implementation:** [`BoundingPatterns.link_changes_to_level_with_binaries()`][flixopt.modeling.BoundingPatterns.link_changes_to_level_with_binaries] in `flixopt/modeling.py:684` +**Implementation:** [`BoundingPatterns.link_changes_to_level_with_binaries()`][flixopt.modeling.BoundingPatterns.link_changes_to_level_with_binaries] --- From e34c8841d2d50422ba04812a583381da6a71c77e Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 16:48:43 +0200 Subject: [PATCH 12/29] Add infos about model dimensions --- .../mathematical-notation/dimensions.md | 240 ++++++++++++++++++ .../user-guide/mathematical-notation/index.md | 11 +- mkdocs.yml | 1 + 3 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 docs/user-guide/mathematical-notation/dimensions.md diff --git a/docs/user-guide/mathematical-notation/dimensions.md b/docs/user-guide/mathematical-notation/dimensions.md new file mode 100644 index 000000000..1e65e1cfb --- /dev/null +++ b/docs/user-guide/mathematical-notation/dimensions.md @@ -0,0 +1,240 @@ +# Dimensions + +FlixOpt's `FlowSystem` supports multiple dimensions for modeling optimization problems. Understanding these dimensions is crucial for interpreting the mathematical formulations presented in this documentation. + +## The Three Dimensions + +FlixOpt models can have up to three dimensions: + +1. **Time (`time`)** - **MANDATORY** + - Represents the temporal evolution of the system + - Defined via `pd.DatetimeIndex` + - Must contain at least 2 timesteps + - All optimization variables and constraints evolve over time + +2. **Period (`period`)** - **OPTIONAL** + - Represents independent planning periods (e.g., years 2020, 2021, 2022) + - Defined via `pd.Index` with integer values + - Used for multi-period optimization such as investment planning across years + - Each period is independent with its own time series + +3. **Scenario (`scenario`)** - **OPTIONAL** + - Represents alternative futures or uncertainty realizations (e.g., "Base Case", "High Demand") + - Defined via `pd.Index` with any labels + - Scenarios within the same period share the same time dimension + - Used for stochastic optimization or scenario comparison + +--- + +## Dimensional Structure + +**Coordinate System:** + +```python +FlowSystemDimensions = Literal['time', 'period', 'scenario'] + +coords = { + 'time': pd.DatetimeIndex, # Always present + 'period': pd.Index | None, # Optional + 'scenario': pd.Index | None # Optional +} +``` + +**Example:** +```python +import pandas as pd +import flixopt as fx + +timesteps = pd.date_range('2020-01-01', periods=24, freq='h') +scenarios = pd.Index(['Base Case', 'High Demand']) +periods = pd.Index([2020, 2021, 2022]) + +flow_system = fx.FlowSystem( + timesteps=timesteps, + periods=periods, + scenarios=scenarios, + weights=[0.5, 0.5] # Scenario weights +) +``` + +This creates a system with: +- 24 time steps per scenario per period +- 2 scenarios with equal weights (0.5 each) +- 3 periods (years) +- **Total decision space:** 24 × 2 × 3 = 144 time-scenario-period combinations + +--- + +## Independence of Formulations + +**All mathematical formulations in this documentation are independent of whether periods or scenarios are present.** + +The equations shown throughout this documentation (for [Flow](elements/Flow.md), [Storage](elements/Storage.md), [Bus](elements/Bus.md), etc.) are written with only the time index $\text{t}_i$. When periods and/or scenarios are added, **the same equations apply** - they are simply expanded to additional dimensions. + +### How Dimensions Expand Formulations + +**Flow rate bounds** (from [Flow](elements/Flow.md)): + +$$ +\text{P} \cdot \text{p}^{\text{L}}_{\text{rel}}(\text{t}_{i}) \leq p(\text{t}_{i}) \leq \text{P} \cdot \text{p}^{\text{U}}_{\text{rel}}(\text{t}_{i}) +$$ + +This equation remains valid regardless of dimensions: + +| Dimensions Present | Variable Indexing | Interpretation | +|-------------------|-------------------|----------------| +| Time only | $p(\text{t}_i)$ | Flow rate at time $\text{t}_i$ | +| Time + Scenario | $p(\text{t}_i, s)$ | Flow rate at time $\text{t}_i$ in scenario $s$ | +| Time + Period | $p(\text{t}_i, y)$ | Flow rate at time $\text{t}_i$ in period $y$ | +| Time + Period + Scenario | $p(\text{t}_i, y, s)$ | Flow rate at time $\text{t}_i$ in period $y$, scenario $s$ | + +**The mathematical relationship remains identical** - only the indexing expands. + +--- + +## Independence Between Scenarios and Periods + +**There is no interconnection between scenarios and periods, except for shared investment decisions within a period.** + +### Scenario Independence + +Scenarios within a period are **operationally independent**: + +- Each scenario has its own operational variables: $p(\text{t}_i, s_1)$ and $p(\text{t}_i, s_2)$ are independent +- Scenarios cannot exchange energy, information, or resources +- Storage states are separate: $c(\text{t}_i, s_1) \neq c(\text{t}_i, s_2)$ +- Binary states (on/off) are independent: $s(\text{t}_i, s_1)$ vs $s(\text{t}_i, s_2)$ + +Scenarios are connected **only through the objective function** via weights: + +$$ +\min \quad \sum_{s \in \mathcal{S}} w_s \cdot \text{Objective}_s +$$ + +Where: +- $\mathcal{S}$ is the set of scenarios +- $w_s$ is the weight for scenario $s$ +- The optimizer balances performance across scenarios according to their weights + +### Period Independence + +Periods are **completely independent** optimization problems: + +- Each period has separate operational variables +- Each period has separate investment decisions +- No temporal coupling between periods (e.g., storage state at end of period $y$ does not affect period $y+1$) +- Periods cannot exchange resources or information + +Periods are connected **only through weighted aggregation** in the objective: + +$$ +\min \quad \sum_{y \in \mathcal{Y}} w_y \cdot \text{Objective}_y +$$ + +### Investment Decisions: The Exception + +**Within a period, investment decisions are shared across all scenarios:** + +If a period has multiple scenarios, investment variables (e.g., component size) are **scenario-independent** but **operational variables are scenario-specific**. + +**Example - Flow with investment:** + +$$ +v_\text{invest}(y) = s_\text{invest}(y) \cdot \text{size}_\text{fixed} \quad \text{(one decision per period)} +$$ + +$$ +p(\text{t}_i, y, s) \leq v_\text{invest}(y) \cdot \text{rel}_\text{upper} \quad \forall s \in \mathcal{S} \quad \text{(same capacity for all scenarios)} +$$ + +**Interpretation:** +- "We decide once in period $y$ how much capacity to build" +- "This capacity is then operated differently in each scenario $s$ within period $y$" +- "Investment costs are incurred once per period, operational costs are weighted across scenarios" + +This reflects real-world investment under uncertainty: you build capacity once (investment decision), but it operates under different conditions (scenarios). + +--- + +## Dimensional Impact on Objective Function + +The objective function aggregates effects across all dimensions with weights: + +### Time Only +$$ +\min \quad \sum_{\text{t}_i \in \mathcal{T}} \sum_{e \in \mathcal{E}} s_{e}(\text{t}_i) +$$ + +### Time + Scenario +$$ +\min \quad \sum_{s \in \mathcal{S}} w_s \cdot \left( \sum_{\text{t}_i \in \mathcal{T}} \sum_{e \in \mathcal{E}} s_{e}(\text{t}_i, s) \right) +$$ + +### Time + Period +$$ +\min \quad \sum_{y \in \mathcal{Y}} w_y \cdot \left( \sum_{\text{t}_i \in \mathcal{T}} \sum_{e \in \mathcal{E}} s_{e}(\text{t}_i, y) \right) +$$ + +### Time + Period + Scenario (Full Multi-Dimensional) +$$ +\min \quad \sum_{y \in \mathcal{Y}} \sum_{s \in \mathcal{S}} w_{y,s} \cdot \left( \sum_{\text{t}_i \in \mathcal{T}} \sum_{e \in \mathcal{E}} s_{e}(\text{t}_i, y, s) \right) +$$ + +Where: +- $\mathcal{T}$ is the set of time steps +- $\mathcal{E}$ is the set of effects +- $\mathcal{S}$ is the set of scenarios +- $\mathcal{Y}$ is the set of periods +- $s_{e}(\cdots)$ are the effect contributions (costs, emissions, etc.) +- $w_s, w_y, w_{y,s}$ are the dimension weights + +**See [Effects, Penalty & Objective](effects-penalty-objective.md) for complete objective function formulation.** + +--- + +## Weights + +Weights determine the relative importance of scenarios and periods in the objective function. + +**Specification:** + +```python +flow_system = fx.FlowSystem( + timesteps=timesteps, + periods=periods, + scenarios=scenarios, + weights=weights # Shape depends on dimensions +) +``` + +**Weight Dimensions:** + +| Dimensions Present | Weight Shape | Example | Meaning | +|-------------------|--------------|---------|---------| +| Time + Scenario | 1D array of length `n_scenarios` | `[0.3, 0.7]` | Scenario probabilities | +| Time + Period | 1D array of length `n_periods` | `[0.5, 0.3, 0.2]` | Period importance | +| Time + Period + Scenario | 2D array `(n_periods, n_scenarios)` | `[[0.25, 0.25], [0.25, 0.25]]` | Combined weights | + +**Default:** If not specified, all scenarios/periods have equal weight (normalized to sum to 1). + +**Normalization:** Set `normalize_weights=True` in `Calculation` to automatically normalize weights to sum to 1. + +--- + +## Summary Table + +| Dimension | Required? | Independence | Typical Use Case | +|-----------|-----------|--------------|------------------| +| **time** | ✅ Yes | Variables evolve over time via constraints (e.g., storage balance) | All optimization problems | +| **scenario** | ❌ No | Fully independent operations; shared investments within period | Uncertainty modeling, risk assessment | +| **period** | ❌ No | Fully independent; no coupling between periods | Multi-year planning, long-term investment | + +**Key Principle:** All constraints and formulations operate **within** each (period, scenario) combination independently. Only the objective function couples them via weighted aggregation. + +--- + +## See Also + +- [Effects, Penalty & Objective](effects-penalty-objective.md) - How dimensions affect the objective function +- [InvestParameters](features/InvestParameters.md) - Investment decisions across scenarios +- [FlowSystem API][flixopt.flow_system.FlowSystem] - Creating multi-dimensional systems diff --git a/docs/user-guide/mathematical-notation/index.md b/docs/user-guide/mathematical-notation/index.md index 2cc44c879..ae89f3b67 100644 --- a/docs/user-guide/mathematical-notation/index.md +++ b/docs/user-guide/mathematical-notation/index.md @@ -18,7 +18,16 @@ FlixOpt uses the following naming conventions: - The letter $i$ is used to denote an index (e.g., $i=1,\dots,\text n$) - All time steps are denoted by the letter $\text{t}$ (e.g., $\text{t}_0$, $\text{t}_1$, $\text{t}_i$) -## Timesteps +## Dimensions and Time Steps + +FlixOpt supports multi-dimensional optimization with up to three dimensions: **time** (mandatory), **period** (optional), and **scenario** (optional). + +**All mathematical formulations in this documentation are independent of whether periods or scenarios are present.** The equations shown are written with time index $\text{t}_i$ only, but automatically expand to additional dimensions when periods/scenarios are added. + +For complete details on dimensions, their relationships, and influence on formulations, see **[Dimensions](dimensions.md)**. + +### Time Steps + Time steps are defined as a sequence of discrete time steps $\text{t}_i \in \mathcal{T} \quad \text{for} \quad i \in \{1, 2, \dots, \text{n}\}$ (left-aligned in its timespan). From this sequence, the corresponding time intervals $\Delta \text{t}_i \in \Delta \mathcal{T}$ are derived as diff --git a/mkdocs.yml b/mkdocs.yml index 6fab852c1..22873f737 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -15,6 +15,7 @@ nav: - user-guide/index.md - Mathematical Notation: - Overview: user-guide/mathematical-notation/index.md + - Dimensions: user-guide/mathematical-notation/dimensions.md - Elements: - Flow: user-guide/mathematical-notation/elements/Flow.md - Bus: user-guide/mathematical-notation/elements/Bus.md From 3976a010919a6740f551da2d50803dc845d525d3 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 16:52:49 +0200 Subject: [PATCH 13/29] Add infos about model dimensions --- .../mathematical-notation/dimensions.md | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/docs/user-guide/mathematical-notation/dimensions.md b/docs/user-guide/mathematical-notation/dimensions.md index 1e65e1cfb..d1eb336d3 100644 --- a/docs/user-guide/mathematical-notation/dimensions.md +++ b/docs/user-guide/mathematical-notation/dimensions.md @@ -7,22 +7,20 @@ FlixOpt's `FlowSystem` supports multiple dimensions for modeling optimization pr FlixOpt models can have up to three dimensions: 1. **Time (`time`)** - **MANDATORY** - - Represents the temporal evolution of the system - - Defined via `pd.DatetimeIndex` - - Must contain at least 2 timesteps - - All optimization variables and constraints evolve over time - + * Represents the temporal evolution of the system + * Defined via `pd.DatetimeIndex` + * Must contain at least 2 timesteps + * All optimization variables and constraints evolve over time 2. **Period (`period`)** - **OPTIONAL** - - Represents independent planning periods (e.g., years 2020, 2021, 2022) - - Defined via `pd.Index` with integer values - - Used for multi-period optimization such as investment planning across years - - Each period is independent with its own time series - + * Represents independent planning periods (e.g., years 2020, 2021, 2022) + * Defined via `pd.Index` with integer values + * Used for multi-period optimization such as investment planning across years + * Each period is independent with its own time series 3. **Scenario (`scenario`)** - **OPTIONAL** - - Represents alternative futures or uncertainty realizations (e.g., "Base Case", "High Demand") - - Defined via `pd.Index` with any labels - - Scenarios within the same period share the same time dimension - - Used for stochastic optimization or scenario comparison + * Represents alternative futures or uncertainty realizations (e.g., "Base Case", "High Demand") + * Defined via `pd.Index` with any labels + * Scenarios within the same period share the same time dimension + * Used for stochastic optimization or scenario comparison --- @@ -43,6 +41,7 @@ coords = { **Example:** ```python import pandas as pd +import numpy as np import flixopt as fx timesteps = pd.date_range('2020-01-01', periods=24, freq='h') @@ -53,15 +52,15 @@ flow_system = fx.FlowSystem( timesteps=timesteps, periods=periods, scenarios=scenarios, - weights=[0.5, 0.5] # Scenario weights + weights=np.array([0.5, 0.5]) # Scenario weights ) ``` This creates a system with: -- 24 time steps per scenario per period -- 2 scenarios with equal weights (0.5 each) -- 3 periods (years) -- **Total decision space:** 24 × 2 × 3 = 144 time-scenario-period combinations +* 24 time steps per scenario per period +* 2 scenarios with equal weights (0.5 each) +* 3 periods (years) +* **Total decision space:** 24 × 2 × 3 = 144 time-scenario-period combinations --- From 8b27c850b7001ff754465f35272ffcec0675a275 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 4 Oct 2025 17:08:27 +0200 Subject: [PATCH 14/29] Update effects --- .../mathematical-notation/dimensions.md | 19 +- .../effects-penalty-objective.md | 312 +++++++++++++----- 2 files changed, 244 insertions(+), 87 deletions(-) diff --git a/docs/user-guide/mathematical-notation/dimensions.md b/docs/user-guide/mathematical-notation/dimensions.md index d1eb336d3..794bc08b6 100644 --- a/docs/user-guide/mathematical-notation/dimensions.md +++ b/docs/user-guide/mathematical-notation/dimensions.md @@ -130,11 +130,11 @@ $$ \min \quad \sum_{y \in \mathcal{Y}} w_y \cdot \text{Objective}_y $$ -### Investment Decisions: The Exception +### Shared Periodic Decisions: The Exception -**Within a period, investment decisions are shared across all scenarios:** +**Within a period, periodic (investment) decisions are shared across all scenarios:** -If a period has multiple scenarios, investment variables (e.g., component size) are **scenario-independent** but **operational variables are scenario-specific**. +If a period has multiple scenarios, periodic variables (e.g., component size) are **scenario-independent** but **temporal variables are scenario-specific**. **Example - Flow with investment:** @@ -147,11 +147,11 @@ p(\text{t}_i, y, s) \leq v_\text{invest}(y) \cdot \text{rel}_\text{upper} \quad $$ **Interpretation:** -- "We decide once in period $y$ how much capacity to build" -- "This capacity is then operated differently in each scenario $s$ within period $y$" -- "Investment costs are incurred once per period, operational costs are weighted across scenarios" +- "We decide once in period $y$ how much capacity to build" (periodic decision) +- "This capacity is then operated differently in each scenario $s$ within period $y$" (temporal decisions) +- "Periodic effects (investment) are incurred once per period, temporal effects (operational) are weighted across scenarios" -This reflects real-world investment under uncertainty: you build capacity once (investment decision), but it operates under different conditions (scenarios). +This reflects real-world investment under uncertainty: you build capacity once (periodic/investment decision), but it operates under different conditions (temporal/operational decisions per scenario). --- @@ -187,7 +187,10 @@ Where: - $s_{e}(\cdots)$ are the effect contributions (costs, emissions, etc.) - $w_s, w_y, w_{y,s}$ are the dimension weights -**See [Effects, Penalty & Objective](effects-penalty-objective.md) for complete objective function formulation.** +**See [Effects, Penalty & Objective](effects-penalty-objective.md) for complete formulations including:** +- How temporal and periodic effects expand with dimensions +- Detailed objective function for each dimensional case +- Periodic (investment) vs temporal (operational) effect handling --- diff --git a/docs/user-guide/mathematical-notation/effects-penalty-objective.md b/docs/user-guide/mathematical-notation/effects-penalty-objective.md index 5fb3ff382..0759ef5ee 100644 --- a/docs/user-guide/mathematical-notation/effects-penalty-objective.md +++ b/docs/user-guide/mathematical-notation/effects-penalty-objective.md @@ -1,132 +1,286 @@ +# Effects, Penalty & Objective + ## Effects -[`Effects`][flixopt.effects.Effect] are used to allocate things like costs, emissions, or other "effects" occurring in the system. -These arise from so called **Shares**, which originate from **Elements** like [Flows](elements/Flow.md). + +[`Effects`][flixopt.effects.Effect] are used to quantify system-wide impacts like costs, emissions, or resource consumption. These arise from **shares** contributed by **Elements** such as [Flows](elements/Flow.md), [Storage](elements/Storage.md), and other components. **Example:** -[`Flows`][flixopt.elements.Flow] have an attribute called `effects_per_flow_hour`, defining the effect amount of per flow hour. -Associated effects could be: -- costs - given in [€/kWh]... -- ...or emissions - given in [kg/kWh]. -- -Effects are allocated separately for investments and operation. +[`Flows`][flixopt.elements.Flow] have an attribute `effects_per_flow_hour` that defines the effect contribution per flow-hour: +- Costs (€/kWh) +- Emissions (kg CO₂/kWh) +- Primary energy consumption (kWh_primary/kWh) + +Effects are categorized into two domains: + +1. **Temporal effects** - Time-dependent contributions (e.g., operational costs, hourly emissions) +2. **Periodic effects** - Time-independent contributions (e.g., investment costs, fixed annual fees) + +### Multi-Dimensional Effects + +**The formulations below are written with time index $\text{t}_i$ only, but automatically expand when periods and/or scenarios are present.** + +When the FlowSystem has additional dimensions (see [Dimensions](dimensions.md)): + +- **Temporal effects** are indexed by all present dimensions: $E_{e,\text{temp}}(\text{t}_i, y, s)$ +- **Periodic effects** are indexed by period only (scenario-independent within a period): $E_{e,\text{per}}(y)$ +- Effects are aggregated with dimension weights in the objective function -### Shares to Effects +For complete details on how dimensions affect effects and the objective, see [Dimensions](dimensions.md). -$$ \label{eq:Share_invest} -s_{l \rightarrow e, \text{inv}} = \sum_{v \in \mathcal{V}_{l, \text{inv}}} v \cdot \text a_{v \rightarrow e} +--- + +## Effect Formulation + +### Shares from Elements + +Each element $l$ contributes shares to effect $e$ in both temporal and periodic domains: + +**Periodic shares** (time-independent): +$$ \label{eq:Share_periodic} +s_{l \rightarrow e, \text{per}} = \sum_{v \in \mathcal{V}_{l, \text{per}}} v \cdot \text{a}_{v \rightarrow e} $$ -$$ \label{eq:Share_operation} -s_{l \rightarrow e, \text{op}}(\text{t}_i) = \sum_{v \in \mathcal{V}_{l,\text{op}}} v(\text{t}_i) \cdot \text a_{v \rightarrow e}(\text{t}_i) +**Temporal shares** (time-dependent): +$$ \label{eq:Share_temporal} +s_{l \rightarrow e, \text{temp}}(\text{t}_i) = \sum_{v \in \mathcal{V}_{l,\text{temp}}} v(\text{t}_i) \cdot \text{a}_{v \rightarrow e}(\text{t}_i) $$ -With: +Where: -- $\text{t}_i$ being the time step -- $\mathcal{V_l}$ being the set of all optimization variables of element $e$ -- $\mathcal{V}_{l, \text{inv}}$ being the set of all optimization variables of element $e$ related to investment -- $\mathcal{V}_{l, \text{op}}$ being the set of all optimization variables of element $e$ related to operation -- $v$ being an optimization variable of the element $l$ -- $v(\text{t}_i)$ being an optimization variable of the element $l$ at timestep $\text{t}_i$ -- $\text a_{v \rightarrow e}$ being the factor between the optimization variable $v$ to effect $e$ -- $\text a_{v \rightarrow e}(\text{t}_i)$ being the factor between the optimization variable $v$ to effect $e$ for timestep $\text{t}_i$ -- $s_{l \rightarrow e, \text{inv}}$ being the share of element $l$ to the investment part of effect $e$ -- $s_{l \rightarrow e, \text{op}}(\text{t}_i)$ being the share of element $l$ to the operation part of effect $e$ +- $\text{t}_i$ is the time step +- $\mathcal{V}_l$ is the set of all optimization variables of element $l$ +- $\mathcal{V}_{l, \text{per}}$ is the subset of periodic (investment-related) variables +- $\mathcal{V}_{l, \text{temp}}$ is the subset of temporal (operational) variables +- $v$ is an optimization variable +- $v(\text{t}_i)$ is the variable value at timestep $\text{t}_i$ +- $\text{a}_{v \rightarrow e}$ is the effect factor (e.g., €/kW for investment, €/kWh for operation) +- $s_{l \rightarrow e, \text{per}}$ is the periodic share of element $l$ to effect $e$ +- $s_{l \rightarrow e, \text{temp}}(\text{t}_i)$ is the temporal share of element $l$ to effect $e$ -### Shares between different Effects +**Examples:** +- **Periodic share**: Investment cost = $\text{size} \cdot \text{specific\_cost}$ (€/kW) +- **Temporal share**: Operational cost = $\text{flow\_rate}(\text{t}_i) \cdot \text{price}(\text{t}_i)$ (€/kWh) -Furthermore, the Effect $x$ can contribute a share to another Effect ${e} \in \mathcal{E}\backslash x$. -This share is defined by the factor $\text r_{x \rightarrow e}$. +--- -For example, the Effect "CO$_2$ emissions" (unit: kg) -can cause an additional share to Effect "monetary costs" (unit: €). -In this case, the factor $\text a_{x \rightarrow e}$ is the specific CO$_2$ price in €/kg. However, circular references have to be avoided. +### Cross-Effect Contributions -The overall sum of investment shares of an Effect $e$ is given by $\eqref{eq:Effect_invest}$ +Effects can contribute shares to other effects, enabling relationships like carbon pricing or resource accounting. -$$ \label{eq:Effect_invest} -E_{e, \text{inv}} = -\sum_{l \in \mathcal{L}} s_{l \rightarrow e,\text{inv}} + -\sum_{x \in \mathcal{E}\backslash e} E_{x, \text{inv}} \cdot \text{r}_{x \rightarrow e,\text{inv}} -$$ +An effect $x$ can contribute to another effect $e \in \mathcal{E}\backslash x$ via conversion factors: -The overall sum of operation shares is given by $\eqref{eq:Effect_Operation}$ +**Example:** CO₂ emissions (kg) → Monetary costs (€) +- Effect $x$: "CO₂ emissions" (unit: kg) +- Effect $e$: "costs" (unit: €) +- Factor $\text{r}_{x \rightarrow e}$: CO₂ price (€/kg) -$$ \label{eq:Effect_Operation} -E_{e, \text{op}}(\text{t}_{i}) = -\sum_{l \in \mathcal{L}} s_{l \rightarrow e, \text{op}}(\text{t}_i) + -\sum_{x \in \mathcal{E}\backslash e} E_{x, \text{op}}(\text{t}_i) \cdot \text{r}_{x \rightarrow {e},\text{op}}(\text{t}_i) -$$ +**Note:** Circular references must be avoided. + +### Total Effect Calculation -and totals to $\eqref{eq:Effect_Operation_total}$ -$$\label{eq:Effect_Operation_total} -E_{e,\text{op},\text{tot}} = \sum_{i=1}^n E_{e,\text{op}}(\text{t}_{i}) +**Periodic effects** aggregate element shares and cross-effect contributions: + +$$ \label{eq:Effect_periodic} +E_{e, \text{per}} = +\sum_{l \in \mathcal{L}} s_{l \rightarrow e,\text{per}} + +\sum_{x \in \mathcal{E}\backslash e} E_{x, \text{per}} \cdot \text{r}_{x \rightarrow e,\text{per}} $$ -With: +**Temporal effects** at each timestep: -- $\mathcal{L}$ being the set of all elements in the FlowSystem -- $\mathcal{E}$ being the set of all effects in the FlowSystem -- $\text r_{x \rightarrow e, \text{inv}}$ being the factor between the invest part of Effect $x$ and Effect $e$ -- $\text r_{x \rightarrow e, \text{op}}(\text{t}_i)$ being the factor between the operation part of Effect $x$ and Effect $e$ +$$ \label{eq:Effect_temporal} +E_{e, \text{temp}}(\text{t}_{i}) = +\sum_{l \in \mathcal{L}} s_{l \rightarrow e, \text{temp}}(\text{t}_i) + +\sum_{x \in \mathcal{E}\backslash e} E_{x, \text{temp}}(\text{t}_i) \cdot \text{r}_{x \rightarrow {e},\text{temp}}(\text{t}_i) +$$ -- $\text{t}_i$ being the time step -- $s_{l \rightarrow e, \text{inv}}$ being the share of element $l$ to the investment part of effect $e$ -- $s_{l \rightarrow e, \text{op}}(\text{t}_i)$ being the share of element $l$ to the operation part of effect $e$ +**Total temporal effects** (sum over all timesteps): +$$\label{eq:Effect_temporal_total} +E_{e,\text{temp},\text{tot}} = \sum_{i=1}^n E_{e,\text{temp}}(\text{t}_{i}) +$$ -The total of an effect $E_{e}$ is given as $\eqref{eq:Effect_Total}$ +**Total effect** (combining both domains): $$ \label{eq:Effect_Total} -E_{e} = E_{\text{inv},e} +E_{\text{op},\text{tot},e} +E_{e} = E_{e,\text{per}} + E_{e,\text{temp},\text{tot}} $$ +Where: + +- $\mathcal{L}$ is the set of all elements in the FlowSystem +- $\mathcal{E}$ is the set of all effects +- $\text{r}_{x \rightarrow e, \text{per}}$ is the periodic conversion factor from effect $x$ to effect $e$ +- $\text{r}_{x \rightarrow e, \text{temp}}(\text{t}_i)$ is the temporal conversion factor + +--- + ### Constraining Effects -For each variable $v \in \{ E_{e,\text{inv}}, E_{e,\text{op},\text{tot}}, E_e\}$, a lower bound $v^\text{L}$ and upper bound $v^\text{U}$ can be defined as +Effects can be bounded to enforce limits on costs, emissions, or other impacts: + +**Total bounds** (apply to $E_{e,\text{per}}$, $E_{e,\text{temp},\text{tot}}$, or $E_e$): -$$ \label{eq:Bounds_Single} -\text v^\text{L} \leq v \leq \text v^\text{U} +$$ \label{eq:Bounds_Total} +E^\text{L} \leq E \leq E^\text{U} $$ -Furthermore, bounds for the operational shares can be set for each time step +**Temporal bounds per timestep:** -$$ \label{eq:Bounds_Time_Steps} -\text E_{e,\text{op}}^\text{L}(\text{t}_i) \leq E_{e,\text{op}}(\text{t}_i) \leq \text E_{e,\text{op}}^\text{U}(\text{t}_i) +$$ \label{eq:Bounds_Timestep} +E_{e,\text{temp}}^\text{L}(\text{t}_i) \leq E_{e,\text{temp}}(\text{t}_i) \leq E_{e,\text{temp}}^\text{U}(\text{t}_i) $$ +**Implementation:** See [`Effect`][flixopt.effects.Effect] parameters: +- `minimum_temporal`, `maximum_temporal` - Total temporal bounds +- `minimum_per_hour`, `maximum_per_hour` - Hourly temporal bounds +- `minimum_periodic`, `maximum_periodic` - Periodic bounds +- `minimum_total`, `maximum_total` - Combined total bounds + +--- + ## Penalty -Additionally to the user defined [Effects](#effects), a Penalty $\Phi$ is part of every FlixOpt Model. -Its used to prevent unsolvable problems and simplify troubleshooting. -Shares to the penalty can originate from every Element and are constructed similarly to -$\eqref{Share_invest}$ and $\eqref{Share_operation}$. +In addition to user-defined [Effects](#effects), every FlixOpt model includes a **Penalty** term $\Phi$ to: +- Prevent infeasible problems +- Simplify troubleshooting by allowing constraint violations with high cost + +Penalty shares originate from elements, similar to effect shares: $$ \label{eq:Penalty} \Phi = \sum_{l \in \mathcal{L}} \left( s_{l \rightarrow \Phi} +\sum_{\text{t}_i \in \mathcal{T}} s_{l \rightarrow \Phi}(\text{t}_{i}) \right) $$ -With: +Where: + +- $\mathcal{L}$ is the set of all elements +- $\mathcal{T}$ is the set of all timesteps +- $s_{l \rightarrow \Phi}$ is the penalty share from element $l$ -- $\mathcal{L}$ being the set of all elements in the FlowSystem -- $\mathcal{T}$ being the set of all timesteps -- $s_{l \rightarrow \Phi}$ being the share of element $l$ to the penalty +**Current usage:** Penalties primarily occur in [Buses](elements/Bus.md) via the `excess_penalty_per_flow_hour` parameter, which allows nodal imbalances at a high cost. -At the moment, penalties only occur in [Buses](elements/Bus.md) +--- -## Objective +## Objective Function + +The optimization objective minimizes the chosen effect plus any penalties: -The optimization objective of a FlixOpt Model is defined as $\eqref{eq:Objective}$ $$ \label{eq:Objective} -\min(E_{\Omega} + \Phi) +\min \left( E_{\Omega} + \Phi \right) +$$ + +Where: + +- $E_{\Omega}$ is the chosen **objective effect** (see $\eqref{eq:Effect_Total}$) +- $\Phi$ is the [penalty](#penalty) term + +One effect must be designated as the objective via `is_objective=True`. + +### Multi-Criteria Optimization + +This formulation supports multiple optimization approaches: + +**1. Weighted Sum Method** +- The objective effect can incorporate other effects via cross-effect factors +- Example: Minimize costs while including carbon pricing: $\text{CO}_2 \rightarrow \text{costs}$ + +**2. ε-Constraint Method** +- Optimize one effect while constraining others +- Example: Minimize costs subject to $\text{CO}_2 \leq 1000$ kg + +--- + +## Objective with Multiple Dimensions + +When the FlowSystem includes **periods** and/or **scenarios** (see [Dimensions](dimensions.md)), the objective aggregates effects across all dimensions using weights. + +### Time Only (Base Case) + +$$ +\min \quad E_{\Omega} + \Phi = \sum_{\text{t}_i \in \mathcal{T}} E_{\Omega,\text{temp}}(\text{t}_i) + E_{\Omega,\text{per}} + \Phi $$ -With: +Where: +- Temporal effects sum over time: $\sum_{\text{t}_i} E_{\Omega,\text{temp}}(\text{t}_i)$ +- Periodic effects are constant: $E_{\Omega,\text{per}}$ +- Penalty sums over time: $\Phi = \sum_{\text{t}_i} \Phi(\text{t}_i)$ -- $\Omega$ being the chosen **Objective [Effect](#effects)** (see $\eqref{eq:Effect_Total}$) -- $\Phi$ being the [Penalty](#penalty) +--- + +### Time + Scenario + +$$ +\min \quad \sum_{s \in \mathcal{S}} w_s \cdot \left( E_{\Omega}(s) + \Phi(s) \right) +$$ + +Where: +- $\mathcal{S}$ is the set of scenarios +- $w_s$ is the weight for scenario $s$ (typically scenario probability) +- Periodic effects are **shared across scenarios**: $E_{\Omega,\text{per}}$ (same for all $s$) +- Temporal effects are **scenario-specific**: $E_{\Omega,\text{temp}}(s) = \sum_{\text{t}_i} E_{\Omega,\text{temp}}(\text{t}_i, s)$ +- Penalties are **scenario-specific**: $\Phi(s) = \sum_{\text{t}_i} \Phi(\text{t}_i, s)$ + +**Interpretation:** +- Investment decisions (periodic) made once, used across all scenarios +- Operations (temporal) differ by scenario +- Objective balances expected value across scenarios + +--- + +### Time + Period + +$$ +\min \quad \sum_{y \in \mathcal{Y}} w_y \cdot \left( E_{\Omega}(y) + \Phi(y) \right) +$$ + +Where: +- $\mathcal{Y}$ is the set of periods (e.g., years) +- $w_y$ is the weight for period $y$ (typically annual discount factor) +- Each period $y$ has **independent** periodic and temporal effects +- Each period $y$ has **independent** investment and operational decisions + +--- + +### Time + Period + Scenario (Full Multi-Dimensional) + +$$ +\min \quad \sum_{y \in \mathcal{Y}} \left[ w_y \cdot E_{\Omega,\text{per}}(y) + \sum_{s \in \mathcal{S}} w_{y,s} \cdot \left( E_{\Omega,\text{temp}}(y,s) + \Phi(y,s) \right) \right] +$$ -This approach allows for a multi-criteria optimization using both... - - ... the **Weighted Sum** method, as the chosen **Objective Effect** can incorporate other Effects. - - ... the ($\epsilon$-constraint method) by constraining effects. +Where: +- $\mathcal{S}$ is the set of scenarios +- $\mathcal{Y}$ is the set of periods +- $w_y$ is the period weight (for periodic effects) +- $w_{y,s}$ is the combined period-scenario weight (for temporal effects) +- **Periodic effects** $E_{\Omega,\text{per}}(y)$ are period-specific but **scenario-independent** +- **Temporal effects** $E_{\Omega,\text{temp}}(y,s) = \sum_{\text{t}_i} E_{\Omega,\text{temp}}(\text{t}_i, y, s)$ are **fully indexed** +- **Penalties** $\Phi(y,s)$ are **fully indexed** + +**Key Principle:** +- Scenarios and periods are **operationally independent** (no energy/resource exchange) +- Coupled **only through the weighted objective function** +- **Periodic effects within a period are shared across all scenarios** (investment made once per period) +- **Temporal effects are independent per scenario** (different operations under different conditions) + +--- + +## Summary + +| Concept | Formulation | Time Dependency | Dimension Indexing | +|---------|-------------|-----------------|-------------------| +| **Temporal share** | $s_{l \rightarrow e, \text{temp}}(\text{t}_i)$ | Time-dependent | $(t, y, s)$ when present | +| **Periodic share** | $s_{l \rightarrow e, \text{per}}$ | Time-independent | $(y)$ when periods present | +| **Total temporal effect** | $E_{e,\text{temp},\text{tot}} = \sum_{\text{t}_i} E_{e,\text{temp}}(\text{t}_i)$ | Sum over time | Depends on dimensions | +| **Total periodic effect** | $E_{e,\text{per}}$ | Constant | $(y)$ when periods present | +| **Total effect** | $E_e = E_{e,\text{per}} + E_{e,\text{temp},\text{tot}}$ | Combined | Depends on dimensions | +| **Objective** | $\min(E_{\Omega} + \Phi)$ | With weights when multi-dimensional | See formulations above | + +--- + +## See Also + +- [Dimensions](dimensions.md) - Complete explanation of multi-dimensional modeling +- [Flow](elements/Flow.md) - Temporal effect contributions via `effects_per_flow_hour` +- [InvestParameters](features/InvestParameters.md) - Periodic effect contributions via investment +- [Effect API][flixopt.effects.Effect] - Implementation details and parameters From b0711561814f341fd7b9d299e94024281b75de39 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sun, 5 Oct 2025 09:42:13 +0200 Subject: [PATCH 15/29] Use static navigation for API Reference --- flixopt/components.py | 2 +- mkdocs.yml | 23 ++++++++++++++++++++++- scripts/gen_ref_pages.py | 17 +++++++++-------- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/flixopt/components.py b/flixopt/components.py index e8fcdf8b2..b5ab525cb 100644 --- a/flixopt/components.py +++ b/flixopt/components.py @@ -249,7 +249,7 @@ class Storage(Component): Mathematical Formulation: See the complete mathematical model in the documentation: - `Storage.md `_ + [Storage.md](docs/user-guide/mathematical-notation/elements/Storage.md) - Equation (1): Charge state bounds - Equation (3): Storage balance (charge state evolution) diff --git a/mkdocs.yml b/mkdocs.yml index 22873f737..74a8b2728 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,7 +33,28 @@ nav: - State Transitions: user-guide/mathematical-notation/modeling-patterns/state-transitions.md - Examples: examples/ - Contribute: contribute.md - - API Reference: api-reference/ + - API Reference: + - api-reference/index.md + - Aggregation: api-reference/aggregation.md + - Calculation: api-reference/calculation.md + - Commons: api-reference/commons.md + - Components: api-reference/components.md + - Config: api-reference/config.md + - Core: api-reference/core.md + - Effects: api-reference/effects.md + - Elements: api-reference/elements.md + - Features: api-reference/features.md + - Flow System: api-reference/flow_system.md + - Interface: api-reference/interface.md + - IO: api-reference/io.md + - Linear Converters: api-reference/linear_converters.md + - Modeling: api-reference/modeling.md + - Network App: api-reference/network_app.md + - Plotting: api-reference/plotting.md + - Results: api-reference/results.md + - Solvers: api-reference/solvers.md + - Structure: api-reference/structure.md + - Utils: api-reference/utils.md - Release Notes: changelog/ diff --git a/scripts/gen_ref_pages.py b/scripts/gen_ref_pages.py index f2de8a701..3c8eb600a 100644 --- a/scripts/gen_ref_pages.py +++ b/scripts/gen_ref_pages.py @@ -1,4 +1,4 @@ -"""Generate the code reference pages and navigation.""" +"""Generate the code reference pages.""" import sys from pathlib import Path @@ -9,11 +9,11 @@ root = Path(__file__).parent.parent sys.path.insert(0, str(root)) -nav = mkdocs_gen_files.Nav() - src = root / 'flixopt' api_dir = 'api-reference' +generated_files = [] + for path in sorted(src.rglob('*.py')): module_path = path.relative_to(src).with_suffix('') doc_path = path.relative_to(src).with_suffix('.md') @@ -30,10 +30,8 @@ elif parts[-1] == '__main__' or parts[-1].startswith('_'): continue - # Only add to navigation if there are actual parts + # Only generate documentation if there are actual parts if parts: - nav[parts] = doc_path.as_posix() - # Generate documentation file - always using the flixopt prefix with mkdocs_gen_files.open(full_doc_path, 'w') as fd: # Use 'flixopt.' prefix for all module references @@ -41,6 +39,7 @@ fd.write(f'::: {module_id}\n options:\n inherited_members: true\n') mkdocs_gen_files.set_edit_path(full_doc_path, path.relative_to(root)) + generated_files.append(str(full_doc_path)) # Create an index file for the API reference with mkdocs_gen_files.open(f'{api_dir}/index.md', 'w') as index_file: @@ -50,5 +49,7 @@ 'For more information on how to use the classes and functions, see the [User Guide](../user-guide/index.md) section.\n' ) -with mkdocs_gen_files.open(f'{api_dir}/SUMMARY.md', 'w') as nav_file: - nav_file.writelines(nav.build_literate_nav()) +# Print generated files for validation +print(f'Generated {len(generated_files)} API reference files:') +for file in sorted(generated_files): + print(f' - {file}') From 3354b975f1b8c9c1b7b3e6860ee5ebd93aafe442 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sun, 5 Oct 2025 10:05:34 +0200 Subject: [PATCH 16/29] Use links in Docstrings --- flixopt/components.py | 6 +++++- flixopt/elements.py | 8 ++++++++ flixopt/interface.py | 12 ++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/flixopt/components.py b/flixopt/components.py index b5ab525cb..253948aed 100644 --- a/flixopt/components.py +++ b/flixopt/components.py @@ -40,6 +40,10 @@ class LinearConverter(Component): straightforward linear relationships, or piecewise conversion for complex non-linear behavior approximated through piecewise linear segments. + Mathematical Formulation: + See the complete mathematical model in the documentation: + [LinearConverter](../user-guide/mathematical-notation/elements/LinearConverter.md) + Args: label: The label of the Element. Used to identify it in the FlowSystem. inputs: list of input Flows that feed into the converter. @@ -249,7 +253,7 @@ class Storage(Component): Mathematical Formulation: See the complete mathematical model in the documentation: - [Storage.md](docs/user-guide/mathematical-notation/elements/Storage.md) + [Storage](../user-guide/mathematical-notation/elements/Storage.md) - Equation (1): Charge state bounds - Equation (3): Storage balance (charge state evolution) diff --git a/flixopt/elements.py b/flixopt/elements.py index d094ed9e0..2089ee925 100644 --- a/flixopt/elements.py +++ b/flixopt/elements.py @@ -126,6 +126,10 @@ class Bus(Element): physical or logical connection points for energy carriers (electricity, heat, gas) or material flows between different Components. + Mathematical Formulation: + See the complete mathematical model in the documentation: + [Bus](../user-guide/mathematical-notation/elements/Bus.md) + Args: label: The label of the Element. Used to identify it in the FlowSystem. excess_penalty_per_flow_hour: Penalty costs for bus balance violations. @@ -242,6 +246,10 @@ class Flow(Element): - **InvestParameters**: Used for `size` when flow Size is an investment decision - **OnOffParameters**: Used for `on_off_parameters` when flow has discrete states + Mathematical Formulation: + See the complete mathematical model in the documentation: + [Flow](../user-guide/mathematical-notation/elements/Flow.md) + Args: label: Unique identifier for the flow within its component. The full label combines component and flow labels. diff --git a/flixopt/interface.py b/flixopt/interface.py index b3edffffc..dfe5b84a1 100644 --- a/flixopt/interface.py +++ b/flixopt/interface.py @@ -239,6 +239,10 @@ class PiecewiseConversion(Interface): When the equipment operates at a given point, ALL flows scale proportionally within their respective pieces. + Mathematical Formulation: + See the complete mathematical model in the documentation: + [Piecewise](../user-guide/mathematical-notation/features/Piecewise.md) + Args: piecewises: Dictionary mapping flow labels to their Piecewise functions. Keys are flow identifiers (e.g., 'electricity_in', 'heat_out', 'fuel_consumed'). @@ -681,6 +685,10 @@ class InvestParameters(Interface): - **Piecewise Effects**: Non-linear relationships (bulk discounts, learning curves) - **Divestment Effects**: Penalties for not investing (demolition, opportunity costs) + Mathematical Formulation: + See the complete mathematical model in the documentation: + [InvestParameters](../user-guide/mathematical-notation/features/InvestParameters.md) + Args: fixed_size: When specified, creates a binary investment decision at exactly this size. When None, allows continuous sizing between minimum and maximum bounds. @@ -936,6 +944,10 @@ class OnOffParameters(Interface): - **Backup Equipment**: Emergency generators, standby systems - **Process Equipment**: Compressors, pumps with operational constraints + Mathematical Formulation: + See the complete mathematical model in the documentation: + [OnOffParameters](../user-guide/mathematical-notation/features/OnOffParameters.md) + Args: effects_per_switch_on: Costs or impacts incurred for each transition from off state (var_on=0) to on state (var_on=1). Represents startup costs, From cdcc9b77319d41fa0fa4c82c5a314d755ea195d5 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sun, 5 Oct 2025 10:06:32 +0200 Subject: [PATCH 17/29] Fix docs --- .../mathematical-notation/elements/Storage.md | 6 +++--- .../mathematical-notation/features/OnOffParameters.md | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/user-guide/mathematical-notation/elements/Storage.md b/docs/user-guide/mathematical-notation/elements/Storage.md index 259958798..f4b51ca82 100644 --- a/docs/user-guide/mathematical-notation/elements/Storage.md +++ b/docs/user-guide/mathematical-notation/elements/Storage.md @@ -62,10 +62,10 @@ When combined with investment parameters, storage can use: **Python Class:** [`Storage`][flixopt.components.Storage] **Key Parameters:** -- `size`: Storage capacity $\text{C}$ +- `capacity_in_flow_hours`: Storage capacity $\text{C}$ - `relative_loss_per_hour`: Self-discharge rate $\dot{\text{c}}_\text{rel,loss}$ -- `charge_state_start`: Initial charge $c(\text{t}_0)$ -- `charge_state_end`: Final charge target $c(\text{t}_\text{end})$ (optional) +- `initial_charge_state`: Initial charge $c(\text{t}_0)$ +- `minimal_final_charge_state`, `maximal_final_charge_state`: Final charge bounds $c(\text{t}_\text{end})$ (optional) - `eta_charge`, `eta_discharge`: Charging/discharging efficiencies $\eta_\text{in}, \eta_\text{out}$ See the [`Storage`][flixopt.components.Storage] API documentation for complete parameter list and usage examples. diff --git a/docs/user-guide/mathematical-notation/features/OnOffParameters.md b/docs/user-guide/mathematical-notation/features/OnOffParameters.md index 87835400a..1a60c85ea 100644 --- a/docs/user-guide/mathematical-notation/features/OnOffParameters.md +++ b/docs/user-guide/mathematical-notation/features/OnOffParameters.md @@ -109,15 +109,15 @@ With: Enforces minimum runtime once started using duration tracking (see [Duration Tracking](../modeling-patterns/duration-tracking.md#minimum-duration-constraints)): $$\label{eq:onoff_min_on_duration} -d^\text{on}(t) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min} \quad \forall t > 0 +d^\text{on}(t-1) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min} \quad \forall t > 0 $$ With: -- $d^\text{on}(t)$ being the consecutive on-time duration +- $d^\text{on}(t-1)$ being the consecutive on-time duration accumulated before time $t$ - $h^\text{on}_\text{min}$ being the minimum required on-time **Behavior:** -- When shutting down: enforces equipment was on for at least $h^\text{on}_\text{min}$ +- When shutting down at time $t$: enforces equipment was on for at least $h^\text{on}_\text{min}$ prior to the switch - Prevents short cycling and frequent startups **Maximum Consecutive On-Time:** @@ -142,11 +142,11 @@ $$ Enforces minimum shutdown duration before restarting: $$\label{eq:onoff_min_off_duration} -d^\text{off}(t) \geq (s(t) - s(t-1)) \cdot h^\text{off}_\text{min} \quad \forall t > 0 +d^\text{off}(t-1) \geq (s(t) - s(t-1)) \cdot h^\text{off}_\text{min} \quad \forall t > 0 $$ With: -- $d^\text{off}(t)$ being the consecutive off-time duration +- $d^\text{off}(t-1)$ being the consecutive off-time duration accumulated before time $t$ - $h^\text{off}_\text{min}$ being the minimum required off-time **Use cases:** From 2cac8c3b7c6cbc4349be439ce6141d46d7aeadda Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sun, 5 Oct 2025 10:18:53 +0200 Subject: [PATCH 18/29] Fix docs --- docs/user-guide/mathematical-notation/elements/Storage.md | 4 ++-- .../mathematical-notation/features/OnOffParameters.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/user-guide/mathematical-notation/elements/Storage.md b/docs/user-guide/mathematical-notation/elements/Storage.md index f4b51ca82..cd7046592 100644 --- a/docs/user-guide/mathematical-notation/elements/Storage.md +++ b/docs/user-guide/mathematical-notation/elements/Storage.md @@ -25,9 +25,9 @@ $ \dot{ \text c}_\text{rel, loss}(\text{t}_i)$ expresses the "loss fraction per $$ \begin{align*} - c(\text{t}_{i+1}) &= c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i) \cdot \Delta \text{t}_{i}) \\ + c(\text{t}_{i+1}) &= c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i))^{\Delta \text{t}_{i}} \\ &\quad + p_{f_\text{in}}(\text{t}_i) \cdot \Delta \text{t}_i \cdot \eta_\text{in}(\text{t}_i) \\ - &\quad - \frac{p_{f_\text{out}}(\text{t}_i) \cdot \Delta \text{t}_i}{\eta_\text{out}(\text{t}_i)} + &\quad - p_{f_\text{out}}(\text{t}_i) \cdot \Delta \text{t}_i \cdot \eta_\text{out}(\text{t}_i) \tag{3} \end{align*} $$ diff --git a/docs/user-guide/mathematical-notation/features/OnOffParameters.md b/docs/user-guide/mathematical-notation/features/OnOffParameters.md index 1a60c85ea..e2cad0af9 100644 --- a/docs/user-guide/mathematical-notation/features/OnOffParameters.md +++ b/docs/user-guide/mathematical-notation/features/OnOffParameters.md @@ -109,11 +109,11 @@ With: Enforces minimum runtime once started using duration tracking (see [Duration Tracking](../modeling-patterns/duration-tracking.md#minimum-duration-constraints)): $$\label{eq:onoff_min_on_duration} -d^\text{on}(t-1) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min} \quad \forall t > 0 +d^\text{on}(t) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min} \quad \forall t > 0 $$ With: -- $d^\text{on}(t-1)$ being the consecutive on-time duration accumulated before time $t$ +- $d^\text{on}(t)$ being the consecutive on-time duration at time $t$ - $h^\text{on}_\text{min}$ being the minimum required on-time **Behavior:** @@ -142,11 +142,11 @@ $$ Enforces minimum shutdown duration before restarting: $$\label{eq:onoff_min_off_duration} -d^\text{off}(t-1) \geq (s(t) - s(t-1)) \cdot h^\text{off}_\text{min} \quad \forall t > 0 +d^\text{off}(t) \geq (s(t) - s(t-1)) \cdot h^\text{off}_\text{min} \quad \forall t > 0 $$ With: -- $d^\text{off}(t-1)$ being the consecutive off-time duration accumulated before time $t$ +- $d^\text{off}(t)$ being the consecutive off-time duration at time $t$ - $h^\text{off}_\text{min}$ being the minimum required off-time **Use cases:** From 887e5ce8bf5c15c9011baf1f6ecb7b17e4d24bec Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sun, 5 Oct 2025 11:35:47 +0200 Subject: [PATCH 19/29] Tighten docstrings --- .../mathematical-notation/elements/Flow.md | 2 + flixopt/components.py | 73 ++++++++----------- flixopt/elements.py | 48 ++++-------- flixopt/interface.py | 38 ++++------ 4 files changed, 63 insertions(+), 98 deletions(-) diff --git a/docs/user-guide/mathematical-notation/elements/Flow.md b/docs/user-guide/mathematical-notation/elements/Flow.md index 6b03fa434..5914ba911 100644 --- a/docs/user-guide/mathematical-notation/elements/Flow.md +++ b/docs/user-guide/mathematical-notation/elements/Flow.md @@ -1,3 +1,5 @@ +# Flow + The flow_rate is the main optimization variable of the Flow. It's limited by the size of the Flow and relative bounds \eqref{eq:flow_rate}. $$ \label{eq:flow_rate} diff --git a/flixopt/components.py b/flixopt/components.py index 253948aed..9af6be153 100644 --- a/flixopt/components.py +++ b/flixopt/components.py @@ -266,38 +266,26 @@ class Storage(Component): - ``eta_discharge`` → η_out (discharging efficiency) Args: - label: The label of the Element. Used to identify it in the FlowSystem. - charging: Incoming flow for loading the storage. Represents energy or material - flowing into the storage system. - discharging: Outgoing flow for unloading the storage. Represents energy or - material flowing out of the storage system. - capacity_in_flow_hours: Nominal capacity/size of the storage in flow-hours - (e.g., kWh for electrical storage, m³ or kg for material storage). Can be a scalar - for fixed capacity or InvestParameters for optimization. - relative_minimum_charge_state: Minimum relative charge state (0-1 range). - Prevents deep discharge that could damage equipment. Default is 0. - relative_maximum_charge_state: Maximum relative charge state (0-1 range). - Accounts for practical capacity limits, safety margins or temperature impacts. Default is 1. - initial_charge_state: Storage charge state at the beginning of the time horizon. - Can be numeric value or 'lastValueOfSim', which is recommended for if the initial start state is not known. - Default is 0. - minimal_final_charge_state: Minimum absolute charge state required at the end of the time horizon. - maximal_final_charge_state: Maximum absolute charge state allowed at the end of the time horizon. - relative_minimum_final_charge_state: Minimum relative charge state required at the end of the time horizon. - Defaults to the last value of the relative_minimum_charge_state. - relative_maximum_final_charge_state: Maximum relative charge state allowed at the end of the time horizon. - Defaults to the last value of the relative_maximum_charge_state. - eta_charge: Charging efficiency factor (0-1 range). Accounts for conversion - losses during charging. Default is 1 (perfect efficiency). - eta_discharge: Discharging efficiency factor (0-1 range). Accounts for - conversion losses during discharging. Default is 1 (perfect efficiency). - relative_loss_per_hour: Self-discharge rate per hour (typically 0-0.1 range). - Represents standby losses, leakage, or degradation. Default is 0. - prevent_simultaneous_charge_and_discharge: If True, prevents charging and - discharging simultaneously. Increases binary variables but improves model - realism and solution interpretation. Default is True. - meta_data: Used to store additional information about the Element. Not used - internally, but saved in results. Only use Python native types. + label: Element identifier used in the FlowSystem. + charging: Incoming flow for loading the storage. + discharging: Outgoing flow for unloading the storage. + capacity_in_flow_hours: Storage capacity in flow-hours (kWh, m³, kg). + Scalar for fixed size or InvestParameters for optimization. + relative_minimum_charge_state: Minimum charge state (0-1). Default: 0. + relative_maximum_charge_state: Maximum charge state (0-1). Default: 1. + initial_charge_state: Charge at start. Numeric or 'lastValueOfSim'. Default: 0. + minimal_final_charge_state: Minimum absolute charge required at end (optional). + maximal_final_charge_state: Maximum absolute charge allowed at end (optional). + relative_minimum_final_charge_state: Minimum relative charge at end. + Defaults to last value of relative_minimum_charge_state. + relative_maximum_final_charge_state: Maximum relative charge at end. + Defaults to last value of relative_maximum_charge_state. + eta_charge: Charging efficiency (0-1). Default: 1. + eta_discharge: Discharging efficiency (0-1). Default: 1. + relative_loss_per_hour: Self-discharge per hour (0-0.1). Default: 0. + prevent_simultaneous_charge_and_discharge: Prevent charging and discharging + simultaneously. Adds binary variables. Default: True. + meta_data: Additional information stored in results. Python native types only. Examples: Battery energy storage system: @@ -373,20 +361,19 @@ class Storage(Component): ``` Note: - Charge state evolution follows the equation: - charge[t+1] = charge[t] × (1-loss_rate)^hours_per_step + - charge_flow[t] × eta_charge × hours_per_step - - discharge_flow[t] × hours_per_step / eta_discharge + **Mathematical formulation**: See [Storage](../user-guide/mathematical-notation/elements/Storage.md) + for charge state evolution equations and balance constraints. - All efficiency parameters (eta_charge, eta_discharge) are dimensionless (0-1 range). - The relative_loss_per_hour parameter represents exponential decay per hour. + **Efficiency parameters** (eta_charge, eta_discharge) are dimensionless (0-1 range). + The relative_loss_per_hour represents exponential decay per hour. - When prevent_simultaneous_charge_and_discharge is True, binary variables are - created to enforce mutual exclusivity, which increases solution time but - prevents unrealistic simultaneous charging and discharging. + **Binary variables**: When prevent_simultaneous_charge_and_discharge is True, binary + variables enforce mutual exclusivity, increasing solution time but preventing unrealistic + simultaneous charging and discharging. - Initial and final charge state constraints use absolute values (not relative), - matching the capacity_in_flow_hours units. + **Units**: Flow rates and charge states are related by the concept of 'flow hours' (=flow_rate * time). + With flow rates in kW, the charge state is therefore (usually) kWh. + With flow rates in m3/h, the charge state is therefore in m3. """ def __init__( diff --git a/flixopt/elements.py b/flixopt/elements.py index 2089ee925..f911b6646 100644 --- a/flixopt/elements.py +++ b/flixopt/elements.py @@ -251,38 +251,22 @@ class Flow(Element): [Flow](../user-guide/mathematical-notation/elements/Flow.md) Args: - label: Unique identifier for the flow within its component. - The full label combines component and flow labels. - bus: Label of the bus this flow connects to. Must match a bus in the FlowSystem. - size: Flow capacity or nominal rating. Can be: - - Scalar value for fixed capacity - - InvestParameters for investment-based sizing decisions - - None to use large default value (CONFIG.modeling.BIG) - relative_minimum: Minimum flow rate as fraction of size. - Example: 0.2 means flow cannot go below 20% of rated capacity. - relative_maximum: Maximum flow rate as fraction of size (typically 1.0). - Values >1.0 allow temporary overload operation. - load_factor_min: Minimum average utilization over the time horizon (0-1). - Calculated as total flow hours divided by (size × total time). - load_factor_max: Maximum average utilization over the time horizon (0-1). - Useful for equipment duty cycle limits or maintenance scheduling. - effects_per_flow_hour: Operational costs and impacts per unit of flow-time. - Dictionary mapping effect names to unit costs (e.g., fuel costs, emissions). - on_off_parameters: Binary operation constraints using OnOffParameters. - Enables modeling of startup costs, minimum run times, cycling limits. - Only relevant when relative_minimum > 0 or discrete operation is required. - flow_hours_total_max: Maximum cumulative flow-hours over time horizon. - Alternative to load_factor_max for absolute energy/material limits. - flow_hours_total_min: Minimum cumulative flow-hours over time horizon. - Alternative to load_factor_min for contractual or operational requirements. - fixed_relative_profile: Predetermined flow pattern as fraction of size. - When specified, flow rate becomes: size × fixed_relative_profile(t). - Used for: demand profiles, renewable generation, fixed schedules. - previous_flow_rate: Initial flow state for startup/shutdown dynamics. - Used with on_off_parameters to determine initial on/off status. - If None, assumes flow was off in previous time period. - meta_data: Additional information stored with results but not used in optimization. - Must contain only Python native types (dict, list, str, int, float, bool). + label: Unique flow identifier within its component. + bus: Bus label this flow connects to. + size: Flow capacity. Scalar, InvestParameters, or None (uses CONFIG.modeling.BIG). + relative_minimum: Minimum flow rate as fraction of size (0-1). Default: 0. + relative_maximum: Maximum flow rate as fraction of size. Default: 1. + load_factor_min: Minimum average utilization (0-1). Default: 0. + load_factor_max: Maximum average utilization (0-1). Default: 1. + effects_per_flow_hour: Operational costs/impacts per flow-hour. + Dict mapping effect names to values (e.g., {'cost': 45, 'CO2': 0.8}). + on_off_parameters: Binary operation constraints (OnOffParameters). Default: None. + flow_hours_total_max: Maximum cumulative flow-hours. Alternative to load_factor_max. + flow_hours_total_min: Minimum cumulative flow-hours. Alternative to load_factor_min. + fixed_relative_profile: Predetermined pattern as fraction of size. + Flow rate = size × fixed_relative_profile(t). + previous_flow_rate: Initial flow state for on/off dynamics. Default: None (off). + meta_data: Additional info stored in results. Python native types only. Examples: Basic power flow with fixed capacity: diff --git a/flixopt/interface.py b/flixopt/interface.py index dfe5b84a1..c3247ee50 100644 --- a/flixopt/interface.py +++ b/flixopt/interface.py @@ -690,29 +690,21 @@ class InvestParameters(Interface): [InvestParameters](../user-guide/mathematical-notation/features/InvestParameters.md) Args: - fixed_size: When specified, creates a binary investment decision at exactly - this size. When None, allows continuous sizing between minimum and maximum bounds. - minimum_size: Lower bound for continuous sizing decisions. Defaults to a small - positive value (CONFIG.modeling.EPSILON) to avoid numerical issues. - Ignored when fixed_size is specified. - maximum_size: Upper bound for continuous sizing decisions. Defaults to a large - value (CONFIG.modeling.BIG) representing unlimited capacity. - Ignored when fixed_size is specified. - optional: Controls whether investment is required. When True (default), - optimization can choose not to invest. When False, forces investment - to occur (useful for mandatory upgrades or replacement decisions). - fix_effects: Fixed costs incurred once if investment is made, regardless - of size. Dictionary mapping effect names to values - (e.g., {'cost': 10000, 'CO2_construction': 500}). - specific_effects: Variable costs proportional to investment size, representing - per-unit costs (€/kW, €/m²). Dictionary mapping effect names to unit values - (e.g., {'cost': 1200, 'steel_required': 0.5}). - piecewise_effects: Non-linear cost relationships using PiecewiseEffects for - economies of scale, learning curves, or threshold effects. Can be combined - with fix_effects and specific_effects. - divest_effects: Costs incurred if the investment is NOT made, such as - demolition of existing equipment, contractual penalties, or lost opportunities. - Dictionary mapping effect names to values. + fixed_size: Creates binary decision at this exact size. None allows continuous sizing. + minimum_size: Lower bound for continuous sizing. Default: CONFIG.modeling.EPSILON. + Ignored if fixed_size is specified. + maximum_size: Upper bound for continuous sizing. Default: CONFIG.modeling.BIG. + Ignored if fixed_size is specified. + optional: If True, can choose not to invest. If False, investment is mandatory. + Default: True. + fix_effects: Fixed costs if investment is made, regardless of size. + Dict: {'effect_name': value} (e.g., {'cost': 10000}). + specific_effects: Variable costs proportional to size (per-unit costs). + Dict: {'effect_name': value/unit} (e.g., {'cost': 1200}). + piecewise_effects: Non-linear costs using PiecewiseEffects. + Combinable with fix_effects and specific_effects. + divest_effects: Costs incurred if NOT investing (demolition, penalties). + Dict: {'effect_name': value}. Cost Annualization Requirements: All cost values must be properly weighted to match the optimization model's time horizon. From 0def25f4a7e0e0f4e59771a745057255e33e406a Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Mon, 6 Oct 2025 08:59:46 +0200 Subject: [PATCH 20/29] Improve README.md --- README.md | 121 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index edb77e74d..b81067e00 100644 --- a/README.md +++ b/README.md @@ -8,84 +8,113 @@ --- -## 🚀 Purpose +## 🎯 Vision -**flixopt** is a Python-based optimization framework designed to tackle energy and material flow problems using mixed-integer linear programming (MILP). +**FlixOpt aims to be the most accessible and flexible Python framework for energy and material flow optimization.** -**flixopt** bridges the gap between high-level energy systems models like [FINE](https://github.com/FZJ-IEK3-VSA/FINE) used for design and (multi-period) investment decisions and low-level dispatch optimization tools used for operation decisions. +We believe that optimization modeling should be **approachable for beginners** yet **powerful for experts**. Too often, frameworks force you to choose between ease of use and flexibility. FlixOpt refuses this compromise. -**flixopt** leverages the fast and efficient [linopy](https://github.com/PyPSA/linopy/) for the mathematical modeling and [xarray](https://github.com/pydata/xarray) for data handling. +### Where We're Going -**flixopt** provides a user-friendly interface with options for advanced users. +**Short-term goals:** +- **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization +- **Enhanced component library**: More pre-built components for common use cases (sector coupling, hydrogen systems, thermal networks) +- **Better debugging tools**: Clear error messages, infeasibility diagnostics, and model inspection capabilities -It was originally developed by [TU Dresden](https://github.com/gewv-tu-dresden) as part of the SMARTBIOGRID project, funded by the German Federal Ministry for Economic Affairs and Energy (FKZ: 03KB159B). Building on the Matlab-based flixOptMat framework (developed in the FAKS project), FlixOpt also incorporates concepts from [oemof/solph](https://github.com/oemof/oemof-solph). +**Long-term vision:** +- **Universal flow modeling**: Apply FlixOpt beyond energy systems to supply chains, water networks, production planning, and any domain involving flows and conversions +- **Seamless integration**: First-class support for coupling with simulation tools, databases, and existing energy system models +- **Scale independence**: From single buildings to national energy systems, with smart algorithms that adapt to problem size +- **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions ---- - -## 🌟 Key Features +### Why FlixOpt Exists -- **High-level Interface** with low-level control - - User-friendly interface for defining flow systems - - Pre-defined components like CHP, Heat Pump, Cooling Tower, etc. - - Fine-grained control for advanced configurations +FlixOpt bridges a critical gap: between high-level strategic models (like [FINE](https://github.com/FZJ-IEK3-VSA/FINE)) used for long-term planning and low-level dispatch tools for operational decisions. We provide the **sweet spot** for: -- **Investment Optimization** - - Combined dispatch and investment optimization - - Size optimization and discrete investment decisions - - Combined with On/Off variables and constraints +- **Researchers** who need to prototype quickly but may require deep customization later +- **Engineers** who want reliable, tested components without black-box abstractions +- **Students** learning optimization who benefit from clear, Pythonic interfaces +- **Practitioners** who need to move from model to production-ready results -- **Effects, not only Costs --> Multi-criteria Optimization** - - flixopt abstracts costs as so called 'Effects'. This allows to model costs, CO2-emissions, primary-energy-demand or area-demand at the same time. - - Effects can interact with each other(e.g., specific CO2 costs) - - Any of these `Effects` can be used as the optimization objective. - - A **Weigted Sum** of Effects can be used as the optimization objective. - - Every Effect can be constrained ($\epsilon$-constraint method). +Built on modern foundations ([linopy](https://github.com/PyPSA/linopy/) and [xarray](https://github.com/pydata/xarray)), FlixOpt delivers both **performance** and **transparency**. You can inspect everything, extend anything, and trust that your model does exactly what you designed. -- **Calculation Modes** - - **Full** - Solve the model with highest accuracy and computational requirements. - - **Segmented** - Speed up solving by using a rolling horizon. - - **Aggregated** - Speed up solving by identifying typical periods using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam). Suitable for large models. +Originally developed at [TU Dresden](https://github.com/gewv-tu-dresden) for the SMARTBIOGRID project (funded by the German Federal Ministry for Economic Affairs and Energy, FKZ: 03KB159B), FlixOpt has evolved from the Matlab-based flixOptMat framework while incorporating the best ideas from [oemof/solph](https://github.com/oemof/oemof-solph). --- -## 📦 Installation +## 🌟 What Makes FlixOpt Different -Install FlixOpt via pip. -`pip install flixopt` -With [HiGHS](https://github.com/ERGO-Code/HiGHS?tab=readme-ov-file) included out of the box, flixopt is ready to use.. +### Start Simple, Scale Complex +Define a working model in minutes with high-level components, then drill down to fine-grained control when needed. No rewriting, no framework switching. -We recommend installing FlixOpt with all dependencies, which enables additional features like interactive network visualizations ([pyvis](https://github.com/WestHealth/pyvis)) and time series aggregation ([tsam](https://github.com/FZJ-IEK3-VSA/tsam)). -`pip install "flixopt[full]"` +```python +import flixopt as fx ---- +# Simple start +boiler = fx.Boiler("Boiler", eta=0.9, ...) + +# Advanced control when needed - extend with native linopy +boiler.model.add_constraints(custom_constraint, name="my_constraint") +``` -## 📚 Documentation +### Multi-Criteria Optimization Done Right +Model costs, emissions, resource use, and any custom metric simultaneously as **Effects**. Optimize any single Effect, use weighted combinations, or apply ε-constraints: -The documentation is available at [https://flixopt.github.io/flixopt/latest/](https://flixopt.github.io/flixopt/latest/) +```python +costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={'CO2': 180}) # 180 €/tCO2 +co2 = fx.Effect('CO2', 'kg', 'Emissions', maximum_periodic=50000) +``` + +### Performance at Any Scale +Choose the right calculation mode for your problem: +- **Full** - Maximum accuracy for smaller problems +- **Segmented** - Rolling horizon for large time series +- **Aggregated** - Typical periods using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam) for massive models + +### Built for Reproducibility +Every result file is self-contained with complete model information. Load it months later and know exactly what you optimized. Export to NetCDF, share with colleagues, archive for compliance. --- -## 🎯️ Solver Integration +## 🚀 Quick Start + +```bash +pip install flixopt +``` -By default, FlixOpt uses the open-source solver [HiGHS](https://highs.dev/) which is installed by default. However, it is compatible with additional solvers such as: +That's it. FlixOpt comes with the [HiGHS](https://highs.dev/) solver included - you're ready to optimize. +Many more solvers are supported (gurobi, cplex, cbc, glpk, ...) -- [Gurobi](https://www.gurobi.com/) -- [CBC](https://github.com/coin-or/Cbc) -- [GLPK](https://www.gnu.org/software/glpk/) -- [CPLEX](https://www.ibm.com/analytics/cplex-optimizer) +For additional features (interactive network visualization, time series aggregation): +```bash +pip install "flixopt[full]" +``` -For detailed licensing and installation instructions, refer to the respective solver documentation. +**Next steps:** +- 📚 [Full Documentation](https://flixopt.github.io/flixopt/latest/) +- 💡 [Examples](https://flixopt.github.io/flixopt/latest/examples/) +- 🔧 [API Reference](https://flixopt.github.io/flixopt/latest/api-reference/) --- -## 🛠 Development Setup -Look into our docs for [development setup](https://flixopt.github.io/flixopt/latest/contribute/) +## 🤝 Contributing + +FlixOpt thrives on community input. Whether you're fixing bugs, adding components, improving docs, or sharing use cases - we welcome your contributions. + +See our [contribution guide](https://flixopt.github.io/flixopt/latest/contribute/) to get started. --- ## 📖 Citation -If you use FlixOpt in your research or project, please cite the following: +If FlixOpt supports your research or project, please cite: - **Main Citation:** [DOI:10.18086/eurosun.2022.04.07](https://doi.org/10.18086/eurosun.2022.04.07) - **Short Overview:** [DOI:10.13140/RG.2.2.14948.24969](https://doi.org/10.13140/RG.2.2.14948.24969) + +--- + +## 📄 License + +MIT License - See [LICENSE](https://github.com/flixopt/flixopt/blob/main/LICENSE) for details. From c787792a04e1f1f4c1c87ac624dd15080baa6600 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Mon, 6 Oct 2025 09:50:56 +0200 Subject: [PATCH 21/29] Improve README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b81067e00..f3bf08a76 100644 --- a/README.md +++ b/README.md @@ -22,19 +22,22 @@ We believe that optimization modeling should be **approachable for beginners** y - **Better debugging tools**: Clear error messages, infeasibility diagnostics, and model inspection capabilities **Long-term vision:** -- **Universal flow modeling**: Apply FlixOpt beyond energy systems to supply chains, water networks, production planning, and any domain involving flows and conversions +- **Showcase universal applicability**: FlixOpt already handles any flow-based system (supply chains, water networks, production planning, chemical processes) - we need more examples and domain-specific component libraries to demonstrate this - **Seamless integration**: First-class support for coupling with simulation tools, databases, and existing energy system models - **Scale independence**: From single buildings to national energy systems, with smart algorithms that adapt to problem size -- **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions +- **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions across all application domains ### Why FlixOpt Exists -FlixOpt bridges a critical gap: between high-level strategic models (like [FINE](https://github.com/FZJ-IEK3-VSA/FINE)) used for long-term planning and low-level dispatch tools for operational decisions. We provide the **sweet spot** for: +FlixOpt is a **general-purpose framework for modeling any system involving flows and conversions** - energy, materials, fluids, goods, or data. While energy systems are our primary focus, the same mathematical foundation applies to supply chains, water networks, production lines, and more. + +We bridge the gap between high-level strategic models (like [FINE](https://github.com/FZJ-IEK3-VSA/FINE)) for long-term planning and low-level dispatch tools for operations. FlixOpt is the **sweet spot** for: - **Researchers** who need to prototype quickly but may require deep customization later - **Engineers** who want reliable, tested components without black-box abstractions - **Students** learning optimization who benefit from clear, Pythonic interfaces - **Practitioners** who need to move from model to production-ready results +- **Domain experts** from any field where things flow, transform, and need optimizing Built on modern foundations ([linopy](https://github.com/PyPSA/linopy/) and [xarray](https://github.com/pydata/xarray)), FlixOpt delivers both **performance** and **transparency**. You can inspect everything, extend anything, and trust that your model does exactly what you designed. From 48df8de3036052147139e812181feedfc81a04fa Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Mon, 6 Oct 2025 13:42:26 +0200 Subject: [PATCH 22/29] Improve docs --- docs/index.md | 73 ++++++++++++++++++++++++++++++++++------ docs/user-guide/index.md | 43 +++++++++++++++++------ 2 files changed, 96 insertions(+), 20 deletions(-) diff --git a/docs/index.md b/docs/index.md index 04020639e..a59d10b66 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,24 +1,77 @@ # FlixOpt -**FlixOpt** is a Python-based optimization framework designed to tackle energy and material flow problems using mixed-integer linear programming (MILP). +## 🎯 Vision -It borrows concepts from both [FINE](https://github.com/FZJ-IEK3-VSA/FINE) and [oemof.solph](https://github.com/oemof/oemof-solph). +**FlixOpt aims to be the most accessible and flexible Python framework for energy and material flow optimization.** -## Why FlixOpt? +We believe that optimization modeling should be **approachable for beginners** yet **powerful for experts**. Too often, frameworks force you to choose between ease of use and flexibility. FlixOpt refuses this compromise. -FlixOpt is designed as a general-purpose optimization framework to get your model running quickly, without sacrificing flexibility down the road: +### Where We're Going -- **Easy to Use API**: FlixOpt provides a Pythonic, object-oriented interface that makes mathematical optimization more accessible to Python developers. +**Short-term goals:** -- **Approachable Learning Curve**: Designed to be accessible from the start, with options for more detailed models down the road. +- **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization +- **Enhanced component library**: More pre-built components for common use cases (sector coupling, hydrogen systems, thermal networks) +- **Better debugging tools**: Clear error messages, infeasibility diagnostics, and model inspection capabilities -- **Domain Independence**: While frameworks like oemof and FINE excel at energy system modeling with domain-specific components, FlixOpt offers a more general mathematical approach that can be applied across different fields. +**Long-term vision:** -- **Extensibility**: Easily add custom constraints or variables to any FlixOpt Model using [linopy](https://github.com/PyPSA/linopy). Tailor any FlixOpt model to your specific needs without loosing the convenience of the framework. +- **Showcase universal applicability**: FlixOpt already handles any flow-based system (supply chains, water networks, production planning, chemical processes) - we need more examples and domain-specific component libraries to demonstrate this +- **Seamless integration**: First-class support for coupling with simulation tools, databases, and existing energy system models +- **Scale independence**: From single buildings to national energy systems, with smart algorithms that adapt to problem size +- **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions across all application domains -- **Solver Agnostic**: Work with different solvers through a consistent interface. +### Why FlixOpt Exists -- **Results File I/O**: Built to analyze results independent of running the optimization. +FlixOpt is a **general-purpose framework for modeling any system involving flows and conversions** - energy, materials, fluids, goods, or data. While energy systems are our primary focus, the same mathematical foundation applies to supply chains, water networks, production lines, and more. + +We bridge the gap between high-level strategic models (like [FINE](https://github.com/FZJ-IEK3-VSA/FINE)) for long-term planning and low-level dispatch tools for operations. FlixOpt is the **sweet spot** for: + +- **Researchers** who need to prototype quickly but may require deep customization later +- **Engineers** who want reliable, tested components without black-box abstractions +- **Students** learning optimization who benefit from clear, Pythonic interfaces +- **Practitioners** who need to move from model to production-ready results +- **Domain experts** from any field where things flow, transform, and need optimizing + +Built on modern foundations ([linopy](https://github.com/PyPSA/linopy/) and [xarray](https://github.com/pydata/xarray)), FlixOpt delivers both **performance** and **transparency**. You can inspect everything, extend anything, and trust that your model does exactly what you designed. + +Originally developed at [TU Dresden](https://github.com/gewv-tu-dresden) for the SMARTBIOGRID project (funded by the German Federal Ministry for Economic Affairs and Energy, FKZ: 03KB159B), FlixOpt has evolved from the Matlab-based flixOptMat framework while incorporating the best ideas from [oemof/solph](https://github.com/oemof/oemof-solph). + +--- + +## What Makes FlixOpt Different + +### Start Simple, Scale Complex +Define a working model in minutes with high-level components, then drill down to fine-grained control when needed. No rewriting, no framework switching. + +```python +import flixopt as fx + +# Simple start +boiler = fx.Boiler("Boiler", eta=0.9, ...) + +# Advanced control when needed - extend with native linopy +boiler.model.add_constraints(custom_constraint, name="my_constraint") +``` + +### Multi-Criteria Optimization Done Right +Model costs, emissions, resource use, and any custom metric simultaneously as **Effects**. Optimize any single Effect, use weighted combinations, or apply ε-constraints: + +```python +costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={'CO2': 180}) # 180 €/tCO2 +co2 = fx.Effect('CO2', 'kg', 'Emissions', maximum_periodic=50000) +``` + +### Performance at Any Scale +Choose the right calculation mode for your problem: + +- **Full** - Maximum accuracy for smaller problems +- **Segmented** - Rolling horizon for large time series +- **Aggregated** - Typical periods using [TSAM](https://github.com/FZJ-IEK3-VSA/tsam) for massive models + +### Built for Reproducibility +Every result file is self-contained with complete model information. Load it months later and know exactly what you optimized. Export to NetCDF, share with colleagues, archive for compliance.
![FlixOpt Conceptual Usage](./images/architecture_flixOpt.png) diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md index bc1738997..df97bf768 100644 --- a/docs/user-guide/index.md +++ b/docs/user-guide/index.md @@ -1,6 +1,8 @@ # FlixOpt Concepts -FlixOpt is built around a set of core concepts that work together to represent and optimize energy and material flow systems. This page provides a high-level overview of these concepts and how they interact. +FlixOpt is built around a set of core concepts that work together to represent and optimize **any system involving flows and conversions** - whether that's energy systems, material flows, supply chains, water networks, or production processes. + +This page provides a high-level overview of these concepts and how they interact. ## Core Concepts @@ -45,28 +47,49 @@ Examples: ### Components -[`Component`][flixopt.elements.Component] objects usually represent physical entities in your system that interact with [`Flows`][flixopt.elements.Flow]. They include: +[`Component`][flixopt.elements.Component] objects usually represent physical entities in your system that interact with [`Flows`][flixopt.elements.Flow]. The generic component types work across all domains: - [`LinearConverters`][flixopt.components.LinearConverter] - Converts input flows to output flows with (piecewise) linear relationships + - *Energy: boilers, heat pumps, turbines* + - *Manufacturing: assembly lines, processing equipment* + - *Chemistry: reactors, separators* - [`Storages`][flixopt.components.Storage] - Stores energy or material over time -- [`Sources`][flixopt.components.Source] / [`Sinks`][flixopt.components.Sink] / [`SourceAndSinks`][flixopt.components.SourceAndSink] - Produce or consume flows. They are usually used to model external demands or supplies. + - *Energy: batteries, thermal storage, gas storage* + - *Logistics: warehouses, buffer inventory* + - *Water: reservoirs, tanks* +- [`Sources`][flixopt.components.Source] / [`Sinks`][flixopt.components.Sink] / [`SourceAndSinks`][flixopt.components.SourceAndSink] - Produce or consume flows + - *Energy: demands, renewable generation* + - *Manufacturing: raw material supply, product demand* + - *Supply chain: suppliers, customers* - [`Transmissions`][flixopt.components.Transmission] - Moves flows between locations with possible losses -- Specialized [`LinearConverters`][flixopt.components.LinearConverter] like [`Boilers`][flixopt.linear_converters.Boiler], [`HeatPumps`][flixopt.linear_converters.HeatPump], [`CHPs`][flixopt.linear_converters.CHP], etc. These simplify the usage of the `LinearConverter` class and can also be used as blueprint on how to define custom classes or parameterize existing ones. + - *Energy: pipelines, power lines* + - *Logistics: transport routes* + - *Water: distribution networks* + +**Pre-built specialized components** for energy systems include [`Boilers`][flixopt.linear_converters.Boiler], [`HeatPumps`][flixopt.linear_converters.HeatPump], [`CHPs`][flixopt.linear_converters.CHP], etc. These can serve as blueprints for custom domain-specific components. ### Effects -[`Effect`][flixopt.effects.Effect] objects represent impacts or metrics related to your system, such as: +[`Effect`][flixopt.effects.Effect] objects represent impacts or metrics related to your system. While commonly used to allocate costs, they're completely flexible: +**Energy systems:** - Costs (investment, operation) - Emissions (CO₂, NOx, etc.) -- Resource consumption -- Area demand +- Primary energy consumption + +**Other domains:** +- Production time, labor hours (manufacturing) +- Water consumption, wastewater (process industries) +- Transport distance, vehicle utilization (logistics) +- Space consumption +- Any custom metric relevant to your domain These can be freely defined and crosslink to each other (`CO₂` ──[specific CO₂-costs]─→ `Costs`). One effect is designated as the **optimization objective** (typically Costs), while others can be constrained. -This approach allows for a multi-criteria optimization using both... - - ... the **Weigted Sum**Method, by Optimizing a theoretical Effect which other Effects crosslink to. - - ... the ($\epsilon$-constraint method) by constraining effects. +This approach allows for multi-criteria optimization using both: + + - **Weighted Sum Method**: Optimize a theoretical Effect which other Effects crosslink to + - **ε-constraint method**: Constrain effects to specific limits ### Calculation From 73323c3d9db4756baccf6feacf112d1602b2cadf Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Mon, 6 Oct 2025 13:45:26 +0200 Subject: [PATCH 23/29] Improve docs --- README.md | 3 +-- docs/index.md | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f3bf08a76..e04321c4b 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,11 @@ We believe that optimization modeling should be **approachable for beginners** y **Short-term goals:** - **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization - **Enhanced component library**: More pre-built components for common use cases (sector coupling, hydrogen systems, thermal networks) -- **Better debugging tools**: Clear error messages, infeasibility diagnostics, and model inspection capabilities **Long-term vision:** - **Showcase universal applicability**: FlixOpt already handles any flow-based system (supply chains, water networks, production planning, chemical processes) - we need more examples and domain-specific component libraries to demonstrate this - **Seamless integration**: First-class support for coupling with simulation tools, databases, and existing energy system models -- **Scale independence**: From single buildings to national energy systems, with smart algorithms that adapt to problem size +- **Modeling to generate alternatives (MGA)**: Build in support to generate alternative result to produce more robust results. - **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions across all application domains ### Why FlixOpt Exists diff --git a/docs/index.md b/docs/index.md index a59d10b66..295bb9322 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,13 +12,11 @@ We believe that optimization modeling should be **approachable for beginners** y - **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization - **Enhanced component library**: More pre-built components for common use cases (sector coupling, hydrogen systems, thermal networks) -- **Better debugging tools**: Clear error messages, infeasibility diagnostics, and model inspection capabilities **Long-term vision:** - **Showcase universal applicability**: FlixOpt already handles any flow-based system (supply chains, water networks, production planning, chemical processes) - we need more examples and domain-specific component libraries to demonstrate this -- **Seamless integration**: First-class support for coupling with simulation tools, databases, and existing energy system models -- **Scale independence**: From single buildings to national energy systems, with smart algorithms that adapt to problem size +- **Modeling to generate alternatives (MGA)**: Build in support to generate alternative result to produce more robust results. - **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions across all application domains ### Why FlixOpt Exists From 2b9384cbac610d5688929b7f08ab2943c41dbb5a Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Mon, 6 Oct 2025 13:58:18 +0200 Subject: [PATCH 24/29] Improve docs --- README.md | 17 ++++++++++++----- docs/index.md | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e04321c4b..957274f1c 100644 --- a/README.md +++ b/README.md @@ -17,14 +17,21 @@ We believe that optimization modeling should be **approachable for beginners** y ### Where We're Going **Short-term goals:** -- **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization -- **Enhanced component library**: More pre-built components for common use cases (sector coupling, hydrogen systems, thermal networks) +- **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization (periods and scenarios are in active development) +- **Enhanced component library**: More pre-built, domain-specific components (sector coupling, hydrogen systems, thermal networks, demand-side management) + +**Medium-term vision:** +- **Modeling to generate alternatives (MGA)**: Built-in support for exploring near-optimal solution spaces to produce more robust, diverse solutions under uncertainty +- **Interactive tutorials**: Browser-based, reactive tutorials for learning FlixOpt without local installation +- **Standardized cost calculations**: Align with industry standards (VDI 2067) for CAPEX/OPEX calculations +- **Advanced result analysis**: Time-series aggregation, automated reporting, and rich visualization options **Long-term vision:** - **Showcase universal applicability**: FlixOpt already handles any flow-based system (supply chains, water networks, production planning, chemical processes) - we need more examples and domain-specific component libraries to demonstrate this -- **Seamless integration**: First-class support for coupling with simulation tools, databases, and existing energy system models -- **Modeling to generate alternatives (MGA)**: Build in support to generate alternative result to produce more robust results. -- **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions across all application domains +- **Seamless integration**: First-class support for coupling with simulation tools, databases, existing energy system models, and GIS data +- **Robust optimization**: Built-in uncertainty quantification and stochastic programming capabilities +- **Community ecosystem**: Rich library of user-contributed components, examples, and domain-specific extensions +- **Model validation tools**: Automated checks for physical plausibility, data consistency, and common modeling errors ### Why FlixOpt Exists diff --git a/docs/index.md b/docs/index.md index 295bb9322..e6dc4e6d9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,14 +10,23 @@ We believe that optimization modeling should be **approachable for beginners** y **Short-term goals:** -- **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization -- **Enhanced component library**: More pre-built components for common use cases (sector coupling, hydrogen systems, thermal networks) +- **Multi-dimensional modeling**: Full support for multi-period investments and scenario-based stochastic optimization (periods and scenarios are in active development) +- **Enhanced component library**: More pre-built, domain-specific components (sector coupling, hydrogen systems, thermal networks, demand-side management) + +**Medium-term vision:** + +- **Modeling to generate alternatives (MGA)**: Built-in support for exploring near-optimal solution spaces to produce more robust, diverse solutions under uncertainty +- **Interactive tutorials**: Browser-based, reactive tutorials for learning FlixOpt without local installation (marimo) +- **Standardized cost calculations**: Align with industry standards (VDI 2067) for CAPEX/OPEX calculations +- **Advanced result analysis**: Time-series aggregation, automated reporting, and rich visualization options **Long-term vision:** - **Showcase universal applicability**: FlixOpt already handles any flow-based system (supply chains, water networks, production planning, chemical processes) - we need more examples and domain-specific component libraries to demonstrate this -- **Modeling to generate alternatives (MGA)**: Build in support to generate alternative result to produce more robust results. -- **Community-driven development**: A rich ecosystem of user-contributed components, examples, and extensions across all application domains +- **Seamless integration**: First-class support for coupling with simulation tools, databases, existing energy system models, and GIS data +- **Robust optimization**: Built-in uncertainty quantification and stochastic programming capabilities +- **Community ecosystem**: Rich library of user-contributed components, examples, and domain-specific extensions +- **Model validation tools**: Automated checks for physical plausibility, data consistency, and common modeling errors ### Why FlixOpt Exists From 4399ca4ac26e9479bd9c12cd1c3716c581bb549b Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Wed, 8 Oct 2025 16:59:37 +0200 Subject: [PATCH 25/29] Add entry to CHANGELOG.md --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72090ccba..4186e6430 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -110,6 +110,42 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir * Improved error handling and validation in serialization processes * Better type consistency across all framework components +### 📝 Docs + +**Major Documentation Overhaul:** + +- **Reorganized Mathematical Notation Documentation** + - Moved from `docs/user-guide/Mathematical Notation/` to `docs/user-guide/mathematical-notation/` (lowercase, kebab-case) + - Created clearer structure with subdirectories: + - `elements/` - Bus, Flow, LinearConverter, Storage + - `features/` - InvestParameters, OnOffParameters, Piecewise + - `modeling-patterns/` - Reusable mathematical building blocks (bounds-and-states, duration-tracking, state-transitions) + - Added comprehensive new pages: + - `dimensions.md` - Complete explanation of time/period/scenario dimensions + - `effects-penalty-objective.md` - Detailed effect formulations and objective function + +- **Enhanced Mathematical Documentation** + - All element pages now include implementation details, cross-references, and "See Also" sections + - Expanded effect formulations to cover multi-dimensional cases (periods and scenarios) + - Added modeling patterns documentation showing reusable mathematical building blocks + - Improved cross-linking between related concepts + +- **Improved README and Landing Page** + - Completely rewritten with clearer vision and value proposition + - Added "Where We're Going" section with short/medium/long-term goals + - Emphasized universal applicability beyond energy systems + - Better quick start and contribution guidance + +- **Updated Documentation Structure** + - Removed deprecated `docs/SUMMARY.md` in favor of `mkdocs.yml` navigation + - Updated `mkdocs.yml` to reflect new documentation structure + - Enhanced user guide index with cross-domain examples + +- **Code Documentation Improvements** + - Tightened docstrings across `flixopt/components.py`, `flixopt/elements.py`, and `flixopt/interface.py` + - Enhanced `scripts/gen_ref_pages.py` for better API reference generation + - Used links in docstrings for better cross-referencing + ### 🚧 Known Issues * IO for single Interfaces/Elements to Datasets might not work properly if the Interface/Element is not part of a fully transformed and connected FlowSystem. This arises from Numeric Data not being stored as xr.DataArray by the user. To avoid this, always use the `to_dataset()` on Elements inside a FlowSystem that's connected and transformed. From eeceaf76eb89a19864e2c060a6f7b04b88c17778 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Wed, 8 Oct 2025 17:01:38 +0200 Subject: [PATCH 26/29] Compact entry to CHANGELOG.md --- CHANGELOG.md | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4186e6430..00d30108a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,39 +112,12 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir ### 📝 Docs -**Major Documentation Overhaul:** - -- **Reorganized Mathematical Notation Documentation** - - Moved from `docs/user-guide/Mathematical Notation/` to `docs/user-guide/mathematical-notation/` (lowercase, kebab-case) - - Created clearer structure with subdirectories: - - `elements/` - Bus, Flow, LinearConverter, Storage - - `features/` - InvestParameters, OnOffParameters, Piecewise - - `modeling-patterns/` - Reusable mathematical building blocks (bounds-and-states, duration-tracking, state-transitions) - - Added comprehensive new pages: - - `dimensions.md` - Complete explanation of time/period/scenario dimensions - - `effects-penalty-objective.md` - Detailed effect formulations and objective function - -- **Enhanced Mathematical Documentation** - - All element pages now include implementation details, cross-references, and "See Also" sections - - Expanded effect formulations to cover multi-dimensional cases (periods and scenarios) - - Added modeling patterns documentation showing reusable mathematical building blocks - - Improved cross-linking between related concepts - -- **Improved README and Landing Page** - - Completely rewritten with clearer vision and value proposition - - Added "Where We're Going" section with short/medium/long-term goals - - Emphasized universal applicability beyond energy systems - - Better quick start and contribution guidance - -- **Updated Documentation Structure** - - Removed deprecated `docs/SUMMARY.md` in favor of `mkdocs.yml` navigation - - Updated `mkdocs.yml` to reflect new documentation structure - - Enhanced user guide index with cross-domain examples - -- **Code Documentation Improvements** - - Tightened docstrings across `flixopt/components.py`, `flixopt/elements.py`, and `flixopt/interface.py` - - Enhanced `scripts/gen_ref_pages.py` for better API reference generation - - Used links in docstrings for better cross-referencing +- Reorganized mathematical notation docs: moved to lowercase `mathematical-notation/` with subdirectories (`elements/`, `features/`, `modeling-patterns/`) +- Added comprehensive documentation pages: `dimensions.md` (time/period/scenario), `effects-penalty-objective.md`, modeling patterns +- Enhanced all element pages with implementation details, cross-references, and "See Also" sections +- Rewrote README and landing page with clearer vision, roadmap, and universal applicability emphasis +- Removed deprecated `docs/SUMMARY.md`, updated `mkdocs.yml` for new structure +- Tightened docstrings in core modules with better cross-referencing ### 🚧 Known Issues * IO for single Interfaces/Elements to Datasets might not work properly if the Interface/Element is not part of a fully transformed and connected FlowSystem. This arises from Numeric Data not being stored as xr.DataArray by the user. To avoid this, always use the `to_dataset()` on Elements inside a FlowSystem that's connected and transformed. From 499d08ae33991102f8a17b656fd49180cce9ee91 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Wed, 8 Oct 2025 17:07:30 +0200 Subject: [PATCH 27/29] Add recipies to docs --- CHANGELOG.md | 1 + docs/index.md | 1 + docs/user-guide/recipies/index.md | 47 +++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 4 files changed, 50 insertions(+) create mode 100644 docs/user-guide/recipies/index.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 00d30108a..f3c9795a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,6 +118,7 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir - Rewrote README and landing page with clearer vision, roadmap, and universal applicability emphasis - Removed deprecated `docs/SUMMARY.md`, updated `mkdocs.yml` for new structure - Tightened docstrings in core modules with better cross-referencing +- Added recipies section to docs ### 🚧 Known Issues * IO for single Interfaces/Elements to Datasets might not work properly if the Interface/Element is not part of a fully transformed and connected FlowSystem. This arises from Numeric Data not being stored as xr.DataArray by the user. To avoid this, always use the `to_dataset()` on Elements inside a FlowSystem that's connected and transformed. diff --git a/docs/index.md b/docs/index.md index e6dc4e6d9..7d2462c67 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,6 +19,7 @@ We believe that optimization modeling should be **approachable for beginners** y - **Interactive tutorials**: Browser-based, reactive tutorials for learning FlixOpt without local installation (marimo) - **Standardized cost calculations**: Align with industry standards (VDI 2067) for CAPEX/OPEX calculations - **Advanced result analysis**: Time-series aggregation, automated reporting, and rich visualization options +- **Recipe collection**: Community-driven library of common modeling patterns, data manipulation techniques, and optimization strategies (see [Recipes](user-guide/recipies/index.md) - help wanted!) **Long-term vision:** diff --git a/docs/user-guide/recipies/index.md b/docs/user-guide/recipies/index.md new file mode 100644 index 000000000..8ac7d1812 --- /dev/null +++ b/docs/user-guide/recipies/index.md @@ -0,0 +1,47 @@ +# Recipes + +**Coming Soon!** 🚧 + +This section will contain quick, copy-paste ready code snippets for common FlixOpt patterns. + +--- + +## What Will Be Here? + +Short, focused code snippets showing **how to do specific things** in FlixOpt: + +- Common modeling patterns +- Integration with other tools +- Performance optimizations +- Domain-specific solutions +- Data analysis shortcuts + +Unlike full examples, recipes will be focused snippets showing a single concept. + +--- + +## Planned Topics + +- **Storage Patterns** - Batteries, thermal storage, seasonal storage +- **Multi-Criteria Optimization** - Balance multiple objectives +- **Data I/O** - Loading time series from CSV, databases, APIs +- **Data Manipulation** - Common xarray operations for parameterization and analysis +- **Investment Optimization** - Size optimization strategies +- **Renewable Integration** - Solar, wind capacity optimization +- **On/Off Constraints** - Minimum runtime, startup costs +- **Large-Scale Problems** - Segmented and aggregated calculations +- **Custom Constraints** - Extend models with linopy +- **Domain-Specific Patterns** - District heating, microgrids, industrial processes + +--- + +## Want to Contribute? + +**We need your help!** If you have recurring modeling patterns or clever solutions to share, please contribute via [GitHub issues](https://github.com/flixopt/flixopt/issues) or pull requests. + +Guidelines: +1. Keep it short (< 100 lines of code) +2. Focus on one specific technique +3. Add brief explanation and when to use it + +Check the [contribution guide](../../contribute.md) for details. diff --git a/mkdocs.yml b/mkdocs.yml index 74a8b2728..8464398c2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,6 +13,7 @@ nav: - Getting Started: getting-started.md - User Guide: - user-guide/index.md + - Recipes: user-guide/recipies/index.md - Mathematical Notation: - Overview: user-guide/mathematical-notation/index.md - Dimensions: user-guide/mathematical-notation/dimensions.md From 2983bd9ef67b85104205c362b5cc5e8d6b3e4dfd Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Wed, 8 Oct 2025 17:20:35 +0200 Subject: [PATCH 28/29] Change all bullet points to * and fix indents --- CHANGELOG.md | 39 ++++++++++++------- .../mathematical-notation/dimensions.md | 24 ++++++------ .../features/OnOffParameters.md | 4 +- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3c9795a5..65905fb46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,19 +46,24 @@ This release introduces new model dimensions (periods and scenarios) for multi-p ### ✨ Added **New model dimensions:** + * **Period dimension**: Enables multi-period investment modeling with distinct decisions in each period for transformation pathway optimization * **Scenario dimension**: Supports stochastic modeling with weighted scenarios for robust decision-making under uncertainty (demand, prices, weather) **Redesigned effect sharing system:** + Effects now use intuitive `share_from_*` syntax that clearly shows contribution sources: + ```python costs = fx.Effect('costs', '€', 'Total costs', share_from_temporal={'CO2': 0.2}, # From temporal effects share_from_periodic={'land': 100}) # From periodic effects ``` + This replaces `specific_share_to_other_effects_*` parameters and inverts the direction for clearer relationships. **Enhanced I/O and data handling:** + * NetCDF/JSON serialization for all Interface objects and FlowSystem with round-trip support * FlowSystem manipulation: `sel()`, `isel()`, `resample()`, `copy()`, `__eq__()` methods * Direct access to FlowSystem from results without manual restoring (lazily loaded) @@ -66,12 +71,14 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir * `effects_per_component()` dataset for component impact evaluation, including all indirect effects through effect shares **Other additions:** + * Balanced storage - charging and discharging sizes can be forced equal via `balanced` parameter * New Storage parameters: `relative_minimum_final_charge_state` and `relative_maximum_final_charge_state` for final state control * Improved filter methods in results * Example for 2-stage investment decisions leveraging FlowSystem resampling ### 💥 Breaking Changes + * `relative_minimum_charge_state` and `relative_maximum_charge_state` don't have an extra timestep anymore. * Renamed class `SystemModel` to `FlowSystemModel` * Renamed class `Model` to `Submodel` @@ -79,33 +86,37 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir * `Calculation.do_modeling()` now returns the `Calculation` object instead of its `linopy.Model`. Callers that previously accessed the linopy model directly should now use `calculation.do_modeling().model` instead of `calculation.do_modeling()`. ### ♻️ Changed + * FlowSystems cannot be shared across multiple Calculations anymore. A copy of the FlowSystem is created instead, making every Calculation independent * Each Subcalculation in `SegmentedCalculation` now has its own distinct `FlowSystem` object * Type system overhaul - added clear separation between temporal and non-temporal data throughout codebase for better clarity * Enhanced FlowSystem interface with improved `__repr__()` and `__str__()` methods * Improved Model Structure - Views and organisation is now divided into: - * Model: The main Model (linopy.Model) that is used to create and store the variables and constraints for the flow_system. - * Submodel: The base class for all submodels. Each is a subset of the Model, for simpler access and clearer code. + - Model: The main Model (linopy.Model) that is used to create and store the variables and constraints for the flow_system. + - Submodel: The base class for all submodels. Each is a subset of the Model, for simpler access and clearer code. ### 🗑️ Deprecated + * The `agg_group` and `agg_weight` parameters of `TimeSeriesData` are deprecated and will be removed in a future version. Use `aggregation_group` and `aggregation_weight` instead. * The `active_timesteps` parameter of `Calculation` is deprecated and will be removed in a future version. Use the new `sel(time=...)` method on the FlowSystem instead. * The assignment of Bus Objects to Flow.bus is deprecated and will be removed in a future version. Use the label of the Bus instead. * The usage of Effects objects in Dicts to assign shares to Effects is deprecated and will be removed in a future version. Use the label of the Effect instead. * Effect parameters renamed: - - `minimum_investment` → `minimum_periodic` - - `maximum_investment` → `maximum_periodic` - - `minimum_operation` → `minimum_temporal` - - `maximum_operation` → `maximum_temporal` - - `minimum_operation_per_hour` → `minimum_per_hour` - - `maximum_operation_per_hour` → `maximum_per_hour` + - `minimum_investment` → `minimum_periodic` + - `maximum_investment` → `maximum_periodic` + - `minimum_operation` → `minimum_temporal` + - `maximum_operation` → `maximum_temporal` + - `minimum_operation_per_hour` → `minimum_per_hour` + - `maximum_operation_per_hour` → `maximum_per_hour` ### 🔥 Removed + * **Effect share parameters**: The old `specific_share_to_other_effects_*` parameters were replaced WITHOUT DEPRECATION - - `specific_share_to_other_effects_operation` → `share_from_temporal` (with inverted direction) - - `specific_share_to_other_effects_invest` → `share_from_periodic` (with inverted direction) + - `specific_share_to_other_effects_operation` → `share_from_temporal` (with inverted direction) + - `specific_share_to_other_effects_invest` → `share_from_periodic` (with inverted direction) ### 🐛 Fixed + * Enhanced NetCDF I/O with proper attribute preservation for DataArrays * Improved error handling and validation in serialization processes * Better type consistency across all framework components @@ -121,9 +132,11 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir - Added recipies section to docs ### 🚧 Known Issues + * IO for single Interfaces/Elements to Datasets might not work properly if the Interface/Element is not part of a fully transformed and connected FlowSystem. This arises from Numeric Data not being stored as xr.DataArray by the user. To avoid this, always use the `to_dataset()` on Elements inside a FlowSystem that's connected and transformed. ### 👷 Development + * FlowSystem data management simplified - removed `time_series_collection` pattern in favor of direct timestep properties * Change modeling hierarchy to allow for more flexibility in future development. This leads to minimal changes in the access and creation of Submodels and their variables. * Added new module `.modeling` that contains Modelling primitives and utilities @@ -131,9 +144,9 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir * Improved access to the Submodels and their variables, constraints and submodels * Added `__repr__()` for Submodels to easily inspect its content * Enhanced data handling methods - * `fit_to_model_coords()` method for data alignment - * `fit_effects_to_model_coords()` method for effect data processing - * `connect_and_transform()` method replacing several operations + - `fit_to_model_coords()` method for data alignment + - `fit_effects_to_model_coords()` method for effect data processing + - `connect_and_transform()` method replacing several operations Until here --> diff --git a/docs/user-guide/mathematical-notation/dimensions.md b/docs/user-guide/mathematical-notation/dimensions.md index 794bc08b6..a4ef9ef20 100644 --- a/docs/user-guide/mathematical-notation/dimensions.md +++ b/docs/user-guide/mathematical-notation/dimensions.md @@ -7,20 +7,20 @@ FlixOpt's `FlowSystem` supports multiple dimensions for modeling optimization pr FlixOpt models can have up to three dimensions: 1. **Time (`time`)** - **MANDATORY** - * Represents the temporal evolution of the system - * Defined via `pd.DatetimeIndex` - * Must contain at least 2 timesteps - * All optimization variables and constraints evolve over time + - Represents the temporal evolution of the system + - Defined via `pd.DatetimeIndex` + - Must contain at least 2 timesteps + - All optimization variables and constraints evolve over time 2. **Period (`period`)** - **OPTIONAL** - * Represents independent planning periods (e.g., years 2020, 2021, 2022) - * Defined via `pd.Index` with integer values - * Used for multi-period optimization such as investment planning across years - * Each period is independent with its own time series + - Represents independent planning periods (e.g., years 2020, 2021, 2022) + - Defined via `pd.Index` with integer values + - Used for multi-period optimization such as investment planning across years + - Each period is independent with its own time series 3. **Scenario (`scenario`)** - **OPTIONAL** - * Represents alternative futures or uncertainty realizations (e.g., "Base Case", "High Demand") - * Defined via `pd.Index` with any labels - * Scenarios within the same period share the same time dimension - * Used for stochastic optimization or scenario comparison + - Represents alternative futures or uncertainty realizations (e.g., "Base Case", "High Demand") + - Defined via `pd.Index` with any labels + - Scenarios within the same period share the same time dimension + - Used for stochastic optimization or scenario comparison --- diff --git a/docs/user-guide/mathematical-notation/features/OnOffParameters.md b/docs/user-guide/mathematical-notation/features/OnOffParameters.md index e2cad0af9..4ec6a9726 100644 --- a/docs/user-guide/mathematical-notation/features/OnOffParameters.md +++ b/docs/user-guide/mathematical-notation/features/OnOffParameters.md @@ -218,8 +218,8 @@ For equipment with OnOffParameters, the complete constraint system includes: 2. **Switch tracking:** $s^\text{on}(t) - s^\text{off}(t) = s(t) - s(t-1)$ 3. **Switch exclusivity:** $s^\text{on}(t) + s^\text{off}(t) \leq 1$ 4. **Duration tracking:** - - On-duration: $d^\text{on}(t)$ following duration tracking pattern - - Off-duration: $d^\text{off}(t)$ following duration tracking pattern + - On-duration: $d^\text{on}(t)$ following duration tracking pattern + - Off-duration: $d^\text{off}(t)$ following duration tracking pattern 5. **Minimum on-time:** $d^\text{on}(t) \geq (s(t-1) - s(t)) \cdot h^\text{on}_\text{min}$ 6. **Maximum on-time:** $d^\text{on}(t) \leq h^\text{on}_\text{max}$ 7. **Minimum off-time:** $d^\text{off}(t) \geq (s(t) - s(t-1)) \cdot h^\text{off}_\text{min}$ From b8cd8c487db77972782e8007d68649374c7d9bc1 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Wed, 8 Oct 2025 17:38:17 +0200 Subject: [PATCH 29/29] Change all bullet points to - instead of * --- CHANGELOG.md | 88 +++++++++---------- .../mathematical-notation/dimensions.md | 8 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85d1b7e60..604769b4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,8 +47,8 @@ This release introduces new model dimensions (periods and scenarios) for multi-p **New model dimensions:** -* **Period dimension**: Enables multi-period investment modeling with distinct decisions in each period for transformation pathway optimization -* **Scenario dimension**: Supports stochastic modeling with weighted scenarios for robust decision-making under uncertainty (demand, prices, weather) +- **Period dimension**: Enables multi-period investment modeling with distinct decisions in each period for transformation pathway optimization +- **Scenario dimension**: Supports stochastic modeling with weighted scenarios for robust decision-making under uncertainty (demand, prices, weather) **Redesigned effect sharing system:** @@ -64,44 +64,44 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir **Enhanced I/O and data handling:** -* NetCDF/JSON serialization for all Interface objects and FlowSystem with round-trip support -* FlowSystem manipulation: `sel()`, `isel()`, `resample()`, `copy()`, `__eq__()` methods -* Direct access to FlowSystem from results without manual restoring (lazily loaded) -* New `FlowResults` class and precomputed DataArrays for sizes/flow_rates/flow_hours -* `effects_per_component()` dataset for component impact evaluation, including all indirect effects through effect shares +- NetCDF/JSON serialization for all Interface objects and FlowSystem with round-trip support +- FlowSystem manipulation: `sel()`, `isel()`, `resample()`, `copy()`, `__eq__()` methods +- Direct access to FlowSystem from results without manual restoring (lazily loaded) +- New `FlowResults` class and precomputed DataArrays for sizes/flow_rates/flow_hours +- `effects_per_component()` dataset for component impact evaluation, including all indirect effects through effect shares **Other additions:** -* Balanced storage - charging and discharging sizes can be forced equal via `balanced` parameter -* New Storage parameters: `relative_minimum_final_charge_state` and `relative_maximum_final_charge_state` for final state control -* Improved filter methods in results -* Example for 2-stage investment decisions leveraging FlowSystem resampling +- Balanced storage - charging and discharging sizes can be forced equal via `balanced` parameter +- New Storage parameters: `relative_minimum_final_charge_state` and `relative_maximum_final_charge_state` for final state control +- Improved filter methods in results +- Example for 2-stage investment decisions leveraging FlowSystem resampling ### 💥 Breaking Changes -* `relative_minimum_charge_state` and `relative_maximum_charge_state` don't have an extra timestep anymore. -* Renamed class `SystemModel` to `FlowSystemModel` -* Renamed class `Model` to `Submodel` -* Renamed `mode` parameter in plotting methods to `style` -* `Calculation.do_modeling()` now returns the `Calculation` object instead of its `linopy.Model`. Callers that previously accessed the linopy model directly should now use `calculation.do_modeling().model` instead of `calculation.do_modeling()`. +- `relative_minimum_charge_state` and `relative_maximum_charge_state` don't have an extra timestep anymore. +- Renamed class `SystemModel` to `FlowSystemModel` +- Renamed class `Model` to `Submodel` +- Renamed `mode` parameter in plotting methods to `style` +- `Calculation.do_modeling()` now returns the `Calculation` object instead of its `linopy.Model`. Callers that previously accessed the linopy model directly should now use `calculation.do_modeling().model` instead of `calculation.do_modeling()`. ### ♻️ Changed -* FlowSystems cannot be shared across multiple Calculations anymore. A copy of the FlowSystem is created instead, making every Calculation independent -* Each Subcalculation in `SegmentedCalculation` now has its own distinct `FlowSystem` object -* Type system overhaul - added clear separation between temporal and non-temporal data throughout codebase for better clarity -* Enhanced FlowSystem interface with improved `__repr__()` and `__str__()` methods -* Improved Model Structure - Views and organisation is now divided into: +- FlowSystems cannot be shared across multiple Calculations anymore. A copy of the FlowSystem is created instead, making every Calculation independent +- Each Subcalculation in `SegmentedCalculation` now has its own distinct `FlowSystem` object +- Type system overhaul - added clear separation between temporal and non-temporal data throughout codebase for better clarity +- Enhanced FlowSystem interface with improved `__repr__()` and `__str__()` methods +- Improved Model Structure - Views and organisation is now divided into: - Model: The main Model (linopy.Model) that is used to create and store the variables and constraints for the flow_system. - Submodel: The base class for all submodels. Each is a subset of the Model, for simpler access and clearer code. ### 🗑️ Deprecated -* The `agg_group` and `agg_weight` parameters of `TimeSeriesData` are deprecated and will be removed in a future version. Use `aggregation_group` and `aggregation_weight` instead. -* The `active_timesteps` parameter of `Calculation` is deprecated and will be removed in a future version. Use the new `sel(time=...)` method on the FlowSystem instead. -* The assignment of Bus Objects to Flow.bus is deprecated and will be removed in a future version. Use the label of the Bus instead. -* The usage of Effects objects in Dicts to assign shares to Effects is deprecated and will be removed in a future version. Use the label of the Effect instead. -* Effect parameters renamed: +- The `agg_group` and `agg_weight` parameters of `TimeSeriesData` are deprecated and will be removed in a future version. Use `aggregation_group` and `aggregation_weight` instead. +- The `active_timesteps` parameter of `Calculation` is deprecated and will be removed in a future version. Use the new `sel(time=...)` method on the FlowSystem instead. +- The assignment of Bus Objects to Flow.bus is deprecated and will be removed in a future version. Use the label of the Bus instead. +- The usage of Effects objects in Dicts to assign shares to Effects is deprecated and will be removed in a future version. Use the label of the Effect instead. +- Effect parameters renamed: - `minimum_investment` → `minimum_periodic` - `maximum_investment` → `maximum_periodic` - `minimum_operation` → `minimum_temporal` @@ -111,15 +111,15 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir ### 🔥 Removed -* **Effect share parameters**: The old `specific_share_to_other_effects_*` parameters were replaced WITHOUT DEPRECATION +- **Effect share parameters**: The old `specific_share_to_other_effects_*` parameters were replaced WITHOUT DEPRECATION - `specific_share_to_other_effects_operation` → `share_from_temporal` (with inverted direction) - `specific_share_to_other_effects_invest` → `share_from_periodic` (with inverted direction) ### 🐛 Fixed -* Enhanced NetCDF I/O with proper attribute preservation for DataArrays -* Improved error handling and validation in serialization processes -* Better type consistency across all framework components +- Enhanced NetCDF I/O with proper attribute preservation for DataArrays +- Improved error handling and validation in serialization processes +- Better type consistency across all framework components ### 📝 Docs @@ -133,26 +133,26 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir ### 🚧 Known Issues -* IO for single Interfaces/Elements to Datasets might not work properly if the Interface/Element is not part of a fully transformed and connected FlowSystem. This arises from Numeric Data not being stored as xr.DataArray by the user. To avoid this, always use the `to_dataset()` on Elements inside a FlowSystem that's connected and transformed. +- IO for single Interfaces/Elements to Datasets might not work properly if the Interface/Element is not part of a fully transformed and connected FlowSystem. This arises from Numeric Data not being stored as xr.DataArray by the user. To avoid this, always use the `to_dataset()` on Elements inside a FlowSystem that's connected and transformed. ### 👷 Development -* FlowSystem data management simplified - removed `time_series_collection` pattern in favor of direct timestep properties -* Change modeling hierarchy to allow for more flexibility in future development. This leads to minimal changes in the access and creation of Submodels and their variables. -* Added new module `.modeling` that contains Modelling primitives and utilities -* Clearer separation between the main Model and "Submodels" -* Improved access to the Submodels and their variables, constraints and submodels -* Added `__repr__()` for Submodels to easily inspect its content -* Enhanced data handling methods +- FlowSystem data management simplified - removed `time_series_collection` pattern in favor of direct timestep properties +- Change modeling hierarchy to allow for more flexibility in future development. This leads to minimal changes in the access and creation of Submodels and their variables. +- Added new module `.modeling` that contains Modelling primitives and utilities +- Clearer separation between the main Model and "Submodels" +- Improved access to the Submodels and their variables, constraints and submodels +- Added `__repr__()` for Submodels to easily inspect its content +- Enhanced data handling methods - `fit_to_model_coords()` method for data alignment - `fit_effects_to_model_coords()` method for effect data processing - `connect_and_transform()` method replacing several operations -* **Testing improvements**: Eliminated warnings during test execution - * Updated deprecated code patterns in tests and examples (e.g., `sink`/`source` → `inputs`/`outputs`, `'H'` → `'h'` frequency) - * Refactored plotting logic to handle test environments explicitly with non-interactive backends - * Added comprehensive warning filters in `__init__.py` and `pyproject.toml` to suppress third-party library warnings - * Improved test fixtures with proper figure cleanup to prevent memory leaks - * Enhanced backend detection and handling in `plotting.py` for both Matplotlib and Plotly +- **Testing improvements**: Eliminated warnings during test execution + - Updated deprecated code patterns in tests and examples (e.g., `sink`/`source` → `inputs`/`outputs`, `'H'` → `'h'` frequency) + - Refactored plotting logic to handle test environments explicitly with non-interactive backends + - Added comprehensive warning filters in `__init__.py` and `pyproject.toml` to suppress third-party library warnings + - Improved test fixtures with proper figure cleanup to prevent memory leaks + - Enhanced backend detection and handling in `plotting.py` for both Matplotlib and Plotly Until here --> diff --git a/docs/user-guide/mathematical-notation/dimensions.md b/docs/user-guide/mathematical-notation/dimensions.md index a4ef9ef20..e7104fa6a 100644 --- a/docs/user-guide/mathematical-notation/dimensions.md +++ b/docs/user-guide/mathematical-notation/dimensions.md @@ -57,10 +57,10 @@ flow_system = fx.FlowSystem( ``` This creates a system with: -* 24 time steps per scenario per period -* 2 scenarios with equal weights (0.5 each) -* 3 periods (years) -* **Total decision space:** 24 × 2 × 3 = 144 time-scenario-period combinations +- 24 time steps per scenario per period +- 2 scenarios with equal weights (0.5 each) +- 3 periods (years) +- **Total decision space:** 24 × 2 × 3 = 144 time-scenario-period combinations ---