diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 1a55a4de6..79fee3f89 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -27,10 +27,16 @@
-
+
+
+
-
-
+
+
+
+
+
+
@@ -136,13 +142,8 @@
-
-
-
-
-
-
+
@@ -160,14 +161,14 @@
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"ignore.virus.scanning.warn.message": "true",
- "last_opened_file_path": "/home/santi/Documentos/Git/GitHub/GridCal/src/GridCal/Engine/Simulations/GTEP",
+ "last_opened_file_path": "C:/Users/santi/Desktop/CLON/REPO",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"run.code.analysis.last.selected.profile": "aDefault",
- "settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable",
+ "settings.editor.selected.configurable": "reference.idesettings.debugger.python",
"vue.rearranger.settings.migration": "true"
}
}
@@ -178,18 +179,18 @@
-
-
+
+
-
-
-
-
-
+
+
+
+
+
@@ -248,20 +249,20 @@
-
-
+
+
-
-
+
+
-
+
@@ -270,20 +271,20 @@
-
-
+
+
-
-
+
+
-
+
@@ -292,7 +293,7 @@
-
+
@@ -300,12 +301,12 @@
-
+
-
+
@@ -322,12 +323,12 @@
-
+
-
+
@@ -344,12 +345,12 @@
-
+
-
+
@@ -470,19 +471,19 @@
-
-
+
+
-
+
-
-
-
+
+
+
@@ -1164,388 +1165,354 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
- 1686526501186
-
-
+
+ 1678370722175
+
+
- 1686526501186
+ 1678370722175
-
- 1686773930405
-
-
+
+ 1678376859776
+
+
- 1686773930405
+ 1678376859776
-
- 1686862290650
-
-
+
+ 1678555802840
+
+
- 1686862290651
+ 1678555802840
-
- 1687333032453
-
-
+
+ 1678744531484
+
+
- 1687333032453
+ 1678744531484
-
- 1687333625912
-
-
+
+ 1678782195149
+
+
- 1687333625912
+ 1678782195149
-
- 1687362884503
-
-
+
+ 1678787211752
+
+
- 1687362884504
+ 1678787211753
-
- 1687365072207
-
-
+
+ 1681476059778
+
+
- 1687365072207
+ 1681476059778
-
- 1687367382350
-
-
+
+ 1681476921626
+
+
- 1687367382350
+ 1681476921626
-
- 1687367394517
-
-
+
+ 1681488526968
+
+
- 1687367394517
+ 1681488526969
-
- 1687419697278
-
-
+
+ 1681729624884
+
+
- 1687419697279
+ 1681729624885
-
- 1687455957693
-
-
+
+ 1681760737423
+
+
- 1687455957693
+ 1681760737424
-
- 1687459766589
-
-
+
+ 1682013200390
+
+
- 1687459766589
+ 1682013200391
-
- 1687727770235
-
-
+
+ 1682015052756
+
+
- 1687727770236
+ 1682015052756
-
- 1687766573076
-
-
+
+ 1682022998715
+
+
- 1687766573077
+ 1682022998715
-
- 1687770607385
-
-
+
+ 1682092175145
+
+
- 1687770607385
+ 1682092175145
-
- 1687799559288
-
-
+
+ 1682163627247
+
+
- 1687799559289
+ 1682163627247
-
- 1687804987106
-
-
+
+ 1682176448632
+
+
- 1687804987106
+ 1682176448632
-
- 1687805510425
-
-
+
+ 1682180026691
+
+
- 1687805510425
+ 1682180026691
-
- 1687853842967
-
-
+
+ 1683712765751
+
+
- 1687853842967
+ 1683712765751
-
- 1687856380255
-
-
+
+ 1683736972339
+
+
- 1687856380255
+ 1683736972340
-
- 1687864427461
-
-
+
+ 1683743817369
+
+
- 1687864427461
+ 1683743817369
-
- 1687881917992
-
-
+
+ 1683743985094
+
+
- 1687881917992
+ 1683743985094
-
- 1687938132794
-
-
+
+ 1683791524059
+
+
- 1687938132794
+ 1683791524059
-
- 1687940216400
-
-
+
+ 1683797255728
+
+
- 1687940216400
+ 1683797255728
-
- 1688049629627
-
-
+
+ 1683825137014
+
+
- 1688049629627
+ 1683825137014
-
- 1688056303197
-
-
+
+ 1683877159802
+
+
- 1688056303197
+ 1683877159802
-
- 1688129827051
-
-
+
+ 1683984806074
+
+
- 1688129827051
+ 1683984806075
-
- 1688330842845
-
-
+
+ 1683985103660
+
+
- 1688330842845
+ 1683985103660
-
- 1688368530597
-
-
+
+ 1684142477756
+
+
- 1688368530597
+ 1684142477756
-
- 1688374423336
-
-
+
+ 1684164546863
+
+
- 1688374423336
+ 1684164546863
-
- 1688374655510
-
-
+
+ 1684170286866
+
+
- 1688374655510
+ 1684170286866
-
- 1688400201512
-
-
+
+ 1684185808700
+
+
- 1688400201512
+ 1684185808700
-
- 1688468189203
-
-
+
+ 1684186628312
+
+
- 1688468189203
+ 1684186628312
-
- 1688477374295
-
-
+
+ 1684237252324
+
+
- 1688477374295
+ 1684237252324
-
- 1688482180696
-
-
+
+ 1686351630774
+
+
- 1688482180697
+ 1686351630775
-
- 1688489345707
-
-
+
+ 1686525840499
+
+
- 1688489345707
+ 1686525840499
-
- 1688491428633
-
-
+
+ 1686526501186
+
+
- 1688491428633
+ 1686526501186
-
- 1688503778634
-
-
+
+ 1686773930405
+
+
- 1688503778635
+ 1686773930405
-
- 1688544358055
-
-
+
+ 1686862290650
+
+
- 1688544358055
+ 1686862290651
-
- 1688550551903
-
-
+
+ 1687333032453
+
+
- 1688550551903
+ 1687333032453
-
- 1688556960092
-
-
+
+ 1687333625912
+
+
- 1688556960092
+ 1687333625912
-
- 1688561658932
-
-
+
+ 1687362884503
+
+
- 1688561658932
+ 1687362884504
-
- 1688565817390
-
-
+
+ 1687365072207
+
+
- 1688565817390
+ 1687365072207
-
- 1688573324429
-
-
+
+ 1687367382350
+
+
- 1688573324429
+ 1687367382350
-
- 1688659860849
-
-
+
+ 1687367394517
+
+
- 1688659860849
+ 1687367394517
-
- 1689074817527
-
-
+
+ 1687419697278
+
+
- 1689074817527
+ 1687419697279
-
- 1689184637451
-
-
+
+ 1687508421219
+
+
- 1689184637452
+ 1687508421219
-
- 1689252500250
-
-
+
+ 1687517208830
+
+
- 1689252500250
+ 1687517208830
-
- 1689253351759
-
-
+
+ 1687546864812
+
+
- 1689253351759
+ 1687546864812
-
+
@@ -1587,32 +1554,32 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1717,6 +1684,17 @@
115
+
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/IO/excel_interface.py
+ 280
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/NumericalMethods/helm_power_flow.py
+ 185
+
+
file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/NumericalMethods/jacobian_based_power_flow.py
1166
@@ -1802,25 +1780,15 @@
135
-
- file://$PROJECT_DIR$/src/GridCal/Gui/Session/results_model.py
- 157
-
-
-
- file://$PROJECT_DIR$/src/GridCal/Gui/Session/results_model.py
- 159
-
-
file://$PROJECT_DIR$/src/GridCal/Engine/Core/DataStructures/generator_data.py
191
- file://$PROJECT_DIR$/src/GridCal/Gui/Session/session.py
- 124
-
+ file://$PROJECT_DIR$/src/GridCal/Engine/IO/power_world_parser.py
+ 201
+
file://$PROJECT_DIR$/src/research/state_estimation/5_bus_se.py
@@ -1832,6 +1800,11 @@
56
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/StateEstimation/state_estimation.py
+ 285
+
+
file://$PROJECT_DIR$/src/research/PTDF/PTDF_ku_leuven.py
137
@@ -1842,6 +1815,11 @@
68
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/results_template.py
+ 101
+
+
file://$PROJECT_DIR$/src/tests/test_generator_q_control.py
28
@@ -1857,6 +1835,16 @@
543
+
+ file://$PROJECT_DIR$/src/tests/test_opf_time_series.py
+ 53
+
+
+
+ file://$PROJECT_DIR$/src/tests/test_opf_time_series.py
+ 58
+
+
file://$PROJECT_DIR$/src/GridCal/Engine/Core/admittance_matrices.py
398
@@ -1868,14 +1856,32 @@
- file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/power_flow_worker.py
- 491
-
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/NumericalMethods/ac_jacobian.py
+ 140
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/NumericalMethods/derivatives.py
+ 165
+
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/NumericalMethods/derivatives.py
+ 159
+
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/NumericalMethods/derivatives.py
+ 145
+
- file://$PROJECT_DIR$/src/GridCal/Engine/IO/cim/cim_parser.py
- 855
-
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/PowerFlow/NumericalMethods/newton_raphson.py
+ 127
+
file://$PROJECT_DIR$/src/research/derivatives_and_jacobian/branch_power_2.py
@@ -1908,228 +1914,242 @@
- file://$PROJECT_DIR$/src/GridCal/Gui/GridEditorWidget/generic_graphics.py
- 25
-
+ file://$PROJECT_DIR$/src/tests/test_unbalanced_faults.py
+ 57
+
- file://$PROJECT_DIR$/src/GridCal/Engine/IO/zip_interface.py
- 51
-
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/ShortCircuitStudies/short_circuit.py
+ 103
+
file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/ShortCircuitStudies/short_circuit_worker.py
268
-
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Simulations/ShortCircuitStudies/short_circuit_worker.py
+ 106
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Engine/Core/Compilers/circuit_to_newton_pa.py
+ 1010
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Gui/Main/GridCalMain.py
+ 1515
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Gui/Main/GridCalMain.py
+ 1519
+
+
+
+ file://$PROJECT_DIR$/src/GridCal/Gui/GridEditorWidget/solar_power_wizzard.py
+ 88
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
\ No newline at end of file
diff --git a/Grids_and_profiles/grids/IEEE 118 Bus - ntc_areas.gridcal b/Grids_and_profiles/grids/IEEE 118 Bus - ntc_areas.gridcal
index 5cfe4ac6e..d5b9ee554 100644
Binary files a/Grids_and_profiles/grids/IEEE 118 Bus - ntc_areas.gridcal and b/Grids_and_profiles/grids/IEEE 118 Bus - ntc_areas.gridcal differ
diff --git a/requirements.txt b/requirements.txt
index 691dc31e7..34482943c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -23,4 +23,6 @@ pyarrow
fastparquet
darkdetect
pyqtdarktheme
-nptyping
\ No newline at end of file
+nptyping
+windpowerlib
+pvlib
diff --git a/requirements_nose.txt b/requirements_nose.txt
index a4c1ce3aa..5e2fbde54 100644
--- a/requirements_nose.txt
+++ b/requirements_nose.txt
@@ -71,3 +71,5 @@ wcwidth==0.2.5
xlrd==2.0.1
xlwt==1.3.0
nptyping==2.5.0
+windpowerlib
+pvlib
\ No newline at end of file
diff --git a/requirements_venv.txt b/requirements_venv.txt
index 40c65031f..fdae13cb2 100644
--- a/requirements_venv.txt
+++ b/requirements_venv.txt
@@ -19,4 +19,6 @@ wcwidth==0.1.7
zipp==0.5.2
numba>=0.46
Cython
-nptyping
\ No newline at end of file
+nptyping
+windpowerlib
+pvlib
\ No newline at end of file
diff --git a/src/GridCal/Gui/GridEditorWidget/generator_graphics.py b/src/GridCal/Gui/GridEditorWidget/generator_graphics.py
index 034964a57..fe256d453 100644
--- a/src/GridCal/Gui/GridEditorWidget/generator_graphics.py
+++ b/src/GridCal/Gui/GridEditorWidget/generator_graphics.py
@@ -20,8 +20,9 @@
from GridCal.Engine.Core.Devices.Injections.generator import Generator, DeviceType
from GridCal.Gui.GridEditorWidget.generic_graphics import ACTIVE, DEACTIVATED, OTHER, Circle
from GridCal.Gui.GuiFunctions import ObjectsModel
-from GridCal.Gui.GridEditorWidget.messages import yes_no_question
+from GridCal.Gui.GridEditorWidget.messages import yes_no_question, info_msg
from GridCal.Gui.GridEditorWidget.matplotlibwidget import MatplotlibWidget
+from GridCal.Gui.GridEditorWidget.solar_power_wizzard import SolarPvWizard
class GeneratorEditor(QDialog):
@@ -182,6 +183,12 @@ def contextMenuEvent(self, event):
pa.setIcon(plot_icon)
pa.triggered.connect(self.plot)
+ pv = menu.addAction('Solar photovoltaic wizard')
+ pv_icon = QIcon()
+ pv_icon.addPixmap(QPixmap(":/Icons/icons/plot.svg"))
+ pv.setIcon(pv_icon)
+ pv.triggered.connect(self.solar_pv_wizard)
+
da = menu.addAction('Delete')
del_icon = QIcon()
del_icon.addPixmap(QPixmap(":/Icons/icons/delete3.svg"))
@@ -287,6 +294,33 @@ def edit(self):
if dlg.exec_():
pass
+ def solar_pv_wizard(self):
+ """
+ Open the appropriate editor dialogue
+ :return:
+ """
+
+ if self.diagramScene.circuit.has_time_series:
+
+ time_array = self.diagramScene.circuit.time_profile
+
+ dlg = SolarPvWizard(time_array=time_array,
+ peak_power=self.api_object.Pmax,
+ latitude=self.api_object.bus.latitude,
+ longitude=self.api_object.bus.longitude,
+ gen_name=self.api_object.name,
+ bus_name=self.api_object.bus.name)
+ if dlg.exec_():
+ if dlg.is_accepted:
+ if len(dlg.P) == len(self.api_object.P_prof):
+ self.api_object.P_prof = dlg.P
+
+ self.plot()
+ else:
+ raise Exception("Wrong length from the solar photovoltaic wizard")
+ else:
+ info_msg("You need to have time profiles for this function")
+
def mousePressEvent(self, QGraphicsSceneMouseEvent):
"""
mouse press: display the editor
diff --git a/src/GridCal/Gui/GridEditorWidget/solar_power_wizzard.py b/src/GridCal/Gui/GridEditorWidget/solar_power_wizzard.py
new file mode 100644
index 000000000..e131d66e7
--- /dev/null
+++ b/src/GridCal/Gui/GridEditorWidget/solar_power_wizzard.py
@@ -0,0 +1,161 @@
+# GridCal
+# Copyright (C) 2015 - 2023 Santiago PeƱate Vera
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+import numpy as np
+from typing import List, Union, Tuple
+from datetime import datetime
+
+import pandas as pd
+import requests
+from PySide6 import QtCore, QtWidgets
+import pvlib
+from GridCal.Gui.GridEditorWidget.messages import error_msg
+from GridCal.Engine.basic_structures import Logger, DateVec
+
+
+def get_pv_lib_weather_df(time_array: DateVec, latitude, longitude, peak_power) -> Tuple[bool, pd.DataFrame]:
+ """
+
+ :param time_array:
+ :param latitude:
+ :param longitude:
+ :param peak_power:
+ :return:
+ """
+ max_year_span = 2015 - 2010 # 10 years, this is due to PVLIB's database
+
+ ts1 = time_array[0]
+ ts2 = time_array[-1]
+ year_span = ts2.year - ts1.year
+
+ if year_span <= max_year_span:
+
+ s = datetime(year=2010, month=ts1.month, day=ts1.day, hour=ts1.hour, minute=ts1.minute)
+ e = datetime(year=2010 + year_span, month=ts2.month, day=ts2.day, hour=ts2.hour, minute=ts2.minute)
+
+ new_ts = pd.to_datetime([datetime(year=2010 + ts.year - ts1.year,
+ month=ts.month,
+ day=ts.day,
+ hour=ts.hour,
+ minute=ts.minute) for ts in time_array]).values.astype(float).astype(
+ np.int64)
+
+ try:
+
+ data, meta, inputs = pvlib.iotools.get_pvgis_hourly(latitude=latitude,
+ longitude=longitude,
+ start=s,
+ end=e,
+ pvcalculation=True,
+ peakpower=peak_power * 1e3, # kW
+ )
+
+ data.index = data.index.values.astype(float).astype(np.int64)
+ data2 = data.reindex(new_ts).interpolate(method='linear')
+
+ P = data2['P'].values / 1e6 # Power in MW
+
+ return True, data2
+
+ except requests.HTTPError as err:
+ error_msg("pvlib's http request failed :(\n" + str(err))
+ return False, pd.DataFrame(data={'P': np.zeros(len(time_array))})
+
+ else:
+ error_msg("The time span of your profile is {} year(s), Pvlib's span is 10 years maximum")
+ return False, pd.DataFrame(data={'P': np.zeros(len(time_array))})
+
+
+class SolarPvWizard(QtWidgets.QDialog):
+ """
+ New solar photovoltaic wizard window
+ """
+
+ def __init__(self, time_array: List[str], peak_power: float, latitude: float, longitude: float,
+ gen_name='', bus_name='',
+ title='solar photovoltaic wizard'):
+ """
+
+ :param time_array: array of time values
+ :param peak_power: generator peak power in MW
+ :param latitude: latitude (float)
+ :param longitude: longitude (float)
+ :param title: Window title
+ """
+ QtWidgets.QDialog.__init__(self)
+ self.setObjectName("self")
+ self.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
+ self.main_layout = QtWidgets.QVBoxLayout(self)
+
+ self.is_accepted: bool = False
+ self.selected_indices: List[int] = list()
+
+ self.label_gen = QtWidgets.QLabel()
+ self.label_gen.setText("Generator {}".format(gen_name))
+
+ self.label_bus = QtWidgets.QLabel()
+ self.label_bus.setText("Bus: {}".format(bus_name))
+
+ self.label_peak = QtWidgets.QLabel()
+ self.label_peak.setText("peak power {} MW".format(peak_power))
+
+ self.lat_label = QtWidgets.QLabel()
+ self.lat_label.setText("Latitude {} deg".format(latitude))
+
+ self.lon_label = QtWidgets.QLabel()
+ self.lon_label.setText("Longitude {} deg".format(longitude))
+
+ self.peak_power = peak_power
+ self.latitude = latitude
+ self.longitude = longitude
+ self.time_array = time_array
+ self.P = np.zeros(len(time_array))
+
+ # accept button
+ self.accept_btn = QtWidgets.QPushButton()
+ self.accept_btn.setText('Accept')
+ self.accept_btn.clicked.connect(self.accept_click)
+
+ # add all to the GUI
+ self.main_layout.addWidget(self.label_gen)
+ self.main_layout.addWidget(self.label_bus)
+ self.main_layout.addWidget(self.label_peak)
+ self.main_layout.addWidget(self.lat_label)
+ self.main_layout.addWidget(self.lon_label)
+ self.main_layout.addWidget(self.accept_btn)
+
+ self.setLayout(self.main_layout)
+
+ self.setWindowTitle(title)
+
+ h = 260
+ self.resize(h, int(0.8 * h))
+
+ def accept_click(self):
+ """
+ Accept and close
+ """
+ ok, df = get_pv_lib_weather_df(time_array=self.time_array,
+ latitude=self.latitude,
+ longitude=self.longitude,
+ peak_power=self.peak_power)
+
+ if ok:
+ self.P = df['P'].values / 1e6 # Power in MW
+
+ self.is_accepted = ok
+ self.accept()
diff --git a/src/GridCal/Gui/GridEditorWidget/wind_power_wizzard.py b/src/GridCal/Gui/GridEditorWidget/wind_power_wizzard.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/setup.py b/src/setup.py
index 58832d69f..a90920ce2 100755
--- a/src/setup.py
+++ b/src/setup.py
@@ -92,6 +92,8 @@
"darkdetect",
"pyqtdarktheme",
"nptyping",
+ "windpowerlib",
+ "pvlib"
]
extras_require = {