Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
e8d04d2
Add planning doc
FBumann Nov 28, 2025
27b1f50
Finalize planning
FBumann Nov 28, 2025
b71a1c5
Add plotting acessor
FBumann Nov 28, 2025
977e9c4
Add plotting acessor
FBumann Nov 28, 2025
efc53d1
Add tests
FBumann Nov 28, 2025
01a92c6
Improve
FBumann Nov 28, 2025
01d8830
Improve
FBumann Nov 28, 2025
1b808a8
Update docs
FBumann Nov 28, 2025
d50e908
Updated the plotting API so that .data always returns xarray DataArra…
FBumann Nov 28, 2025
3234b93
All .data now returns xr.Dataset consistently.
FBumann Nov 28, 2025
93e5a4d
Fixed Inconsistencies and Unused Parameters
FBumann Nov 28, 2025
f3d5310
New Plot Accessors
FBumann Nov 28, 2025
d4cf175
Fix duration curve
FBumann Nov 28, 2025
fa1345f
Fix duration curve
FBumann Nov 28, 2025
c80dd2e
Fix duration curve
FBumann Nov 28, 2025
5517d23
Fix duration curve
FBumann Nov 28, 2025
cf61c50
xr.apply_ufunc to sort along the time axis while preserving all othe…
FBumann Nov 28, 2025
0f88aec
⏺ The example runs successfully. Now let me summarize the fixes:
FBumann Nov 28, 2025
d6ffe57
make variable names public in results
FBumann Nov 29, 2025
bf4d5ac
Fix sankey
FBumann Nov 29, 2025
360ff58
Fix effects()
FBumann Nov 29, 2025
67b4cf0
Fix effects
FBumann Nov 29, 2025
de4eecb
Remove bargaps
FBumann Nov 29, 2025
8b03112
made faceting consistent across all plot methods:
FBumann Nov 29, 2025
fc72976
Update storage method
FBumann Nov 29, 2025
0bdc45c
Remove mode parameter for simpli
FBumann Nov 29, 2025
5e9cb98
Make plotting_accessors.py more self contained
FBumann Nov 29, 2025
c088726
Use faster to_long()
FBumann Nov 29, 2025
4e43077
Add 0-dim case
FBumann Nov 29, 2025
ad34d05
sankey diagram now properly handles scenarios and periods:
FBumann Nov 29, 2025
b98b8ea
Add colors to sankey
FBumann Nov 29, 2025
628adea
Add sizes
FBumann Nov 29, 2025
aaf832b
Add size filtering
FBumann Nov 29, 2025
be31f69
Include storage sizes
FBumann Nov 29, 2025
71444de
Remove storage sizes
FBumann Nov 29, 2025
ecd441b
Merge branch 'feature/v5' into feature/plotting-acessors
FBumann Dec 3, 2025
ae8a793
Add charge state and status accessor
FBumann Dec 3, 2025
a7ac398
Summary of Changes
FBumann Dec 3, 2025
e5a4da1
1. New methods added to PlotAccessor
FBumann Dec 3, 2025
6d992d4
Move deprectated functionality into results.py instead of porting to …
FBumann Dec 3, 2025
193b2ff
Revert to simply deprectae old methods without forwarding to new code
FBumann Dec 3, 2025
ae74e81
Remove planning file
FBumann Dec 3, 2025
eb0aebf
Update plotting methods for new datasets
FBumann Dec 3, 2025
404df2b
1. Renamed data properties in PlotAccessor to use all_ prefix:
FBumann Dec 3, 2025
e7eb5ca
Update deprecations messages
FBumann Dec 3, 2025
8f11795
Update deprecations messages
FBumann Dec 3, 2025
bd5014c
Thsi seems much better.
FBumann Dec 3, 2025
60d84a2
Updaet docstrings and variable name generation in plotting acessor
FBumann Dec 3, 2025
0d762a5
Change __ to _ in private dataset caching
FBumann Dec 3, 2025
3542920
Revert breaking io changes
FBumann Dec 3, 2025
8e41c56
New solution storing interface
FBumann Dec 3, 2025
759b18c
Merge branch 'feature/solution-storage-change' into feature/solution-…
FBumann Dec 4, 2025
fc09bf1
Add new focused statistics and plot accessors
FBumann Dec 4, 2025
9446806
Renamed all properties:
FBumann Dec 4, 2025
1de29cc
Cache Statistics
FBumann Dec 4, 2025
19d5f55
Invalidate caches
FBumann Dec 4, 2025
f0601b4
Add effect related statistics
FBumann Dec 4, 2025
9d2cb51
Simplify statistics accessor to rely on flow_system directly instead …
FBumann Dec 4, 2025
691fe84
Fix heatma fallback for 1D Data
FBumann Dec 4, 2025
6a66be3
Merge remote-tracking branch 'origin/feature/solution-storage-change'…
FBumann Dec 4, 2025
0c952a9
Add topology accessor
FBumann Dec 4, 2025
d1472c0
Merge remote-tracking branch 'origin/feature/solution-storage-change'…
FBumann Dec 4, 2025
793b3a2
All deprecation warnings in the codebase now consistently use the for…
FBumann Dec 4, 2025
3d7142f
Update tests
FBumann Dec 4, 2025
7547522
created comprehensive documentation for all FlowSystem accessors
FBumann Dec 4, 2025
234b39d
Update results documentation
FBumann Dec 4, 2025
db2fc43
Update results documentation
FBumann Dec 4, 2025
76e9776
Update effect statistics
FBumann Dec 4, 2025
12d1917
Update effect statistics
FBumann Dec 4, 2025
d29fbd2
Update effect statistics
FBumann Dec 4, 2025
5a40e97
Add mkdocs plotly plugin
FBumann Dec 4, 2025
52ca80d
Add section about custom constraints
FBumann Dec 4, 2025
558bc58
documentation updates:
FBumann Dec 4, 2025
603e9e0
implemented the effects() method in StatisticsPlotAccessor at flixopt…
FBumann Dec 4, 2025
173ed3a
Remove intermediate plot accessor
FBumann Dec 4, 2025
a648974
1. pyproject.toml: Removed duplicate mkdocs-plotly-plugin>=0.1.3 en…
FBumann Dec 5, 2025
c149268
_create_effects_dataset method in statistics_accessor.py was simplified:
FBumann Dec 5, 2025
ab8ee9c
Update docs
FBumann Dec 5, 2025
4ae33d0
Improve to_netcdf method
FBumann Dec 5, 2025
af1557d
Update examples
FBumann Dec 5, 2025
33e04e3
Fix IIS computaion flag
FBumann Dec 5, 2025
0a0ceea
Fix examples
FBumann Dec 5, 2025
5f7a710
Fix faceting in heatmap and use period as facet col everywhere
FBumann Dec 6, 2025
e686932
Inline plotting methods to deprecate plotting.py (#508)
FBumann Dec 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions docs/home/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,31 @@ battery = fx.Storage(
flow_system.add_elements(solar, demand, battery, electricity_bus)
```

### 5. Run Optimization
### 5. Visualize and Run Optimization

```python
# Run optimization directly on the flow system
# Optional: visualize your system structure
flow_system.topology.plot(path='system.html')

# Run optimization
flow_system.optimize(fx.solvers.HighsSolver())
```

### 6. Access Results
### 6. Access and Visualize Results

```python
# Access results directly from the flow system
# Access raw solution data
print(flow_system.solution)

# Or access component-specific results
# Use statistics for aggregated data
print(flow_system.statistics.flow_hours)

# Access component-specific results
print(flow_system.components['battery'].solution)

# Visualize results
flow_system.statistics.plot.balance('electricity')
flow_system.statistics.plot.storage('battery')
```

### 7. Save Results (Optional)
Expand Down Expand Up @@ -132,8 +142,10 @@ Most flixOpt projects follow this pattern:
2. **Create flow system** - Initialize with time series and effects
3. **Add buses** - Define connection points
4. **Add components** - Create generators, storage, converters, loads
5. **Run optimization** - Call `flow_system.optimize(solver)`
6. **Access Results** - Via `flow_system.solution` or component `.solution` attributes
5. **Verify structure** - Use `flow_system.topology.plot()` to visualize
6. **Run optimization** - Call `flow_system.optimize(solver)`
7. **Analyze results** - Via `flow_system.statistics` and `.solution`
8. **Visualize** - Use `flow_system.statistics.plot.*` methods

## Tips

Expand Down
31 changes: 21 additions & 10 deletions docs/user-guide/core-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,23 +127,29 @@ Define your system structure, parameters, and time series data.

### 2. Run the Optimization

Create an [`Optimization`][flixopt.optimization.Optimization] and solve it:
Optimize your FlowSystem with a solver:

```python
optimization = fx.Optimization('my_model', flow_system)
results = optimization.solve(fx.solvers.HighsSolver())
flow_system.optimize(fx.solvers.HighsSolver())
```

### 3. Analyze Results

The [`Results`][flixopt.results.Results] object contains all solution data:
Access solution data directly from the FlowSystem:

```python
# Access component results
boiler_output = results['Boiler'].node_balance()
# Access component solutions
boiler = flow_system.components['Boiler']
print(boiler.solution)

# Get total costs
total_costs = results.solution['Costs']
total_costs = flow_system.solution['costs|total']

# Use statistics for aggregated data
print(flow_system.statistics.flow_hours)

# Plot results
flow_system.statistics.plot.balance('HeatBus')
```

<figure markdown>
Expand Down Expand Up @@ -185,12 +191,17 @@ While our example used a heating system, flixOpt works for any flow-based optimi
flixOpt is built on [linopy](https://github.com/PyPSA/linopy). You can access and extend the underlying optimization model for custom constraints:

```python
# Access the linopy model after building
optimization.do_modeling()
model = optimization.model
# Build the model (without solving)
flow_system.build_model()

# Access the linopy model
model = flow_system.model

# Add custom constraints using linopy API
model.add_constraints(...)

# Then solve
flow_system.solve(fx.solvers.HighsSolver())
```

This allows advanced users to add domain-specific constraints while keeping flixOpt's convenience for standard modeling.
25 changes: 25 additions & 0 deletions docs/user-guide/migration-guide-v6.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,31 @@ The new API also applies to advanced optimization modes:

---

## Statistics Accessor

The new `statistics` accessor provides convenient aggregated data:

```python
stats = flow_system.statistics

# Flow data (clean labels, no |flow_rate suffix)
stats.flow_rates['Boiler(Q_th)'] # Not 'Boiler(Q_th)|flow_rate'
stats.flow_hours['Boiler(Q_th)']
stats.sizes['Boiler(Q_th)']
stats.charge_states['Battery']

# Effect breakdown by contributor (replaces effects_per_component)
stats.temporal_effects['costs'] # Per timestep, per contributor
stats.periodic_effects['costs'] # Investment costs per contributor
stats.total_effects['costs'] # Total per contributor

# Group by component or component type
stats.total_effects['costs'].groupby('component').sum()
stats.total_effects['costs'].groupby('component_type').sum()
```

---

## 🔧 Quick Reference

### Common Conversions
Expand Down
116 changes: 116 additions & 0 deletions docs/user-guide/optimization/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

This section covers how to run optimizations in flixOpt, including different optimization modes and solver configuration.

## Verifying Your Model

Before running an optimization, it's helpful to visualize your system structure:

```python
# Generate an interactive network diagram
flow_system.topology.plot(path='my_system.html')

# Or get structure info programmatically
nodes, edges = flow_system.topology.infos()
print(f"Components: {[n for n, d in nodes.items() if d['class'] == 'Component']}")
print(f"Buses: {[n for n, d in nodes.items() if d['class'] == 'Bus']}")
print(f"Flows: {list(edges.keys())}")
```

## Standard Optimization

The recommended way to run an optimization is directly on the `FlowSystem`:
Expand Down Expand Up @@ -78,6 +93,107 @@ print(clustered_fs.solution)
| Standard | Small-Medium | Slow | Optimal |
| Clustered | Very Large | Fast | Approximate |

## Custom Constraints

flixOpt is built on [linopy](https://github.com/PyPSA/linopy), allowing you to add custom constraints beyond what's available through the standard API.

### Adding Custom Constraints

To add custom constraints, build the model first, then access the underlying linopy model:

```python
# Build the model (without solving)
flow_system.build_model()

# Access the linopy model
model = flow_system.model

# Access variables from the solution namespace
# Variables are named: "ElementLabel|variable_name"
boiler_flow = model.variables['Boiler(Q_th)|flow_rate']
chp_flow = model.variables['CHP(Q_th)|flow_rate']

# Add a custom constraint: Boiler must produce at least as much as CHP
model.add_constraints(
boiler_flow >= chp_flow,
name='boiler_min_chp'
)

# Solve with the custom constraint
flow_system.solve(fx.solvers.HighsSolver())
```

### Common Use Cases

**Minimum runtime constraint:**
```python
# Require component to run at least 100 hours total
on_var = model.variables['CHP|on'] # Binary on/off variable
hours = flow_system.hours_per_timestep
model.add_constraints(
(on_var * hours).sum() >= 100,
name='chp_min_runtime'
)
```

**Linking flows across components:**
```python
# Heat pump and boiler combined must meet minimum base load
hp_flow = model.variables['HeatPump(Q_th)|flow_rate']
boiler_flow = model.variables['Boiler(Q_th)|flow_rate']
model.add_constraints(
hp_flow + boiler_flow >= 50, # At least 50 kW combined
name='min_heat_supply'
)
```

**Seasonal constraints:**
```python
import pandas as pd

# Different constraints for summer vs winter
summer_mask = flow_system.timesteps.month.isin([6, 7, 8])
winter_mask = flow_system.timesteps.month.isin([12, 1, 2])

flow_var = model.variables['Boiler(Q_th)|flow_rate']

# Lower capacity in summer
model.add_constraints(
flow_var.sel(time=flow_system.timesteps[summer_mask]) <= 100,
name='summer_limit'
)
```

### Inspecting the Model

Before adding constraints, inspect available variables and existing constraints:

```python
flow_system.build_model()
model = flow_system.model

# List all variables
print(model.variables)

# List all constraints
print(model.constraints)

# Get details about a specific variable
print(model.variables['Boiler(Q_th)|flow_rate'])
```

### Variable Naming Convention

Variables follow this naming pattern:

| Element Type | Pattern | Example |
|--------------|---------|---------|
| Flow rate | `Component(FlowLabel)\|flow_rate` | `Boiler(Q_th)\|flow_rate` |
| Flow size | `Component(FlowLabel)\|size` | `Boiler(Q_th)\|size` |
| On/off status | `Component\|on` | `CHP\|on` |
| Charge state | `Storage\|charge_state` | `Battery\|charge_state` |
| Effect totals | `effect_name\|total` | `costs\|total` |

## Solver Configuration

### Available Solvers
Expand Down
Loading