Repository: CLOVER-energy/CLOVER

Issue:
Prioitise self-generation bug
### Describe the bug
When running CLOVER, there are two possible flows for how the code selects its source of power, which are set within the `scenario_inputs.yaml` file:
- `prioiritise_self_generation: true`, where CLOVER should attempt to get power from the solar and storage first,
- and `prioritise_self_generation: false`, where CLOVER should get its power from the grid first.

However, when running a CLOVER `optimisation`, there is **no difference** between these two flows, with the same outputs being selected despite the second scenario being expected to produce systems with a lower renewable capacity due to the reliance on the grid as the primary source of power.

### To Reproduce
Steps to reproduce the behavior:
1. Set up two identical scenarios in the `scenario_inputs.yaml` file with the only difference between the two being the `prioritise_self_generation` flag;
2. Set up two identical optimisations in the `optimisation_inputs.yaml` file with the only difference between the two being the scenario that each uses;
3. Run an optimisation with `python -u -m src.clover --location <location_name> --optimisation`;
4. See error.

### Expected behaviour
The two scenario should produce different results, with the `true` scenario selecting a higher renewable capacity and the `false` scenario selecting a smaller renewable capacity.

### Screenshots
Screenshots are not needed to explain this problem.

## Additional Information
### Desktop
**(please complete the following information)**
 - OS: Linux, applies to all
 - Installation setup: downloaded source from GitHub
 - Version: 5.0.1b1
 - Branch: `dev`

### Modifications
This version is up-to-date with `origin/dev`.


Discussion:

Patch:
diff --git a/src/clover/simulation/storage.py b/src/clover/simulation/storage.py
index 9b4a58a..44061d6 100644
--- a/src/clover/simulation/storage.py
+++ b/src/clover/simulation/storage.py
@@ -640,16 +640,43 @@ def get_electric_battery_storage_profile(  # pylint: disable=too-many-locals, to
             grid_energy = pd.DataFrame([0] * (end_hour - start_hour))
         # as needed for load
         remaining_profile = (grid_energy[0] <= 0).mul(load_energy[0])  # type: ignore
+        logger.debug(
+            "Remainig profile: %s kWh",
+            round(float(np.sum(remaining_profile)), 2),  # type: ignore [arg-type]
+        )
 
         # Then take energy from PV if generated
+        logger.debug(
+            "Renewables profile: %s kWh",
+            f"{round(float(np.sum(renewables_energy)), 2)}",  # type: ignore [arg-type]
+        )
         battery_storage_profile = pd.DataFrame(
             renewables_energy[0].values - remaining_profile.values  # type: ignore
         )
+        logger.debug(
+            "Storage profile: %s kWh",
+            f"{round(float(np.sum(battery_storage_profile)), 2)}",  # type: ignore [arg-type]
+        )
+
         renewables_energy_used_directly = pd.DataFrame(
-            (battery_storage_profile > 0)  # type: ignore
-            .mul(remaining_profile[0])  # type: ignore
-            .add((battery_storage_profile < 0).mul(renewables_energy))  # type: ignore
+            ((renewables_energy[0] > 0) * (remaining_profile > 0))  # type: ignore [call-overload]
+            * pd.concat(  # type: ignore [call-overload]
+                [renewables_energy[0], remaining_profile], axis=1  # type: ignore [call-overload]
+            ).min(axis=1)
+        )
+
+        logger.debug(
+            "Grid energy: %s kWh",
+            f"{round(float(np.sum(grid_energy)), 2)}",  # type: ignore [arg-type]
+        )
+        renewables_direct_rounded: float = round(
+            float(np.sum(renewables_energy_used_directly)), 2  # type: ignore [arg-type]
+        )
+        logger.debug(
+            "Renewables direct: %s kWh",
+            round(float(np.sum(renewables_energy_used_directly)), 2),  # type: ignore [arg-type]
         )
+        logger.debug("Renewables direct: %s kWh", renewables_direct_rounded)
 
     battery_storage_profile.columns = pd.Index([ColumnHeader.STORAGE_PROFILE.value])
     grid_energy.columns = pd.Index([ColumnHeader.GRID_ENERGY.value])


Test patch:
diff --git a/src/clover/tests/integration/test_clover.py b/src/clover/tests/integration/test_clover.py
index 38aa070..d2ec24e 100644
--- a/src/clover/tests/integration/test_clover.py
+++ b/src/clover/tests/integration/test_clover.py
@@ -480,24 +480,24 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
         )
         self._check_output(
             info_file_data,
-            average_daily_diesel=1.65,
+            average_daily_diesel=0.0,
             average_daily_grid_energy=7.196,
             average_daily_grid_times=9.338,
-            average_daily_renewables_energy=4.262,
+            average_daily_renewables_energy=3.893,
             average_daily_storage_energy=7.52,
-            blackouts=0.1,
-            cumulative_cost=32249.869,
-            cumulative_ghgs=91620.383,
+            blackouts=0.029,
+            cumulative_cost=31641.481,
+            cumulative_ghgs=84941.765,
             cumulative_pv_generation=36685.0,
-            diesel_capacity=3.0,
-            diesel_times=0.12,
+            diesel_capacity=0.0,
+            diesel_times=0.0,
             final_pv_size=19.0,
             final_storage_size=21.34,
             initial_pv_size=20.0,
             initial_storage_size=25.0,
-            lcue=1.124,
-            renewables_fraction=0.571,
-            unmet_energy_fraction=0.018,
+            lcue=1.212,
+            renewables_fraction=0.613,
+            unmet_energy_fraction=0.031,
         )
 
     @pytest.mark.integrest
@@ -515,24 +515,24 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
         )
         self._check_output(
             info_file_data,
-            average_daily_diesel=8.821,
+            average_daily_diesel=6.568,
             average_daily_grid_energy=7.196,
             average_daily_grid_times=9.338,
-            average_daily_renewables_energy=4.262,
+            average_daily_renewables_energy=3.893,
             average_daily_storage_energy=0.0,
             blackouts=0.1,
-            cumulative_cost=26343.181,
-            cumulative_ghgs=100650.761,
+            cumulative_cost=25059.446,
+            cumulative_ghgs=109974.46,
             cumulative_pv_generation=36685.0,
             diesel_capacity=3.0,
-            diesel_times=0.394,
+            diesel_times=0.202,
             final_pv_size=19.0,
             final_storage_size=0.0,
             initial_pv_size=20.0,
             initial_storage_size=0.0,
-            lcue=0.934,
-            renewables_fraction=0.21,
-            unmet_energy_fraction=0.016,
+            lcue=0.95,
+            renewables_fraction=0.22,
+            unmet_energy_fraction=0.062,
         )
 
     @pytest.mark.integrest
@@ -626,24 +626,24 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
         )
         self._check_output(
             info_file_data,
-            average_daily_diesel=5.548,
+            average_daily_diesel=2.116,
             average_daily_grid_energy=0.0,
             average_daily_grid_times=0.0,
-            average_daily_renewables_energy=4.271,
+            average_daily_renewables_energy=5.801,
             average_daily_storage_energy=9.807,
-            blackouts=0.099,
-            cumulative_cost=32209.939,
-            cumulative_ghgs=91493.592,
+            blackouts=0.1,
+            cumulative_cost=33821.539,
+            cumulative_ghgs=96230.431,
             cumulative_pv_generation=36685.0,
             diesel_capacity=3.0,
-            diesel_times=0.356,
+            diesel_times=0.071,
             final_pv_size=19.0,
             final_storage_size=20.227,
             initial_pv_size=20.0,
             initial_storage_size=25.0,
-            lcue=1.179,
-            renewables_fraction=0.717,
-            unmet_energy_fraction=0.011,
+            lcue=1.309,
+            renewables_fraction=0.881,
+            unmet_energy_fraction=0.084,
         )
 
     @pytest.mark.integrest
@@ -661,24 +661,24 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
         )
         self._check_output(
             info_file_data,
-            average_daily_diesel=14.879,
+            average_daily_diesel=12.193,
             average_daily_grid_energy=0.0,
             average_daily_grid_times=0.0,
-            average_daily_renewables_energy=4.271,
+            average_daily_renewables_energy=5.801,
             average_daily_storage_energy=0.0,
             blackouts=0.1,
-            cumulative_cost=29025.727,
-            cumulative_ghgs=104115.842,
+            cumulative_cost=26548.761,
+            cumulative_ghgs=108666.131,
             cumulative_pv_generation=36685.0,
             diesel_capacity=3.0,
-            diesel_times=0.726,
+            diesel_times=0.443,
             final_pv_size=19.0,
             final_storage_size=0.0,
             initial_pv_size=20.0,
             initial_storage_size=0.0,
-            lcue=1.092,
-            renewables_fraction=0.223,
-            unmet_energy_fraction=0.011,
+            lcue=0.997,
+            renewables_fraction=0.322,
+            unmet_energy_fraction=0.045,
         )
 
     @pytest.mark.integrest
@@ -775,11 +775,11 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             average_daily_diesel=0.0,
             average_daily_grid_energy=7.196,
             average_daily_grid_times=9.338,
-            average_daily_renewables_energy=4.262,
+            average_daily_renewables_energy=3.893,
             average_daily_storage_energy=7.52,
-            blackouts=0.22,
-            cumulative_cost=31728.191,
-            cumulative_ghgs=85650.33,
+            blackouts=0.029,
+            cumulative_cost=31641.481,
+            cumulative_ghgs=84941.765,
             cumulative_pv_generation=36685.0,
             diesel_capacity=0.0,
             diesel_times=0.0,
@@ -787,9 +787,9 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             final_storage_size=21.34,
             initial_pv_size=20.0,
             initial_storage_size=25.0,
-            lcue=1.172,
-            renewables_fraction=0.621,
-            unmet_energy_fraction=0.105,
+            lcue=1.212,
+            renewables_fraction=0.613,
+            unmet_energy_fraction=0.031,
         )
 
     @pytest.mark.integrest
@@ -810,11 +810,11 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             average_daily_diesel=0.0,
             average_daily_grid_energy=7.196,
             average_daily_grid_times=9.338,
-            average_daily_renewables_energy=4.262,
+            average_daily_renewables_energy=3.893,
             average_daily_storage_energy=0.0,
-            blackouts=0.493,
-            cumulative_cost=33980.723,
-            cumulative_ghgs=196112.02,
+            blackouts=0.302,
+            cumulative_cost=33894.013,
+            cumulative_ghgs=195403.455,
             cumulative_pv_generation=36685.0,
             diesel_capacity=0.0,
             diesel_times=0.0,
@@ -822,9 +822,9 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             final_storage_size=0.0,
             initial_pv_size=20.0,
             initial_storage_size=0.0,
-            lcue=1.256,
-            renewables_fraction=0.372,
-            unmet_energy_fraction=0.485,
+            lcue=1.329,
+            renewables_fraction=0.351,
+            unmet_energy_fraction=0.411,
         )
 
     @pytest.mark.integrest
@@ -922,11 +922,11 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             average_daily_diesel=0.0,
             average_daily_grid_energy=0.0,
             average_daily_grid_times=0.0,
-            average_daily_renewables_energy=4.271,
+            average_daily_renewables_energy=5.801,
             average_daily_storage_energy=9.807,
-            blackouts=0.454,
-            cumulative_cost=34386.293,
-            cumulative_ghgs=102913.66,
+            blackouts=0.171,
+            cumulative_cost=34260.245,
+            cumulative_ghgs=101882.52,
             cumulative_pv_generation=36685.0,
             diesel_capacity=0.0,
             diesel_times=0.0,
@@ -934,9 +934,9 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             final_storage_size=20.227,
             initial_pv_size=20.0,
             initial_storage_size=25.0,
-            lcue=1.534,
+            lcue=1.415,
             renewables_fraction=1.0,
-            unmet_energy_fraction=0.306,
+            unmet_energy_fraction=0.196,
         )
 
     @pytest.mark.integrest
@@ -957,11 +957,11 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             average_daily_diesel=0.0,
             average_daily_grid_energy=0.0,
             average_daily_grid_times=0.0,
-            average_daily_renewables_energy=4.271,
+            average_daily_renewables_energy=5.801,
             average_daily_storage_energy=0.0,
-            blackouts=0.826,
-            cumulative_cost=41931.345,
-            cumulative_ghgs=256032.195,
+            blackouts=0.543,
+            cumulative_cost=41805.298,
+            cumulative_ghgs=255001.055,
             cumulative_pv_generation=36685.0,
             diesel_capacity=0.0,
             diesel_times=0.0,
@@ -969,9 +969,9 @@ class SimulationTests(_BaseTest):  # pylint: disable=too-many-public-methods
             final_storage_size=0.0,
             initial_pv_size=20.0,
             initial_storage_size=0.0,
-            lcue=3.249,
+            lcue=2.548,
             renewables_fraction=1.0,
-            unmet_energy_fraction=0.801,
+            unmet_energy_fraction=0.692,
         )
 
     @pytest.mark.integtest