@@ -357,9 +357,7 @@ def solve(self, force: bool = False, warmstart: bool = False, **kwargs) -> None:
357
357
elif mode == "spores" :
358
358
results = self ._solve_spores (self .config .solve )
359
359
else :
360
- results = self .backend ._solve (
361
- warmstart = warmstart , ** self .config .solve .model_dump ()
362
- )
360
+ results = self .backend ._solve (self .config .solve , warmstart = warmstart )
363
361
364
362
log_time (
365
363
LOGGER ,
@@ -510,6 +508,9 @@ def _solve_operate(self, solver_config: config.Solve) -> xr.Dataset:
510
508
Optimisation is undertaken iteratively for slices of the timeseries, with
511
509
some data being passed between slices.
512
510
511
+ Args:
512
+ solver_config (config.Solve): Calliope Solver configuration object.
513
+
513
514
Returns:
514
515
xr.Dataset: Results dataset.
515
516
"""
@@ -519,9 +520,7 @@ def _solve_operate(self, solver_config: config.Solve) -> xr.Dataset:
519
520
520
521
LOGGER .info ("Optimisation model | Running first time window." )
521
522
522
- step_results = self .backend ._solve (
523
- warmstart = False , ** solver_config .model_dump ()
524
- )
523
+ iteration_results = self .backend ._solve (solver_config , warmstart = False )
525
524
526
525
results_list = []
527
526
@@ -531,15 +530,17 @@ def _solve_operate(self, solver_config: config.Solve) -> xr.Dataset:
531
530
f"Optimisation model | Running time window starting at { windowstep_as_string } ."
532
531
)
533
532
results_list .append (
534
- step_results .sel (timesteps = slice (None , windowstep - self ._TS_OFFSET ))
533
+ iteration_results .sel (
534
+ timesteps = slice (None , windowstep - self ._TS_OFFSET )
535
+ )
535
536
)
536
- previous_step_results = results_list [- 1 ]
537
+ previous_iteration_results = results_list [- 1 ]
537
538
horizonstep = self ._model_data .horizonsteps .sel (windowsteps = windowstep )
538
539
new_inputs = self .inputs .sel (
539
540
timesteps = slice (windowstep , horizonstep )
540
541
).drop_vars (["horizonsteps" , "windowsteps" ], errors = "ignore" )
541
542
542
- if len (new_inputs .timesteps ) != len (step_results .timesteps ):
543
+ if len (new_inputs .timesteps ) != len (iteration_results .timesteps ):
543
544
LOGGER .info (
544
545
"Optimisation model | Reaching the end of the timeseries. "
545
546
"Re-building model with shorter time horizon."
@@ -554,18 +555,16 @@ def _solve_operate(self, solver_config: config.Solve) -> xr.Dataset:
554
555
self .backend .update_parameter (param_name , param_data )
555
556
self .backend .inputs [param_name ] = param_data
556
557
557
- if "storage" in step_results :
558
+ if "storage" in iteration_results :
558
559
self .backend .update_parameter (
559
560
"storage_initial" ,
560
- self ._recalculate_storage_initial (previous_step_results ),
561
+ self ._recalculate_storage_initial (previous_iteration_results ),
561
562
)
562
563
563
- step_results = self .backend ._solve (
564
- warmstart = False , ** solver_config .model_dump ()
565
- )
564
+ iteration_results = self .backend ._solve (solver_config , warmstart = False )
566
565
567
566
self ._start_window_idx = 0
568
- results_list .append (step_results .sel (timesteps = slice (windowstep , None )))
567
+ results_list .append (iteration_results .sel (timesteps = slice (windowstep , None )))
569
568
results = xr .concat (results_list , dim = "timesteps" , combine_attrs = "no_conflicts" )
570
569
results .attrs ["termination_condition" ] = "," .join (
571
570
set (result .attrs ["termination_condition" ] for result in results_list )
@@ -599,21 +598,18 @@ def _solve_spores(self, solver_config: config.Solve) -> xr.Dataset:
599
598
xr.Dataset: Results dataset.
600
599
"""
601
600
LOGGER .info ("Optimisation model | Resetting SPORES parameters." )
602
- self .backend .update_parameter (
603
- "spores_score" , self .inputs .get ("spores_score" , xr .DataArray (0 ))
604
- )
605
- self .backend .update_parameter (
606
- "spores_baseline_cost" ,
607
- self .inputs .get ("spores_baseline_cost" , xr .DataArray (np .inf )),
608
- )
601
+ for init_param in ["spores_score" , "spores_baseline_cost" ]:
602
+ default = xr .DataArray (self .inputs .attrs ["defaults" ][init_param ])
603
+ self .backend .update_parameter (
604
+ init_param , self .inputs .get (init_param , default )
605
+ )
606
+
609
607
self .backend .set_objective (self .config .build .objective )
610
608
611
609
spores_config : config .SolveSpores = solver_config .spores
612
610
if not spores_config .skip_baseline_run :
613
611
LOGGER .info ("Optimisation model | Running baseline model." )
614
- baseline_results = self .backend ._solve (
615
- warmstart = False , ** solver_config .model_dump ()
616
- )
612
+ baseline_results = self .backend ._solve (solver_config , warmstart = False )
617
613
else :
618
614
LOGGER .info ("Optimisation model | Using existing baseline model results." )
619
615
baseline_results = self .results .copy ()
@@ -625,20 +621,19 @@ def _solve_spores(self, solver_config: config.Solve) -> xr.Dataset:
625
621
spores_config .save_per_spore_path / "baseline.nc"
626
622
)
627
623
624
+ # We store the results from each iteration in the `results_list` to later concatenate into a single dataset.
628
625
results_list : list [xr .Dataset ] = [baseline_results ]
629
626
spore_range = range (1 , spores_config .number + 1 )
630
627
for spore in spore_range :
631
628
LOGGER .info (f"Optimisation model | Running SPORE { spore } ." )
632
629
self ._spores_update_model (baseline_results , results_list [- 1 ], spores_config )
633
630
634
- step_results = self .backend ._solve (
635
- warmstart = False , ** solver_config .model_dump ()
636
- )
637
- results_list .append (step_results )
631
+ iteration_results = self .backend ._solve (solver_config , warmstart = False )
632
+ results_list .append (iteration_results )
638
633
639
634
if spores_config .save_per_spore_path is not None :
640
635
LOGGER .info (f"Optimisation model | Saving SPORE { spore } to file." )
641
- step_results .assign_coords (spores = spore ).to_netcdf (
636
+ iteration_results .assign_coords (spores = spore ).to_netcdf (
642
637
spores_config .save_per_spore_path / f"spore_{ spore } .nc"
643
638
)
644
639
@@ -672,7 +667,10 @@ def _spores_update_model(
672
667
previous_cap = previous_results ["flow_cap" ].where (spores_techs )
673
668
674
669
# Make sure that penalties are applied only to non-negligible deployments of capacity
675
- min_relevant_size = 0.1 * previous_cap .max (["nodes" , "techs" ])
670
+ min_relevant_size = (
671
+ spores_config .score_iteration_threshold_relative
672
+ * previous_cap .max (["nodes" , "techs" ])
673
+ )
676
674
677
675
new_score = (
678
676
# Where capacity was deployed more than the minimal relevant size, assign an integer penalty (score)
0 commit comments