OPT-36 round 2: test_opt34 keeps its tolerances; fresh sensors read the day they are on
The silent and fresh nights diverged only because the test's fresh sensors kept reading the evening's 0.4 kWh 'left today' after midnight, while the kept figure is the 4th's 6.0 kWh (solarfc.Hold.stand_in, as_today): two different shortfalls (16.5 and 12.7 kWh) that A's ceiling hid until B was counted. Fresh sensors now read 6.0 after midnight, so fresh and kept are the same figure; the 0.3 tolerance is back, the other exact values are recomputed. test_ux54 literals are recomputed too. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
6a527de851
commit
3a18475a5a
@@ -268,6 +268,7 @@ PROFILE_LATE = ('{"periods": ['
|
||||
CHOICE = {"a": (True, "leftover_solar", False),
|
||||
"b": (True, "cheap_hours", False)}
|
||||
LAST = at(3, 17, 5)
|
||||
MIDNIGHT = at(4, 0, 0)
|
||||
EVENING = [at(3, 16, 0) + timedelta(minutes=30 * i) for i in range(12)] \
|
||||
+ [at(3, 21, 55)]
|
||||
|
||||
@@ -290,7 +291,12 @@ def sensors(*, silent=True, fresh_from=None, fresh=(1.0, 5.0),
|
||||
when = now if fresh_until is None else min(now, fresh_until)
|
||||
return st(fresh[0] if ent == T_ENT else fresh[1], when)
|
||||
when = min(now, LAST) if silent else now
|
||||
return st(0.4 if ent == T_ENT else 6.0, when)
|
||||
# OPT-36: a fresh sensor reads the day it is on. After midnight "today"
|
||||
# is the 4th (6.0 kWh, the figure the 17:05 reading called tomorrow's),
|
||||
# not the evening's 0.4 kWh left of the 3rd; with that, fresh and
|
||||
# kept are the same figure all night (before, the plans only agreed
|
||||
# because A was capped at the ceiling in both).
|
||||
return st(0.4 if ent == T_ENT and now < MIDNIGHT else 6.0, when)
|
||||
return f
|
||||
|
||||
|
||||
@@ -509,12 +515,14 @@ for k in R:
|
||||
fa, si, rr = R["fresh"], R["silent"], R["restart"]
|
||||
|
||||
# a. silent from 17:05
|
||||
check("a fresh figure all night: A ends high (OPT-36: the ceiling, 87 % "
|
||||
"before B was counted), B full", fa["soc"][0] > 80.0 and fa["soc"][1] > 94.5)
|
||||
# OPT-36: A's level is 95 % to ~05:00, then 78.4 % when B's cheap run is longer
|
||||
# (B's give 5.9 -> 7.1 kWh); A, already at 81.5 %, stops there.
|
||||
check("a fresh figure all night: A ends at 81.5 % (the plan's 78.4 % came "
|
||||
"after it had passed), B full",
|
||||
abs(fa["soc"][0] - 81.5) < 0.5 and fa["soc"][1] > 94.5)
|
||||
check("sensors silent from 17:05: A ends where the fresh run ends it "
|
||||
f"({si['soc'][0]:.1f} against {fa['soc'][0]:.1f} %; OPT-36: the "
|
||||
"plans are equal at 04:30 below, the path to them is not)",
|
||||
abs(si["soc"][0] - fa["soc"][0]) < 15.0 and si["soc"][0] > 75.0)
|
||||
f"({si['soc'][0]:.1f} against {fa['soc'][0]:.1f} %)",
|
||||
abs(si["soc"][0] - fa["soc"][0]) < 0.3)
|
||||
check("... and so does B (Cheap hours; the wide no-forecast gap does not "
|
||||
f"stop its slices): {si['soc'][1]:.1f} against {fa['soc'][1]:.1f} %",
|
||||
abs(si["soc"][1] - fa["soc"][1]) < 0.3)
|
||||
@@ -530,7 +538,7 @@ check("01:00 and 04:30: the kept figure is in use, with a day plan, and the "
|
||||
and m4["target_a"] is not None
|
||||
and near(m4["target_a"], fa["marks"]["04:30"]["target_a"], 1e-9))
|
||||
check("... and the level is the fresh run's (the kept figure counts as a "
|
||||
"fresh one)", m4["target_a"] > 50.0)
|
||||
"fresh one)", near(m4["target_a"], 95.0, 0.2))
|
||||
m6 = si["marks"]["06:30"]
|
||||
check("06:30: the kept figure has ended (the bell started) and the screen "
|
||||
"does not say 'kept' (the charge was done by then in this shape)",
|
||||
@@ -653,15 +661,19 @@ md = fd["marks"]
|
||||
print(f" f1_dark: A level 01:55 {md['01:55']['target_a']} -> 02:15 "
|
||||
f"{md['02:15']['target_a']}; A {fd['soc_at']['06:55'][0]:.1f} % "
|
||||
"at 06:55")
|
||||
# OPT-36: the level (82.3 % at 02:15) falls to 64.2 % by 04:00 as B's cheap run
|
||||
# is made longer (B's expected give grows); A stops at its SoC of that moment
|
||||
# (72.8 %) and the latch holds 64.2 % after the figure ends.
|
||||
check("F-1 darker fresh figure at 02:00: the level rises, is held after "
|
||||
"05:00 with no forecast (never 'read 17:05'), and A charges to it",
|
||||
"05:00 with no forecast (never 'read 17:05'), and A charges while it is "
|
||||
"above its level",
|
||||
md["02:15"]["target_a"] is not None
|
||||
and md["01:55"]["target_a"] is not None
|
||||
and md["02:15"]["target_a"] > md["01:55"]["target_a"] + 3.0
|
||||
and all("17:05" not in md[h]["line"] for h in md if h >= "02:15")
|
||||
and all(md[h]["fc_none"] for h in md if "05:15" <= h < "07:00")
|
||||
and fd["soc_at"]["06:55"][0] > fd["soc_at"]["02:15"][0] + 8.0
|
||||
and fd["soc_at"]["06:55"][0] < md["02:15"]["target_a"] + 1.5)
|
||||
and near(md["05:15"]["target_a"], 64.24, 0.2)
|
||||
and near(fd["soc_at"]["06:55"][0], 72.8, 0.5))
|
||||
|
||||
tb = R["tail_bfull"]
|
||||
check("B full: the run ends at 06:33 before A is at its level, so the next "
|
||||
|
||||
@@ -225,9 +225,7 @@ check("Leftover solar and Cheap hours: a give block exactly on the give run "
|
||||
# OPT-36: a larger evening (4.8 kW) so that B (Cheap hours) does not cover the
|
||||
# dear hours alone and A still buys from the grid; A starts at 30 %.
|
||||
c_n = S.make("dynamic", at(0, 18), soc=(30.0, 40.0), evening=4800.0)
|
||||
RUN_END = c_n.mode_runs.cheap.end
|
||||
END_S = RUN_END.astimezone(S.brussels(RUN_END).tzinfo).strftime("%H:%M")
|
||||
END_H = S.brussels(RUN_END).hour + S.brussels(RUN_END).minute / 60.0
|
||||
END_S, END_H = "03:00", 3.0 # the run's end, recomputed for this house
|
||||
nb = tab(c_n, at(0, 18))["days"][0]["batteries"]
|
||||
check("in the night before the cheap run both charge from the grid in it "
|
||||
f"(01:00 to {END_S}), then give at 17:00",
|
||||
@@ -251,11 +249,11 @@ def at_h(b, h):
|
||||
return dict((round(x, 3), v) for x, v in b["levels"]).get(h, float("nan"))
|
||||
|
||||
|
||||
check("the curve charges in a grid block: A (planned level 64 %) and B "
|
||||
check("the curve charges in a grid block: A (planned level 73 %) and B "
|
||||
"(Cheap hours, to the end of its run) are well above where they "
|
||||
"were at 01:00, and stay put after the run",
|
||||
all(at_h(b, END_H) - at_h(b, 1.0) > 8.0
|
||||
and abs(at_h(b, END_H + 1.0) - at_h(b, END_H)) < 1e-6
|
||||
and abs(at_h(b, 4.0) - at_h(b, END_H)) < 1e-6
|
||||
for b in nb) and nb[0]["levels"][0][1] == 30.0)
|
||||
# Modes off: the verdict's legs.
|
||||
c_f = S.make("off", at(10, 7))
|
||||
|
||||
Reference in New Issue
Block a user