battery c min is ignored if charge demand p demand is greater than zero#95
Conversation
|
I checked this branch out and ran it against #91. Summary up front: the optimizer change does not enforce 1. The
|
| scenario | this PR | #91 |
|---|---|---|
headroom 800 Wh (s_max=800), demand 500 Wh |
410 W | 0 W |
| headroom 1000 Wh, demand 1400 Wh | 513 W | 0 W |
charge_from_grid: false, 400 Wh solar, demand 500 Wh |
400 W | 0 W |
| demand 500 Wh (ample headroom) | 1400 W | 1400 W |
| demand 500 Wh in all three slots | 1400/1400/1400 W | 1400/1400/1400 W |
The last two rows are the cases this PR does fix; the first three are the ones it does not. #91 returns 0 there because the semi-continuous bound (c == 0 or c >= c_min, via the existing z_c binary) is a hard constraint, so "cannot reach the minimum" correctly resolves to "do not charge" rather than "charge something impossible". Solar-limited charging is not an exotic case — it is the everyday PV-surplus scenario, and it is where a wallbox that cannot run below ~1.4 kW matters most.
3. The new test case bakes the remaining defect into the expected output
test_cases/023-c_min-limit-kept-with-p_demand-set.json has c_min = 1380, and expected_response.batteries[0].charging_power contains at indices 18 and 19 (both dt = 3600, both with p_demand = 4000):
1019.4 Wh -> 1019 W
536.5 Wh -> 537 W
Both are below c_min. As a snapshot comparison this locks the bug in as the expected result — a future correct fix would have to change this file to land. (Index 0 is fine: dt = 31 s, so 31.7 Wh is 3680 W.) If the case is kept, it should assert the invariant (c == 0 or c >= c_min * dt/3600 for every slot) rather than pin exact values.
4. testbench.py is correct and unrelated
ts_Wh_to_kW = 3.6 / dt followed by multiply converts Wh-per-slot to kW properly; the old divide(x, dt) produced Wh/s and was plotted under axes already labelled [kW]. Purely a diagram fix, no effect on any assertion (ts_grid_dev is a ratio, so the scaling cancels). Worth splitting into its own PR so it can merge immediately.
5. On CI being green
The suite passing is not evidence here — nothing in it asserted c_min in demand slots before #91 added tests/test_semicontinuous.py. I dropped that test file onto this branch as well and it passes, because it only covers the ample-headroom case (row 4 above). The three failing scenarios above need explicit coverage either way.
Recommendation
Take #91 for the optimizer change and cherry-pick the testbench.py unit fix out of this branch. If you prefer the target-clipping formulation for other reasons, it still needs the hard semi-continuous bound underneath it — the two are complementary, not alternatives: the bound guarantees feasible power levels, the clip keeps the soft target reachable so the penalty term stays meaningful.
|
@andig, sorry this one is not ready, I'm aware it still has a flaw. Sorry for creating confusion ... I'm still working on it. |
|
I have a solution but this is changing results in other test cases ... I want to understand why they changed before I commit it. |
|
Sorry, didn't want to pressure you. Thought Claude might help with its comments. |
|
Fixing this bug reveals another problem: If a charge demand that cannot be fulfilled 100% is set for a battery that can discharge, the optimizer will start playing around with charging and discharging the battery to minimize the penalty for not reaching the charge demand target. Question: is it a requirement to set charge demands on batteries that can discharge (maybe not home batteries but bidirectionally chargeable vehicles)? |
|
At least not at the moment- we don't have bidi support and home batteries don't have charging targets. Eventually I would expect that a charging demand is fulfilled even if it requires battery discharging if no other source of energy is available. Does that make sense? |
... due to different charging behavior if p_demand is set of a battery.
|
OK, I think I figured it out, also for the case that batteries can be discharged. The trick was to deacivate the penalty for not meeting the charge demand once the battery is full. @andig, Plesse check. |
|
Yes, absolutely. I think that requirement is met but I shall create a test case to make sure. |
Alternative fix to PR #91
NOT ready for merging!