Browse Source

limitations

Lucas Gautheron 1 year ago
parent
commit
c7f11817dd
7 changed files with 23 additions and 6 deletions
  1. 10 0
      README.md
  2. 1 1
      mix_simul/scenarios.py
  3. BIN
      output/dispatch.png
  4. BIN
      output/gap_distribution.png
  5. BIN
      output/load_supply.png
  6. BIN
      output/storage.png
  7. 12 5
      run.py

+ 10 - 0
README.md

@@ -8,6 +8,7 @@
 - [Usage du code](#usage-du-code)
   - [Exécution](#exécution)
 - [Output](#output)
+- [Limitations](#limitations)
 - [TODO](#todo)
 
 Ce code implémente une simulation simpliste de mix énergétiques, avec une modélisation (grossière) des sources intermittentes, du nucléaire, des sources pilotables, des moyens de stockage, et de la flexibilité de la demande.
@@ -100,6 +101,15 @@ python run.py --begin 2012-01-01 --end 2015-01-01
 
 ![](output/gap_distribution.png)
 
+## Limitations
+
+Outre les limitations mentionnées plus haut, il faut en souligner d'autres ici :
+
+ - Chaque optimisation du modèle est effectuée séquentiellement. Mais de meilleurs optimums pourraient être trouvés en optimisant simultanément toutes les commandes (stockage, flexibilités et sources pilotables). En particulier la performance du modèle actuel dépend de l'ordre des optimisations.
+ - La question cruciale est bien sûr, pour quoi optimise-t-on ? Dans le cas présent la fonction de coût est égale à l'énergie manquante totale pour absorber la demande française avec la production française. Cela est pertinent dans le sens suivant : ce manque doit être compensé par, soit, des énergies fossiles raréfiées émettrices de CO2 ; soit des importations ; soit de l'effacement. On cherche à minimiser simultanément ces conséquences indésirables, et donc l'énergie totale manquante est un paramètre relativement sensé. Cependant, une telle stratégie :
+   - ne tient pas compte du fait que l'on peut aussi vouloir minimiser la fréquence des situations dans lesquelles ni l'importation ni d'éventuelles capacités fossiles additionnelles ne peuvent couvrir la demande (black-out). Autrement dit, au lieu de minimiser le déficit total (ou de façon équivalente, le déficit /moyen/), on peut chercher à vouloir minimiser les événements extrêmes.
+   - ici l'optimisation est faite au niveau national, ce qui minimise le recours aux interconnexions avec l'Europe. On pourrait aussi chercher à considérer des optimums européens, lesquels seront d'autant meilleurs que l'usage des interconnexions (et donc leur capacité a fortiori) est important. À cela j'opposerais que l'on peut vouloir étudier un scénario pessimiste concernant les facultés de coopération futures entre pays européens.
+
 ## TODO
 
   - Optimisation de disponibilité du nucléaire (actuellement un facteur de charge constant est assumé, ce qui pénalise les modèles avec nucléaire)

+ 1 - 1
mix_simul/scenarios.py

@@ -12,7 +12,7 @@ class Scenario:
         sources: dict = {},
         multistorage: dict = {},
         flexibility_power=0,
-        flexibility_time=8,
+        flexibility_time=4,
     ) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
         """Run a mix scenario.
 

BIN
output/dispatch.png


BIN
output/gap_distribution.png


BIN
output/load_supply.png


BIN
output/storage.png


+ 12 - 5
run.py

@@ -246,7 +246,9 @@ for scenario in scenarios:
         hist = np.cumsum(hist)
         hist = 100 * (hist - hist.min()) / hist.ptp()
         keep = np.abs(bin_edges[:-1]) < 50
-        ax.plot(bin_edges[:-1][keep], hist[keep], lw=1, label="power gap", color="#ff7f00")
+        ax.plot(
+            bin_edges[:-1][keep], hist[keep], lw=1, label="power gap", color="#ff7f00"
+        )
 
         years = pd.date_range(start=begin, end=end, freq="Y")
         for i in range(len(years) - 1):
@@ -280,6 +282,11 @@ for axs in [axes, axes_dispatch, axes_storage]:
 
 flex = "With" if flexibility else "Without"
 
+
+def plot_path(name):
+    return "output/{}{}.png".format(name, "_flexibility" if flexibility else "")
+
+
 plt.subplots_adjust(wspace=0, hspace=0)
 fig.suptitle(
     f"Simulations based on {begin}--{end} weather data.\n{flex} consumption flexibility; no nuclear seasonality (unrealistic)"
@@ -292,7 +299,7 @@ fig.legend(
     ncol=len(labels),
     bbox_transform=fig.transFigure,
 )
-fig.savefig("output/load_supply.png", bbox_inches="tight", dpi=200)
+fig.savefig(plot_path("load_supply"), bbox_inches="tight", dpi=200)
 
 fig_storage.suptitle(
     f"Simulations based on {begin}--{end} weather data.\n{flex} consumption flexibility; no nuclear seasonality (unrealistic)"
@@ -305,7 +312,7 @@ fig_storage.legend(
     ncol=len(labels_storage),
     bbox_transform=fig_storage.transFigure,
 )
-fig_storage.savefig("output/storage.png", bbox_inches="tight", dpi=200)
+fig_storage.savefig(plot_path("storage"), bbox_inches="tight", dpi=200)
 
 fig_dispatch.suptitle(
     f"Simulations based on {begin}--{end} weather data.\n{flex} consumption flexibility; no nuclear seasonality (unrealistic)"
@@ -318,7 +325,7 @@ fig_dispatch.legend(
     ncol=len(labels_dispatch),
     bbox_transform=fig_dispatch.transFigure,
 )
-fig_dispatch.savefig("output/dispatch.png", bbox_inches="tight", dpi=200)
+fig_dispatch.savefig(plot_path("dispatch"), bbox_inches="tight", dpi=200)
 
 fig_gap_distribution.suptitle(
     f"Power gap cumulative distribution (%)\nSimulations based on {begin}--{end} weather data.\n{flex} consumption flexibility; no nuclear seasonality (unrealistic)"
@@ -332,7 +339,7 @@ fig_gap_distribution.legend(
 )
 fig_gap_distribution.text(1, 0, "Lucas Gautheron", ha="right")
 fig_gap_distribution.savefig(
-    "output/gap_distribution.png", bbox_inches="tight", dpi=200
+    plot_path("gap_distribution"), bbox_inches="tight", dpi=200
 )
 
 plt.show()