Adds inverter AC/DC efficiency and break-even penalty (#888)
Some checks failed
Bump Version / Bump Version Workflow (push) Has been cancelled
docker-build / platform-excludes (push) Has been cancelled
docker-build / build (push) Has been cancelled
docker-build / merge (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
Run Pytest on Pull Request / test (push) Has been cancelled

* feat: add inverter AC/DC efficiency and break-even penalty

* test: update tests/test_geneticoptimize.py with new ac_charge_break_even parameter

* docs: update documentation

* chore: update version numbers in configuration files to v0.2.0.dev2602272006923535
This commit is contained in:
Christopher Nadler
2026-02-27 23:12:08 +01:00
committed by GitHub
parent 04420e66ab
commit 3ccc25d731
30 changed files with 3043 additions and 152 deletions

View File

@@ -182,11 +182,21 @@ The behavior of the genetic algorithm can be customized using the following conf
:::{note}
**Supported Penalty Functions**
Currently, the only supported penalty function parameter is:
- `ev_soc_miss`:
Applies a penalty when the **state of charge (SOC)** of the electric vehicle battery falls below
the required minimum. This encourages the optimizer to ensure sufficient EV charging.
Default: `10`.
- `ac_charge_break_even`:
Applies a penalty for each scheduled AC grid-charging hour where the round-trip losses
(AC→DC inverter, battery internal, DC→AC inverter) mean the stored energy can never be
discharged at a price that recovers the charging cost. Energy already stored in the battery
from PV generation is treated as free and covers the most expensive future hours first, so
the penalty only fires for the hours that remain genuinely uncovered.
A value of `1.0` (default) means the penalty equals the actual economic loss in €.
Use larger values (e.g. `3.0`) to make the optimizer more aggressively avoid unprofitable
AC charging, or `0.0` to disable this penalty entirely.
:::
#### Value Formats
@@ -214,7 +224,8 @@ Currently, the only supported penalty function parameter is:
"generations": 400,
"seed": null,
"penalties": {
"ev_soc_miss": 10
"ev_soc_miss": 10,
"ac_charge_break_even": 1.0
}
}
}
@@ -254,13 +265,25 @@ that is configured, even if more devices are configured.
{
"device_id": "inv1",
"max_power_w": 10000,
"battery_id": "bat1"
"battery_id": "bat1",
"ac_to_dc_efficiency": 0.95,
"dc_to_ac_efficiency": 0.95,
"max_ac_charge_power_w": 5000
}
]
}
}
```
The inverter supports separate AC↔DC conversion efficiencies:
- `ac_to_dc_efficiency`: Conversion loss when charging the battery from AC grid power (0-1).
Set to `0` to disable AC charging. Default `1.0`.
- `dc_to_ac_efficiency`: Conversion loss when discharging battery to AC load/grid (0-1).
Must be > 0. Default `1.0`.
- `max_ac_charge_power_w`: Maximum AC charging power in watts. `null` = no additional limit.
Set to `0` to disable AC charging. Default `null`.
#### Electric vehicle simulation configuration
**Example:**

View File

@@ -71,7 +71,10 @@ passed to the request. You have to set the parameters even if given in the confi
"inverter": {
"device_id": "inverter1",
"max_power_wh": 10000,
"battery_id": "battery1"
"battery_id": "battery1",
"ac_to_dc_efficiency": 0.95,
"dc_to_ac_efficiency": 0.95,
"max_ac_charge_power_w": 5000
},
"eauto": {
"device_id": "ev1",
@@ -160,6 +163,65 @@ Verify prices against your local tariffs.
- `device_id`: ID of inverter
- `max_power_wh`: Maximum inverter power in Wh
- `battery_id`: ID of battery
- `ac_to_dc_efficiency`: Efficiency of AC→DC conversion for grid-to-battery AC charging (0-1).
Set to `0` to disable AC charging via inverter. Default `1.0` (backward compatible, no additional
inverter loss — existing battery `charging_efficiency` applies).
- `dc_to_ac_efficiency`: Efficiency of DC→AC conversion for battery discharging to AC load/grid
(0-1). Must be > 0. Default `1.0` (backward compatible).
- `max_ac_charge_power_w`: Maximum AC charging power in watts. `null` means no additional limit
(battery's own `max_charge_power_w` applies). Set to `0` to disable AC charging. Default `null`.
#### Efficiency Model
The inverter efficiency parameters cleanly separate the **DC battery efficiency** from the
**AC↔DC inverter conversion efficiency**:
- **DC charging from PV surplus**: PV → Battery (direct DC, only `charging_efficiency` applies)
- **AC charging from grid**: Grid (AC) → Inverter (`ac_to_dc_efficiency`) → Battery
(`charging_efficiency`)
- **Discharging to AC load/grid**: Battery (`discharging_efficiency`) → Inverter
(`dc_to_ac_efficiency`) → Load/Grid (AC)
Round-trip efficiency for AC charging and discharging:
`η_round_trip = ac_to_dc_efficiency × charging_efficiency × discharging_efficiency × dc_to_ac_efficiency`
For profitability, the discharge electricity price must exceed:
`buy_price / η_round_trip`
**Backward compatibility**: With default values (`ac_to_dc_efficiency=1.0`,
`dc_to_ac_efficiency=1.0`, `max_ac_charge_power_w=null`), existing configurations work identically.
To model realistic inverter losses, set both efficiencies to a value like `0.95` and adjust
battery efficiencies to reflect pure DC losses only (typically `0.96``0.99` for Li-ion).
#### AC Charging Break-Even Penalty
The genetic optimizer includes an economic break-even check as a fitness penalty to guide
convergence away from unprofitable AC grid charging. For each scheduled AC charging hour the
optimizer checks whether the best future discharge price (after accounting for round-trip losses)
actually recovers the charging cost.
**Free PV energy handling**: Energy already stored in the battery from PV generation (zero
grid cost) is treated as a free resource that covers the most expensive future hours first.
AC grid charging is only evaluated against the *remaining* uncovered hours.
The penalty magnitude is:
```text
penalty = ac_wh_charged × (break_even_price best_uncovered_price) × factor
```
where:
- `break_even_price = charge_price / η_round_trip`
- `best_uncovered_price` = highest future price not already covered by free PV battery energy
- `factor` = `optimization.genetic.penalties.ac_charge_break_even` (default `1.0`)
The penalty does not replace the simulation cost — it amplifies the economic loss signal so the
algorithm converges faster away from unprofitable charging regions.
To tune the aggressiveness of this penalty, set `penalties.ac_charge_break_even` in the
optimization configuration. A value of `1.0` corresponds to the exact economic loss in €.
Larger values (e.g. `3.0`) make the algorithm more aggressively avoid unprofitable AC charging;
smaller values (e.g. `0.0`) disable the penalty entirely.
### Electric Vehicle (EV)