@@ -54,8 +54,8 @@ def __init__(self, file_name=None):
5454 def calc_optimum (
5555 self , _start_dt : dt .datetime | None = None , _start_soc : float | None = None
5656 ):
57- # _start_dt = datetime.datetime(year=2026, month=1, day=8, hour=16 , minute=0)
58- # _start_soc = 37
57+ # _start_dt = datetime.datetime(year=2026, month=1, day=8, hour=18 , minute=0)
58+ # _start_soc = 18.8
5959 if _start_dt is not None or _start_soc is not None :
6060 self .debug = True
6161 logging .info (f"Debug = { self .debug } " )
@@ -324,6 +324,7 @@ def calc_optimum(
324324 pv_dc_num = 0
325325 for b in range (B ):
326326 for s in range (len (self .battery_options [b ]["solar" ])):
327+ solar_option = self .battery_options [b ]["solar" ][s ]
327328 if pv_dc_num <= 9 :
328329 pv_dc_varcode .append ("pv_dc_" + str (pv_dc_num ))
329330 pv_dc_num += 1
@@ -334,12 +335,12 @@ def calc_optimum(
334335 == "true"
335336 ):
336337 prod = (
337- max (0 , getattr (row , self . solar [ s ] ["name" ]))
338+ max (0 , getattr (row , solar_option ["name" ]))
338339 * interval_fraction [- 1 ]
339340 )
340341 else :
341342 prod = self .calc_prod_solar (
342- self . battery_options [ b ][ "solar" ][ s ] ,
343+ solar_option ,
343344 row .time ,
344345 gr ,
345346 hour_fraction [- 1 ],
@@ -612,8 +613,8 @@ def calc_optimum(
612613 for b in range (B )
613614 ]
614615
615- # ac_to_dc met aan uit #############################################################
616616 """
617+ # declaraties laden ac_to_dc met aan uit zonder sos #######################################
617618 #ac_to_dc: wat er gaat er vanuit ac naar de omvormer
618619 ac_to_dc = [[model.add_var(var_type=CONTINUOUS, lb=0, ub=max_charge_power[b])
619620 for u in range(U)] for b in range(B)]
@@ -626,8 +627,9 @@ def calc_optimum(
626627 # vermogens klasse aan/uit
627628 ac_to_dc_st_on = [[[model.add_var(var_type=BINARY)
628629 for u in range(U)] for cs in range(CS[b])] for b in range(B)]
630+ # tot hier declaraties laden zonder sos ##################################################
629631 """
630- # met sos #### ###############################################################
632+ # declaraties laden met sos ###############################################################
631633 ac_to_dc_samples = [
632634 [charge_stages [b ][cs ]["power" ] / 1000 for cs in range (CS [b ])]
633635 for b in range (B )
@@ -664,8 +666,10 @@ def calc_optimum(
664666 ]
665667 for b in range (B )
666668 ]
667- # tot hier met sos
668- # '''
669+ # declaraties laden tot hier met sos ####################################################
670+
671+ """
672+ # vanaf hier decalaties ontladen zonder sos #############################################
669673 ac_from_dc = [
670674 [
671675 model.add_var(
@@ -700,6 +704,51 @@ def calc_optimum(
700704 [[model.add_var(var_type=BINARY) for _ in range(U)] for _ in range(DS[b])]
701705 for b in range(B)
702706 ]
707+ # tot hier declaraties ontladen zonder sos ###############################################
708+ """
709+
710+ # vanaf hier declaraties ontladen met sos ###############################################
711+ ac_from_dc_samples = [
712+ [
713+ (
714+ discharge_stages [b ][ds ]["power" ]
715+ / 1000
716+ )
717+ for ds in range (DS [b ])]
718+ for b in range (B )
719+ ]
720+ dc_to_ac_samples = [
721+ [
722+ (
723+ discharge_stages [b ][ds ]["power" ]
724+ / (discharge_stages [b ][ds ]["efficiency" ] * 1000 )
725+ )
726+ for ds in range (DS [b ])
727+ ]
728+ for b in range (B )
729+ ]
730+ ac_from_dc = [
731+ [
732+ model .add_var (
733+ var_type = CONTINUOUS ,
734+ lb = 0 ,
735+ ub = min (reduced_power [b ][u ], max_discharge_power [b ]),
736+ )
737+ for u in range (U )
738+ ]
739+ for b in range (B )
740+ ]
741+ ac_from_dc_on = [
742+ [model .add_var (var_type = BINARY ) for _ in range (U )] for _ in range (B )
743+ ]
744+ ac_from_dc_w = [
745+ [
746+ [model .add_var (var_type = CONTINUOUS , lb = 0 , ub = 1 ) for _ in range (DS [b ])]
747+ for _ in range (U )
748+ ]
749+ for b in range (B )
750+ ]
751+ # tot hier declaraties ontladen met sos ###############################################
703752
704753 # energiebalans dc
705754 dc_from_ac = [
@@ -771,7 +820,7 @@ def calc_optimum(
771820 for b in range (B ):
772821 for u in range (U ):
773822 # laden, alles uitgedrukt in vermogen kW
774- # met aan/uit
823+ # vanaf hier laden met aan/uit zonder sos
775824 """
776825 for cs in range(CS[b]):
777826 model += (ac_to_dc_st[b][cs][u] <=
@@ -787,8 +836,9 @@ def calc_optimum(
787836 model += dc_from_ac[b][u] == xsum(ac_to_dc_st[b][cs][u] * \
788837 charge_stages[b][cs]["efficiency"]
789838 for cs in range(CS[b]))
839+ # tot hier laden met aan/uit zonder sos #######################################
790840 """
791- # met sos
841+ # vanaf hier laden met sos ######################################################
792842 model += xsum (ac_to_dc_w [b ][u ][cs ] for cs in range (CS [b ])) == 1
793843 model += (
794844 xsum (
@@ -811,9 +861,10 @@ def calc_optimum(
811861 ],
812862 2 ,
813863 )
814- # tot hier met sos
864+ # tot hier constraints laden met sos
815865
816- # ontladen
866+ """
867+ # vanaf hier ontladen met aan/uit
817868 for ds in range(DS[b]):
818869 model += (
819870 ac_from_dc_st[b][ds][u]
@@ -837,6 +888,33 @@ def calc_optimum(
837888 ac_from_dc_st[b][ds][u] / discharge_stages[b][ds]["efficiency"]
838889 for ds in range(DS[b])
839890 )
891+ #tot hier ontladen met aan/uit
892+ """
893+
894+ # vanaf hier ontladen met sos ######################################################
895+ model += xsum (ac_from_dc_w [b ][u ][ds ] for ds in range (DS [b ])) <= 1
896+ model += (
897+ xsum (
898+ ac_from_dc_w [b ][u ][ds ] * ac_from_dc_samples [b ][ds ]
899+ for ds in range (DS [b ])
900+ )
901+ == ac_from_dc [b ][u ]
902+ )
903+ model += (
904+ xsum (
905+ ac_from_dc_w [b ][u ][ds ] * dc_to_ac_samples [b ][ds ]
906+ for ds in range (DS [b ])
907+ )
908+ == dc_to_ac [b ][u ]
909+ )
910+ model .add_sos (
911+ [
912+ (ac_from_dc_w [b ][u ][ds ], ac_from_dc_samples [b ][ds ])
913+ for ds in range (DS [b ])
914+ ],
915+ 2 ,
916+ )
917+ # tot hier constraints ontladen met sos
840918
841919 for b in range (B ):
842920 for u in range (U + 1 ):
@@ -3111,6 +3189,24 @@ def calc_optimum(
31113189 dc_to_ac_eff =
31123190 discharge_stages[ds]["efficiency"] * 100.0
31133191 """
3192+ if self .log_level == logging .INFO :
3193+ # debug laden
3194+ if ac_to_dc [b ][u ].x > 0.0 :
3195+ logging .info (f"Laad volume in uur { u } { uur [u ]} "
3196+ f"{ ac_from_dc [b ][u ].x * hour_fraction [u ]} kWh" )
3197+ for cs in range (CS [b ]):
3198+ if ac_to_dc_w [b ][u ][cs ].x > 0 :
3199+ logging .info (f"{ cs } { ac_to_dc_w [b ][u ][cs ].x } "
3200+ f"{ ac_to_dc_samples [b ][cs ]} " )
3201+
3202+ # debug ontladen
3203+ if ac_from_dc [b ][u ].x > 0.0 :
3204+ logging .info (f"Ontlaad volume in uur { u } { uur [u ]} "
3205+ f"{ ac_from_dc [b ][u ].x * hour_fraction [u ]} kWh" )
3206+ for ds in range (DS [b ]):
3207+ if ac_from_dc_w [b ][u ][ds ].x > 0 :
3208+ logging .info (f"{ ds } { ac_from_dc_w [b ][u ][ds ].x } "
3209+ f"{ ac_from_dc_samples [b ][ds ]} " )
31143210
31153211 row = [
31163212 str (uur [u ]),
@@ -3599,7 +3695,7 @@ def calc_optimum(
35993695 ############################################
36003696 for b in range (B ):
36013697 # vermogen aan ac kant
3602- netto_vermogen = int (1000 * (ac_to_dc [b ][0 ].x - ac_from_dc [b ][0 ].x ))
3698+ netto_vermogen_bat = int (1000 * (ac_to_dc [b ][0 ].x - ac_from_dc [b ][0 ].x ))
36033699 minimum_power = int (self .battery_options [b ]["minimum power" ])
36043700 battery_state_on_value = self .config .get (
36053701 ["entity set operating mode on" ], self .battery_options [b ], "Aan"
@@ -3608,27 +3704,68 @@ def calc_optimum(
36083704 ["entity set operating mode off" ], self .battery_options [b ], "Uit"
36093705 )
36103706 bat_name = self .battery_options [b ]["name" ]
3611- if abs (netto_vermogen ) <= 20 :
3612- netto_vermogen = 0
3707+ if abs (netto_vermogen_bat ) <= 20 :
3708+ netto_vermogen_bat = 0
36133709 new_state = battery_state_off_value
36143710 stop_omvormer = None
36153711 balance = False
36163712 elif abs (c_l [0 ].x - c_t [0 ].x ) <= 0.01 :
36173713 new_state = battery_state_on_value
36183714 balance = True
36193715 stop_omvormer = None
3620- elif abs (netto_vermogen ) < minimum_power :
3716+ elif abs (netto_vermogen_bat ) < minimum_power :
36213717 new_state = battery_state_on_value
36223718 balance = False
36233719 new_ts = (
36243720 start_dt .timestamp ()
3625- + (abs (netto_vermogen ) / minimum_power ) * self .interval_s
3721+ + (abs (netto_vermogen_bat ) / minimum_power ) * self .interval_s
36263722 )
36273723 stop_omvormer = dt .datetime .fromtimestamp (int (new_ts ))
3628- if netto_vermogen > 0 :
3629- netto_vermogen = minimum_power
3724+ if netto_vermogen_bat > 0 :
3725+ netto_vermogen_bat = minimum_power
3726+ else :
3727+ netto_vermogen_bat = - minimum_power
3728+ elif ac_to_dc [b ][0 ].x > 0.0 : # laden met optimaal vermogen
3729+ sum_weight_factor = 0
3730+ sum_power = 0 # in W
3731+ for cs in range (CS [b ]):
3732+ wf = ac_to_dc_w [b ][0 ][ds ].x
3733+ if wf > 0 :
3734+ sum_weight_factor += wf
3735+ sum_power += wf * charge_stages [b ][cs ]["power" ]
3736+ if sum_weight_factor < 0.95 :
3737+ new_state = battery_state_on_value
3738+ balance = False
3739+ netto_vermogen_bat = round (sum_power / sum_weight_factor )
3740+ new_ts = (
3741+ start_dt .timestamp () + self .interval_s * sum_weight_factor * interval_fraction [0 ]
3742+ )
3743+ stop_omvormer = dt .datetime .fromtimestamp (int (new_ts ))
36303744 else :
3631- netto_vermogen = - minimum_power
3745+ new_state = battery_state_on_value
3746+ balance = False
3747+ stop_omvormer = None
3748+ elif ac_from_dc [b ][0 ].x > 0.0 : # ontladen met optimaal vermogen
3749+ sum_weight_factor = 0
3750+ sum_power = 0 # in W
3751+ for ds in range (DS [b ]):
3752+ wf = ac_from_dc_w [b ][0 ][ds ].x
3753+ if wf > 0 :
3754+ sum_weight_factor += wf
3755+ sum_power += wf * discharge_stages [b ][ds ]["power" ]
3756+ if sum_weight_factor < 0.95 :
3757+ new_state = battery_state_on_value
3758+ balance = False
3759+ netto_vermogen_bat = - round (sum_power / sum_weight_factor )
3760+ new_ts = (
3761+ start_dt .timestamp () + self .interval_s * sum_weight_factor *
3762+ interval_fraction [0 ]
3763+ )
3764+ stop_omvormer = dt .datetime .fromtimestamp (int (new_ts ))
3765+ else :
3766+ new_state = battery_state_on_value
3767+ balance = False
3768+ stop_omvormer = None
36323769 else :
36333770 new_state = battery_state_on_value
36343771 balance = False
@@ -3652,7 +3789,7 @@ def calc_optimum(
36523789 if self .debug :
36533790 logging .info (
36543791 f"Netto vermogen naar(+)/uit(-) batterij { bat_name } "
3655- f"zou zijn: { netto_vermogen } W"
3792+ f"zou zijn: { netto_vermogen_bat } W"
36563793 )
36573794 if stop_omvormer :
36583795 logging .info (f"tot: { stop_str } " )
@@ -3667,7 +3804,7 @@ def calc_optimum(
36673804 self .set_entity_value (
36683805 "entity set power feedin" ,
36693806 self .battery_options [b ],
3670- netto_vermogen ,
3807+ netto_vermogen_bat ,
36713808 )
36723809 self .set_entity_option (
36733810 "entity set operating mode" , self .battery_options [b ], new_state
@@ -3678,7 +3815,7 @@ def calc_optimum(
36783815 )
36793816 logging .info (
36803817 f"Netto vermogen naar(+)/uit(-) omvormer { bat_name } : "
3681- f"{ netto_vermogen } W"
3818+ f"{ netto_vermogen_bat } W"
36823819 f"{ ' tot: ' + stop_str if stop_omvormer else '' } "
36833820 )
36843821 logging .info (
@@ -4555,7 +4692,7 @@ def main():
45554692 if arg .lower () == "calc_baseloads" :
45564693 da_calc .run_task_function ("calc_baseloads" )
45574694 continue
4558- if arg .lower () == "train " :
4695+ if arg .lower () == "train_ml_predictions " :
45594696 da_calc .run_task_function ("train_ml_predictions" )
45604697 continue
45614698 da_calc .db_da .log_pool_status ()
0 commit comments