From 9cf1692a94a856be47eead831060560bf5b0b311 Mon Sep 17 00:00:00 2001 From: uvchik Date: Mon, 9 Dec 2019 11:20:53 +0100 Subject: [PATCH 01/16] Add stickler and black config files --- .stickler.yml | 13 +++++++++++++ pyproject.toml | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 .stickler.yml create mode 100644 pyproject.toml diff --git a/.stickler.yml b/.stickler.yml new file mode 100644 index 00000000..b744ef91 --- /dev/null +++ b/.stickler.yml @@ -0,0 +1,13 @@ +linters: + flake8: + python: 3 + black: + config: ./pyproject.toml + fixer: true: + +files: + ignore: + - 'src/generated/*' + +fixers: + enable: true diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0f5afa16 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,18 @@ +[tool.black] +line-length = 88 +target-version = ['py36', 'py37', 'py38'] +include = '\.pyi?$' +exclude = ''' +/( + \.eggs + | \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist +)/ +''' \ No newline at end of file From 356ad2e723bf09e82cbace1a6aee909a244378cf Mon Sep 17 00:00:00 2001 From: uvchik Date: Mon, 9 Dec 2019 11:31:18 +0100 Subject: [PATCH 02/16] Add a long line --- windpowerlib/wind_turbine.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index a4210895..363c3bef 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -507,8 +507,7 @@ def get_turbine_types(turbine_library='local', print_out=True, filter_=True): """ if turbine_library == 'local': - filename = os.path.join(os.path.dirname(__file__), 'oedb', - 'turbine_data.csv') + filename = os.path.join(os.path.dirname(__file__), 'oedb', 'turbine_data.csv') df = pd.read_csv(filename, index_col=0).reset_index() elif turbine_library == 'oedb': df = load_turbine_data_from_oedb() From 344ef4e0477b1435641f9bc69ba21533a2307966 Mon Sep 17 00:00:00 2001 From: uvchik Date: Mon, 9 Dec 2019 11:36:04 +0100 Subject: [PATCH 03/16] Adapt stickler config file --- .stickler.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stickler.yml b/.stickler.yml index b744ef91..1b4f61b8 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -3,11 +3,11 @@ linters: python: 3 black: config: ./pyproject.toml - fixer: true: + fixer: true files: ignore: - - 'src/generated/*' + - '.github/*' fixers: enable: true From d21da5309a8c31d2ec176827187c46b797ff1d6b Mon Sep 17 00:00:00 2001 From: uvchik Date: Mon, 9 Dec 2019 12:03:50 +0100 Subject: [PATCH 04/16] Reduce config file to get stickler work --- .stickler.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.stickler.yml b/.stickler.yml index 1b4f61b8..52cf0790 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -1,13 +1,4 @@ linters: flake8: python: 3 - black: - config: ./pyproject.toml - fixer: true - -files: - ignore: - - '.github/*' - -fixers: - enable: true + max-line-length: 79 From 04eb0f57fb55dbdf2a471f38668febb1f342c459 Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:05:03 +0100 Subject: [PATCH 05/16] Use tested config files --- .stickler.yml | 8 ++++++++ .travis.yml | 13 +++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.stickler.yml b/.stickler.yml index 52cf0790..49b2bdd8 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -2,3 +2,11 @@ linters: flake8: python: 3 max-line-length: 79 + select: C,E,F,W,B,B950 + ignore: E203, E501, W503 + black: + config: ./pyproject.toml + fixer: true + +fixers: + enable: true diff --git a/.travis.yml b/.travis.yml index 9fb5c8f3..446da186 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,24 +2,25 @@ language: python matrix: include: - - python: 3.5 - python: 3.6 + dist: xenial + sudo: true - python: 3.7 dist: xenial sudo: true # command to install dependencies -#before_install: -# - sudo apt-get install coinor-cbc +before_install: + - sudo apt-get install libhdf5-serial-dev proj-bin libproj-dev libgeos-dev libspatialindex-dev install: + - pip install cython - pip install . - - pip install coveralls sphinx sphinx_rtd_theme nbformat pytest-cov jupyter + - pip install coveralls # command to run tests script: - - coverage run --rcfile=.coveragerc --source windpowerlib -m py.test - - coverage report + - nosetests --with-doctest --with-coverage -c nose.cfg after_success: - coveralls From fa641d6b7615c1854a2a0942019b711d60a5de61 Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:07:28 +0100 Subject: [PATCH 06/16] Revert "Use tested config files" This reverts commit 04eb0f57fb55dbdf2a471f38668febb1f342c459. --- .stickler.yml | 8 -------- .travis.yml | 13 ++++++------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/.stickler.yml b/.stickler.yml index 49b2bdd8..52cf0790 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -2,11 +2,3 @@ linters: flake8: python: 3 max-line-length: 79 - select: C,E,F,W,B,B950 - ignore: E203, E501, W503 - black: - config: ./pyproject.toml - fixer: true - -fixers: - enable: true diff --git a/.travis.yml b/.travis.yml index 446da186..9fb5c8f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,25 +2,24 @@ language: python matrix: include: + - python: 3.5 - python: 3.6 - dist: xenial - sudo: true - python: 3.7 dist: xenial sudo: true # command to install dependencies -before_install: - - sudo apt-get install libhdf5-serial-dev proj-bin libproj-dev libgeos-dev libspatialindex-dev +#before_install: +# - sudo apt-get install coinor-cbc install: - - pip install cython - pip install . - - pip install coveralls + - pip install coveralls sphinx sphinx_rtd_theme nbformat pytest-cov jupyter # command to run tests script: - - nosetests --with-doctest --with-coverage -c nose.cfg + - coverage run --rcfile=.coveragerc --source windpowerlib -m py.test + - coverage report after_success: - coveralls From 6e9b0a53e9bf54acf9cdf72d12713e91f8aef55a Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:08:17 +0100 Subject: [PATCH 07/16] Use tested yml and toml files --- .stickler.yml | 8 ++++++++ pyproject.toml | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.stickler.yml b/.stickler.yml index 52cf0790..49b2bdd8 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -2,3 +2,11 @@ linters: flake8: python: 3 max-line-length: 79 + select: C,E,F,W,B,B950 + ignore: E203, E501, W503 + black: + config: ./pyproject.toml + fixer: true + +fixers: + enable: true diff --git a/pyproject.toml b/pyproject.toml index 0f5afa16..3dbb3802 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [tool.black] -line-length = 88 +line-length = 79 target-version = ['py36', 'py37', 'py38'] include = '\.pyi?$' exclude = ''' @@ -15,4 +15,4 @@ exclude = ''' | build | dist )/ -''' \ No newline at end of file +''' From 199eb9dfeb837bb0c20d2b9b452d64950230c730 Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:10:34 +0100 Subject: [PATCH 08/16] Test automatic fixing of stickler and black --- example/modelchain_example.py | 48 ++--- example/test_examples.py | 28 +-- example/turbine_cluster_modelchain_example.py | 34 ++-- tests/test_density.py | 28 +-- tests/test_modelchain.py | 174 +++++++++--------- tests/test_power_curves.py | 48 ++--- tests/test_power_output.py | 86 ++++----- tests/test_temperature.py | 8 +- tests/test_tools.py | 44 ++--- tests/test_turbine_cluster_modelchain.py | 144 +++++++-------- tests/test_wake_losses.py | 16 +- tests/test_wind_farm.py | 74 ++++---- tests/test_wind_speed.py | 50 ++--- tests/test_wind_turbine.py | 20 +- windpowerlib/__init__.py | 6 +- windpowerlib/modelchain.py | 68 +++---- windpowerlib/power_curves.py | 46 ++--- windpowerlib/power_output.py | 22 +-- windpowerlib/tools.py | 20 +- windpowerlib/turbine_cluster_modelchain.py | 34 ++-- windpowerlib/wake_losses.py | 38 ++-- windpowerlib/wind_farm.py | 86 ++++----- windpowerlib/wind_speed.py | 22 +-- windpowerlib/wind_turbine.py | 132 ++++++------- windpowerlib/wind_turbine_cluster.py | 32 ++-- 25 files changed, 654 insertions(+), 654 deletions(-) diff --git a/example/modelchain_example.py b/example/modelchain_example.py index 6aec70f2..07149387 100644 --- a/example/modelchain_example.py +++ b/example/modelchain_example.py @@ -19,7 +19,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt = None + plt=None from windpowerlib import ModelChain from windpowerlib import WindTurbine @@ -65,23 +65,23 @@ def get_weather_data(filename='weather.csv', **kwargs): """ if 'datapath' not in kwargs: - kwargs['datapath'] = os.path.join(os.path.split( + kwargs['datapath']=os.path.join(os.path.split( os.path.dirname(__file__))[0], 'example') - file = os.path.join(kwargs['datapath'], filename) + file=os.path.join(kwargs['datapath'], filename) # read csv file - weather_df = pd.read_csv( + weather_df=pd.read_csv( file, index_col=0, header=[0, 1], date_parser=lambda idx: pd.to_datetime(idx, utc=True)) # change type of index to datetime and set time zone - weather_df.index = pd.to_datetime(weather_df.index).tz_convert( + weather_df.index=pd.to_datetime(weather_df.index).tz_convert( 'Europe/Berlin') # change type of height from str to int by resetting columns - l0 = [_[0] for _ in weather_df.columns] - l1 = [int(_[1]) for _ in weather_df.columns] - weather_df.columns = [l0, l1] + l0=[_[0] for _ in weather_df.columns] + l1=[int(_[1]) for _ in weather_df.columns] + weather_df.columns=[l0, l1] return weather_df @@ -111,16 +111,16 @@ def initialize_wind_turbines(): # specification of wind turbine where data is provided in the oedb # turbine library - enercon_e126 = { + enercon_e126={ 'turbine_type': 'E-126/4200', # turbine type as in register 'hub_height': 135 # in m } # initialize WindTurbine object - e126 = WindTurbine(**enercon_e126) + e126=WindTurbine(**enercon_e126) # specification of own wind turbine (Note: power values and nominal power # have to be in Watt) - my_turbine = { + my_turbine={ 'nominal_power': 3e6, # in W 'hub_height': 105, # in m 'power_curve': pd.DataFrame( @@ -129,19 +129,19 @@ def initialize_wind_turbines(): 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}) # in m/s } # initialize WindTurbine object - my_turbine = WindTurbine(**my_turbine) + my_turbine=WindTurbine(**my_turbine) # specification of wind turbine where power coefficient curve and nominal # power is provided in an own csv file - csv_path = os.path.join(os.path.dirname(__file__), 'data') - dummy_turbine = { + csv_path=os.path.join(os.path.dirname(__file__), 'data') + dummy_turbine={ 'turbine_type': "DUMMY 1", 'hub_height': 100, # in m 'rotor_diameter': 70, # in m 'path': csv_path } # initialize WindTurbine object - dummy_turbine = WindTurbine(**dummy_turbine) + dummy_turbine=WindTurbine(**dummy_turbine) return my_turbine, e126, dummy_turbine @@ -175,13 +175,13 @@ def calculate_power_output(weather, my_turbine, e126, dummy_turbine): # power output calculation for my_turbine # initialize ModelChain with default parameters and use run_model method # to calculate power output - mc_my_turbine = ModelChain(my_turbine).run_model(weather) + mc_my_turbine=ModelChain(my_turbine).run_model(weather) # write power output time series to WindTurbine object - my_turbine.power_output = mc_my_turbine.power_output + my_turbine.power_output=mc_my_turbine.power_output # power output calculation for e126 # own specifications for ModelChain setup - modelchain_data = { + modelchain_data={ 'wind_speed_model': 'logarithmic', # 'logarithmic' (default), # 'hellman' or # 'interpolation_extrapolation' @@ -196,16 +196,16 @@ def calculate_power_output(weather, my_turbine, e126, dummy_turbine): 'hellman_exp': None} # None (default) or None # initialize ModelChain with own specifications and use run_model method # to calculate power output - mc_e126 = ModelChain(e126, **modelchain_data).run_model(weather) + mc_e126=ModelChain(e126, **modelchain_data).run_model(weather) # write power output time series to WindTurbine object - e126.power_output = mc_e126.power_output + e126.power_output=mc_e126.power_output # power output calculation for example_turbine # own specification for 'power_output_model' - mc_example_turbine = ModelChain( + mc_example_turbine=ModelChain( dummy_turbine, power_output_model='power_coefficient_curve').run_model(weather) - dummy_turbine.power_output = mc_example_turbine.power_output + dummy_turbine.power_output=mc_example_turbine.power_output return @@ -272,8 +272,8 @@ def run_example(): Runs the basic example. """ - weather = get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine = initialize_wind_turbines() + weather=get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=initialize_wind_turbines() calculate_power_output(weather, my_turbine, e126, dummy_turbine) plot_or_print(my_turbine, e126, dummy_turbine) diff --git a/example/test_examples.py b/example/test_examples.py index 8b18e8db..aed5fd0c 100644 --- a/example/test_examples.py +++ b/example/test_examples.py @@ -18,8 +18,8 @@ class TestExamples: def test_modelchain_example_flh(self): # tests full load hours - weather = mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() + weather=mc_e.get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() mc_e.calculate_power_output(weather, my_turbine, e126, dummy_turbine) assert_allclose(2764.194772, (e126.power_output.sum() / @@ -29,11 +29,11 @@ def test_modelchain_example_flh(self): def test_turbine_cluster_modelchain_example_flh(self): # tests full load hours - weather = mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() - example_farm, example_farm_2 = tc_mc_e.initialize_wind_farms( + weather=mc_e.get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() + example_farm, example_farm_2=tc_mc_e.initialize_wind_farms( my_turbine, e126) - example_cluster = tc_mc_e.initialize_wind_turbine_cluster( + example_cluster=tc_mc_e.initialize_wind_turbine_cluster( example_farm, example_farm_2) tc_mc_e.calculate_power_output(weather, example_farm, example_cluster) assert_allclose(1956.164053, (example_farm.power_output.sum() / @@ -46,18 +46,18 @@ def _notebook_run(self, path): Execute a notebook via nbconvert and collect output. Returns (parsed nb object, execution errors) """ - dirname, __ = os.path.split(path) + dirname, __=os.path.split(path) os.chdir(dirname) with tempfile.NamedTemporaryFile(suffix=".ipynb") as fout: - args = ["jupyter", "nbconvert", "--to", "notebook", "--execute", + args=["jupyter", "nbconvert", "--to", "notebook", "--execute", "--ExecutePreprocessor.timeout=60", "--output", fout.name, path] subprocess.check_call(args) fout.seek(0) - nb = nbformat.read(fout, nbformat.current_nbformat) + nb=nbformat.read(fout, nbformat.current_nbformat) - errors = [output for cell in nb.cells if "outputs" in cell + errors=[output for cell in nb.cells if "outputs" in cell for output in cell["outputs"] if output.output_type == "error"] @@ -65,14 +65,14 @@ def _notebook_run(self, path): @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_modelchain_example_ipynb(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - nb, errors = self._notebook_run( + dir_path=os.path.dirname(os.path.realpath(__file__)) + nb, errors=self._notebook_run( os.path.join(dir_path, 'modelchain_example.ipynb')) assert errors == [] @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_turbine_cluster_modelchain_example_ipynb(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - nb, errors = self._notebook_run( + dir_path=os.path.dirname(os.path.realpath(__file__)) + nb, errors=self._notebook_run( os.path.join(dir_path, 'turbine_cluster_modelchain_example.ipynb')) assert errors == [] diff --git a/example/turbine_cluster_modelchain_example.py b/example/turbine_cluster_modelchain_example.py index c308bc02..9903dbf1 100644 --- a/example/turbine_cluster_modelchain_example.py +++ b/example/turbine_cluster_modelchain_example.py @@ -15,7 +15,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt = None + plt=None from example import modelchain_example as mc_e from windpowerlib import WindFarm @@ -58,24 +58,24 @@ def initialize_wind_farms(my_turbine, e126): # for each turbine type you can either specify the number of turbines of # that type in the wind farm (float values are possible as well) or the # total installed capacity of that turbine type in W - wind_turbine_fleet = pd.DataFrame( + wind_turbine_fleet=pd.DataFrame( {'wind_turbine': [my_turbine, e126], # as windpowerlib.WindTurbine 'number_of_turbines': [6, None], 'total_capacity': [None, 12.6e6]} ) # initialize WindFarm object - example_farm = WindFarm(name='example_farm', + example_farm=WindFarm(name='example_farm', wind_turbine_fleet=wind_turbine_fleet) # specification of wind farm data (2) containing a wind farm efficiency # wind turbine fleet is provided using the to_group function - example_farm_2_data = { + example_farm_2_data={ 'name': 'example_farm_2', 'wind_turbine_fleet': [my_turbine.to_group(6), e126.to_group(total_capacity=12.6e6)], 'efficiency': 0.9} # initialize WindFarm object - example_farm_2 = WindFarm(**example_farm_2_data) + example_farm_2=WindFarm(**example_farm_2_data) return example_farm, example_farm_2 @@ -103,11 +103,11 @@ def initialize_wind_turbine_cluster(example_farm, example_farm_2): """ # specification of cluster data - example_cluster_data = { + example_cluster_data={ 'name': 'example_cluster', 'wind_farms': [example_farm, example_farm_2]} # initialize WindTurbineCluster object - example_cluster = WindTurbineCluster(**example_cluster_data) + example_cluster=WindTurbineCluster(**example_cluster_data) return example_cluster @@ -133,17 +133,17 @@ class that provides all necessary steps to calculate the power output of a WindTurbineCluster object. """ - example_farm.efficiency = 0.9 + example_farm.efficiency=0.9 # power output calculation for example_farm # initialize TurbineClusterModelChain with default parameters and use # run_model method to calculate power output - mc_example_farm = TurbineClusterModelChain(example_farm).run_model(weather) + mc_example_farm=TurbineClusterModelChain(example_farm).run_model(weather) # write power output time series to WindFarm object - example_farm.power_output = mc_example_farm.power_output + example_farm.power_output=mc_example_farm.power_output # power output calculation for turbine_cluster # own specifications for TurbineClusterModelChain setup - modelchain_data = { + modelchain_data={ 'wake_losses_model': 'wind_farm_efficiency', # 'dena_mean' (default), None, # 'wind_farm_efficiency' or name @@ -171,10 +171,10 @@ class that provides all necessary steps to calculate the power output of a 'hellman_exp': None} # None (default) or None # initialize TurbineClusterModelChain with own specifications and use # run_model method to calculate power output - mc_example_cluster = TurbineClusterModelChain( + mc_example_cluster=TurbineClusterModelChain( example_cluster, **modelchain_data).run_model(weather) # write power output time series to WindTurbineCluster object - example_cluster.power_output = mc_example_cluster.power_output + example_cluster.power_output=mc_example_cluster.power_output return @@ -209,10 +209,10 @@ def run_example(): Runs the example. """ - weather = mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() - example_farm, example_farm_2 = initialize_wind_farms(my_turbine, e126) - example_cluster = initialize_wind_turbine_cluster(example_farm, + weather=mc_e.get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() + example_farm, example_farm_2=initialize_wind_farms(my_turbine, e126) + example_cluster=initialize_wind_turbine_cluster(example_farm, example_farm_2) calculate_power_output(weather, example_farm, example_cluster) plot_or_print(example_farm, example_cluster) diff --git a/tests/test_density.py b/tests/test_density.py index 7dd681af..67c4b4b5 100644 --- a/tests/test_density.py +++ b/tests/test_density.py @@ -14,55 +14,55 @@ class TestDensity: def test_barometric(self): - parameters = {'pressure': pd.Series(data=[101125, 101000]), + parameters={'pressure': pd.Series(data=[101125, 101000]), 'pressure_height': 0, 'hub_height': 100, 'temperature_hub_height': pd.Series(data=[267, 268])} # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp = pd.Series(data=[1.30305336, 1.29656645]) + rho_exp=pd.Series(data=[1.30305336, 1.29656645]) assert_series_equal(barometric(**parameters), rho_exp) - parameters['temperature_hub_height'] = np.array( + parameters['temperature_hub_height']=np.array( parameters['temperature_hub_height']) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters['pressure'] = np.array(parameters['pressure']) - parameters['temperature_hub_height'] = pd.Series( + parameters['pressure']=np.array(parameters['pressure']) + parameters['temperature_hub_height']=pd.Series( data=parameters['temperature_hub_height']) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp = np.array([1.30305336, 1.29656645]) - parameters['temperature_hub_height'] = np.array( + rho_exp=np.array([1.30305336, 1.29656645]) + parameters['temperature_hub_height']=np.array( parameters['temperature_hub_height']) assert_allclose(barometric(**parameters), rho_exp) assert isinstance(barometric(**parameters), np.ndarray) def test_ideal_gas(self): - parameters = {'pressure': pd.Series(data=[101125, 101000]), + parameters={'pressure': pd.Series(data=[101125, 101000]), 'pressure_height': 0, 'hub_height': 100, 'temperature_hub_height': pd.Series(data=[267, 268])} # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp = pd.Series(data=[1.30309439, 1.29660728]) + rho_exp=pd.Series(data=[1.30309439, 1.29660728]) assert_series_equal(ideal_gas(**parameters), rho_exp) - parameters['temperature_hub_height'] = np.array( + parameters['temperature_hub_height']=np.array( parameters['temperature_hub_height']) assert_series_equal(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters['pressure'] = np.array(parameters['pressure']) - parameters['temperature_hub_height'] = pd.Series( + parameters['pressure']=np.array(parameters['pressure']) + parameters['temperature_hub_height']=pd.Series( data=parameters['temperature_hub_height']) assert_allclose(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp = np.array([1.30309439, 1.29660728]) - parameters['temperature_hub_height'] = np.array( + rho_exp=np.array([1.30309439, 1.29660728]) + parameters['temperature_hub_height']=np.array( parameters['temperature_hub_height']) assert_allclose(ideal_gas(**parameters), rho_exp) assert isinstance(ideal_gas(**parameters), np.ndarray) diff --git a/tests/test_modelchain.py b/tests/test_modelchain.py index fbc1b5d4..2fea51aa 100644 --- a/tests/test_modelchain.py +++ b/tests/test_modelchain.py @@ -18,19 +18,19 @@ class TestModelChain: @classmethod def setup_class(self): """Setup default values""" - self.test_turbine = {'hub_height': 100, + self.test_turbine={'hub_height': 100, 'turbine_type': 'E-126/4200', 'power_curve': pd.DataFrame( data={'value': [0.0, 4200 * 1000], 'wind_speed': [0.0, 25.0]})} - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - pressure_0m = np.array([[101125], [101000]]) - wind_speed_8m = np.array([[4.0], [5.0]]) - wind_speed_10m = np.array([[5.0], [6.5]]) - roughness_length = np.array([[0.15], [0.15]]) - self.weather_df = pd.DataFrame( + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + pressure_0m=np.array([[101125], [101000]]) + wind_speed_8m=np.array([[4.0], [5.0]]) + wind_speed_10m=np.array([[5.0], [6.5]]) + roughness_length=np.array([[0.15], [0.15]]) + self.weather_df=pd.DataFrame( np.hstack((temperature_2m, temperature_10m, pressure_0m, wind_speed_8m, wind_speed_10m, roughness_length)), index=[0, 1], @@ -41,16 +41,16 @@ def setup_class(self): def test_temperature_hub(self): # Test modelchain with temperature_model='linear_gradient' - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with temperature_model='interpolation_extrapolation' - test_mc_2 = mc.ModelChain( + test_mc_2=mc.ModelChain( wt.WindTurbine(**self.test_turbine), temperature_model='interpolation_extrapolation') # Parameters for tests - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - weather_df = pd.DataFrame(np.hstack((temperature_2m, + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + weather_df=pd.DataFrame(np.hstack((temperature_2m, temperature_10m)), index=[0, 1], columns=[np.array(['temperature', @@ -58,40 +58,40 @@ def test_temperature_hub(self): np.array([2, 10])]) # temperature_10m is closer to hub height than temperature_2m - temp_exp = pd.Series(data=[266.415, 265.415], name=10) + temp_exp=pd.Series(data=[266.415, 265.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp = pd.Series(data=[267.0, 243.5]) + temp_exp=pd.Series(data=[267.0, 243.5]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns = [np.array(['temperature', 'temperature']), + weather_df.columns=[np.array(['temperature', 'temperature']), np.array([10, 200])] - temp_exp = pd.Series(data=[266.415, 267.415], name=10) + temp_exp=pd.Series(data=[266.415, 267.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp = pd.Series(data=[267.0, 267.052632]) + temp_exp=pd.Series(data=[267.0, 267.052632]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # temperature at hub height - weather_df.columns = [np.array(['temperature', 'temperature']), + weather_df.columns=[np.array(['temperature', 'temperature']), np.array([100, 10])] - temp_exp = pd.Series(data=[267, 268], name=100) + temp_exp=pd.Series(data=[267, 268], name=100) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) def test_density_hub(self): # Test modelchain with density_model='barometric' - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with density_model='ideal_gas' - test_mc_2 = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), density_model='ideal_gas') # Test modelchain with density_model='interpolation_extrapolation' - test_mc_3 = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc_3=mc.ModelChain(wt.WindTurbine(**self.test_turbine), density_model='interpolation_extrapolation') # Parameters for tests - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - pressure_0m = np.array([[101125], [101000]]) - weather_df = pd.DataFrame(np.hstack((temperature_2m, + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + pressure_0m=np.array([[101125], [101000]]) + weather_df=pd.DataFrame(np.hstack((temperature_2m, temperature_10m, pressure_0m)), index=[0, 1], @@ -101,60 +101,60 @@ def test_density_hub(self): np.array([2, 10, 0])]) # temperature_10m is closer to hub height than temperature_2m - rho_exp = pd.Series(data=[1.30591, 1.30919]) + rho_exp=pd.Series(data=[1.30591, 1.30919]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp = pd.Series(data=[1.30595575725, 1.30923554056]) + rho_exp=pd.Series(data=[1.30595575725, 1.30923554056]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns = [np.array(['temperature', 'temperature', + weather_df.columns=[np.array(['temperature', 'temperature', 'pressure']), np.array([10, 200, 0])] - rho_exp = pd.Series(data=[1.30591, 1.29940]) + rho_exp=pd.Series(data=[1.30591, 1.29940]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp = pd.Series(data=[1.30595575725, 1.29944375221]) + rho_exp=pd.Series(data=[1.30595575725, 1.29944375221]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # temperature at hub height - weather_df.columns = [np.array(['temperature', 'temperature', + weather_df.columns=[np.array(['temperature', 'temperature', 'pressure']), np.array([100, 10, 0])] - rho_exp = pd.Series(data=[1.30305, 1.29657]) + rho_exp=pd.Series(data=[1.30305, 1.29657]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) # density interpolation - density_10m = np.array([[1.30591], [1.29940]]) - density_150m = np.array([[1.30305], [1.29657]]) - weather_df = pd.DataFrame(np.hstack((density_10m, + density_10m=np.array([[1.30591], [1.29940]]) + density_150m=np.array([[1.30305], [1.29657]]) + weather_df=pd.DataFrame(np.hstack((density_10m, density_150m)), index=[0, 1], columns=[np.array(['density', 'density']), np.array([10, 150])]) - rho_exp = pd.Series(data=[1.304071, 1.297581]) + rho_exp=pd.Series(data=[1.304071, 1.297581]) assert_series_equal(test_mc_3.density_hub(weather_df), rho_exp) def test_wind_speed_hub(self): # Test modelchain with wind_speed_model='logarithmic' - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with wind_speed_model='hellman' - test_mc_2 = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), wind_speed_model='hellman') # Test modelchain with wind_speed_model='interpolation_extrapolation' - test_mc_3 = mc.ModelChain( + test_mc_3=mc.ModelChain( wt.WindTurbine(**self.test_turbine), wind_speed_model='interpolation_extrapolation') # Test modelchain with # wind_speed_model='log_interpolation_extrapolation' - test_mc_4 = mc.ModelChain( + test_mc_4=mc.ModelChain( wt.WindTurbine(**self.test_turbine), wind_speed_model='log_interpolation_extrapolation') # Parameters for tests - wind_speed_8m = np.array([[4.0], [5.0]]) - wind_speed_10m = np.array([[5.0], [6.5]]) - roughness_length = np.array([[0.15], [0.15]]) - weather_df = pd.DataFrame(np.hstack((wind_speed_8m, + wind_speed_8m=np.array([[4.0], [5.0]]) + wind_speed_10m=np.array([[5.0], [6.5]]) + roughness_length=np.array([[0.15], [0.15]]) + weather_df=pd.DataFrame(np.hstack((wind_speed_8m, wind_speed_10m, roughness_length)), index=[0, 1], @@ -164,64 +164,64 @@ def test_wind_speed_hub(self): np.array([8, 10, 0])]) # wind_speed_10m is closer to hub height than wind_speed_8m - v_wind_exp = pd.Series(data=[7.74137, 10.06377]) + v_wind_exp=pd.Series(data=[7.74137, 10.06377]) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp = pd.Series(data=[7.12462, 9.26201]) + v_wind_exp=pd.Series(data=[7.12462, 9.26201]) assert_series_equal(test_mc_2.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp = pd.Series(data=[50.0, 74.0]) + v_wind_exp=pd.Series(data=[50.0, 74.0]) assert_series_equal(test_mc_3.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp = pd.Series(data=[15.3188511585, 21.9782767378]) + v_wind_exp=pd.Series(data=[15.3188511585, 21.9782767378]) assert_series_equal(test_mc_4.wind_speed_hub(weather_df), v_wind_exp) # wind_speed is given at hub height - weather_df.columns = [np.array(['wind_speed', 'wind_speed', + weather_df.columns=[np.array(['wind_speed', 'wind_speed', 'roughness_length']), np.array([10, 100, 0])] - v_wind_exp = pd.Series(data=[5.0, 6.5], name=100) + v_wind_exp=pd.Series(data=[5.0, 6.5], name=100) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) # ***** test_run_model ********* def test_with_default_parameter(self): """Test with default parameters of modelchain (power curve)""" - test_turbine = {'hub_height': 100, + test_turbine={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'E-126/4200'} - power_output_exp = pd.Series(data=[1637405.4840444783, + power_output_exp=pd.Series(data=[1637405.4840444783, 3154438.3894902095], name='feedin_power_plant') - test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_density_corrected_power_curve_and_hellman(self): """Test with density corrected power curve and hellman""" - test_turbine = {'hub_height': 100, + test_turbine={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'E-126/4200'} - test_modelchain = {'wind_speed_model': 'hellman', + test_modelchain={'wind_speed_model': 'hellman', 'power_output_model': 'power_curve', 'density_correction': True} - power_output_exp = pd.Series(data=[1366958.544547462, + power_output_exp=pd.Series(data=[1366958.544547462, 2823402.837201821], name='feedin_power_plant') - test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_power_coefficient_curve_and_hellman(self): """Test with power coefficient curve and hellman""" - test_turbine = {'hub_height': 100, + test_turbine={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'E-126/4200'} - power_output_exp = pd.Series(data=[534137.5112701517, + power_output_exp=pd.Series(data=[534137.5112701517, 1103611.1736067757], name='feedin_power_plant') - test_modelchain = {'wind_speed_model': 'hellman', + test_modelchain={'wind_speed_model': 'hellman', 'power_output_model': 'power_coefficient_curve', 'density_correction': False} - test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) @@ -229,85 +229,85 @@ def test_with_power_coefficient_curve_and_hellman(self): def test_wrong_spelling_power_output_model(self): """Raise ValueErrors due to wrong spelling of power_output_model""" with pytest.raises(ValueError): - test_modelchain = {'wind_speed_model': 'hellman', + test_modelchain={'wind_speed_model': 'hellman', 'power_output_model': 'wrong_spelling', 'density_correction': False} - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_spelling_density_model(self): """Raise ValueErrors due to wrong spelling of density_model""" with pytest.raises(ValueError): - test_modelchain = {'wind_speed_model': 'hellman', + test_modelchain={'wind_speed_model': 'hellman', 'power_output_model': 'power_coefficient_curve', 'density_correction': False, 'density_model': 'wrong_spelling'} - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_spelling_temperature_model(self): """Raise ValueErrors due to wrong spelling of temperature_model""" with pytest.raises(ValueError): - test_modelchain = {'wind_speed_model': 'hellman', + test_modelchain={'wind_speed_model': 'hellman', 'power_output_model': 'power_coefficient_curve', 'density_correction': False, 'temperature_model': 'wrong_spelling'} - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_spelling_wind_speed_model(self): """Raise ValueErrors due to wrong spelling of wind_speed_model""" with pytest.raises(ValueError): - test_modelchain = {'wind_speed_model': 'wrong_spelling', + test_modelchain={'wind_speed_model': 'wrong_spelling', 'power_output_model': 'power_coefficient_curve', 'density_correction': False} - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_density_correction_type(self): """Raise TypeErrors due to wrong type of `density_correction`""" with pytest.raises(TypeError): - test_modelchain = {'power_output_model': 'power_curve', + test_modelchain={'power_output_model': 'power_curve', 'density_correction': 'wrong_type'} - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_cp_values(self): """Raise TypeErrors due to missing cp-values""" - test_turbine = {'hub_height': 100, + test_turbine={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'E-126/4201'} - msg = "Power coefficient curve values of" + msg="Power coefficient curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain = {'power_output_model': 'power_coefficient_curve', + test_modelchain={'power_output_model': 'power_coefficient_curve', 'density_correction': True} - test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_p_values(self): """Raise TypeErrors due to missing p-values""" - test_turbine = {'hub_height': 100, + test_turbine={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'E-126/4205'} - msg = "Power curve values of" + msg="Power curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain = {'power_output_model': 'power_curve', + test_modelchain={'power_output_model': 'power_curve', 'density_corr': True} - test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), **test_modelchain) test_mc.run_model(self.weather_df) def test_modelchain_with_power_curve_as_dict(self): """Test power curves as dict""" - my_turbine = {'nominal_power': 3e6, 'hub_height': 105, + my_turbine={'nominal_power': 3e6, 'hub_height': 105, 'rotor_diameter': 70, 'power_curve': { 'value': [p * 1000 for p in [ @@ -316,16 +316,16 @@ def test_modelchain_with_power_curve_as_dict(self): 'power_coefficient_curve': { 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - power_output_exp = pd.Series(data=[919055.54840, + power_output_exp=pd.Series(data=[919055.54840, 1541786.60559], name='feedin_power_plant') - test_mc = mc.ModelChain(wt.WindTurbine(**my_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_modelchain_with_power_coefficient_curve_as_dict(self): """Test power coefficient curves as dict""" - my_turbine = {'nominal_power': 3e6, 'hub_height': 105, + my_turbine={'nominal_power': 3e6, 'hub_height': 105, 'rotor_diameter': 70, 'power_curve': { 'value': [p * 1000 for p in [ @@ -334,10 +334,10 @@ def test_modelchain_with_power_coefficient_curve_as_dict(self): 'power_coefficient_curve': { 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - power_output_exp = pd.Series(data=[469518.35104, + power_output_exp=pd.Series(data=[469518.35104, 901794.28532], name='feedin_power_plant') - test_mc = mc.ModelChain(wt.WindTurbine(**my_turbine), + test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine), power_output_model='power_coefficient_curve') test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) diff --git a/tests/test_power_curves.py b/tests/test_power_curves.py index 6e530e7e..5814969b 100644 --- a/tests/test_power_curves.py +++ b/tests/test_power_curves.py @@ -17,73 +17,73 @@ class TestPowerCurves: @classmethod def setup_class(self): - self.test_turbine = {'hub_height': 100, + self.test_turbine={'hub_height': 100, 'turbine_type': 'E-126/4200'} def test_smooth_power_curve(self): - test_curve = wt.WindTurbine(**self.test_turbine).power_curve - parameters = {'power_curve_wind_speeds': test_curve['wind_speed'], + test_curve=wt.WindTurbine(**self.test_turbine).power_curve + parameters={'power_curve_wind_speeds': test_curve['wind_speed'], 'power_curve_values': test_curve['value'], 'standard_deviation_method': 'turbulence_intensity'} # Raise ValueError - `turbulence_intensity` missing with pytest.raises(ValueError): - parameters['standard_deviation_method'] = 'turbulence_intensity' + parameters['standard_deviation_method']='turbulence_intensity' smooth_power_curve(**parameters) # Test turbulence_intensity method - parameters['turbulence_intensity'] = 0.5 - wind_speed_values_exp = pd.Series([6.0, 7.0, 8.0, 9.0, 10.0], + parameters['turbulence_intensity']=0.5 + wind_speed_values_exp=pd.Series([6.0, 7.0, 8.0, 9.0, 10.0], name='wind_speed') - power_values_exp = pd.Series([ + power_values_exp=pd.Series([ 1141906.9806766496, 1577536.8085282773, 1975480.993355767, 2314059.4022704284, 2590216.6802602503], name='value') - smoothed_curve_exp = pd.DataFrame(data=pd.concat([ + smoothed_curve_exp=pd.DataFrame(data=pd.concat([ wind_speed_values_exp, power_values_exp], axis=1)) - smoothed_curve_exp.index = np.arange(5, 10, 1) + smoothed_curve_exp.index=np.arange(5, 10, 1) assert_frame_equal(smooth_power_curve(**parameters)[5:10], smoothed_curve_exp) # Test Staffel_Pfenninger method - parameters['standard_deviation_method'] = 'Staffell_Pfenninger' - power_values_exp = pd.Series([ + parameters['standard_deviation_method']='Staffell_Pfenninger' + power_values_exp=pd.Series([ 929405.1348918702, 1395532.5468724659, 1904826.6851982325, 2402659.118305521, 2844527.1732449625], name='value') - smoothed_curve_exp = pd.DataFrame( + smoothed_curve_exp=pd.DataFrame( data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1)) - smoothed_curve_exp.index = np.arange(5, 10, 1) + smoothed_curve_exp.index=np.arange(5, 10, 1) assert_frame_equal(smooth_power_curve(**parameters)[5:10], smoothed_curve_exp) # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters['standard_deviation_method'] = 'misspelled' + parameters['standard_deviation_method']='misspelled' smooth_power_curve(**parameters) def test_wake_losses_to_power_curve(self): - test_curve = wt.WindTurbine(**self.test_turbine).power_curve - parameters = {'power_curve_wind_speeds': test_curve['wind_speed'], + test_curve=wt.WindTurbine(**self.test_turbine).power_curve + parameters={'power_curve_wind_speeds': test_curve['wind_speed'], 'power_curve_values': test_curve['value'], 'wind_farm_efficiency': 0.9} # Test constant efficiency - power_curve_exp = test_curve.copy(deep=True) - power_curve_exp['value'] = power_curve_exp['value'].values * 0.9 + power_curve_exp=test_curve.copy(deep=True) + power_curve_exp['value']=power_curve_exp['value'].values * 0.9 assert_frame_equal(wake_losses_to_power_curve(**parameters), power_curve_exp) # Test efficiency curve - parameters['wind_farm_efficiency'] = pd.DataFrame( + parameters['wind_farm_efficiency']=pd.DataFrame( pd.concat([pd.Series(np.arange(1, 26, 1)), pd.Series([ 1.0, 1.0, 1.0, 0.84, 0.85, 0.86, 0.85, 0.85, 0.85, 0.86, 0.87, 0.89, 0.92, 0.95, 0.95, 0.96, 0.99, 0.95, 0.98, 0.97, 0.99, 1.0, 1.0, 1.0, 1.0])], axis=1)) - parameters['wind_farm_efficiency'].columns = ['wind_speed', + parameters['wind_farm_efficiency'].columns=['wind_speed', 'efficiency'] - power_curve_exp = test_curve.copy(deep=True) - power_curve_exp['value'] = ( + power_curve_exp=test_curve.copy(deep=True) + power_curve_exp['value']=( power_curve_exp['value'].values * parameters[ 'wind_farm_efficiency']['efficiency']) assert_frame_equal(wake_losses_to_power_curve(**parameters), @@ -91,12 +91,12 @@ def test_wake_losses_to_power_curve(self): # Raise TypeError if wind farm efficiency is of wrong type with pytest.raises(TypeError): - parameters['wind_farm_efficiency'] = 1 + parameters['wind_farm_efficiency']=1 wake_losses_to_power_curve(**parameters) if __name__ == "__main__": - test = TestPowerCurves() + test=TestPowerCurves() test.setup_class() test.test_smooth_power_curve() test.test_wake_losses_to_power_curve() diff --git a/tests/test_power_output.py b/tests/test_power_output.py index 4476da9c..0a5c6f84 100644 --- a/tests/test_power_output.py +++ b/tests/test_power_output.py @@ -17,7 +17,7 @@ class TestPowerOutput: def test_power_coefficient_curve(self): - parameters = {'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), 'density': pd.Series(data=[1.3, 1.3, 1.3]), 'rotor_diameter': 80, 'power_coefficient_curve_wind_speeds': @@ -27,40 +27,40 @@ def test_power_coefficient_curve(self): # Test wind_speed as pd.Series with density and power_coefficient_curve # as pd.Series and np.array - power_output_exp = pd.Series(data=[0.0, 244615.399, 0.0], + power_output_exp=pd.Series(data=[0.0, 244615.399, 0.0], name='feedin_power_plant') assert_series_equal(power_coefficient_curve(**parameters), power_output_exp) - parameters['density'] = np.array(parameters['density']) + parameters['density']=np.array(parameters['density']) assert_series_equal(power_coefficient_curve(**parameters), power_output_exp) - parameters['power_coefficient_curve_values'] = np.array( + parameters['power_coefficient_curve_values']=np.array( parameters['power_coefficient_curve_values']) - parameters['power_coefficient_curve_wind_speeds'] = np.array( + parameters['power_coefficient_curve_wind_speeds']=np.array( parameters['power_coefficient_curve_wind_speeds']) assert_series_equal(power_coefficient_curve(**parameters), power_output_exp) # Test wind_speed as np.array with density and power_coefficient_curve # as np.array and pd.Series - power_output_exp = np.array([0.0, 244615.399, 0.0]) - parameters['wind_speed'] = np.array(parameters['wind_speed']) + power_output_exp=np.array([0.0, 244615.399, 0.0]) + parameters['wind_speed']=np.array(parameters['wind_speed']) assert_allclose(power_coefficient_curve(**parameters), power_output_exp) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters['density'] = pd.Series(data=parameters['density']) + parameters['density']=pd.Series(data=parameters['density']) assert_allclose(power_coefficient_curve(**parameters), power_output_exp) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters['power_coefficient_curve_wind_speeds'] = pd.Series( + parameters['power_coefficient_curve_wind_speeds']=pd.Series( data=parameters['power_coefficient_curve_wind_speeds']) - parameters['power_coefficient_curve_values'] = pd.Series( + parameters['power_coefficient_curve_values']=pd.Series( data=parameters['power_coefficient_curve_values']) assert_allclose(power_coefficient_curve(**parameters), power_output_exp) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) def test_power_curve(self): - parameters = {'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), 'density': pd.Series(data=[1.3, 1.3, 1.3]), 'density_correction': False, 'power_curve_wind_speeds': @@ -72,24 +72,24 @@ def test_power_curve(self): # Tests without density correction: # Test wind_speed as pd.Series and power_curve as pd.Series and # np.array - power_output_exp = pd.Series(data=[0.0, 450.0, 0.0], + power_output_exp=pd.Series(data=[0.0, 450.0, 0.0], name='feedin_power_plant') assert_series_equal(power_curve(**parameters), power_output_exp) - parameters['power_curve_values'] = np.array( + parameters['power_curve_values']=np.array( parameters['power_curve_values']) - parameters['power_curve_wind_speeds'] = np.array( + parameters['power_curve_wind_speeds']=np.array( parameters['power_curve_wind_speeds']) assert_series_equal(power_curve(**parameters), power_output_exp) # Test wind_speed as np.array and power_curve as pd.Series and np.array - power_output_exp = np.array([0.0, 450.0, 0.0]) - parameters['wind_speed'] = np.array(parameters['wind_speed']) + power_output_exp=np.array([0.0, 450.0, 0.0]) + parameters['wind_speed']=np.array(parameters['wind_speed']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_wind_speeds'] = pd.Series( + parameters['power_curve_wind_speeds']=pd.Series( data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values'] = pd.Series( + parameters['power_curve_values']=pd.Series( data=parameters['power_curve_values']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) @@ -97,43 +97,43 @@ def test_power_curve(self): # Tests with density correction: # Test wind_speed as np.array with density and power_curve as pd.Series # and np.array - power_output_exp = np.array([0.0, 461.00290572, 0.0]) - parameters['density_correction'] = True + power_output_exp=np.array([0.0, 461.00290572, 0.0]) + parameters['density_correction']=True assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['density'] = np.array(parameters['density']) + parameters['density']=np.array(parameters['density']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_values'] = np.array( + parameters['power_curve_values']=np.array( parameters['power_curve_values']) - parameters['power_curve_wind_speeds'] = np.array( + parameters['power_curve_wind_speeds']=np.array( parameters['power_curve_wind_speeds']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Test wind_speed as pd.Series with density and power_curve as # np. array and pd.Series - power_output_exp = pd.Series(data=[0.0, 461.00290572, 0.0], + power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], name='feedin_power_plant') - parameters['wind_speed'] = pd.Series(data=parameters['wind_speed']) + parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) assert_series_equal(power_curve(**parameters), power_output_exp) - parameters['density'] = pd.Series(data=parameters['density']) + parameters['density']=pd.Series(data=parameters['density']) assert_series_equal(power_curve(**parameters), power_output_exp) - parameters['power_curve_wind_speeds'] = pd.Series( + parameters['power_curve_wind_speeds']=pd.Series( data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values'] = pd.Series( + parameters['power_curve_values']=pd.Series( data=parameters['power_curve_values']) assert_series_equal(power_curve(**parameters), power_output_exp) # Raise TypeErrors due to wrong type of `density_correction` with pytest.raises(TypeError): - parameters['density'] = 'wrong_type' + parameters['density']='wrong_type' power_curve(**parameters) def test_power_curve_density_correction(self): - parameters = {'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), 'density': pd.Series(data=[1.3, 1.3, 1.3]), 'power_curve_wind_speeds': pd.Series([4.0, 5.0, 6.0]), @@ -143,34 +143,34 @@ def test_power_curve_density_correction(self): # Test wind_speed as pd.Series with density and power_curve as # pd.Series and np.array - power_output_exp = pd.Series(data=[0.0, 461.00290572, 0.0], + power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], name='feedin_power_plant') assert_series_equal(power_curve_density_correction(**parameters), power_output_exp) - parameters['density'] = np.array(parameters['density']) + parameters['density']=np.array(parameters['density']) assert_series_equal(power_curve_density_correction(**parameters), power_output_exp) - parameters['power_curve_values'] = np.array( + parameters['power_curve_values']=np.array( parameters['power_curve_values']) - parameters['power_curve_wind_speeds'] = np.array( + parameters['power_curve_wind_speeds']=np.array( parameters['power_curve_wind_speeds']) assert_series_equal(power_curve_density_correction(**parameters), power_output_exp) # Test wind_speed as np.array with density and power_curve as np.array # and pd.Series - parameters['wind_speed'] = np.array(parameters['wind_speed']) - power_output_exp = np.array([0.0, 461.00290572, 0.0]) + parameters['wind_speed']=np.array(parameters['wind_speed']) + power_output_exp=np.array([0.0, 461.00290572, 0.0]) assert_allclose(power_curve_density_correction(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['density'] = pd.Series(data=parameters['density']) + parameters['density']=pd.Series(data=parameters['density']) assert_allclose(power_curve_density_correction(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_wind_speeds'] = pd.Series( + parameters['power_curve_wind_speeds']=pd.Series( data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values'] = pd.Series( + parameters['power_curve_values']=pd.Series( data=parameters['power_curve_values']) assert_allclose(power_curve_density_correction(**parameters), power_output_exp) @@ -178,18 +178,18 @@ def test_power_curve_density_correction(self): # Raise TypeError due to density is None with pytest.raises(TypeError): - parameters['density'] = None + parameters['density']=None power_curve_density_correction(**parameters) def test_wrong_spelling_density_correction(self): - parameters = {'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), 'density': pd.Series(data=[1.3, 1.3, 1.3]), 'power_curve_wind_speeds': pd.Series([4.0, 5.0, 6.0]), 'power_curve_values': pd.Series([300, 400, 500]) } - msg = "is an invalid type. `density_correction` must be Boolean" + msg="is an invalid type. `density_correction` must be Boolean" with pytest.raises(TypeError, match=msg): - parameters['density_correction'] = None + parameters['density_correction']=None power_curve(**parameters) diff --git a/tests/test_temperature.py b/tests/test_temperature.py index 11427df2..59070069 100644 --- a/tests/test_temperature.py +++ b/tests/test_temperature.py @@ -15,17 +15,17 @@ class TestTemperature: def test_linear_gradient(self): """Test temperature as pd.Series""" - parameters = {'temperature': pd.Series(data=[267, 268]), + parameters={'temperature': pd.Series(data=[267, 268]), 'temperature_height': 2, 'hub_height': 100} - temp_hub_exp = pd.Series(data=[266.363, 267.36300]) + temp_hub_exp=pd.Series(data=[266.363, 267.36300]) assert_series_equal(linear_gradient(**parameters), temp_hub_exp) def test_temperature_as_np_array(self): """Test temperature as np.array""" - parameters = {'temperature': np.array([267, 268]), + parameters={'temperature': np.array([267, 268]), 'temperature_height': 2, 'hub_height': 100} - temp_hub_exp = np.array([266.363, 267.36300]) + temp_hub_exp=np.array([266.363, 267.36300]) assert_array_equal(linear_gradient(**parameters), temp_hub_exp) assert isinstance(linear_gradient(**parameters), np.ndarray) diff --git a/tests/test_tools.py b/tests/test_tools.py index e51584c9..91d87223 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -14,8 +14,8 @@ class TestTools: @classmethod def setup_class(cls): - cls.parameters = {'target_height': 80} - cls.df = pd.DataFrame(data={10: [2.0, 2.0, 3.0], + cls.parameters={'target_height': 80} + cls.df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], 80: [4.0, 5.0, 6.0], 200: [5.0, 8.0, 10.0]}, index=[0, 1, 2]) @@ -25,7 +25,7 @@ def test_linear_target_height_is_equal_to_given_height(self): Test linear interpolation and extrapolation if target_height is equal to height given in a column of the DataFrame. """ - exp_output = pd.Series(data=[4.0, 5.0, 6.0]) + exp_output=pd.Series(data=[4.0, 5.0, 6.0]) assert_series_equal(linear_interpolation_extrapolation( self.df, **self.parameters), exp_output) @@ -34,13 +34,13 @@ def test_linear_target_height_is_between_given_heights(self): Test linear interpolation and extrapolation if target_height is between heights given in the columns of the DataFrame """ - exp_output = pd.Series(data=[4.5, 6.5, 8.0]) - self.parameters['target_height'] = 140 + exp_output=pd.Series(data=[4.5, 6.5, 8.0]) + self.parameters['target_height']=140 assert_series_equal(linear_interpolation_extrapolation( self.df, **self.parameters), exp_output) - exp_output = pd.Series(data=[4.285714, 5.428571, 6.428571]) - self.parameters['target_height'] = 90 + exp_output=pd.Series(data=[4.285714, 5.428571, 6.428571]) + self.parameters['target_height']=90 assert_series_equal(linear_interpolation_extrapolation( self.df, **self.parameters), exp_output) @@ -49,8 +49,8 @@ def test_linear_target_height_is_greater_than_the_given_heights(self): Test linear interpolation and extrapolation if target_height is greater than the heights given in the columns of the DataFrame """ - exp_output = pd.Series(data=[5.333333, 9.0, 11.333333]) - self.parameters['target_height'] = 240 + exp_output=pd.Series(data=[5.333333, 9.0, 11.333333]) + self.parameters['target_height']=240 assert_series_equal(linear_interpolation_extrapolation( self.df, **self.parameters), exp_output) @@ -59,43 +59,43 @@ def test_linear_target_height_is_smaller_than_the_given_heights(self): Test linear interpolation and extrapolation if target_height is smaller than the heights given in the columns of the DataFrame """ - exp_output = pd.Series(data=[1.857143, 1.785714, 2.785714]) - self.parameters['target_height'] = 5 + exp_output=pd.Series(data=[1.857143, 1.785714, 2.785714]) + self.parameters['target_height']=5 assert_series_equal(linear_interpolation_extrapolation( self.df, **self.parameters), exp_output) def test_logarithmic_interpolation_extrapolation(self): - parameters = {'target_height': 80} - df = pd.DataFrame(data={10: [2.0, 2.0, 3.0], + parameters={'target_height': 80} + df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], 80: [4.0, 5.0, 6.0], 200: [5.0, 8.0, 10.0]}, index=[0, 1, 2]) # target_height is equal to height given in a column of the DataFrame - exp_output = pd.Series(data=[4.0, 5.0, 6.0]) + exp_output=pd.Series(data=[4.0, 5.0, 6.0]) assert_series_equal(logarithmic_interpolation_extrapolation( df, **parameters), exp_output) # target_height is between heights given in the columns of the # DataFrame - exp_output = pd.Series( + exp_output=pd.Series( data=[4.61074042165, 6.83222126494, 8.44296168659]) - parameters['target_height'] = 140 + parameters['target_height']=140 assert_series_equal(logarithmic_interpolation_extrapolation( df, **parameters), exp_output) - exp_output = pd.Series( + exp_output=pd.Series( data=[4.11328333429, 5.16992500144, 6.16992500144]) - parameters['target_height'] = 90 + parameters['target_height']=90 assert_series_equal(logarithmic_interpolation_extrapolation( df, **parameters), exp_output) # target_height is greater than the heights given in the columns of the # DataFrame - exp_output = pd.Series( + exp_output=pd.Series( data=[5.19897784672, 8.59693354015, 10.7959113869]) - parameters['target_height'] = 240 + parameters['target_height']=240 assert_series_equal(logarithmic_interpolation_extrapolation( df, **parameters), exp_output) # target_height is smaller than the heights given in the columns of the # DataFrame - exp_output = pd.Series(data=[1.33333333333, 1.0, 2.0]) - parameters['target_height'] = 5 + exp_output=pd.Series(data=[1.33333333333, 1.0, 2.0]) + parameters['target_height']=5 assert_series_equal(logarithmic_interpolation_extrapolation( df, **parameters), exp_output) diff --git a/tests/test_turbine_cluster_modelchain.py b/tests/test_turbine_cluster_modelchain.py index 6e9356be..80f9bcfd 100644 --- a/tests/test_turbine_cluster_modelchain.py +++ b/tests/test_turbine_cluster_modelchain.py @@ -18,13 +18,13 @@ class TestTurbineClusterModelChain: @classmethod def setup_class(self): - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - pressure_0m = np.array([[101125], [101000]]) - wind_speed_8m = np.array([[4.0], [5.0]]) - wind_speed_10m = np.array([[5.0], [6.5]]) - roughness_length = np.array([[0.15], [0.15]]) - self.weather_df = pd.DataFrame( + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + pressure_0m=np.array([[101125], [101000]]) + wind_speed_8m=np.array([[4.0], [5.0]]) + wind_speed_10m=np.array([[5.0], [6.5]]) + roughness_length=np.array([[0.15], [0.15]]) + self.weather_df=pd.DataFrame( np.hstack((temperature_2m, temperature_10m, pressure_0m, @@ -39,18 +39,18 @@ def setup_class(self): 'wind_speed', 'roughness_length']), np.array([2, 10, 0, 8, 10, 0])]) - self.test_turbine = {'hub_height': 100, + self.test_turbine={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'E-126/4200'} - self.test_turbine_2 = {'hub_height': 90, + self.test_turbine_2={'hub_height': 90, 'rotor_diameter': 60, 'turbine_type': 'V90/2000', 'nominal_power': 2000000.0} - self.test_farm = {'wind_turbine_fleet': [ + self.test_farm={'wind_turbine_fleet': [ {'wind_turbine': wt.WindTurbine(**self.test_turbine), 'number_of_turbines': 3}]} - self.test_farm_2 = {'name': 'test farm', + self.test_farm_2={'name': 'test farm', 'wind_turbine_fleet': [{'wind_turbine': wt.WindTurbine(**self.test_turbine), @@ -58,135 +58,135 @@ def setup_class(self): {'wind_turbine': wt.WindTurbine(**self.test_turbine_2), 'number_of_turbines': 3}]} - self.test_cluster = {'name': 'example_cluster', + self.test_cluster={'name': 'example_cluster', 'wind_farms': [wf.WindFarm(**self.test_farm), wf.WindFarm(**self.test_farm_2)]} def test_run_model(self): - parameters = {'wake_losses_model': 'dena_mean', + parameters={'wake_losses_model': 'dena_mean', 'smoothing': False, 'standard_deviation_method': 'turbulence_intensity', 'smoothing_order': 'wind_farm_power_curves'} # Test modelchain with default values - power_output_exp = pd.Series(data=[4198361.4830405945, + power_output_exp=pd.Series(data=[4198361.4830405945, 8697966.121234536], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wf.WindFarm(**self.test_farm), **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters['wake_losses_model'] = 'wind_farm_efficiency' - test_wind_farm = wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[4420994.806920091, + parameters['wake_losses_model']='wind_farm_efficiency' + test_wind_farm=wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[4420994.806920091, 8516983.651623568], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters['smoothing'] = 'True' - test_wind_farm = wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[4581109.03847444, + parameters['smoothing']='True' + test_wind_farm=wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[4581109.03847444, 8145581.914240712], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_wind_farm = wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[6777087.9658657005, + test_wind_farm=wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[6777087.9658657005, 12180374.036660176], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters['smoothing_order'] = 'turbine_power_curves' - test_wind_farm = wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[6790706.001026006, + parameters['smoothing_order']='turbine_power_curves' + test_wind_farm=wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[6790706.001026006, 12179417.461328149], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) def test_run_model_turbine_cluster(self): - parameters = {'wake_losses_model': 'dena_mean', + parameters={'wake_losses_model': 'dena_mean', 'smoothing': False, 'standard_deviation_method': 'turbulence_intensity', 'smoothing_order': 'wind_farm_power_curves'} # Test modelchain with default values - power_output_exp = pd.Series(data=[10363047.755401008, + power_output_exp=pd.Series(data=[10363047.755401008, 21694496.68221325], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters['wake_losses_model'] = 'wind_farm_efficiency' - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + parameters['wake_losses_model']='wind_farm_efficiency' + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[10920128.570572512, + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[10920128.570572512, 21273144.336885825], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters['smoothing'] = 'True' - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + parameters['smoothing']='True' + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[11360309.77979467, + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[11360309.77979467, 20328652.64490018], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[11360309.77979467, + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[11360309.77979467, 20328652.64490018], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters['smoothing_order'] = 'turbine_power_curves' - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + parameters['smoothing_order']='turbine_power_curves' + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series(data=[11373183.797085874, + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[11373183.797085874, 20325877.105744187], name='feedin_power_plant') - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) @@ -195,20 +195,20 @@ def test_error_raising(self): # Raise ValueError when aggregated wind farm power curve needs to be # calculated but turbine does not have a power curve - test_turbine_data = { + test_turbine_data={ 'hub_height': 100, 'rotor_diameter': 98, 'turbine_type': 'V90/2000'} - test_turbine = wt.WindTurbine(**test_turbine_data) - test_turbine.power_curve = True - test_farm = {'wind_turbine_fleet': + test_turbine=wt.WindTurbine(**test_turbine_data) + test_turbine.power_curve=True + test_farm={'wind_turbine_fleet': [{'wind_turbine': wt.WindTurbine(**self.test_turbine), 'number_of_turbines': 3}, {'wind_turbine': test_turbine, 'number_of_turbines': 3}]} - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wf.WindFarm(**test_farm)) with pytest.raises(ValueError): test_tc_mc.run_model(self.weather_df) @@ -216,24 +216,24 @@ def test_error_raising(self): # Raise ValueError when neither turbulence intensity nor roughness # length are provided to apply power curve smoothing with standard # deviation method 'turbulence_intensity' - parameters = {'smoothing': True, + parameters={'smoothing': True, 'standard_deviation_method': 'turbulence_intensity'} - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wf.WindFarm(**self.test_farm), **parameters) - weather_df = self.weather_df.copy() + weather_df=self.weather_df.copy() weather_df.pop('roughness_length') with pytest.raises(ValueError): test_tc_mc.run_model(weather_df) def test_ignore_wake_losses(self): """Run model without wake losses.""" - parameters = {'wake_losses_model': None, + parameters={'wake_losses_model': None, 'smoothing': False, 'standard_deviation_method': 'turbulence_intensity', 'smoothing_order': 'wind_farm_power_curves'} # Test modelchain with default values - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), **parameters) test_tc_mc.run_model(self.weather_df) @@ -245,30 +245,30 @@ def test_wind_turbine_cluster_repr_with_name(self): def test_wind_turbine_cluster_repr_without_name(self): """Test string representation of WindTurbineCluster without a name.""" - test_cluster = {'wind_farms': [wf.WindFarm(**self.test_farm), + test_cluster={'wind_farms': [wf.WindFarm(**self.test_farm), wf.WindFarm(**self.test_farm_2)]} assert 'Wind turbine cluster with:' in repr( wtc.WindTurbineCluster(**test_cluster)) def test_tc_modelchain_with_power_curve_as_dict(self): """Test power curves as dict in TurbineClusterModelChain.run_model()""" - my_turbine = {'nominal_power': 3e6, 'hub_height': 105, + my_turbine={'nominal_power': 3e6, 'hub_height': 105, 'power_curve': { 'value': [p * 1000 for p in [ 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - my_farm = {'wind_turbine_fleet': + my_farm={'wind_turbine_fleet': [{'wind_turbine': wt.WindTurbine(**my_turbine), 'number_of_turbines': 3}, {'wind_turbine': wt.WindTurbine(**self.test_turbine), 'number_of_turbines': 3}]} - my_cluster = {'wind_farms': [wf.WindFarm(**my_farm), + my_cluster= {'wind_farms': [wf.WindFarm(**my_farm), wf.WindFarm(**self.test_farm)]} - power_output_exp = pd.Series(data=[10853277.966972714, + power_output_exp=pd.Series(data=[10853277.966972714, 21731814.593688786], name='feedin_power_plant') # run model with my_cluster - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**my_cluster)) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) diff --git a/tests/test_wake_losses.py b/tests/test_wake_losses.py index 7ac66ff7..951ddcd1 100644 --- a/tests/test_wake_losses.py +++ b/tests/test_wake_losses.py @@ -15,9 +15,9 @@ class TestWakeLosses: def test_reduce_wind_speed(self): - parameters = {'wind_speed': pd.Series(np.arange(0, 26, 1.0)), + parameters={'wind_speed': pd.Series(np.arange(0, 26, 1.0)), 'wind_efficiency_curve_name': 'dena_mean'} - wind_speed_exp = pd.Series([ + wind_speed_exp=pd.Series([ 0.0, 0.9949534234119396, 1.9897327884892086, 2.9843374545454546, 3.807636264984227, 4.714931284760845, 5.642507531914893, 6.607021108049704, 7.592423167192429, 8.59498170212766, @@ -31,26 +31,26 @@ def test_reduce_wind_speed(self): # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters['wind_efficiency_curve_name'] = 'misspelled' + parameters['wind_efficiency_curve_name']='misspelled' reduce_wind_speed(**parameters) with pytest.raises(ValueError): - parameters['wind_efficiency_curve_name'] = 'dena_misspelled' + parameters['wind_efficiency_curve_name']='dena_misspelled' reduce_wind_speed(**parameters) def test_get_wind_efficiency_curve_one(self): """Test get_wind_efficiency_curve() for one curve.""" - wec = get_wind_efficiency_curve('dena_mean').sum() - wec_exp = pd.Series({'efficiency': 162.45047, + wec=get_wind_efficiency_curve('dena_mean').sum() + wec_exp=pd.Series({'efficiency': 162.45047, 'wind_speed': 1915.23620}) assert_series_equal(wec.sort_index(), wec_exp.sort_index()) def test_get_wind_efficiency_curve_all(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum = int(get_wind_efficiency_curve('all').sum().round().sum()) + wec_all_sum=int(get_wind_efficiency_curve('all').sum().round().sum()) assert wec_all_sum == 12145 def test_get_wind_efficiency_curve_list(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum = int(get_wind_efficiency_curve( + wec_all_sum=int(get_wind_efficiency_curve( ['dena_mean', 'knorr_mean']).sum().round().sum()) assert wec_all_sum == 3568 diff --git a/tests/test_wind_farm.py b/tests/test_wind_farm.py index 6e5c8aed..a2aa4dba 100644 --- a/tests/test_wind_farm.py +++ b/tests/test_wind_farm.py @@ -15,45 +15,45 @@ class TestWindFarm: @classmethod def setup_class(self): """Setup default values""" - self.test_turbine = {'hub_height': 100, + self.test_turbine={'hub_height': 100, 'turbine_type': 'E-126/4200'} - self.test_turbine_2 = {'hub_height': 90, + self.test_turbine_2={'hub_height': 90, 'turbine_type': 'V90/2000', 'nominal_power': 2e6} def test_initialization_list(self): """test simple initialization with wind turbine fleet list""" - wind_turbine_fleet = [ + wind_turbine_fleet=[ {'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 3}, {'wind_turbine': WindTurbine(**self.test_turbine_2), 'number_of_turbines': 2}] - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_list_2(self): """test simple initialization with wind turbine fleet list where once number of turbines and once total capacity is provided""" - wind_turbine_fleet = [ + wind_turbine_fleet=[ {'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 3}, {'wind_turbine': WindTurbine(**self.test_turbine_2), 'total_capacity': 2 * 2e6}] - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_dataframe(self): """test simple initialization with wind turbine fleet dataframe""" - wind_turbine_fleet = pd.DataFrame( + wind_turbine_fleet=pd.DataFrame( data={'wind_turbine': [WindTurbine(**self.test_turbine), WindTurbine(**self.test_turbine_2)], 'number_of_turbines': [3, 2]}) - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_1(self): """test catching error when wind_turbine_fleet not provided as list""" - msg = 'Wind turbine must be provided as WindTurbine object' + msg='Wind turbine must be provided as WindTurbine object' with pytest.raises(ValueError, match=msg): WindFarm(wind_turbine_fleet={'wind_turbine': 'turbine', 'number_of_turbines': 2}, @@ -62,40 +62,40 @@ def test_initialization_1(self): def test_initialization_2(self): """test catching error when WindTurbine in wind_turbine_fleet not initialized""" - test_farm = {'wind_turbine_fleet': [ + test_farm={'wind_turbine_fleet': [ {'wind_turbine': None, 'number_of_turbines': 3}]} - msg = 'Wind turbine must be provided as WindTurbine object' + msg='Wind turbine must be provided as WindTurbine object' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_3(self): """test catching error when wind_turbine not specified in wind_turbine_fleet""" - wind_turbine_fleet = pd.DataFrame( + wind_turbine_fleet=pd.DataFrame( data={'wind_turbines': [WindTurbine(**self.test_turbine), WindTurbine(**self.test_turbine_2)], 'number_of_turbines': [3, 2]}) - msg = 'Missing wind_turbine key/column in wind_turbine_fleet' + msg='Missing wind_turbine key/column in wind_turbine_fleet' with pytest.raises(KeyError, match=msg): WindFarm(wind_turbine_fleet=wind_turbine_fleet) def test_initialization_4(self, recwarn): """test overwriting and raising warning when number_of_turbines and total_capacity in wind turbine fleet do not fit""" - wt1 = WindTurbine(**self.test_turbine) - wt2 = WindTurbine(**self.test_turbine_2) - wind_turbine_fleet = pd.DataFrame( + wt1=WindTurbine(**self.test_turbine) + wt2=WindTurbine(**self.test_turbine_2) + wind_turbine_fleet=pd.DataFrame( data={'wind_turbine': [wt1, wt2], 'number_of_turbines': [3, 2], 'total_capacity': [3, np.nan]}, index=[0, 1]) - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) - total_cap_wt1_expected = \ + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + total_cap_wt1_expected=\ wt1.nominal_power * wind_turbine_fleet.loc[0, 'number_of_turbines'] assert windfarm.wind_turbine_fleet.loc[0, 'total_capacity'] == \ total_cap_wt1_expected - total_cap_wt2_expected = \ + total_cap_wt2_expected=\ wt2.nominal_power * wind_turbine_fleet.loc[1, 'number_of_turbines'] assert windfarm.wind_turbine_fleet.loc[1, 'total_capacity'] == \ total_cap_wt2_expected @@ -103,63 +103,63 @@ def test_initialization_4(self, recwarn): def test_initialization_5(self): """test catching error when number of turbines cannot be deduced""" - wt = WindTurbine(**self.test_turbine) - wt.nominal_power = None - test_farm = {'wind_turbine_fleet': [ + wt=WindTurbine(**self.test_turbine) + wt.nominal_power=None + test_farm={'wind_turbine_fleet': [ {'wind_turbine': wt, 'total_capacity': 3e6}]} - msg = 'Number of turbines of type' + msg='Number of turbines of type' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_6(self): """test catching error when neither number_of_turbines nor total_capacity is provided""" - test_farm = {'wind_turbine_fleet': [ + test_farm={'wind_turbine_fleet': [ {'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbine': 3e6}]} - msg = 'Number of turbines of type ' + msg='Number of turbines of type ' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_7(self): """test catching error when total capacity cannot be deduced""" - wt = WindTurbine(**self.test_turbine) - wt.nominal_power = None - test_farm = {'wind_turbine_fleet': [ + wt=WindTurbine(**self.test_turbine) + wt.nominal_power=None + test_farm={'wind_turbine_fleet': [ {'wind_turbine': wt, 'number_of_turbines': 3}]} - msg = 'Total capacity of turbines of type' + msg='Total capacity of turbines of type' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_mean_hub_height(self): """tests mean_hub_height method""" - test_farm = {'wind_turbine_fleet': [ + test_farm={'wind_turbine_fleet': [ {'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 2}, {'wind_turbine': WindTurbine(**self.test_turbine_2), 'total_capacity': 3e6}]} - windfarm = WindFarm(**test_farm) + windfarm=WindFarm(**test_farm) assert 97.265 == pytest.approx( windfarm.mean_hub_height().hub_height, 1e-3) def test_repr(self): """Test string representation of WindFarm""" - test_fleet = [{'wind_turbine': WindTurbine(**self.test_turbine), + test_fleet=[{'wind_turbine': WindTurbine(**self.test_turbine), 'number_of_turbines': 2}] assert 'E-126/4200' in repr(WindFarm(wind_turbine_fleet=test_fleet)) def test_aggregation_of_power_curve_with_missing_power_curve(self): """Test WindFarm.assign_power_curve() with missing power_curve.""" - wt1 = WindTurbine(**self.test_turbine) - wt1.power_curve = None - wind_turbine_fleet = [ + wt1=WindTurbine(**self.test_turbine) + wt1.power_curve=None + wind_turbine_fleet=[ {'wind_turbine': wt1, 'number_of_turbines': 3}, {'wind_turbine': WindTurbine(**self.test_turbine_2), 'number_of_turbines': 2}] - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) - msg = 'For an aggregated wind farm power curve each wind' + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + msg='For an aggregated wind farm power curve each wind' with pytest.raises(ValueError, match=msg): windfarm.assign_power_curve() diff --git a/tests/test_wind_speed.py b/tests/test_wind_speed.py index 162084c7..88712a3d 100644 --- a/tests/test_wind_speed.py +++ b/tests/test_wind_speed.py @@ -15,7 +15,7 @@ class TestWindSpeed: def test_logarithmic_profile(self): - parameters = {'wind_speed': pd.Series(data=[5.0, 6.5]), + parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), 'wind_speed_height': 10, 'hub_height': 100, 'roughness_length': pd.Series(data=[0.15, 0.15]), @@ -23,45 +23,45 @@ def test_logarithmic_profile(self): # Test wind_speed as pd.Series with roughness_length as pd.Series, # np.array and float - v_wind_hub_exp = pd.Series(data=[7.74136523, 10.0637748]) + v_wind_hub_exp=pd.Series(data=[7.74136523, 10.0637748]) assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) - parameters['roughness_length'] = np.array( + parameters['roughness_length']=np.array( parameters['roughness_length']) assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) - parameters['roughness_length'] = parameters['roughness_length'][0] + parameters['roughness_length']=parameters['roughness_length'][0] assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) # Test wind_speed as np.array with roughness_length as float, pd.Series # and np.array - v_wind_hub_exp = np.array([7.74136523, 10.0637748]) - parameters['wind_speed'] = np.array(parameters['wind_speed']) + v_wind_hub_exp=np.array([7.74136523, 10.0637748]) + parameters['wind_speed']=np.array(parameters['wind_speed']) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters['roughness_length'] = pd.Series( + parameters['roughness_length']=pd.Series( data=[parameters['roughness_length'], parameters['roughness_length']]) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters['roughness_length'] = np.array( + parameters['roughness_length']=np.array( parameters['roughness_length']) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) # Test obstacle_height is not zero - v_wind_hub_exp = np.array([13.54925281, 17.61402865]) - parameters['obstacle_height'] = 12 + v_wind_hub_exp=np.array([13.54925281, 17.61402865]) + parameters['obstacle_height']=12 assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) # Raise ValueError due to 0.7 * `obstacle_height` > `wind_speed_height` with pytest.raises(ValueError): - parameters['obstacle_height'] = 20 + parameters['obstacle_height']=20 logarithmic_profile(**parameters) def test_hellman(self): - parameters = {'wind_speed': pd.Series(data=[5.0, 6.5]), + parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), 'wind_speed_height': 10, 'hub_height': 100, 'roughness_length': pd.Series(data=[0.15, 0.15]), @@ -69,38 +69,38 @@ def test_hellman(self): # Test wind_speed is pd.Series with roughness_length is pd.Series, # np.array and float - v_wind_hub_exp = pd.Series(data=[7.12462437, 9.26201168]) + v_wind_hub_exp=pd.Series(data=[7.12462437, 9.26201168]) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters['roughness_length'] = np.array( + parameters['roughness_length']=np.array( parameters['roughness_length']) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters['roughness_length'] = parameters['roughness_length'][0] + parameters['roughness_length']=parameters['roughness_length'][0] assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test wind_speed as np.array with roughness_length is float, pd.Series # and np.array - v_wind_hub_exp = np.array([7.12462437, 9.26201168]) - parameters['wind_speed'] = np.array(parameters['wind_speed']) + v_wind_hub_exp=np.array([7.12462437, 9.26201168]) + parameters['wind_speed']=np.array(parameters['wind_speed']) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters['roughness_length'] = pd.Series( + parameters['roughness_length']=pd.Series( data=(parameters['roughness_length'], parameters['roughness_length'])) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters['roughness_length'] = np.array( + parameters['roughness_length']=np.array( parameters['roughness_length']) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) # Test roughness_length is None and hellman_exponent is None - v_wind_hub_exp = pd.Series(data=[6.9474774, 9.03172]) - parameters['wind_speed'] = pd.Series(data=parameters['wind_speed']) - parameters['roughness_length'] = None + v_wind_hub_exp=pd.Series(data=[6.9474774, 9.03172]) + parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) + parameters['roughness_length']=None assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test hellman_exponent is not None - v_wind_hub_exp = pd.Series(data=[7.92446596, 10.30180575]) - parameters['roughness_length'] = 0.15 - parameters['hellman_exponent'] = 0.2 + v_wind_hub_exp=pd.Series(data=[7.92446596, 10.30180575]) + parameters['roughness_length']=0.15 + parameters['hellman_exponent']=0.2 assert_series_equal(hellman(**parameters), v_wind_hub_exp) diff --git a/tests/test_wind_turbine.py b/tests/test_wind_turbine.py index 5ba627a2..fdcf4472 100644 --- a/tests/test_wind_turbine.py +++ b/tests/test_wind_turbine.py @@ -19,10 +19,10 @@ class TestWindTurbine: @classmethod def setup_class(cls): """Setup default values""" - cls.source = os.path.join(os.path.dirname(__file__), '../example/data') + cls.source=os.path.join(os.path.dirname(__file__), '../example/data') def test_warning(self, recwarn): - test_turbine_data = {'hub_height': 100, + test_turbine_data={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'turbine_not_in_file', 'path': self.source} @@ -37,10 +37,10 @@ def test_get_turbine_data_from_file(self): def test_get_turbine_types(self, capsys): get_turbine_types() - captured = capsys.readouterr() + captured=capsys.readouterr() assert 'Enercon' in captured.out get_turbine_types('oedb', print_out=False, filter_=False) - msg = "`turbine_library` is 'wrong' but must be 'local' or 'oedb'." + msg="`turbine_library` is 'wrong' but must be 'local' or 'oedb'." with pytest.raises(ValueError, match=msg): get_turbine_types('wrong') @@ -57,7 +57,7 @@ def test_string_representation_of_wind_turbine(self): def test_power_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_curve.""" - test_turbine_data = {'hub_height': 100, + test_turbine_data={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'test_type', 'power_curve': 'string'} @@ -67,7 +67,7 @@ def test_power_curve_is_of_wrong_type(self): def test_power_coefficient_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_coefficient_curve.""" - test_turbine_data = {'hub_height': 100, + test_turbine_data={'hub_height': 100, 'rotor_diameter': 80, 'turbine_type': 'test_type', 'power_coefficient_curve': 'string'} @@ -75,24 +75,24 @@ def test_power_coefficient_curve_is_of_wrong_type(self): WindTurbine(**test_turbine_data) def test_to_group_method(self): - example_turbine = { + example_turbine={ 'hub_height': 100, 'rotor_diameter': 70, 'turbine_type': 'DUMMY 3', 'path': self.source} - e_t_1 = WindTurbine(**example_turbine) + e_t_1=WindTurbine(**example_turbine) assert(isinstance(e_t_1.to_group(), WindTurbineGroup)) assert(e_t_1.to_group(5).number_of_turbines == 5) assert(e_t_1.to_group(number_turbines=5).number_of_turbines == 5) assert(e_t_1.to_group(total_capacity=3e6).number_of_turbines == 2.0) def test_wrongly_defined_to_group_method(self): - example_turbine = { + example_turbine={ 'hub_height': 100, 'rotor_diameter': 70, 'turbine_type': 'DUMMY 3', 'path': self.source} - e_t_1 = WindTurbine(**example_turbine) + e_t_1=WindTurbine(**example_turbine) with pytest.raises(ValueError, match="The 'number' and the 'total_capacity' " "parameter are mutually exclusive."): diff --git a/windpowerlib/__init__.py b/windpowerlib/__init__.py index 23ebcb2b..7ffd29ce 100644 --- a/windpowerlib/__init__.py +++ b/windpowerlib/__init__.py @@ -1,6 +1,6 @@ -__copyright__ = "Copyright oemof developer group" -__license__ = "MIT" -__version__ = '0.2.1dev' +__copyright__="Copyright oemof developer group" +__license__="MIT" +__version__='0.2.1dev' from windpowerlib.wind_turbine import WindTurbine from windpowerlib.wind_farm import WindFarm diff --git a/windpowerlib/modelchain.py b/windpowerlib/modelchain.py index 0a4cfc4e..e137934a 100644 --- a/windpowerlib/modelchain.py +++ b/windpowerlib/modelchain.py @@ -122,13 +122,13 @@ class ModelChain(object): -------- >>> from windpowerlib import modelchain >>> from windpowerlib import wind_turbine - >>> enerconE126 = { + >>> enerconE126={ ... 'hub_height': 135, ... 'rotor_diameter': 127, ... 'turbine_type': 'E-126/4200'} - >>> e126 = wind_turbine.WindTurbine(**enerconE126) - >>> modelchain_data = {'density_model': 'ideal_gas'} - >>> e126_mc = modelchain.ModelChain(e126, **modelchain_data) + >>> e126=wind_turbine.WindTurbine(**enerconE126) + >>> modelchain_data={'density_model': 'ideal_gas'} + >>> e126_mc=modelchain.ModelChain(e126, **modelchain_data) >>> print(e126_mc.density_model) ideal_gas @@ -143,15 +143,15 @@ def __init__(self, power_plant, obstacle_height=0, hellman_exp=None, **kwargs): - self.power_plant = power_plant - self.obstacle_height = obstacle_height - self.wind_speed_model = wind_speed_model - self.temperature_model = temperature_model - self.density_model = density_model - self.power_output_model = power_output_model - self.density_correction = density_correction - self.hellman_exp = hellman_exp - self.power_output = None + self.power_plant=power_plant + self.obstacle_height=obstacle_height + self.wind_speed_model=wind_speed_model + self.temperature_model=temperature_model + self.density_model=density_model + self.power_output_model=power_output_model + self.density_correction=density_correction + self.hellman_exp=hellman_exp + self.power_output=None def temperature_hub(self, weather_df): r""" @@ -183,22 +183,22 @@ def temperature_hub(self, weather_df): """ if self.power_plant.hub_height in weather_df['temperature']: - temperature_hub = weather_df['temperature'][ + temperature_hub=weather_df['temperature'][ self.power_plant.hub_height] elif self.temperature_model == 'linear_gradient': logging.debug('Calculating temperature using temperature ' 'gradient.') - closest_height = weather_df['temperature'].columns[ + closest_height=weather_df['temperature'].columns[ min(range(len(weather_df['temperature'].columns)), key=lambda i: abs(weather_df['temperature'].columns[i] - self.power_plant.hub_height))] - temperature_hub = temperature.linear_gradient( + temperature_hub=temperature.linear_gradient( weather_df['temperature'][closest_height], closest_height, self.power_plant.hub_height) elif self.temperature_model == 'interpolation_extrapolation': logging.debug('Calculating temperature using linear inter- or ' 'extrapolation.') - temperature_hub = tools.linear_interpolation_extrapolation( + temperature_hub=tools.linear_interpolation_extrapolation( weather_df['temperature'], self.power_plant.hub_height) else: raise ValueError("'{0}' is an invalid value. ".format( @@ -242,32 +242,32 @@ def density_hub(self, weather_df): density. """ if self.density_model != 'interpolation_extrapolation': - temperature_hub = self.temperature_hub(weather_df) + temperature_hub=self.temperature_hub(weather_df) # Calculation of density in kg/m³ at hub height if self.density_model == 'barometric': logging.debug('Calculating density using barometric height ' 'equation.') - closest_height = weather_df['pressure'].columns[ + closest_height=weather_df['pressure'].columns[ min(range(len(weather_df['pressure'].columns)), key=lambda i: abs(weather_df['pressure'].columns[i] - self.power_plant.hub_height))] - density_hub = density.barometric( + density_hub=density.barometric( weather_df['pressure'][closest_height], closest_height, self.power_plant.hub_height, temperature_hub) elif self.density_model == 'ideal_gas': logging.debug('Calculating density using ideal gas equation.') - closest_height = weather_df['pressure'].columns[ + closest_height=weather_df['pressure'].columns[ min(range(len(weather_df['pressure'].columns)), key=lambda i: abs(weather_df['pressure'].columns[i] - self.power_plant.hub_height))] - density_hub = density.ideal_gas( + density_hub=density.ideal_gas( weather_df['pressure'][closest_height], closest_height, self.power_plant.hub_height, temperature_hub) elif self.density_model == 'interpolation_extrapolation': logging.debug('Calculating density using linear inter- or ' 'extrapolation.') - density_hub = tools.linear_interpolation_extrapolation( + density_hub=tools.linear_interpolation_extrapolation( weather_df['density'], self.power_plant.hub_height) else: raise ValueError("'{0}' is an invalid value. ".format( @@ -306,27 +306,27 @@ def wind_speed_hub(self, weather_df): """ if self.power_plant.hub_height in weather_df['wind_speed']: - wind_speed_hub = weather_df['wind_speed'][ + wind_speed_hub=weather_df['wind_speed'][ self.power_plant.hub_height] elif self.wind_speed_model == 'logarithmic': logging.debug('Calculating wind speed using logarithmic wind ' 'profile.') - closest_height = weather_df['wind_speed'].columns[ + closest_height=weather_df['wind_speed'].columns[ min(range(len(weather_df['wind_speed'].columns)), key=lambda i: abs(weather_df['wind_speed'].columns[i] - self.power_plant.hub_height))] - wind_speed_hub = wind_speed.logarithmic_profile( + wind_speed_hub=wind_speed.logarithmic_profile( weather_df['wind_speed'][closest_height], closest_height, self.power_plant.hub_height, weather_df['roughness_length'].iloc[:, 0], self.obstacle_height) elif self.wind_speed_model == 'hellman': logging.debug('Calculating wind speed using hellman equation.') - closest_height = weather_df['wind_speed'].columns[ + closest_height=weather_df['wind_speed'].columns[ min(range(len(weather_df['wind_speed'].columns)), key=lambda i: abs(weather_df['wind_speed'].columns[i] - self.power_plant.hub_height))] - wind_speed_hub = wind_speed.hellman( + wind_speed_hub=wind_speed.hellman( weather_df['wind_speed'][closest_height], closest_height, self.power_plant.hub_height, weather_df['roughness_length'].iloc[:, 0], @@ -334,12 +334,12 @@ def wind_speed_hub(self, weather_df): elif self.wind_speed_model == 'interpolation_extrapolation': logging.debug('Calculating wind speed using linear inter- or ' 'extrapolation.') - wind_speed_hub = tools.linear_interpolation_extrapolation( + wind_speed_hub=tools.linear_interpolation_extrapolation( weather_df['wind_speed'], self.power_plant.hub_height) elif self.wind_speed_model == 'log_interpolation_extrapolation': logging.debug('Calculating wind speed using logarithmic inter- or ' 'extrapolation.') - wind_speed_hub = tools.logarithmic_interpolation_extrapolation( + wind_speed_hub=tools.logarithmic_interpolation_extrapolation( weather_df['wind_speed'], self.power_plant.hub_height) else: raise ValueError("'{0}' is an invalid value. ".format( @@ -422,7 +422,7 @@ def run_model(self, weather_df): --------- >>> import numpy as np >>> import pandas as pd - >>> weather_df = pd.DataFrame(np.random.rand(2,6), + >>> weather_df=pd.DataFrame(np.random.rand(2,6), ... index=pd.date_range('1/1/2012', ... periods=2, ... freq='H'), @@ -438,10 +438,10 @@ def run_model(self, weather_df): 'wind_speed' """ - wind_speed_hub = self.wind_speed_hub(weather_df) - density_hub = (None if (self.power_output_model == 'power_curve' and + wind_speed_hub=self.wind_speed_hub(weather_df) + density_hub=(None if (self.power_output_model == 'power_curve' and self.density_correction is False) else self.density_hub(weather_df)) - self.power_output = self.calculate_power_output(wind_speed_hub, + self.power_output=self.calculate_power_output(wind_speed_hub, density_hub) return self diff --git a/windpowerlib/power_curves.py b/windpowerlib/power_curves.py index 96829474..0aa6acaf 100644 --- a/windpowerlib/power_curves.py +++ b/windpowerlib/power_curves.py @@ -60,7 +60,7 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, The following equation is used to calculated the power curves values of the smoothed power curve [1]_: - .. math:: P_{smoothed}(v_{std}) = \sum\limits_{v_i} \Delta v_i \cdot P(v_i) + .. math:: P_{smoothed}(v_{std})=\sum\limits_{v_i} \Delta v_i \cdot P(v_i) \cdot \frac{1}{\sigma \sqrt{2 \pi}} \exp \left[-\frac{(v_{std} - v_i -\mu)^2}{2 \sigma^2} \right] :label: power @@ -83,7 +83,7 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, 'turbulence_intensity' [2]_: - .. math:: \sigma = v_\text{std} \cdot \sigma_\text{n} = v_\text{std} + .. math:: \sigma=v_\text{std} \cdot \sigma_\text{n}=v_\text{std} \cdot TI with: @@ -91,7 +91,7 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, 'Staffell_Pfenninger' [4]_: - .. math:: \sigma = 0.6 \cdot 0.2 \cdot v_\text{std} + .. math:: \sigma=0.6 \cdot 0.2 \cdot v_\text{std} References ---------- @@ -113,37 +113,37 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, if standard_deviation_method == 'turbulence_intensity': if ('turbulence_intensity' in kwargs and kwargs['turbulence_intensity'] is not np.nan): - normalized_standard_deviation = kwargs['turbulence_intensity'] + normalized_standard_deviation=kwargs['turbulence_intensity'] else: raise ValueError("Turbulence intensity must be defined for " + "using 'turbulence_intensity' as " + "`standard_deviation_method`") elif standard_deviation_method == 'Staffell_Pfenninger': - normalized_standard_deviation = 0.2 + normalized_standard_deviation=0.2 else: raise ValueError("{} is no valid `standard_deviation_method`. Valid " + "options are 'turbulence_intensity', or " + "'Staffell_Pfenninger'".format( standard_deviation_method)) # Initialize list for power curve values - smoothed_power_curve_values = [] + smoothed_power_curve_values=[] # Append wind speeds to `power_curve_wind_speeds` - maximum_value = power_curve_wind_speeds.iloc[-1] + wind_speed_range + maximum_value=power_curve_wind_speeds.iloc[-1] + wind_speed_range while power_curve_wind_speeds.values[-1] < maximum_value: - power_curve_wind_speeds = power_curve_wind_speeds.append( + power_curve_wind_speeds=power_curve_wind_speeds.append( pd.Series(power_curve_wind_speeds.iloc[-1] + (power_curve_wind_speeds.iloc[5] - power_curve_wind_speeds.iloc[4]), index=[power_curve_wind_speeds.index[-1] + 1])) - power_curve_values = power_curve_values.append( + power_curve_values=power_curve_values.append( pd.Series(0.0, index=[power_curve_values.index[-1] + 1])) for power_curve_wind_speed in power_curve_wind_speeds: # Create array of wind speeds for the sum - wind_speeds_block = (np.arange( + wind_speeds_block=(np.arange( -wind_speed_range, wind_speed_range + block_width, block_width) + power_curve_wind_speed) # Get standard deviation for Gauss function - standard_deviation = ( + standard_deviation=( (power_curve_wind_speed * normalized_standard_deviation + 0.6) if standard_deviation_method is 'Staffell_Pfenninger' else power_curve_wind_speed * normalized_standard_deviation) @@ -151,9 +151,9 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, if standard_deviation == 0.0: # The gaussian distribution is not defined for a standard deviation # of zero. Smoothed power curve value is set to zero. - smoothed_value = 0.0 + smoothed_value=0.0 else: - smoothed_value = sum( + smoothed_value=sum( block_width * np.interp(wind_speed, power_curve_wind_speeds, power_curve_values, left=0, right=0) * tools.gauss_distribution( @@ -164,11 +164,11 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, # distribution for a standard deviation of zero. smoothed_power_curve_values.append(smoothed_value) # Create smoothed power curve data frame - smoothed_power_curve_df = pd.DataFrame( + smoothed_power_curve_df=pd.DataFrame( data=[list(power_curve_wind_speeds.values), smoothed_power_curve_values]).transpose() # Rename columns of the data frame - smoothed_power_curve_df.columns = ['wind_speed', 'value'] + smoothed_power_curve_df.columns=['wind_speed', 'value'] return smoothed_power_curve_df @@ -200,25 +200,25 @@ def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values, """ # Create power curve DataFrame - power_curve_df = pd.DataFrame( + power_curve_df=pd.DataFrame( data=[list(power_curve_wind_speeds), list(power_curve_values)]).transpose() # Rename columns of DataFrame - power_curve_df.columns = ['wind_speed', 'value'] + power_curve_df.columns=['wind_speed', 'value'] if isinstance(wind_farm_efficiency, float): - power_curve_df['value'] = power_curve_values * wind_farm_efficiency + power_curve_df['value']=power_curve_values * wind_farm_efficiency elif (isinstance(wind_farm_efficiency, dict) or isinstance(wind_farm_efficiency, pd.DataFrame)): - df = pd.concat([power_curve_df.set_index('wind_speed'), + df=pd.concat([power_curve_df.set_index('wind_speed'), wind_farm_efficiency.set_index('wind_speed')], axis=1) # Add column with reduced power (nan values of efficiency are # interpolated) - df['reduced_power'] = df['value'] * df['efficiency'].interpolate( + df['reduced_power']=df['value'] * df['efficiency'].interpolate( method='index') - reduced_power = df['reduced_power'].dropna() - power_curve_df = pd.DataFrame([reduced_power.index, + reduced_power=df['reduced_power'].dropna() + power_curve_df=pd.DataFrame([reduced_power.index, reduced_power.values]).transpose() - power_curve_df.columns = ['wind_speed', 'value'] + power_curve_df.columns=['wind_speed', 'value'] else: raise TypeError( "'wind_farm_efficiency' must be float, dict or pd.DataFrame " diff --git a/windpowerlib/power_output.py b/windpowerlib/power_output.py index ff9c658f..ba446e6a 100644 --- a/windpowerlib/power_output.py +++ b/windpowerlib/power_output.py @@ -63,18 +63,18 @@ def power_coefficient_curve(wind_speed, power_coefficient_curve_wind_speeds, Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 542 """ - power_coefficient_time_series = np.interp( + power_coefficient_time_series=np.interp( wind_speed, power_coefficient_curve_wind_speeds, power_coefficient_curve_values, left=0, right=0) - power_output = (1 / 8 * density * rotor_diameter ** 2 * np.pi * + power_output=(1 / 8 * density * rotor_diameter ** 2 * np.pi * np.power(wind_speed, 3) * power_coefficient_time_series) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output = pd.Series(data=power_output, index=wind_speed.index, + power_output=pd.Series(data=power_output, index=wind_speed.index, name='feedin_power_plant') else: - power_output = np.array(power_output) + power_output=np.array(power_output) return power_output @@ -120,16 +120,16 @@ def power_curve(wind_speed, power_curve_wind_speeds, power_curve_values, """ if density_correction is False: - power_output = np.interp(wind_speed, power_curve_wind_speeds, + power_output=np.interp(wind_speed, power_curve_wind_speeds, power_curve_values, left=0, right=0) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output = pd.Series(data=power_output, index=wind_speed.index, + power_output=pd.Series(data=power_output, index=wind_speed.index, name='feedin_power_plant') else: - power_output = np.array(power_output) + power_output=np.array(power_output) elif density_correction is True: - power_output = power_curve_density_correction( + power_output=power_curve_density_correction( wind_speed, power_curve_wind_speeds, power_curve_values, density) else: raise TypeError("'{0}' is an invalid type. ".format(type( @@ -210,15 +210,15 @@ def power_curve_density_correction(wind_speed, power_curve_wind_speeds, raise TypeError("`density` is None. For the calculation with a " + "density corrected power curve density at hub " + "height is needed.") - power_output = [(np.interp( + power_output=[(np.interp( wind_speed[i], power_curve_wind_speeds * (1.225 / density[i]) ** ( np.interp(power_curve_wind_speeds, [7.5, 12.5], [1/3, 2/3])), power_curve_values, left=0, right=0)) for i in range(len(wind_speed))] # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output = pd.Series(data=power_output, index=wind_speed.index, + power_output=pd.Series(data=power_output, index=wind_speed.index, name='feedin_power_plant') else: - power_output = np.array(power_output) + power_output=np.array(power_output) return power_output diff --git a/windpowerlib/tools.py b/windpowerlib/tools.py index 25f6b99c..3d4c593c 100644 --- a/windpowerlib/tools.py +++ b/windpowerlib/tools.py @@ -56,16 +56,16 @@ def linear_interpolation_extrapolation(df, target_height): For the inter- and extrapolation the following equation is used: - .. math:: f(x) = \frac{(f(x_2) - f(x_1))}{(x_2 - x_1)} \cdot + .. math:: f(x)=\frac{(f(x_2) - f(x_1))}{(x_2 - x_1)} \cdot (x - x_1) + f(x_1) Examples --------- >>> import numpy as np >>> import pandas as pd - >>> wind_speed_10m = np.array([[3], [4]]) - >>> wind_speed_80m = np.array([[6], [6]]) - >>> weather_df = pd.DataFrame(np.hstack((wind_speed_10m, + >>> wind_speed_10m=np.array([[3], [4]]) + >>> wind_speed_80m=np.array([[6], [6]]) + >>> weather_df=pd.DataFrame(np.hstack((wind_speed_10m, ... wind_speed_80m)), ... index=pd.date_range('1/1/2012', ... periods=2, @@ -73,12 +73,12 @@ def linear_interpolation_extrapolation(df, target_height): ... columns=[np.array(['wind_speed', ... 'wind_speed']), ... np.array([10, 80])]) - >>> value = linear_interpolation_extrapolation( + >>> value=linear_interpolation_extrapolation( ... weather_df['wind_speed'], 100)[0] """ # find closest heights - heights_sorted = df.columns[ + heights_sorted=df.columns[ sorted(range(len(df.columns)), key=lambda i: abs(df.columns[i] - target_height))] return ((df[heights_sorted[1]] - df[heights_sorted[0]]) / @@ -120,7 +120,7 @@ def logarithmic_interpolation_extrapolation(df, target_height): For the logarithmic inter- and extrapolation the following equation is used [1]_: - .. math:: f(x) = \frac{\ln(x) \cdot (f(x_2) - f(x_1)) - f(x_2) \cdot + .. math:: f(x)=\frac{\ln(x) \cdot (f(x_2) - f(x_1)) - f(x_2) \cdot \ln(x_1) + f(x_1) \cdot \ln(x_2)}{\ln(x_2) - \ln(x_1)} References @@ -132,7 +132,7 @@ def logarithmic_interpolation_extrapolation(df, target_height): """ # find closest heights - heights_sorted = df.columns[ + heights_sorted=df.columns[ sorted(range(len(df.columns)), key=lambda i: abs(df.columns[i] - target_height))] return ((np.log(target_height) * @@ -168,7 +168,7 @@ def gauss_distribution(function_variable, standard_deviation, mean=0): ----- The following equation is used [1]_: - .. math:: f(x) = \frac{1}{\sigma \sqrt{2 \pi}} \exp + .. math:: f(x)=\frac{1}{\sigma \sqrt{2 \pi}} \exp \left[-\frac{(x-\mu)^2}{2 \sigma^2}\right] with: @@ -201,7 +201,7 @@ def estimate_turbulence_intensity(height, roughness_length): ----- The following equation is used [1]_: - .. math:: TI = \frac{1}{\ln\left(\frac{h}{z_\text{0}}\right)} + .. math:: TI=\frac{1}{\ln\left(\frac{h}{z_\text{0}}\right)} with: TI: turbulence intensity, h: height, :math:`z_{0}`: roughness length diff --git a/windpowerlib/turbine_cluster_modelchain.py b/windpowerlib/turbine_cluster_modelchain.py index 39c87480..4d978d3a 100644 --- a/windpowerlib/turbine_cluster_modelchain.py +++ b/windpowerlib/turbine_cluster_modelchain.py @@ -148,15 +148,15 @@ def __init__(self, power_plant, wake_losses_model='dena_mean', smoothing_order='wind_farm_power_curves', **kwargs): super(TurbineClusterModelChain, self).__init__(power_plant, **kwargs) - self.power_plant = power_plant - self.wake_losses_model = wake_losses_model - self.smoothing = smoothing - self.block_width = block_width - self.standard_deviation_method = standard_deviation_method - self.smoothing_order = smoothing_order + self.power_plant=power_plant + self.wake_losses_model=wake_losses_model + self.smoothing=smoothing + self.block_width=block_width + self.standard_deviation_method=standard_deviation_method + self.smoothing_order=smoothing_order - self.power_curve = None - self.power_output = None + self.power_curve=None + self.power_output=None def assign_power_curve(self, weather_df): r""" @@ -186,18 +186,18 @@ def assign_power_curve(self, weather_df): """ # Get turbulence intensity from weather if existent - turbulence_intensity = ( + turbulence_intensity=( weather_df['turbulence_intensity'].values.mean() if 'turbulence_intensity' in weather_df.columns.get_level_values(0) else None) - roughness_length = ( + roughness_length=( weather_df['roughness_length'].values.mean() if 'roughness_length' in weather_df.columns.get_level_values(0) else None) # Assign power curve if (self.wake_losses_model == 'wind_farm_efficiency' or self.wake_losses_model is None): - wake_losses_model_to_power_curve = self.wake_losses_model + wake_losses_model_to_power_curve=self.wake_losses_model if self.wake_losses_model is None: logging.debug('Wake losses in wind farms are not considered.') else: @@ -206,7 +206,7 @@ def assign_power_curve(self, weather_df): else: logging.debug('Wake losses considered by {} wind '.format( self.wake_losses_model) + 'efficiency curve.') - wake_losses_model_to_power_curve = None + wake_losses_model_to_power_curve=None self.power_plant.assign_power_curve( wake_losses_model=wake_losses_model_to_power_curve, smoothing=self.smoothing, block_width=self.block_width, @@ -250,7 +250,7 @@ def run_model(self, weather_df): --------- >>> import numpy as np >>> import pandas as pd - >>> weather_df = pd.DataFrame(np.random.rand(2,6), + >>> weather_df=pd.DataFrame(np.random.rand(2,6), ... index=pd.date_range('1/1/2012', ... periods=2, ... freq='H'), @@ -269,16 +269,16 @@ def run_model(self, weather_df): self.assign_power_curve(weather_df) self.power_plant.mean_hub_height() - wind_speed_hub = self.wind_speed_hub(weather_df) - density_hub = (None if (self.power_output_model == 'power_curve' and + wind_speed_hub=self.wind_speed_hub(weather_df) + density_hub=(None if (self.power_output_model == 'power_curve' and self.density_correction is False) else self.density_hub(weather_df)) if (self.wake_losses_model != 'wind_farm_efficiency' and self.wake_losses_model is not None): # Reduce wind speed with wind efficiency curve - wind_speed_hub = wake_losses.reduce_wind_speed( + wind_speed_hub=wake_losses.reduce_wind_speed( wind_speed_hub, wind_efficiency_curve_name=self.wake_losses_model) - self.power_output = self.calculate_power_output(wind_speed_hub, + self.power_output=self.calculate_power_output(wind_speed_hub, density_hub) return self diff --git a/windpowerlib/wake_losses.py b/windpowerlib/wake_losses.py index 7bc83549..59d0ea37 100644 --- a/windpowerlib/wake_losses.py +++ b/windpowerlib/wake_losses.py @@ -45,10 +45,10 @@ def reduce_wind_speed(wind_speed, wind_efficiency_curve_name='dena_mean'): """ # Get wind efficiency curve - wind_efficiency_curve = get_wind_efficiency_curve( + wind_efficiency_curve=get_wind_efficiency_curve( curve_name=wind_efficiency_curve_name) # Reduce wind speed by wind efficiency - reduced_wind_speed = wind_speed * np.interp( + reduced_wind_speed=wind_speed * np.interp( wind_speed, wind_efficiency_curve['wind_speed'], wind_efficiency_curve['efficiency']) return reduced_wind_speed @@ -98,54 +98,54 @@ def get_wind_efficiency_curve(curve_name='all'): -------- .. parsed-literal:: # Example to plot all curves - fig, ax = plt.subplots() /n - df = get_wind_efficiency_curve(curve_name='all') + fig, ax=plt.subplots() /n + df=get_wind_efficiency_curve(curve_name='all') for t in df.columns.get_level_values(0).unique(): - p = df[t].set_index('wind_speed')['efficiency'] - p.name = t - ax = p.plot(ax=ax, legend=True) + p=df[t].set_index('wind_speed')['efficiency'] + p.name=t + ax=p.plot(ax=ax, legend=True) plt.show() """ - possible_curve_names = ['dena_mean', 'knorr_mean', 'dena_extreme1', + possible_curve_names=['dena_mean', 'knorr_mean', 'dena_extreme1', 'dena_extreme2', 'knorr_extreme1', 'knorr_extreme2', 'knorr_extreme3'] if curve_name == 'all': - curve_names = possible_curve_names + curve_names=possible_curve_names elif isinstance(curve_name, str): - curve_names = [curve_name] + curve_names=[curve_name] else: - curve_names = curve_name + curve_names=curve_name - efficiency_curve = pd.DataFrame() + efficiency_curve=pd.DataFrame() for curve_name in curve_names: if curve_name.split('_')[0] not in ['dena', 'knorr']: raise ValueError("`curve_name` must be one of the following: " + "{} but is {}".format(possible_curve_names, curve_name)) - path = os.path.join(os.path.dirname(__file__), 'data', + path=os.path.join(os.path.dirname(__file__), 'data', 'wind_efficiency_curves_{}.csv'.format( curve_name.split('_')[0])) # Read wind efficiency curves from file - wind_efficiency_curves = pd.read_csv(path) + wind_efficiency_curves=pd.read_csv(path) # Raise error if wind efficiency curve specified in 'curve_name' does # not exist if curve_name not in list(wind_efficiency_curves): - msg = ("Efficiency curve <{0}> does not exist. Must be one of the " + msg=("Efficiency curve <{0}> does not exist. Must be one of the " "following: {1}.") raise ValueError(msg.format(curve_name, *possible_curve_names)) # Get wind efficiency curve and rename column containing efficiency - wec = wind_efficiency_curves[['wind_speed', curve_name]] + wec=wind_efficiency_curves[['wind_speed', curve_name]] if efficiency_curve.empty: - efficiency_curve = pd.DataFrame( + efficiency_curve=pd.DataFrame( {(curve_name, 'wind_speed'): wec['wind_speed'], (curve_name, 'efficiency'): wec[curve_name]}) else: - efficiency_curve[(curve_name, 'wind_speed')] = wec['wind_speed'] - efficiency_curve[(curve_name, 'efficiency')] = wec[curve_name] + efficiency_curve[(curve_name, 'wind_speed')]=wec['wind_speed'] + efficiency_curve[(curve_name, 'efficiency')]=wec[curve_name] if len(curve_names) == 1: return efficiency_curve[curve_names[0]] else: diff --git a/windpowerlib/wind_farm.py b/windpowerlib/wind_farm.py index 2030ce48..8df8c2b8 100644 --- a/windpowerlib/wind_farm.py +++ b/windpowerlib/wind_farm.py @@ -76,52 +76,52 @@ class WindFarm(object): >>> from windpowerlib import wind_farm >>> from windpowerlib import WindTurbine >>> import pandas as pd - >>> enerconE126 = { + >>> enerconE126={ ... 'hub_height': 135, ... 'rotor_diameter': 127, ... 'turbine_type': 'E-126/4200'} - >>> e126 = WindTurbine(**enerconE126) - >>> vestasV90 = { + >>> e126=WindTurbine(**enerconE126) + >>> vestasV90={ ... 'hub_height': 90, ... 'turbine_type': 'V90/2000', ... 'nominal_power': 2e6} - >>> v90 = WindTurbine(**vestasV90) + >>> v90=WindTurbine(**vestasV90) >>> # turbine fleet as DataFrame - >>> wind_turbine_fleet = pd.DataFrame( + >>> wind_turbine_fleet=pd.DataFrame( ... {'wind_turbine': [e126, v90], ... 'number_of_turbines': [6, None], ... 'total_capacity': [None, 3 * 2e6]}) - >>> example_farm = wind_farm.WindFarm(wind_turbine_fleet, name='my_farm') + >>> example_farm=wind_farm.WindFarm(wind_turbine_fleet, name='my_farm') >>> print(example_farm.nominal_power) 31200000.0 >>> # turbine fleet as a list of WindTurbineGroup objects using the >>> # 'to_group' method. - >>> wind_turbine_fleet = [e126.to_group(6), + >>> wind_turbine_fleet=[e126.to_group(6), ... v90.to_group(total_capacity=3 * 2e6)] - >>> example_farm = wind_farm.WindFarm(wind_turbine_fleet, name='my_farm') + >>> example_farm=wind_farm.WindFarm(wind_turbine_fleet, name='my_farm') >>> print(example_farm.nominal_power) 31200000.0 >>> # turbine fleet as list of dictionaries (not recommended) - >>> example_farm_data = { + >>> example_farm_data={ ... 'name': 'my_farm', ... 'wind_turbine_fleet': [{'wind_turbine': e126, ... 'number_of_turbines': 6}, ... {'wind_turbine': v90, ... 'total_capacity': 3 * 2e6}]} - >>> example_farm = wind_farm.WindFarm(**example_farm_data) + >>> example_farm=wind_farm.WindFarm(**example_farm_data) >>> print(example_farm.nominal_power) 31200000.0 """ def __init__(self, wind_turbine_fleet, efficiency=None, name='', **kwargs): - self.wind_turbine_fleet = wind_turbine_fleet - self.efficiency = efficiency - self.name = name + self.wind_turbine_fleet=wind_turbine_fleet + self.efficiency=efficiency + self.name=name - self.hub_height = None - self._nominal_power = None - self.power_curve = None + self.hub_height=None + self._nominal_power=None + self.power_curve=None self.check_and_complete_wind_turbine_fleet() @@ -137,7 +137,7 @@ def check_and_complete_wind_turbine_fleet(self): """ # convert list to dataframe if necessary if isinstance(self.wind_turbine_fleet, list): - self.wind_turbine_fleet = pd.DataFrame(self.wind_turbine_fleet) + self.wind_turbine_fleet=pd.DataFrame(self.wind_turbine_fleet) # check wind turbines try: @@ -153,25 +153,25 @@ def check_and_complete_wind_turbine_fleet(self): # add columns for number of turbines and total capacity if they don't # yet exist if 'number_of_turbines' not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet['number_of_turbines'] = np.nan + self.wind_turbine_fleet['number_of_turbines']=np.nan if 'total_capacity' not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet['total_capacity'] = np.nan + self.wind_turbine_fleet['total_capacity']=np.nan # calculate number of turbines if necessary - number_turbines_not_provided = self.wind_turbine_fleet[ + number_turbines_not_provided=self.wind_turbine_fleet[ self.wind_turbine_fleet['number_of_turbines'].isnull()] for ix, row in number_turbines_not_provided.iterrows(): - msg = 'Number of turbines of type {0} can not be deduced ' \ + msg='Number of turbines of type {0} can not be deduced ' \ 'from total capacity. Please either provide ' \ '`number_of_turbines` in the turbine fleet definition or ' \ 'set the nominal power of the wind turbine.' try: - number_of_turbines = row['total_capacity'] / \ + number_of_turbines=row['total_capacity'] / \ row['wind_turbine'].nominal_power if np.isnan(number_of_turbines): raise ValueError(msg.format(row['wind_turbine'])) else: - self.wind_turbine_fleet.loc[ix, 'number_of_turbines'] = \ + self.wind_turbine_fleet.loc[ix, 'number_of_turbines']=\ number_of_turbines except TypeError: raise ValueError(msg.format(row['wind_turbine'])) @@ -181,7 +181,7 @@ def check_and_complete_wind_turbine_fleet(self): for ix, row in self.wind_turbine_fleet.iterrows(): if np.isnan(row['total_capacity']): try: - self.wind_turbine_fleet.loc[ix, 'total_capacity'] = \ + self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ row['number_of_turbines'] * \ row['wind_turbine'].nominal_power except TypeError: @@ -194,10 +194,10 @@ def check_and_complete_wind_turbine_fleet(self): if not abs(row['total_capacity'] - ( row['number_of_turbines'] * row['wind_turbine'].nominal_power)) < 1: - self.wind_turbine_fleet.loc[ix, 'total_capacity'] = \ + self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ row['number_of_turbines'] * \ row['wind_turbine'].nominal_power - msg = ( + msg=( 'The provided total capacity of WindTurbine {0} has ' 'been overwritten as it was not consistent with the ' 'number of turbines provided for this type.') @@ -224,12 +224,12 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power = self.wind_turbine_fleet.total_capacity.sum() + self.nominal_power=self.wind_turbine_fleet.total_capacity.sum() return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power = nominal_power + self._nominal_power=nominal_power def mean_hub_height(self): r""" @@ -251,7 +251,7 @@ def mean_hub_height(self): ----- The following equation is used [1]_: - .. math:: h_{WF} = e^{\sum\limits_{k}{ln(h_{WT,k})} + .. math:: h_{WF}=e^{\sum\limits_{k}{ln(h_{WT,k})} \frac{P_{N,k}}{\sum\limits_{k}{P_{N,k}}}} with: @@ -267,7 +267,7 @@ def mean_hub_height(self): p. 35 """ - self.hub_height = np.exp( + self.hub_height=np.exp( sum(np.log(row['wind_turbine'].hub_height) * row['total_capacity'] for ix, row in self.wind_turbine_fleet.iterrows()) / self.nominal_power) @@ -334,7 +334,7 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', "but `power_curve` of '{}' is None.".format( turbine)) # Initialize data frame for power curve values - df = pd.DataFrame() + df=pd.DataFrame() for ix, row in self.wind_turbine_fleet.iterrows(): # Check if needed parameters are available and/or assign them if smoothing: @@ -343,11 +343,11 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', if 'roughness_length' in kwargs and \ kwargs['roughness_length'] is not None: # Calculate turbulence intensity and write to kwargs - turbulence_intensity = ( + turbulence_intensity=( tools.estimate_turbulence_intensity( row['wind_turbine'].hub_height, kwargs['roughness_length'])) - kwargs['turbulence_intensity'] = turbulence_intensity + kwargs['turbulence_intensity']=turbulence_intensity else: raise ValueError( "`roughness_length` must be defined for using " + @@ -355,10 +355,10 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', "`standard_deviation_method` if " + "`turbulence_intensity` is not given") # Get original power curve - power_curve = pd.DataFrame(row['wind_turbine'].power_curve) + power_curve=pd.DataFrame(row['wind_turbine'].power_curve) # Editions to the power curves before the summation if smoothing and smoothing_order == 'turbine_power_curves': - power_curve = power_curves.smooth_power_curve( + power_curve=power_curves.smooth_power_curve( power_curve['wind_speed'], power_curve['value'], standard_deviation_method=standard_deviation_method, block_width=block_width, **kwargs) @@ -366,37 +366,37 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', # Add value zero to start and end of curve as otherwise # problems can occur during the aggregation if power_curve.iloc[0]['wind_speed'] != 0.0: - power_curve = pd.concat( + power_curve=pd.concat( [pd.DataFrame(data={ 'value': [0.0], 'wind_speed': [0.0]}), power_curve], join='inner') if power_curve.iloc[-1]['value'] != 0.0: - power_curve = pd.concat( + power_curve=pd.concat( [power_curve, pd.DataFrame(data={ 'wind_speed': [power_curve['wind_speed'].loc[ power_curve.index[-1]] + 0.5], 'value': [0.0]})], join='inner') # Add power curves of all turbine types to data frame # (multiplied by turbine amount) - df = pd.concat( + df=pd.concat( [df, pd.DataFrame(power_curve.set_index(['wind_speed']) * row['number_of_turbines'])], axis=1) # Aggregate all power curves - wind_farm_power_curve = pd.DataFrame( + wind_farm_power_curve=pd.DataFrame( df.interpolate(method='index').sum(axis=1)) - wind_farm_power_curve.columns = ['value'] + wind_farm_power_curve.columns=['value'] wind_farm_power_curve.reset_index(inplace=True) # Apply power curve smoothing and consideration of wake losses # after the summation if smoothing and smoothing_order == 'wind_farm_power_curves': - wind_farm_power_curve = power_curves.smooth_power_curve( + wind_farm_power_curve=power_curves.smooth_power_curve( wind_farm_power_curve['wind_speed'], wind_farm_power_curve['value'], standard_deviation_method=standard_deviation_method, block_width=block_width, **kwargs) if wake_losses_model == 'wind_farm_efficiency': if self.efficiency is not None: - wind_farm_power_curve = ( + wind_farm_power_curve=( power_curves.wake_losses_to_power_curve( wind_farm_power_curve['wind_speed'].values, wind_farm_power_curve['value'].values, @@ -405,5 +405,5 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', logging.info("`wake_losses_model` is {} but wind farm ".format( wake_losses_model) + "efficiency is NOT taken into " "account as it is None.") - self.power_curve = wind_farm_power_curve + self.power_curve=wind_farm_power_curve return self diff --git a/windpowerlib/wind_speed.py b/windpowerlib/wind_speed.py index 9c8c0033..60882805 100644 --- a/windpowerlib/wind_speed.py +++ b/windpowerlib/wind_speed.py @@ -48,9 +48,9 @@ def logarithmic_profile(wind_speed, wind_speed_height, hub_height, with: v: wind speed, h: height, :math:`z_{0}`: roughness length, - d: boundary layer offset (estimated by d = 0.7 * `obstacle_height`) + d: boundary layer offset (estimated by d=0.7 * `obstacle_height`) - For d = 0 it results in the following equation [2]_ [3]_: + For d=0 it results in the following equation [2]_ [3]_: .. math:: v_{wind,hub}=v_{wind,data}\cdot\frac{\ln\left(\frac{h_{hub}} {z_{0}}\right)}{\ln\left(\frac{h_{data}}{z_{0}}\right)} @@ -79,7 +79,7 @@ def logarithmic_profile(wind_speed, wind_speed_height, hub_height, # Return np.array if wind_speed is np.array if (isinstance(wind_speed, np.ndarray) and isinstance(roughness_length, pd.Series)): - roughness_length = np.array(roughness_length) + roughness_length=np.array(roughness_length) return (wind_speed * np.log((hub_height - 0.7 * obstacle_height) / roughness_length) / @@ -106,14 +106,14 @@ def hellman(wind_speed, wind_speed_height, hub_height, Hub height of wind turbine. roughness_length : :pandas:`pandas.Series` or numpy.array or float Roughness length. If given and `hellman_exponent` is None: - `hellman_exponent` = 1 / ln(hub_height/roughness_length), - otherwise `hellman_exponent` = 1/7. Default: None. + `hellman_exponent`=1 / ln(hub_height/roughness_length), + otherwise `hellman_exponent`=1/7. Default: None. hellman_exponent : None or float The Hellman exponent, which combines the increase in wind speed due to stability of atmospheric conditions and surface roughness into one constant. If None and roughness length is given - `hellman_exponent` = 1 / ln(hub_height/roughness_length), - otherwise `hellman_exponent` = 1/7. Default: None. + `hellman_exponent`=1 / ln(hub_height/roughness_length), + otherwise `hellman_exponent`=1/7. Default: None. Returns ------- @@ -138,7 +138,7 @@ def hellman(wind_speed, wind_speed_height, hub_height, onshore and a value of 1/9 for offshore. The Hellman exponent can also be calulated by the following equation [2]_ [3]_: - .. math:: \alpha = \frac{1}{\ln\left(\frac{h_{hub}}{z_0} \right)} + .. math:: \alpha=\frac{1}{\ln\left(\frac{h_{hub}}{z_0} \right)} with: :math:`z_{0}`: roughness length @@ -162,8 +162,8 @@ def hellman(wind_speed, wind_speed_height, hub_height, # Return np.array if wind_speed is np.array if (isinstance(wind_speed, np.ndarray) and isinstance(roughness_length, pd.Series)): - roughness_length = np.array(roughness_length) - hellman_exponent = 1 / np.log(hub_height / roughness_length) + roughness_length=np.array(roughness_length) + hellman_exponent=1 / np.log(hub_height / roughness_length) else: - hellman_exponent = 1/7 + hellman_exponent=1/7 return wind_speed * (hub_height / wind_speed_height) ** hellman_exponent diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 363c3bef..b1ac7fa2 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -94,20 +94,20 @@ class WindTurbine(object): -------- >>> import os >>> from windpowerlib import WindTurbine - >>> enerconE126 = { + >>> enerconE126={ ... 'hub_height': 135, ... 'turbine_type': 'E-126/4200'} - >>> e126 = WindTurbine(**enerconE126) + >>> e126=WindTurbine(**enerconE126) >>> print(e126.nominal_power) 4200000.0 >>> # Example with own path - >>> path = os.path.join(os.path.dirname(__file__), '../example/data') - >>> example_turbine = { + >>> path=os.path.join(os.path.dirname(__file__), '../example/data') + >>> example_turbine={ ... 'hub_height': 100, ... 'rotor_diameter': 70, ... 'turbine_type': 'DUMMY 3', ... 'path' : path} - >>> e_t_1 = WindTurbine(**example_turbine) + >>> e_t_1=WindTurbine(**example_turbine) >>> print(e_t_1.power_curve['value'][7]) 18000.0 >>> print(e_t_1.nominal_power) @@ -118,53 +118,53 @@ def __init__(self, hub_height, nominal_power=None, path='oedb', power_curve=None, power_coefficient_curve=None, rotor_diameter=None, turbine_type=None, **kwargs): - self.hub_height = hub_height - self.turbine_type = turbine_type - self.rotor_diameter = rotor_diameter - self.nominal_power = nominal_power - self.power_curve = power_curve - self.power_coefficient_curve = power_coefficient_curve + self.hub_height=hub_height + self.turbine_type=turbine_type + self.rotor_diameter=rotor_diameter + self.nominal_power=nominal_power + self.power_curve=power_curve + self.power_coefficient_curve=power_coefficient_curve if path == 'oedb': - path = os.path.join(os.path.dirname(__file__), 'oedb') + path=os.path.join(os.path.dirname(__file__), 'oedb') if turbine_type is not None and path is not None: if power_curve is None: try: - fn = os.path.join(path, 'power_curves.csv') - self.power_curve = get_turbine_data_from_file( + fn=os.path.join(path, 'power_curves.csv') + self.power_curve=get_turbine_data_from_file( self.turbine_type, fn) except KeyError: - msg = "No power curve found for {0}" + msg="No power curve found for {0}" logging.debug(msg.format(self.turbine_type)) if power_coefficient_curve is None: try: - fn = os.path.join(path, 'power_coefficient_curves.csv') - self.power_coefficient_curve = get_turbine_data_from_file( + fn=os.path.join(path, 'power_coefficient_curves.csv') + self.power_coefficient_curve=get_turbine_data_from_file( self.turbine_type, fn) except KeyError: - msg = "No power coefficient curve found for {0}" + msg="No power coefficient curve found for {0}" logging.debug(msg.format(self.turbine_type)) if nominal_power is None or ( rotor_diameter is None and self.power_coefficient_curve is not None): - turbine_data = None + turbine_data=None try: - fn = os.path.join(path, 'turbine_data.csv') - turbine_data = get_turbine_data_from_file( + fn=os.path.join(path, 'turbine_data.csv') + turbine_data=get_turbine_data_from_file( self.turbine_type, fn) except KeyError: - msg = "No turbine data found for {0}" + msg="No turbine data found for {0}" logging.debug(msg.format(self.turbine_type)) if self.nominal_power is None and turbine_data is not None: - self.nominal_power = float(turbine_data['nominal_power']) + self.nominal_power=float(turbine_data['nominal_power']) if self.rotor_diameter is None and turbine_data is not None: - self.rotor_diameter = float(turbine_data['rotor_diameter']) + self.rotor_diameter=float(turbine_data['rotor_diameter']) if self.power_curve is None and self.power_coefficient_curve is None: - msg = ("The WindTurbine has been initialised without a power curve" + msg=("The WindTurbine has been initialised without a power curve" " and without a power coefficient curve.\nYou will not be" " able to calculate the power output.\n" " Check if the turbine type {0} is in your database file" @@ -173,28 +173,28 @@ def __init__(self, hub_height, nominal_power=None, path='oedb', else: # power (coefficient) curve to pd.DataFrame in case of being dict if isinstance(self.power_curve, dict): - self.power_curve = pd.DataFrame(self.power_curve) + self.power_curve=pd.DataFrame(self.power_curve) if isinstance(self.power_coefficient_curve, dict): - self.power_coefficient_curve = pd.DataFrame( + self.power_coefficient_curve=pd.DataFrame( self.power_coefficient_curve) # sort power (coefficient) curve by wind speed if isinstance(self.power_curve, pd.DataFrame): self.power_curve.sort_values(by='wind_speed') elif self.power_curve is not None: - msg = "Type of power curve of {} is {} but should be " \ + msg="Type of power curve of {} is {} but should be " \ "pd.DataFrame or dict." raise TypeError(msg.format(self.__repr__(), type(self.power_curve))) if isinstance(self.power_coefficient_curve, pd.DataFrame): self.power_coefficient_curve.sort_values(by='wind_speed') elif self.power_coefficient_curve is not None: - msg = "Type of power coefficient curve of {} is {} but " \ + msg="Type of power coefficient curve of {} is {} but " \ "should be pd.DataFrame or dict." raise TypeError(msg.format(self.__repr__(), type(self.power_coefficient_curve))) def __repr__(self): - info = [] + info=[] if self.nominal_power is not None: info.append('nominal power={} W'.format(self.nominal_power)) if self.hub_height is not None: @@ -211,10 +211,10 @@ def __repr__(self): info.append('power_curve={}'.format('False')) if self.turbine_type is not None: - turbine_repr = 'Wind turbine: {name} {info}'.format( + turbine_repr='Wind turbine: {name} {info}'.format( name=self.turbine_type, info=info) else: - turbine_repr = 'Wind turbine: {info}'.format(info=info) + turbine_repr='Wind turbine: {info}'.format(info=info) return turbine_repr @@ -245,10 +245,10 @@ def to_group(self, number_turbines=None, total_capacity=None): Examples -------- >>> from windpowerlib import WindTurbine - >>> enerconE126 = { + >>> enerconE126={ ... 'hub_height': 135, ... 'turbine_type': 'E-126/4200'} - >>> e126 = WindTurbine(**enerconE126) + >>> e126=WindTurbine(**enerconE126) >>> e126.to_group(5).number_of_turbines 5 >>> e126.to_group().number_of_turbines @@ -274,9 +274,9 @@ def to_group(self, number_turbines=None, total_capacity=None): raise ValueError("The 'number' and the 'total_capacity' parameter " "are mutually exclusive. Use just one of them.") elif total_capacity is not None: - number_turbines = total_capacity / self.nominal_power + number_turbines=total_capacity / self.nominal_power elif number_turbines is None: - number_turbines = 1 + number_turbines=1 return WindTurbineGroup( wind_turbine=self, number_of_turbines=number_turbines) @@ -300,12 +300,12 @@ class WindTurbineGroup(NamedTuple('WindTurbineGroup', [ 'number_of_turbines' : float The number of turbines. The number is not restricted to integer values. """ - __slots__ = () + __slots__=() -WindTurbineGroup.wind_turbine.__doc__ = ( +WindTurbineGroup.wind_turbine.__doc__=( 'A :class:`~windpowerlib.wind_farm.WindTurbine` object.') -WindTurbineGroup.number_of_turbines.__doc__ = ( +WindTurbineGroup.number_of_turbines.__doc__=( 'Number of turbines of type WindTurbine') @@ -339,9 +339,9 @@ def get_turbine_data_from_file(turbine_type, path): -------- >>> from windpowerlib import wind_turbine >>> import os - >>> path = os.path.join(os.path.dirname(__file__), '../example/data', + >>> path=os.path.join(os.path.dirname(__file__), '../example/data', ... 'power_curves.csv') - >>> d3 = get_turbine_data_from_file('DUMMY 3', path) + >>> d3=get_turbine_data_from_file('DUMMY 3', path) >>> print(d3['value'][7]) 18000.0 >>> print(d3['value'].max()) @@ -349,13 +349,13 @@ def get_turbine_data_from_file(turbine_type, path): """ try: - df = pd.read_csv(path, index_col=0) + df=pd.read_csv(path, index_col=0) except FileNotFoundError: raise FileNotFoundError("The file '{}' was not found.".format(path)) - wpp_df = df[df.index == turbine_type].copy() + wpp_df=df[df.index == turbine_type].copy() # if turbine not in data file if wpp_df.shape[0] == 0: - msg = "Wind converter type {0} not provided. Possible types: {1}" + msg="Wind converter type {0} not provided. Possible types: {1}" raise KeyError(msg.format(turbine_type, list(df.index))) # if turbine in data file # get nominal power or power (coefficient) curve @@ -363,10 +363,10 @@ def get_turbine_data_from_file(turbine_type, path): return wpp_df else: wpp_df.dropna(axis=1, inplace=True) - wpp_df = wpp_df.transpose().reset_index() - wpp_df.columns = ['wind_speed', 'value'] + wpp_df=wpp_df.transpose().reset_index() + wpp_df.columns=['wind_speed', 'value'] # transform wind speeds to floats - wpp_df['wind_speed'] = wpp_df['wind_speed'].apply(lambda x: float(x)) + wpp_df['wind_speed']=wpp_df['wind_speed'].apply(lambda x: float(x)) return wpp_df @@ -393,52 +393,52 @@ def load_turbine_data_from_oedb(schema='supply', table='wind_turbine_library'): """ # url of OpenEnergy Platform that contains the oedb - oep_url = 'http://oep.iks.cs.ovgu.de/' + oep_url='http://oep.iks.cs.ovgu.de/' # load data - result = requests.get( + result=requests.get( oep_url + '/api/v0/schema/{}/tables/{}/rows/?'.format( schema, table), ) if not result.status_code == 200: raise ConnectionError("Database connection not successful. " "Response: [{}]".format(result.status_code)) # extract data to dataframe - turbine_data = pd.DataFrame(result.json()) + turbine_data=pd.DataFrame(result.json()) # standard file name for saving data - filename = os.path.join(os.path.dirname(__file__), 'oedb', + filename=os.path.join(os.path.dirname(__file__), 'oedb', '{}.csv') # get all power (coefficient) curves and save to file # for curve_type in ['power_curve', 'power_coefficient_curve']: for curve_type in ['power_curve', 'power_coefficient_curve']: - curves_df = pd.DataFrame(columns=['wind_speed']) + curves_df=pd.DataFrame(columns=['wind_speed']) for index in turbine_data.index: if (turbine_data['{}_wind_speeds'.format(curve_type)][index] and turbine_data['{}_values'.format(curve_type)][index]): - df = pd.DataFrame(data=[ + df=pd.DataFrame(data=[ eval(turbine_data['{}_wind_speeds'.format(curve_type)][ index]), eval(turbine_data['{}_values'.format(curve_type)][ index])]).transpose().rename( columns={0: 'wind_speed', 1: turbine_data['turbine_type'][index]}) - curves_df = pd.merge(left=curves_df, right=df, how='outer', + curves_df=pd.merge(left=curves_df, right=df, how='outer', on='wind_speed') - curves_df = curves_df.set_index('wind_speed').sort_index().transpose() + curves_df=curves_df.set_index('wind_speed').sort_index().transpose() # power curve values in W if curve_type == 'power_curve': curves_df *= 1000 - curves_df.index.name = 'turbine_type' + curves_df.index.name='turbine_type' curves_df.to_csv(filename.format('{}s'.format(curve_type))) # get turbine data and save to file (excl. curves) - turbine_data_df = turbine_data.drop( + turbine_data_df=turbine_data.drop( ['power_curve_wind_speeds', 'power_curve_values', 'power_coefficient_curve_wind_speeds', 'power_coefficient_curve_values', 'thrust_coefficient_curve_wind_speeds', 'thrust_coefficient_curve_values'], axis=1).set_index('turbine_type') # nominal power in W - turbine_data_df['nominal_power'] = turbine_data_df[ + turbine_data_df['nominal_power']=turbine_data_df[ 'nominal_power'] * 1000 turbine_data_df.to_csv(filename.format('turbine_data')) return turbine_data @@ -491,7 +491,7 @@ def get_turbine_types(turbine_library='local', print_out=True, filter_=True): Examples -------- >>> from windpowerlib import wind_turbine - >>> df = wind_turbine.get_turbine_types(print_out=False) + >>> df=wind_turbine.get_turbine_types(print_out=False) >>> print(df[df["turbine_type"].str.contains("E-126")].iloc[0]) manufacturer Enercon turbine_type E-126/4200 @@ -507,22 +507,22 @@ def get_turbine_types(turbine_library='local', print_out=True, filter_=True): """ if turbine_library == 'local': - filename = os.path.join(os.path.dirname(__file__), 'oedb', 'turbine_data.csv') - df = pd.read_csv(filename, index_col=0).reset_index() + filename=os.path.join(os.path.dirname(__file__), 'oedb', 'turbine_data.csv') + df=pd.read_csv(filename, index_col=0).reset_index() elif turbine_library == 'oedb': - df = load_turbine_data_from_oedb() + df=load_turbine_data_from_oedb() else: raise ValueError("`turbine_library` is '{}' ".format(turbine_library) + "but must be 'local' or 'oedb'.") if filter_: - cp_curves_df = df.loc[df['has_cp_curve']][ + cp_curves_df=df.loc[df['has_cp_curve']][ ['manufacturer', 'turbine_type', 'has_cp_curve']] - p_curves_df = df.loc[df['has_power_curve']][ + p_curves_df=df.loc[df['has_power_curve']][ ['manufacturer', 'turbine_type', 'has_power_curve']] - curves_df = pd.merge(p_curves_df, cp_curves_df, how='outer', + curves_df=pd.merge(p_curves_df, cp_curves_df, how='outer', sort=True).fillna(False) else: - curves_df = df[['manufacturer', 'turbine_type', 'has_power_curve', + curves_df=df[['manufacturer', 'turbine_type', 'has_power_curve', 'has_cp_curve']] if print_out: pd.set_option('display.max_rows', len(curves_df)) diff --git a/windpowerlib/wind_turbine_cluster.py b/windpowerlib/wind_turbine_cluster.py index b67b8739..bb2d2f79 100644 --- a/windpowerlib/wind_turbine_cluster.py +++ b/windpowerlib/wind_turbine_cluster.py @@ -39,21 +39,21 @@ class WindTurbineCluster(object): """ def __init__(self, wind_farms, name='', **kwargs): - self.wind_farms = wind_farms - self.name = name + self.wind_farms=wind_farms + self.name=name - self.hub_height = None - self._nominal_power = None - self.power_curve = None + self.hub_height=None + self._nominal_power=None + self.power_curve=None def __repr__(self): if self.name is not '': - wf_repr = 'Wind turbine cluster: {name}'.format(name=self.name) + wf_repr='Wind turbine cluster: {name}'.format(name=self.name) else: - info = [] + info=[] for wind_farm in self.wind_farms: info.append(wind_farm) - wf_repr = r'Wind turbine cluster with: {info}'.format(info=info) + wf_repr=r'Wind turbine cluster with: {info}'.format(info=info) return wf_repr @property @@ -69,13 +69,13 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power = sum(wind_farm.nominal_power + self.nominal_power=sum(wind_farm.nominal_power for wind_farm in self.wind_farms) return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power = nominal_power + self._nominal_power=nominal_power def mean_hub_height(self): r""" @@ -97,7 +97,7 @@ def mean_hub_height(self): ----- The following equation is used [1]_: - .. math:: h_{WTC} = e^{\sum\limits_{k}{ln(h_{WF,k})} + .. math:: h_{WTC}=e^{\sum\limits_{k}{ln(h_{WF,k})} \frac{P_{N,k}}{\sum\limits_{k}{P_{N,k}}}} with: @@ -113,7 +113,7 @@ def mean_hub_height(self): p. 35 """ - self.hub_height = np.exp(sum( + self.hub_height=np.exp(sum( np.log(wind_farm.hub_height) * wind_farm.nominal_power for wind_farm in self.wind_farms) / self.nominal_power) return self @@ -185,15 +185,15 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', smoothing_order=smoothing_order, turbulence_intensity=turbulence_intensity, **kwargs) # Create data frame from power curves of all wind farms - df = pd.concat([farm.power_curve.set_index(['wind_speed']).rename( + df=pd.concat([farm.power_curve.set_index(['wind_speed']).rename( columns={'value': i}) for farm, i in zip(self.wind_farms, list(range(len(self.wind_farms))))], axis=1) # Sum up power curves - cluster_power_curve = pd.DataFrame( + cluster_power_curve=pd.DataFrame( df.interpolate(method='index').sum(axis=1)) - cluster_power_curve.columns = ['value'] + cluster_power_curve.columns=['value'] # Return wind speed (index) to a column of the data frame cluster_power_curve.reset_index(inplace=True) - self.power_curve = cluster_power_curve + self.power_curve=cluster_power_curve return self From b5c3a1eb9f3ac36835dc61b58833745d1cc7734d Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 12 Dec 2019 15:10:54 +0000 Subject: [PATCH 09/16] Fixing style errors. --- example/modelchain_example.py | 121 +++-- example/test_examples.py | 90 ++-- example/turbine_cluster_modelchain_example.py | 117 +++-- tests/test_density.py | 63 ++- tests/test_modelchain.py | 490 +++++++++++------- tests/test_power_curves.py | 170 ++++-- tests/test_power_output.py | 271 +++++----- tests/test_temperature.py | 21 +- tests/test_tools.py | 140 +++-- tests/test_turbine_cluster_modelchain.py | 434 +++++++++------- tests/test_wake_losses.py | 74 ++- tests/test_wind_farm.py | 230 ++++---- tests/test_wind_speed.py | 106 ++-- tests/test_wind_turbine.py | 107 ++-- windpowerlib/__init__.py | 6 +- windpowerlib/modelchain.py | 354 ++++++++----- windpowerlib/power_curves.py | 151 ++++-- windpowerlib/power_output.py | 76 ++- windpowerlib/tools.py | 34 +- windpowerlib/turbine_cluster_modelchain.py | 119 +++-- windpowerlib/wake_losses.py | 79 +-- windpowerlib/wind_farm.py | 312 ++++++----- windpowerlib/wind_speed.py | 41 +- windpowerlib/wind_turbine.py | 330 +++++++----- windpowerlib/wind_turbine_cluster.py | 84 +-- 25 files changed, 2425 insertions(+), 1595 deletions(-) diff --git a/example/modelchain_example.py b/example/modelchain_example.py index 07149387..c4686e61 100644 --- a/example/modelchain_example.py +++ b/example/modelchain_example.py @@ -19,7 +19,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt=None + plt = None from windpowerlib import ModelChain from windpowerlib import WindTurbine @@ -64,24 +64,29 @@ def get_weather_data(filename='weather.csv', **kwargs): """ - if 'datapath' not in kwargs: - kwargs['datapath']=os.path.join(os.path.split( - os.path.dirname(__file__))[0], 'example') - file=os.path.join(kwargs['datapath'], filename) + if "datapath" not in kwargs: + kwargs["datapath"] = os.path.join( + os.path.split(os.path.dirname(__file__))[0], "example" + ) + file = os.path.join(kwargs["datapath"], filename) # read csv file - weather_df=pd.read_csv( - file, index_col=0, header=[0, 1], - date_parser=lambda idx: pd.to_datetime(idx, utc=True)) + weather_df = pd.read_csv( + file, + index_col=0, + header=[0, 1], + date_parser=lambda idx: pd.to_datetime(idx, utc=True), + ) # change type of index to datetime and set time zone - weather_df.index=pd.to_datetime(weather_df.index).tz_convert( - 'Europe/Berlin') + weather_df.index = pd.to_datetime(weather_df.index).tz_convert( + "Europe/Berlin" + ) # change type of height from str to int by resetting columns - l0=[_[0] for _ in weather_df.columns] - l1=[int(_[1]) for _ in weather_df.columns] - weather_df.columns=[l0, l1] + l0 = [_[0] for _ in weather_df.columns] + l1 = [int(_[1]) for _ in weather_df.columns] + weather_df.columns = [l0, l1] return weather_df @@ -111,37 +116,42 @@ def initialize_wind_turbines(): # specification of wind turbine where data is provided in the oedb # turbine library - enercon_e126={ - 'turbine_type': 'E-126/4200', # turbine type as in register - 'hub_height': 135 # in m + enercon_e126 = { + "turbine_type": "E-126/4200", # turbine type as in register + "hub_height": 135, # in m } # initialize WindTurbine object - e126=WindTurbine(**enercon_e126) + e126 = WindTurbine(**enercon_e126) # specification of own wind turbine (Note: power values and nominal power # have to be in Watt) - my_turbine={ - 'nominal_power': 3e6, # in W - 'hub_height': 105, # in m - 'power_curve': pd.DataFrame( - data={'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}) # in m/s + my_turbine = { + "nominal_power": 3e6, # in W + "hub_height": 105, # in m + "power_curve": pd.DataFrame( + data={ + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], # in W + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + } + ), # in m/s } # initialize WindTurbine object - my_turbine=WindTurbine(**my_turbine) + my_turbine = WindTurbine(**my_turbine) # specification of wind turbine where power coefficient curve and nominal # power is provided in an own csv file - csv_path=os.path.join(os.path.dirname(__file__), 'data') - dummy_turbine={ - 'turbine_type': "DUMMY 1", - 'hub_height': 100, # in m - 'rotor_diameter': 70, # in m - 'path': csv_path + csv_path = os.path.join(os.path.dirname(__file__), "data") + dummy_turbine = { + "turbine_type": "DUMMY 1", + "hub_height": 100, # in m + "rotor_diameter": 70, # in m + "path": csv_path, } # initialize WindTurbine object - dummy_turbine=WindTurbine(**dummy_turbine) + dummy_turbine = WindTurbine(**dummy_turbine) return my_turbine, e126, dummy_turbine @@ -175,37 +185,38 @@ def calculate_power_output(weather, my_turbine, e126, dummy_turbine): # power output calculation for my_turbine # initialize ModelChain with default parameters and use run_model method # to calculate power output - mc_my_turbine=ModelChain(my_turbine).run_model(weather) + mc_my_turbine = ModelChain(my_turbine).run_model(weather) # write power output time series to WindTurbine object - my_turbine.power_output=mc_my_turbine.power_output + my_turbine.power_output = mc_my_turbine.power_output # power output calculation for e126 # own specifications for ModelChain setup - modelchain_data={ - 'wind_speed_model': 'logarithmic', # 'logarithmic' (default), - # 'hellman' or - # 'interpolation_extrapolation' - 'density_model': 'ideal_gas', # 'barometric' (default), 'ideal_gas' or - # 'interpolation_extrapolation' - 'temperature_model': 'linear_gradient', # 'linear_gradient' (def.) or - # 'interpolation_extrapolation' - 'power_output_model': 'power_curve', # 'power_curve' (default) or - # 'power_coefficient_curve' - 'density_correction': True, # False (default) or True - 'obstacle_height': 0, # default: 0 - 'hellman_exp': None} # None (default) or None + modelchain_data = { + "wind_speed_model": "logarithmic", # 'logarithmic' (default), + # 'hellman' or + # 'interpolation_extrapolation' + "density_model": "ideal_gas", # 'barometric' (default), 'ideal_gas' or + # 'interpolation_extrapolation' + "temperature_model": "linear_gradient", # 'linear_gradient' (def.) or + # 'interpolation_extrapolation' + "power_output_model": "power_curve", # 'power_curve' (default) or + # 'power_coefficient_curve' + "density_correction": True, # False (default) or True + "obstacle_height": 0, # default: 0 + "hellman_exp": None, + } # None (default) or None # initialize ModelChain with own specifications and use run_model method # to calculate power output - mc_e126=ModelChain(e126, **modelchain_data).run_model(weather) + mc_e126 = ModelChain(e126, **modelchain_data).run_model(weather) # write power output time series to WindTurbine object - e126.power_output=mc_e126.power_output + e126.power_output = mc_e126.power_output # power output calculation for example_turbine # own specification for 'power_output_model' - mc_example_turbine=ModelChain( - dummy_turbine, - power_output_model='power_coefficient_curve').run_model(weather) - dummy_turbine.power_output=mc_example_turbine.power_output + mc_example_turbine = ModelChain( + dummy_turbine, power_output_model="power_coefficient_curve" + ).run_model(weather) + dummy_turbine.power_output = mc_example_turbine.power_output return @@ -272,8 +283,8 @@ def run_example(): Runs the basic example. """ - weather=get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=initialize_wind_turbines() + weather = get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = initialize_wind_turbines() calculate_power_output(weather, my_turbine, e126, dummy_turbine) plot_or_print(my_turbine, e126, dummy_turbine) diff --git a/example/test_examples.py b/example/test_examples.py index aed5fd0c..afa612f4 100644 --- a/example/test_examples.py +++ b/example/test_examples.py @@ -15,64 +15,92 @@ class TestExamples: - def test_modelchain_example_flh(self): # tests full load hours - weather=mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() + weather = mc_e.get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() mc_e.calculate_power_output(weather, my_turbine, e126, dummy_turbine) - assert_allclose(2764.194772, (e126.power_output.sum() / - e126.nominal_power), 0.01) - assert_allclose(1882.7567, (my_turbine.power_output.sum() / - my_turbine.nominal_power), 0.01) + assert_allclose( + 2764.194772, (e126.power_output.sum() / e126.nominal_power), 0.01 + ) + assert_allclose( + 1882.7567, + (my_turbine.power_output.sum() / my_turbine.nominal_power), + 0.01, + ) def test_turbine_cluster_modelchain_example_flh(self): # tests full load hours - weather=mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() - example_farm, example_farm_2=tc_mc_e.initialize_wind_farms( - my_turbine, e126) - example_cluster=tc_mc_e.initialize_wind_turbine_cluster( - example_farm, example_farm_2) + weather = mc_e.get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() + example_farm, example_farm_2 = tc_mc_e.initialize_wind_farms( + my_turbine, e126 + ) + example_cluster = tc_mc_e.initialize_wind_turbine_cluster( + example_farm, example_farm_2 + ) tc_mc_e.calculate_power_output(weather, example_farm, example_cluster) - assert_allclose(1956.164053, (example_farm.power_output.sum() / - example_farm.nominal_power), 0.01) - assert_allclose(2156.794154, (example_cluster.power_output.sum() / - example_cluster.nominal_power), 0.01) + assert_allclose( + 1956.164053, + (example_farm.power_output.sum() / example_farm.nominal_power), + 0.01, + ) + assert_allclose( + 2156.794154, + ( + example_cluster.power_output.sum() + / example_cluster.nominal_power + ), + 0.01, + ) def _notebook_run(self, path): """ Execute a notebook via nbconvert and collect output. Returns (parsed nb object, execution errors) """ - dirname, __=os.path.split(path) + dirname, __ = os.path.split(path) os.chdir(dirname) with tempfile.NamedTemporaryFile(suffix=".ipynb") as fout: - args=["jupyter", "nbconvert", "--to", "notebook", "--execute", - "--ExecutePreprocessor.timeout=60", - "--output", fout.name, path] + args = [ + "jupyter", + "nbconvert", + "--to", + "notebook", + "--execute", + "--ExecutePreprocessor.timeout=60", + "--output", + fout.name, + path, + ] subprocess.check_call(args) fout.seek(0) - nb=nbformat.read(fout, nbformat.current_nbformat) + nb = nbformat.read(fout, nbformat.current_nbformat) - errors=[output for cell in nb.cells if "outputs" in cell - for output in cell["outputs"] - if output.output_type == "error"] + errors = [ + output + for cell in nb.cells + if "outputs" in cell + for output in cell["outputs"] + if output.output_type == "error" + ] return nb, errors @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_modelchain_example_ipynb(self): - dir_path=os.path.dirname(os.path.realpath(__file__)) - nb, errors=self._notebook_run( - os.path.join(dir_path, 'modelchain_example.ipynb')) + dir_path = os.path.dirname(os.path.realpath(__file__)) + nb, errors = self._notebook_run( + os.path.join(dir_path, "modelchain_example.ipynb") + ) assert errors == [] @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_turbine_cluster_modelchain_example_ipynb(self): - dir_path=os.path.dirname(os.path.realpath(__file__)) - nb, errors=self._notebook_run( - os.path.join(dir_path, 'turbine_cluster_modelchain_example.ipynb')) + dir_path = os.path.dirname(os.path.realpath(__file__)) + nb, errors = self._notebook_run( + os.path.join(dir_path, "turbine_cluster_modelchain_example.ipynb") + ) assert errors == [] diff --git a/example/turbine_cluster_modelchain_example.py b/example/turbine_cluster_modelchain_example.py index 9903dbf1..ea0584bd 100644 --- a/example/turbine_cluster_modelchain_example.py +++ b/example/turbine_cluster_modelchain_example.py @@ -15,7 +15,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt=None + plt = None from example import modelchain_example as mc_e from windpowerlib import WindFarm @@ -58,24 +58,30 @@ def initialize_wind_farms(my_turbine, e126): # for each turbine type you can either specify the number of turbines of # that type in the wind farm (float values are possible as well) or the # total installed capacity of that turbine type in W - wind_turbine_fleet=pd.DataFrame( - {'wind_turbine': [my_turbine, e126], # as windpowerlib.WindTurbine - 'number_of_turbines': [6, None], - 'total_capacity': [None, 12.6e6]} + wind_turbine_fleet = pd.DataFrame( + { + "wind_turbine": [my_turbine, e126], # as windpowerlib.WindTurbine + "number_of_turbines": [6, None], + "total_capacity": [None, 12.6e6], + } ) # initialize WindFarm object - example_farm=WindFarm(name='example_farm', - wind_turbine_fleet=wind_turbine_fleet) + example_farm = WindFarm( + name="example_farm", wind_turbine_fleet=wind_turbine_fleet + ) # specification of wind farm data (2) containing a wind farm efficiency # wind turbine fleet is provided using the to_group function - example_farm_2_data={ - 'name': 'example_farm_2', - 'wind_turbine_fleet': [my_turbine.to_group(6), - e126.to_group(total_capacity=12.6e6)], - 'efficiency': 0.9} + example_farm_2_data = { + "name": "example_farm_2", + "wind_turbine_fleet": [ + my_turbine.to_group(6), + e126.to_group(total_capacity=12.6e6), + ], + "efficiency": 0.9, + } # initialize WindFarm object - example_farm_2=WindFarm(**example_farm_2_data) + example_farm_2 = WindFarm(**example_farm_2_data) return example_farm, example_farm_2 @@ -103,11 +109,12 @@ def initialize_wind_turbine_cluster(example_farm, example_farm_2): """ # specification of cluster data - example_cluster_data={ - 'name': 'example_cluster', - 'wind_farms': [example_farm, example_farm_2]} + example_cluster_data = { + "name": "example_cluster", + "wind_farms": [example_farm, example_farm_2], + } # initialize WindTurbineCluster object - example_cluster=WindTurbineCluster(**example_cluster_data) + example_cluster = WindTurbineCluster(**example_cluster_data) return example_cluster @@ -133,48 +140,49 @@ class that provides all necessary steps to calculate the power output of a WindTurbineCluster object. """ - example_farm.efficiency=0.9 + example_farm.efficiency = 0.9 # power output calculation for example_farm # initialize TurbineClusterModelChain with default parameters and use # run_model method to calculate power output - mc_example_farm=TurbineClusterModelChain(example_farm).run_model(weather) + mc_example_farm = TurbineClusterModelChain(example_farm).run_model(weather) # write power output time series to WindFarm object - example_farm.power_output=mc_example_farm.power_output + example_farm.power_output = mc_example_farm.power_output # power output calculation for turbine_cluster # own specifications for TurbineClusterModelChain setup - modelchain_data={ - 'wake_losses_model': - 'wind_farm_efficiency', # 'dena_mean' (default), None, - # 'wind_farm_efficiency' or name - # of another wind efficiency curve - # see :py:func:`~.wake_losses.get_wind_efficiency_curve` - 'smoothing': True, # False (default) or True - 'block_width': 0.5, # default: 0.5 - 'standard_deviation_method': 'Staffell_Pfenninger', # - # 'turbulence_intensity' (default) - # or 'Staffell_Pfenninger' - 'smoothing_order': 'wind_farm_power_curves', # - # 'wind_farm_power_curves' (default) or - # 'turbine_power_curves' - 'wind_speed_model': 'logarithmic', # 'logarithmic' (default), - # 'hellman' or - # 'interpolation_extrapolation' - 'density_model': 'ideal_gas', # 'barometric' (default), 'ideal_gas' or - # 'interpolation_extrapolation' - 'temperature_model': 'linear_gradient', # 'linear_gradient' (def.) or - # 'interpolation_extrapolation' - 'power_output_model': 'power_curve', # 'power_curve' (default) or - # 'power_coefficient_curve' - 'density_correction': True, # False (default) or True - 'obstacle_height': 0, # default: 0 - 'hellman_exp': None} # None (default) or None + modelchain_data = { + "wake_losses_model": "wind_farm_efficiency", # 'dena_mean' (default), None, + # 'wind_farm_efficiency' or name + # of another wind efficiency curve + # see :py:func:`~.wake_losses.get_wind_efficiency_curve` + "smoothing": True, # False (default) or True + "block_width": 0.5, # default: 0.5 + "standard_deviation_method": "Staffell_Pfenninger", # + # 'turbulence_intensity' (default) + # or 'Staffell_Pfenninger' + "smoothing_order": "wind_farm_power_curves", # + # 'wind_farm_power_curves' (default) or + # 'turbine_power_curves' + "wind_speed_model": "logarithmic", # 'logarithmic' (default), + # 'hellman' or + # 'interpolation_extrapolation' + "density_model": "ideal_gas", # 'barometric' (default), 'ideal_gas' or + # 'interpolation_extrapolation' + "temperature_model": "linear_gradient", # 'linear_gradient' (def.) or + # 'interpolation_extrapolation' + "power_output_model": "power_curve", # 'power_curve' (default) or + # 'power_coefficient_curve' + "density_correction": True, # False (default) or True + "obstacle_height": 0, # default: 0 + "hellman_exp": None, + } # None (default) or None # initialize TurbineClusterModelChain with own specifications and use # run_model method to calculate power output - mc_example_cluster=TurbineClusterModelChain( - example_cluster, **modelchain_data).run_model(weather) + mc_example_cluster = TurbineClusterModelChain( + example_cluster, **modelchain_data + ).run_model(weather) # write power output time series to WindTurbineCluster object - example_cluster.power_output=mc_example_cluster.power_output + example_cluster.power_output = mc_example_cluster.power_output return @@ -209,11 +217,12 @@ def run_example(): Runs the example. """ - weather=mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() - example_farm, example_farm_2=initialize_wind_farms(my_turbine, e126) - example_cluster=initialize_wind_turbine_cluster(example_farm, - example_farm_2) + weather = mc_e.get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() + example_farm, example_farm_2 = initialize_wind_farms(my_turbine, e126) + example_cluster = initialize_wind_turbine_cluster( + example_farm, example_farm_2 + ) calculate_power_output(weather, example_farm, example_cluster) plot_or_print(example_farm, example_cluster) diff --git a/tests/test_density.py b/tests/test_density.py index 67c4b4b5..68556f4d 100644 --- a/tests/test_density.py +++ b/tests/test_density.py @@ -12,57 +12,66 @@ class TestDensity: - def test_barometric(self): - parameters={'pressure': pd.Series(data=[101125, 101000]), - 'pressure_height': 0, - 'hub_height': 100, - 'temperature_hub_height': pd.Series(data=[267, 268])} + parameters = { + "pressure": pd.Series(data=[101125, 101000]), + "pressure_height": 0, + "hub_height": 100, + "temperature_hub_height": pd.Series(data=[267, 268]), + } # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp=pd.Series(data=[1.30305336, 1.29656645]) + rho_exp = pd.Series(data=[1.30305336, 1.29656645]) assert_series_equal(barometric(**parameters), rho_exp) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters['pressure']=np.array(parameters['pressure']) - parameters['temperature_hub_height']=pd.Series( - data=parameters['temperature_hub_height']) + parameters["pressure"] = np.array(parameters["pressure"]) + parameters["temperature_hub_height"] = pd.Series( + data=parameters["temperature_hub_height"] + ) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp=np.array([1.30305336, 1.29656645]) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + rho_exp = np.array([1.30305336, 1.29656645]) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_allclose(barometric(**parameters), rho_exp) assert isinstance(barometric(**parameters), np.ndarray) def test_ideal_gas(self): - parameters={'pressure': pd.Series(data=[101125, 101000]), - 'pressure_height': 0, - 'hub_height': 100, - 'temperature_hub_height': pd.Series(data=[267, 268])} + parameters = { + "pressure": pd.Series(data=[101125, 101000]), + "pressure_height": 0, + "hub_height": 100, + "temperature_hub_height": pd.Series(data=[267, 268]), + } # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp=pd.Series(data=[1.30309439, 1.29660728]) + rho_exp = pd.Series(data=[1.30309439, 1.29660728]) assert_series_equal(ideal_gas(**parameters), rho_exp) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_series_equal(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters['pressure']=np.array(parameters['pressure']) - parameters['temperature_hub_height']=pd.Series( - data=parameters['temperature_hub_height']) + parameters["pressure"] = np.array(parameters["pressure"]) + parameters["temperature_hub_height"] = pd.Series( + data=parameters["temperature_hub_height"] + ) assert_allclose(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp=np.array([1.30309439, 1.29660728]) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + rho_exp = np.array([1.30309439, 1.29660728]) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_allclose(ideal_gas(**parameters), rho_exp) assert isinstance(ideal_gas(**parameters), np.ndarray) diff --git a/tests/test_modelchain.py b/tests/test_modelchain.py index 2fea51aa..8bdac075 100644 --- a/tests/test_modelchain.py +++ b/tests/test_modelchain.py @@ -14,330 +14,420 @@ class TestModelChain: - @classmethod def setup_class(self): """Setup default values""" - self.test_turbine={'hub_height': 100, - 'turbine_type': 'E-126/4200', - 'power_curve': pd.DataFrame( - data={'value': [0.0, 4200 * 1000], - 'wind_speed': [0.0, 25.0]})} - - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - pressure_0m=np.array([[101125], [101000]]) - wind_speed_8m=np.array([[4.0], [5.0]]) - wind_speed_10m=np.array([[5.0], [6.5]]) - roughness_length=np.array([[0.15], [0.15]]) - self.weather_df=pd.DataFrame( - np.hstack((temperature_2m, temperature_10m, pressure_0m, - wind_speed_8m, wind_speed_10m, roughness_length)), + self.test_turbine = { + "hub_height": 100, + "turbine_type": "E-126/4200", + "power_curve": pd.DataFrame( + data={"value": [0.0, 4200 * 1000], "wind_speed": [0.0, 25.0]} + ), + } + + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + pressure_0m = np.array([[101125], [101000]]) + wind_speed_8m = np.array([[4.0], [5.0]]) + wind_speed_10m = np.array([[5.0], [6.5]]) + roughness_length = np.array([[0.15], [0.15]]) + self.weather_df = pd.DataFrame( + np.hstack( + ( + temperature_2m, + temperature_10m, + pressure_0m, + wind_speed_8m, + wind_speed_10m, + roughness_length, + ) + ), index=[0, 1], - columns=[np.array(['temperature', 'temperature', 'pressure', - 'wind_speed', 'wind_speed', - 'roughness_length']), - np.array([2, 10, 0, 8, 10, 0])]) + columns=[ + np.array( + [ + "temperature", + "temperature", + "pressure", + "wind_speed", + "wind_speed", + "roughness_length", + ] + ), + np.array([2, 10, 0, 8, 10, 0]), + ], + ) def test_temperature_hub(self): # Test modelchain with temperature_model='linear_gradient' - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with temperature_model='interpolation_extrapolation' - test_mc_2=mc.ModelChain( + test_mc_2 = mc.ModelChain( wt.WindTurbine(**self.test_turbine), - temperature_model='interpolation_extrapolation') + temperature_model="interpolation_extrapolation", + ) # Parameters for tests - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - weather_df=pd.DataFrame(np.hstack((temperature_2m, - temperature_10m)), - index=[0, 1], - columns=[np.array(['temperature', - 'temperature']), - np.array([2, 10])]) + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + weather_df = pd.DataFrame( + np.hstack((temperature_2m, temperature_10m)), + index=[0, 1], + columns=[ + np.array(["temperature", "temperature"]), + np.array([2, 10]), + ], + ) # temperature_10m is closer to hub height than temperature_2m - temp_exp=pd.Series(data=[266.415, 265.415], name=10) + temp_exp = pd.Series(data=[266.415, 265.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp=pd.Series(data=[267.0, 243.5]) + temp_exp = pd.Series(data=[267.0, 243.5]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns=[np.array(['temperature', 'temperature']), - np.array([10, 200])] - temp_exp=pd.Series(data=[266.415, 267.415], name=10) + weather_df.columns = [ + np.array(["temperature", "temperature"]), + np.array([10, 200]), + ] + temp_exp = pd.Series(data=[266.415, 267.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp=pd.Series(data=[267.0, 267.052632]) + temp_exp = pd.Series(data=[267.0, 267.052632]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # temperature at hub height - weather_df.columns=[np.array(['temperature', 'temperature']), - np.array([100, 10])] - temp_exp=pd.Series(data=[267, 268], name=100) + weather_df.columns = [ + np.array(["temperature", "temperature"]), + np.array([100, 10]), + ] + temp_exp = pd.Series(data=[267, 268], name=100) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) def test_density_hub(self): # Test modelchain with density_model='barometric' - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with density_model='ideal_gas' - test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - density_model='ideal_gas') + test_mc_2 = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), density_model="ideal_gas" + ) # Test modelchain with density_model='interpolation_extrapolation' - test_mc_3=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - density_model='interpolation_extrapolation') + test_mc_3 = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), + density_model="interpolation_extrapolation", + ) # Parameters for tests - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - pressure_0m=np.array([[101125], [101000]]) - weather_df=pd.DataFrame(np.hstack((temperature_2m, - temperature_10m, - pressure_0m)), - index=[0, 1], - columns=[np.array(['temperature', - 'temperature', - 'pressure']), - np.array([2, 10, 0])]) + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + pressure_0m = np.array([[101125], [101000]]) + weather_df = pd.DataFrame( + np.hstack((temperature_2m, temperature_10m, pressure_0m)), + index=[0, 1], + columns=[ + np.array(["temperature", "temperature", "pressure"]), + np.array([2, 10, 0]), + ], + ) # temperature_10m is closer to hub height than temperature_2m - rho_exp=pd.Series(data=[1.30591, 1.30919]) + rho_exp = pd.Series(data=[1.30591, 1.30919]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp=pd.Series(data=[1.30595575725, 1.30923554056]) + rho_exp = pd.Series(data=[1.30595575725, 1.30923554056]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns=[np.array(['temperature', 'temperature', - 'pressure']), - np.array([10, 200, 0])] - rho_exp=pd.Series(data=[1.30591, 1.29940]) + weather_df.columns = [ + np.array(["temperature", "temperature", "pressure"]), + np.array([10, 200, 0]), + ] + rho_exp = pd.Series(data=[1.30591, 1.29940]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp=pd.Series(data=[1.30595575725, 1.29944375221]) + rho_exp = pd.Series(data=[1.30595575725, 1.29944375221]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # temperature at hub height - weather_df.columns=[np.array(['temperature', 'temperature', - 'pressure']), - np.array([100, 10, 0])] - rho_exp=pd.Series(data=[1.30305, 1.29657]) + weather_df.columns = [ + np.array(["temperature", "temperature", "pressure"]), + np.array([100, 10, 0]), + ] + rho_exp = pd.Series(data=[1.30305, 1.29657]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) # density interpolation - density_10m=np.array([[1.30591], [1.29940]]) - density_150m=np.array([[1.30305], [1.29657]]) - weather_df=pd.DataFrame(np.hstack((density_10m, - density_150m)), - index=[0, 1], - columns=[np.array(['density', - 'density']), - np.array([10, 150])]) - rho_exp=pd.Series(data=[1.304071, 1.297581]) + density_10m = np.array([[1.30591], [1.29940]]) + density_150m = np.array([[1.30305], [1.29657]]) + weather_df = pd.DataFrame( + np.hstack((density_10m, density_150m)), + index=[0, 1], + columns=[np.array(["density", "density"]), np.array([10, 150])], + ) + rho_exp = pd.Series(data=[1.304071, 1.297581]) assert_series_equal(test_mc_3.density_hub(weather_df), rho_exp) def test_wind_speed_hub(self): # Test modelchain with wind_speed_model='logarithmic' - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with wind_speed_model='hellman' - test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - wind_speed_model='hellman') + test_mc_2 = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), wind_speed_model="hellman" + ) # Test modelchain with wind_speed_model='interpolation_extrapolation' - test_mc_3=mc.ModelChain( + test_mc_3 = mc.ModelChain( wt.WindTurbine(**self.test_turbine), - wind_speed_model='interpolation_extrapolation') + wind_speed_model="interpolation_extrapolation", + ) # Test modelchain with # wind_speed_model='log_interpolation_extrapolation' - test_mc_4=mc.ModelChain( + test_mc_4 = mc.ModelChain( wt.WindTurbine(**self.test_turbine), - wind_speed_model='log_interpolation_extrapolation') + wind_speed_model="log_interpolation_extrapolation", + ) # Parameters for tests - wind_speed_8m=np.array([[4.0], [5.0]]) - wind_speed_10m=np.array([[5.0], [6.5]]) - roughness_length=np.array([[0.15], [0.15]]) - weather_df=pd.DataFrame(np.hstack((wind_speed_8m, - wind_speed_10m, - roughness_length)), - index=[0, 1], - columns=[np.array(['wind_speed', - 'wind_speed', - 'roughness_length']), - np.array([8, 10, 0])]) + wind_speed_8m = np.array([[4.0], [5.0]]) + wind_speed_10m = np.array([[5.0], [6.5]]) + roughness_length = np.array([[0.15], [0.15]]) + weather_df = pd.DataFrame( + np.hstack((wind_speed_8m, wind_speed_10m, roughness_length)), + index=[0, 1], + columns=[ + np.array(["wind_speed", "wind_speed", "roughness_length"]), + np.array([8, 10, 0]), + ], + ) # wind_speed_10m is closer to hub height than wind_speed_8m - v_wind_exp=pd.Series(data=[7.74137, 10.06377]) + v_wind_exp = pd.Series(data=[7.74137, 10.06377]) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp=pd.Series(data=[7.12462, 9.26201]) + v_wind_exp = pd.Series(data=[7.12462, 9.26201]) assert_series_equal(test_mc_2.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp=pd.Series(data=[50.0, 74.0]) + v_wind_exp = pd.Series(data=[50.0, 74.0]) assert_series_equal(test_mc_3.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp=pd.Series(data=[15.3188511585, 21.9782767378]) + v_wind_exp = pd.Series(data=[15.3188511585, 21.9782767378]) assert_series_equal(test_mc_4.wind_speed_hub(weather_df), v_wind_exp) # wind_speed is given at hub height - weather_df.columns=[np.array(['wind_speed', 'wind_speed', - 'roughness_length']), - np.array([10, 100, 0])] - v_wind_exp=pd.Series(data=[5.0, 6.5], name=100) + weather_df.columns = [ + np.array(["wind_speed", "wind_speed", "roughness_length"]), + np.array([10, 100, 0]), + ] + v_wind_exp = pd.Series(data=[5.0, 6.5], name=100) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) # ***** test_run_model ********* def test_with_default_parameter(self): """Test with default parameters of modelchain (power curve)""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - power_output_exp=pd.Series(data=[1637405.4840444783, - 3154438.3894902095], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine)) + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + power_output_exp = pd.Series( + data=[1637405.4840444783, 3154438.3894902095], + name="feedin_power_plant", + ) + test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_density_corrected_power_curve_and_hellman(self): """Test with density corrected power curve and hellman""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_curve', - 'density_correction': True} - power_output_exp=pd.Series(data=[1366958.544547462, - 2823402.837201821], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_curve", + "density_correction": True, + } + power_output_exp = pd.Series( + data=[1366958.544547462, 2823402.837201821], + name="feedin_power_plant", + ) + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_power_coefficient_curve_and_hellman(self): """Test with power coefficient curve and hellman""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - power_output_exp=pd.Series(data=[534137.5112701517, - 1103611.1736067757], - name='feedin_power_plant') - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False} - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + power_output_exp = pd.Series( + data=[534137.5112701517, 1103611.1736067757], + name="feedin_power_plant", + ) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_wrong_spelling_power_output_model(self): """Raise ValueErrors due to wrong spelling of power_output_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'wrong_spelling', - 'density_correction': False} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "wrong_spelling", + "density_correction": False, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_spelling_density_model(self): """Raise ValueErrors due to wrong spelling of density_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False, - 'density_model': 'wrong_spelling'} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + "density_model": "wrong_spelling", + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_spelling_temperature_model(self): """Raise ValueErrors due to wrong spelling of temperature_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False, - 'temperature_model': 'wrong_spelling'} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + "temperature_model": "wrong_spelling", + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_spelling_wind_speed_model(self): """Raise ValueErrors due to wrong spelling of wind_speed_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'wrong_spelling', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "wrong_spelling", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_density_correction_type(self): """Raise TypeErrors due to wrong type of `density_correction`""" with pytest.raises(TypeError): - test_modelchain={'power_output_model': 'power_curve', - 'density_correction': 'wrong_type'} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "power_output_model": "power_curve", + "density_correction": "wrong_type", + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_cp_values(self): """Raise TypeErrors due to missing cp-values""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4201'} - msg="Power coefficient curve values of" + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4201", + } + msg = "Power coefficient curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain={'power_output_model': 'power_coefficient_curve', - 'density_correction': True} - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_modelchain = { + "power_output_model": "power_coefficient_curve", + "density_correction": True, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_p_values(self): """Raise TypeErrors due to missing p-values""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4205'} - msg="Power curve values of" + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4205", + } + msg = "Power curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain={'power_output_model': 'power_curve', - 'density_corr': True} - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_modelchain = { + "power_output_model": "power_curve", + "density_corr": True, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_modelchain_with_power_curve_as_dict(self): """Test power curves as dict""" - my_turbine={'nominal_power': 3e6, 'hub_height': 105, - 'rotor_diameter': 70, - 'power_curve': { - 'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}, - 'power_coefficient_curve': { - 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - power_output_exp=pd.Series(data=[919055.54840, - 1541786.60559], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine)) + my_turbine = { + "nominal_power": 3e6, + "hub_height": 105, + "rotor_diameter": 70, + "power_curve": { + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + "power_coefficient_curve": { + "value": [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + } + power_output_exp = pd.Series( + data=[919055.54840, 1541786.60559], name="feedin_power_plant" + ) + test_mc = mc.ModelChain(wt.WindTurbine(**my_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_modelchain_with_power_coefficient_curve_as_dict(self): """Test power coefficient curves as dict""" - my_turbine={'nominal_power': 3e6, 'hub_height': 105, - 'rotor_diameter': 70, - 'power_curve': { - 'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}, - 'power_coefficient_curve': { - 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - power_output_exp=pd.Series(data=[469518.35104, - 901794.28532], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine), - power_output_model='power_coefficient_curve') + my_turbine = { + "nominal_power": 3e6, + "hub_height": 105, + "rotor_diameter": 70, + "power_curve": { + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + "power_coefficient_curve": { + "value": [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + } + power_output_exp = pd.Series( + data=[469518.35104, 901794.28532], name="feedin_power_plant" + ) + test_mc = mc.ModelChain( + wt.WindTurbine(**my_turbine), + power_output_model="power_coefficient_curve", + ) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) diff --git a/tests/test_power_curves.py b/tests/test_power_curves.py index 5814969b..ccf296ab 100644 --- a/tests/test_power_curves.py +++ b/tests/test_power_curves.py @@ -8,95 +8,153 @@ import pytest from pandas.util.testing import assert_frame_equal -from windpowerlib.power_curves import (smooth_power_curve, - wake_losses_to_power_curve) +from windpowerlib.power_curves import ( + smooth_power_curve, + wake_losses_to_power_curve, +) import windpowerlib.wind_turbine as wt class TestPowerCurves: - @classmethod def setup_class(self): - self.test_turbine={'hub_height': 100, - 'turbine_type': 'E-126/4200'} + self.test_turbine = {"hub_height": 100, "turbine_type": "E-126/4200"} def test_smooth_power_curve(self): - test_curve=wt.WindTurbine(**self.test_turbine).power_curve - parameters={'power_curve_wind_speeds': test_curve['wind_speed'], - 'power_curve_values': test_curve['value'], - 'standard_deviation_method': 'turbulence_intensity'} + test_curve = wt.WindTurbine(**self.test_turbine).power_curve + parameters = { + "power_curve_wind_speeds": test_curve["wind_speed"], + "power_curve_values": test_curve["value"], + "standard_deviation_method": "turbulence_intensity", + } # Raise ValueError - `turbulence_intensity` missing with pytest.raises(ValueError): - parameters['standard_deviation_method']='turbulence_intensity' + parameters["standard_deviation_method"] = "turbulence_intensity" smooth_power_curve(**parameters) # Test turbulence_intensity method - parameters['turbulence_intensity']=0.5 - wind_speed_values_exp=pd.Series([6.0, 7.0, 8.0, 9.0, 10.0], - name='wind_speed') - power_values_exp=pd.Series([ - 1141906.9806766496, 1577536.8085282773, 1975480.993355767, - 2314059.4022704284, 2590216.6802602503], name='value') - smoothed_curve_exp=pd.DataFrame(data=pd.concat([ - wind_speed_values_exp, power_values_exp], axis=1)) - smoothed_curve_exp.index=np.arange(5, 10, 1) - assert_frame_equal(smooth_power_curve(**parameters)[5:10], - smoothed_curve_exp) + parameters["turbulence_intensity"] = 0.5 + wind_speed_values_exp = pd.Series( + [6.0, 7.0, 8.0, 9.0, 10.0], name="wind_speed" + ) + power_values_exp = pd.Series( + [ + 1141906.9806766496, + 1577536.8085282773, + 1975480.993355767, + 2314059.4022704284, + 2590216.6802602503, + ], + name="value", + ) + smoothed_curve_exp = pd.DataFrame( + data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1) + ) + smoothed_curve_exp.index = np.arange(5, 10, 1) + assert_frame_equal( + smooth_power_curve(**parameters)[5:10], smoothed_curve_exp + ) # Test Staffel_Pfenninger method - parameters['standard_deviation_method']='Staffell_Pfenninger' - power_values_exp=pd.Series([ - 929405.1348918702, 1395532.5468724659, 1904826.6851982325, - 2402659.118305521, 2844527.1732449625], name='value') - smoothed_curve_exp=pd.DataFrame( - data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1)) - smoothed_curve_exp.index=np.arange(5, 10, 1) - assert_frame_equal(smooth_power_curve(**parameters)[5:10], - smoothed_curve_exp) + parameters["standard_deviation_method"] = "Staffell_Pfenninger" + power_values_exp = pd.Series( + [ + 929405.1348918702, + 1395532.5468724659, + 1904826.6851982325, + 2402659.118305521, + 2844527.1732449625, + ], + name="value", + ) + smoothed_curve_exp = pd.DataFrame( + data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1) + ) + smoothed_curve_exp.index = np.arange(5, 10, 1) + assert_frame_equal( + smooth_power_curve(**parameters)[5:10], smoothed_curve_exp + ) # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters['standard_deviation_method']='misspelled' + parameters["standard_deviation_method"] = "misspelled" smooth_power_curve(**parameters) def test_wake_losses_to_power_curve(self): - test_curve=wt.WindTurbine(**self.test_turbine).power_curve - parameters={'power_curve_wind_speeds': test_curve['wind_speed'], - 'power_curve_values': test_curve['value'], - 'wind_farm_efficiency': 0.9} + test_curve = wt.WindTurbine(**self.test_turbine).power_curve + parameters = { + "power_curve_wind_speeds": test_curve["wind_speed"], + "power_curve_values": test_curve["value"], + "wind_farm_efficiency": 0.9, + } # Test constant efficiency - power_curve_exp=test_curve.copy(deep=True) - power_curve_exp['value']=power_curve_exp['value'].values * 0.9 - assert_frame_equal(wake_losses_to_power_curve(**parameters), - power_curve_exp) + power_curve_exp = test_curve.copy(deep=True) + power_curve_exp["value"] = power_curve_exp["value"].values * 0.9 + assert_frame_equal( + wake_losses_to_power_curve(**parameters), power_curve_exp + ) # Test efficiency curve - parameters['wind_farm_efficiency']=pd.DataFrame( - pd.concat([pd.Series(np.arange(1, 26, 1)), - pd.Series([ - 1.0, 1.0, 1.0, 0.84, 0.85, 0.86, 0.85, 0.85, 0.85, - 0.86, 0.87, 0.89, 0.92, 0.95, 0.95, 0.96, 0.99, - 0.95, 0.98, 0.97, 0.99, 1.0, 1.0, 1.0, 1.0])], - axis=1)) - parameters['wind_farm_efficiency'].columns=['wind_speed', - 'efficiency'] - power_curve_exp=test_curve.copy(deep=True) - power_curve_exp['value']=( - power_curve_exp['value'].values * parameters[ - 'wind_farm_efficiency']['efficiency']) - assert_frame_equal(wake_losses_to_power_curve(**parameters), - power_curve_exp) + parameters["wind_farm_efficiency"] = pd.DataFrame( + pd.concat( + [ + pd.Series(np.arange(1, 26, 1)), + pd.Series( + [ + 1.0, + 1.0, + 1.0, + 0.84, + 0.85, + 0.86, + 0.85, + 0.85, + 0.85, + 0.86, + 0.87, + 0.89, + 0.92, + 0.95, + 0.95, + 0.96, + 0.99, + 0.95, + 0.98, + 0.97, + 0.99, + 1.0, + 1.0, + 1.0, + 1.0, + ] + ), + ], + axis=1, + ) + ) + parameters["wind_farm_efficiency"].columns = [ + "wind_speed", + "efficiency", + ] + power_curve_exp = test_curve.copy(deep=True) + power_curve_exp["value"] = ( + power_curve_exp["value"].values + * parameters["wind_farm_efficiency"]["efficiency"] + ) + assert_frame_equal( + wake_losses_to_power_curve(**parameters), power_curve_exp + ) # Raise TypeError if wind farm efficiency is of wrong type with pytest.raises(TypeError): - parameters['wind_farm_efficiency']=1 + parameters["wind_farm_efficiency"] = 1 wake_losses_to_power_curve(**parameters) if __name__ == "__main__": - test=TestPowerCurves() + test = TestPowerCurves() test.setup_class() test.test_smooth_power_curve() test.test_wake_losses_to_power_curve() diff --git a/tests/test_power_output.py b/tests/test_power_output.py index 0a5c6f84..d29d6e35 100644 --- a/tests/test_power_output.py +++ b/tests/test_power_output.py @@ -9,187 +9,214 @@ from numpy.testing import assert_allclose from pandas.util.testing import assert_series_equal -from windpowerlib.power_output import (power_coefficient_curve, - power_curve, - power_curve_density_correction) +from windpowerlib.power_output import ( + power_coefficient_curve, + power_curve, + power_curve_density_correction, +) class TestPowerOutput: - def test_power_coefficient_curve(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'rotor_diameter': 80, - 'power_coefficient_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_coefficient_curve_values': - pd.Series([0.3, 0.4, 0.5])} + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "rotor_diameter": 80, + "power_coefficient_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_coefficient_curve_values": pd.Series([0.3, 0.4, 0.5]), + } # Test wind_speed as pd.Series with density and power_coefficient_curve # as pd.Series and np.array - power_output_exp=pd.Series(data=[0.0, 244615.399, 0.0], - name='feedin_power_plant') - assert_series_equal(power_coefficient_curve(**parameters), - power_output_exp) - parameters['density']=np.array(parameters['density']) - assert_series_equal(power_coefficient_curve(**parameters), - power_output_exp) - parameters['power_coefficient_curve_values']=np.array( - parameters['power_coefficient_curve_values']) - parameters['power_coefficient_curve_wind_speeds']=np.array( - parameters['power_coefficient_curve_wind_speeds']) - assert_series_equal(power_coefficient_curve(**parameters), - power_output_exp) + power_output_exp = pd.Series( + data=[0.0, 244615.399, 0.0], name="feedin_power_plant" + ) + assert_series_equal( + power_coefficient_curve(**parameters), power_output_exp + ) + parameters["density"] = np.array(parameters["density"]) + assert_series_equal( + power_coefficient_curve(**parameters), power_output_exp + ) + parameters["power_coefficient_curve_values"] = np.array( + parameters["power_coefficient_curve_values"] + ) + parameters["power_coefficient_curve_wind_speeds"] = np.array( + parameters["power_coefficient_curve_wind_speeds"] + ) + assert_series_equal( + power_coefficient_curve(**parameters), power_output_exp + ) # Test wind_speed as np.array with density and power_coefficient_curve # as np.array and pd.Series - power_output_exp=np.array([0.0, 244615.399, 0.0]) - parameters['wind_speed']=np.array(parameters['wind_speed']) - assert_allclose(power_coefficient_curve(**parameters), - power_output_exp) + power_output_exp = np.array([0.0, 244615.399, 0.0]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) + assert_allclose( + power_coefficient_curve(**parameters), power_output_exp + ) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters['density']=pd.Series(data=parameters['density']) - assert_allclose(power_coefficient_curve(**parameters), - power_output_exp) + parameters["density"] = pd.Series(data=parameters["density"]) + assert_allclose( + power_coefficient_curve(**parameters), power_output_exp + ) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters['power_coefficient_curve_wind_speeds']=pd.Series( - data=parameters['power_coefficient_curve_wind_speeds']) - parameters['power_coefficient_curve_values']=pd.Series( - data=parameters['power_coefficient_curve_values']) - assert_allclose(power_coefficient_curve(**parameters), - power_output_exp) + parameters["power_coefficient_curve_wind_speeds"] = pd.Series( + data=parameters["power_coefficient_curve_wind_speeds"] + ) + parameters["power_coefficient_curve_values"] = pd.Series( + data=parameters["power_coefficient_curve_values"] + ) + assert_allclose( + power_coefficient_curve(**parameters), power_output_exp + ) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) def test_power_curve(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'density_correction': False, - 'power_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_curve_values': - pd.Series([300, 400, 500]) - } + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "density_correction": False, + "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_curve_values": pd.Series([300, 400, 500]), + } # Tests without density correction: # Test wind_speed as pd.Series and power_curve as pd.Series and # np.array - power_output_exp=pd.Series(data=[0.0, 450.0, 0.0], - name='feedin_power_plant') + power_output_exp = pd.Series( + data=[0.0, 450.0, 0.0], name="feedin_power_plant" + ) + assert_series_equal(power_curve(**parameters), power_output_exp) + parameters["power_curve_values"] = np.array( + parameters["power_curve_values"] + ) + parameters["power_curve_wind_speeds"] = np.array( + parameters["power_curve_wind_speeds"] + ) assert_series_equal(power_curve(**parameters), power_output_exp) - parameters['power_curve_values']=np.array( - parameters['power_curve_values']) - parameters['power_curve_wind_speeds']=np.array( - parameters['power_curve_wind_speeds']) - assert_series_equal(power_curve(**parameters), - power_output_exp) # Test wind_speed as np.array and power_curve as pd.Series and np.array - power_output_exp=np.array([0.0, 450.0, 0.0]) - parameters['wind_speed']=np.array(parameters['wind_speed']) + power_output_exp = np.array([0.0, 450.0, 0.0]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_wind_speeds']=pd.Series( - data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values']=pd.Series( - data=parameters['power_curve_values']) + parameters["power_curve_wind_speeds"] = pd.Series( + data=parameters["power_curve_wind_speeds"] + ) + parameters["power_curve_values"] = pd.Series( + data=parameters["power_curve_values"] + ) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Tests with density correction: # Test wind_speed as np.array with density and power_curve as pd.Series # and np.array - power_output_exp=np.array([0.0, 461.00290572, 0.0]) - parameters['density_correction']=True + power_output_exp = np.array([0.0, 461.00290572, 0.0]) + parameters["density_correction"] = True assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['density']=np.array(parameters['density']) + parameters["density"] = np.array(parameters["density"]) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_values']=np.array( - parameters['power_curve_values']) - parameters['power_curve_wind_speeds']=np.array( - parameters['power_curve_wind_speeds']) + parameters["power_curve_values"] = np.array( + parameters["power_curve_values"] + ) + parameters["power_curve_wind_speeds"] = np.array( + parameters["power_curve_wind_speeds"] + ) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Test wind_speed as pd.Series with density and power_curve as # np. array and pd.Series - power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], - name='feedin_power_plant') - parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) + power_output_exp = pd.Series( + data=[0.0, 461.00290572, 0.0], name="feedin_power_plant" + ) + parameters["wind_speed"] = pd.Series(data=parameters["wind_speed"]) + assert_series_equal(power_curve(**parameters), power_output_exp) + parameters["density"] = pd.Series(data=parameters["density"]) + assert_series_equal(power_curve(**parameters), power_output_exp) + parameters["power_curve_wind_speeds"] = pd.Series( + data=parameters["power_curve_wind_speeds"] + ) + parameters["power_curve_values"] = pd.Series( + data=parameters["power_curve_values"] + ) assert_series_equal(power_curve(**parameters), power_output_exp) - parameters['density']=pd.Series(data=parameters['density']) - assert_series_equal(power_curve(**parameters), - power_output_exp) - parameters['power_curve_wind_speeds']=pd.Series( - data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values']=pd.Series( - data=parameters['power_curve_values']) - assert_series_equal(power_curve(**parameters), - power_output_exp) # Raise TypeErrors due to wrong type of `density_correction` with pytest.raises(TypeError): - parameters['density']='wrong_type' + parameters["density"] = "wrong_type" power_curve(**parameters) def test_power_curve_density_correction(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'power_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_curve_values': - pd.Series([300, 400, 500]) - } + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_curve_values": pd.Series([300, 400, 500]), + } # Test wind_speed as pd.Series with density and power_curve as # pd.Series and np.array - power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], - name='feedin_power_plant') - assert_series_equal(power_curve_density_correction(**parameters), - power_output_exp) - parameters['density']=np.array(parameters['density']) - assert_series_equal(power_curve_density_correction(**parameters), - power_output_exp) - parameters['power_curve_values']=np.array( - parameters['power_curve_values']) - parameters['power_curve_wind_speeds']=np.array( - parameters['power_curve_wind_speeds']) - assert_series_equal(power_curve_density_correction(**parameters), - power_output_exp) + power_output_exp = pd.Series( + data=[0.0, 461.00290572, 0.0], name="feedin_power_plant" + ) + assert_series_equal( + power_curve_density_correction(**parameters), power_output_exp + ) + parameters["density"] = np.array(parameters["density"]) + assert_series_equal( + power_curve_density_correction(**parameters), power_output_exp + ) + parameters["power_curve_values"] = np.array( + parameters["power_curve_values"] + ) + parameters["power_curve_wind_speeds"] = np.array( + parameters["power_curve_wind_speeds"] + ) + assert_series_equal( + power_curve_density_correction(**parameters), power_output_exp + ) # Test wind_speed as np.array with density and power_curve as np.array # and pd.Series - parameters['wind_speed']=np.array(parameters['wind_speed']) - power_output_exp=np.array([0.0, 461.00290572, 0.0]) - assert_allclose(power_curve_density_correction(**parameters), - power_output_exp) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) + power_output_exp = np.array([0.0, 461.00290572, 0.0]) + assert_allclose( + power_curve_density_correction(**parameters), power_output_exp + ) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['density']=pd.Series(data=parameters['density']) - assert_allclose(power_curve_density_correction(**parameters), - power_output_exp) + parameters["density"] = pd.Series(data=parameters["density"]) + assert_allclose( + power_curve_density_correction(**parameters), power_output_exp + ) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_wind_speeds']=pd.Series( - data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values']=pd.Series( - data=parameters['power_curve_values']) - assert_allclose(power_curve_density_correction(**parameters), - power_output_exp) + parameters["power_curve_wind_speeds"] = pd.Series( + data=parameters["power_curve_wind_speeds"] + ) + parameters["power_curve_values"] = pd.Series( + data=parameters["power_curve_values"] + ) + assert_allclose( + power_curve_density_correction(**parameters), power_output_exp + ) assert isinstance(power_curve(**parameters), np.ndarray) # Raise TypeError due to density is None with pytest.raises(TypeError): - parameters['density']=None + parameters["density"] = None power_curve_density_correction(**parameters) def test_wrong_spelling_density_correction(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'power_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_curve_values': - pd.Series([300, 400, 500]) - } - msg="is an invalid type. `density_correction` must be Boolean" + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_curve_values": pd.Series([300, 400, 500]), + } + msg = "is an invalid type. `density_correction` must be Boolean" with pytest.raises(TypeError, match=msg): - parameters['density_correction']=None + parameters["density_correction"] = None power_curve(**parameters) diff --git a/tests/test_temperature.py b/tests/test_temperature.py index 59070069..d0e2ba4b 100644 --- a/tests/test_temperature.py +++ b/tests/test_temperature.py @@ -12,20 +12,23 @@ class TestTemperature: - def test_linear_gradient(self): """Test temperature as pd.Series""" - parameters={'temperature': pd.Series(data=[267, 268]), - 'temperature_height': 2, - 'hub_height': 100} - temp_hub_exp=pd.Series(data=[266.363, 267.36300]) + parameters = { + "temperature": pd.Series(data=[267, 268]), + "temperature_height": 2, + "hub_height": 100, + } + temp_hub_exp = pd.Series(data=[266.363, 267.36300]) assert_series_equal(linear_gradient(**parameters), temp_hub_exp) def test_temperature_as_np_array(self): """Test temperature as np.array""" - parameters={'temperature': np.array([267, 268]), - 'temperature_height': 2, - 'hub_height': 100} - temp_hub_exp=np.array([266.363, 267.36300]) + parameters = { + "temperature": np.array([267, 268]), + "temperature_height": 2, + "hub_height": 100, + } + temp_hub_exp = np.array([266.363, 267.36300]) assert_array_equal(linear_gradient(**parameters), temp_hub_exp) assert isinstance(linear_gradient(**parameters), np.ndarray) diff --git a/tests/test_tools.py b/tests/test_tools.py index 91d87223..2392d89d 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -6,96 +6,128 @@ import pandas as pd from pandas.util.testing import assert_series_equal -from windpowerlib.tools import (linear_interpolation_extrapolation, - logarithmic_interpolation_extrapolation) +from windpowerlib.tools import ( + linear_interpolation_extrapolation, + logarithmic_interpolation_extrapolation, +) class TestTools: - @classmethod def setup_class(cls): - cls.parameters={'target_height': 80} - cls.df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], - 80: [4.0, 5.0, 6.0], - 200: [5.0, 8.0, 10.0]}, - index=[0, 1, 2]) + cls.parameters = {"target_height": 80} + cls.df = pd.DataFrame( + data={ + 10: [2.0, 2.0, 3.0], + 80: [4.0, 5.0, 6.0], + 200: [5.0, 8.0, 10.0], + }, + index=[0, 1, 2], + ) def test_linear_target_height_is_equal_to_given_height(self): """ Test linear interpolation and extrapolation if target_height is equal to height given in a column of the DataFrame. """ - exp_output=pd.Series(data=[4.0, 5.0, 6.0]) - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[4.0, 5.0, 6.0]) + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_linear_target_height_is_between_given_heights(self): """ Test linear interpolation and extrapolation if target_height is between heights given in the columns of the DataFrame """ - exp_output=pd.Series(data=[4.5, 6.5, 8.0]) - self.parameters['target_height']=140 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[4.5, 6.5, 8.0]) + self.parameters["target_height"] = 140 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) - exp_output=pd.Series(data=[4.285714, 5.428571, 6.428571]) - self.parameters['target_height']=90 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[4.285714, 5.428571, 6.428571]) + self.parameters["target_height"] = 90 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_linear_target_height_is_greater_than_the_given_heights(self): """ Test linear interpolation and extrapolation if target_height is greater than the heights given in the columns of the DataFrame """ - exp_output=pd.Series(data=[5.333333, 9.0, 11.333333]) - self.parameters['target_height']=240 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[5.333333, 9.0, 11.333333]) + self.parameters["target_height"] = 240 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_linear_target_height_is_smaller_than_the_given_heights(self): """ Test linear interpolation and extrapolation if target_height is smaller than the heights given in the columns of the DataFrame """ - exp_output=pd.Series(data=[1.857143, 1.785714, 2.785714]) - self.parameters['target_height']=5 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[1.857143, 1.785714, 2.785714]) + self.parameters["target_height"] = 5 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_logarithmic_interpolation_extrapolation(self): - parameters={'target_height': 80} - df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], - 80: [4.0, 5.0, 6.0], - 200: [5.0, 8.0, 10.0]}, - index=[0, 1, 2]) + parameters = {"target_height": 80} + df = pd.DataFrame( + data={ + 10: [2.0, 2.0, 3.0], + 80: [4.0, 5.0, 6.0], + 200: [5.0, 8.0, 10.0], + }, + index=[0, 1, 2], + ) # target_height is equal to height given in a column of the DataFrame - exp_output=pd.Series(data=[4.0, 5.0, 6.0]) - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series(data=[4.0, 5.0, 6.0]) + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) # target_height is between heights given in the columns of the # DataFrame - exp_output=pd.Series( - data=[4.61074042165, 6.83222126494, 8.44296168659]) - parameters['target_height']=140 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) - exp_output=pd.Series( - data=[4.11328333429, 5.16992500144, 6.16992500144]) - parameters['target_height']=90 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series( + data=[4.61074042165, 6.83222126494, 8.44296168659] + ) + parameters["target_height"] = 140 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) + exp_output = pd.Series( + data=[4.11328333429, 5.16992500144, 6.16992500144] + ) + parameters["target_height"] = 90 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) # target_height is greater than the heights given in the columns of the # DataFrame - exp_output=pd.Series( - data=[5.19897784672, 8.59693354015, 10.7959113869]) - parameters['target_height']=240 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series( + data=[5.19897784672, 8.59693354015, 10.7959113869] + ) + parameters["target_height"] = 240 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) # target_height is smaller than the heights given in the columns of the # DataFrame - exp_output=pd.Series(data=[1.33333333333, 1.0, 2.0]) - parameters['target_height']=5 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series(data=[1.33333333333, 1.0, 2.0]) + parameters["target_height"] = 5 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) diff --git a/tests/test_turbine_cluster_modelchain.py b/tests/test_turbine_cluster_modelchain.py index 80f9bcfd..2b20e151 100644 --- a/tests/test_turbine_cluster_modelchain.py +++ b/tests/test_turbine_cluster_modelchain.py @@ -15,179 +15,230 @@ class TestTurbineClusterModelChain: - @classmethod def setup_class(self): - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - pressure_0m=np.array([[101125], [101000]]) - wind_speed_8m=np.array([[4.0], [5.0]]) - wind_speed_10m=np.array([[5.0], [6.5]]) - roughness_length=np.array([[0.15], [0.15]]) - self.weather_df=pd.DataFrame( - np.hstack((temperature_2m, - temperature_10m, - pressure_0m, - wind_speed_8m, - wind_speed_10m, - roughness_length)), - index=[0, 1], - columns=[np.array(['temperature', - 'temperature', - 'pressure', - 'wind_speed', - 'wind_speed', - 'roughness_length']), - np.array([2, 10, 0, 8, 10, 0])]) - self.test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - self.test_turbine_2={'hub_height': 90, - 'rotor_diameter': 60, - 'turbine_type': 'V90/2000', - 'nominal_power': 2000000.0} - self.test_farm={'wind_turbine_fleet': [ - {'wind_turbine': - wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}]} - self.test_farm_2={'name': 'test farm', - 'wind_turbine_fleet': - [{'wind_turbine': - wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': - wt.WindTurbine(**self.test_turbine_2), - 'number_of_turbines': 3}]} - self.test_cluster={'name': 'example_cluster', - 'wind_farms': [wf.WindFarm(**self.test_farm), - wf.WindFarm(**self.test_farm_2)]} + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + pressure_0m = np.array([[101125], [101000]]) + wind_speed_8m = np.array([[4.0], [5.0]]) + wind_speed_10m = np.array([[5.0], [6.5]]) + roughness_length = np.array([[0.15], [0.15]]) + self.weather_df = pd.DataFrame( + np.hstack( + ( + temperature_2m, + temperature_10m, + pressure_0m, + wind_speed_8m, + wind_speed_10m, + roughness_length, + ) + ), + index=[0, 1], + columns=[ + np.array( + [ + "temperature", + "temperature", + "pressure", + "wind_speed", + "wind_speed", + "roughness_length", + ] + ), + np.array([2, 10, 0, 8, 10, 0]), + ], + ) + self.test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + self.test_turbine_2 = { + "hub_height": 90, + "rotor_diameter": 60, + "turbine_type": "V90/2000", + "nominal_power": 2000000.0, + } + self.test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + } + ] + } + self.test_farm_2 = { + "name": "test farm", + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": wt.WindTurbine(**self.test_turbine_2), + "number_of_turbines": 3, + }, + ], + } + self.test_cluster = { + "name": "example_cluster", + "wind_farms": [ + wf.WindFarm(**self.test_farm), + wf.WindFarm(**self.test_farm_2), + ], + } def test_run_model(self): - parameters={'wake_losses_model': 'dena_mean', - 'smoothing': False, - 'standard_deviation_method': 'turbulence_intensity', - 'smoothing_order': 'wind_farm_power_curves'} + parameters = { + "wake_losses_model": "dena_mean", + "smoothing": False, + "standard_deviation_method": "turbulence_intensity", + "smoothing_order": "wind_farm_power_curves", + } # Test modelchain with default values - power_output_exp=pd.Series(data=[4198361.4830405945, - 8697966.121234536], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**self.test_farm), **parameters) + power_output_exp = pd.Series( + data=[4198361.4830405945, 8697966.121234536], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**self.test_farm), **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters['wake_losses_model']='wind_farm_efficiency' - test_wind_farm=wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[4420994.806920091, - 8516983.651623568], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + parameters["wake_losses_model"] = "wind_farm_efficiency" + test_wind_farm = wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[4420994.806920091, 8516983.651623568], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters['smoothing']='True' - test_wind_farm=wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[4581109.03847444, - 8145581.914240712], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + parameters["smoothing"] = "True" + test_wind_farm = wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[4581109.03847444, 8145581.914240712], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_wind_farm=wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[6777087.9658657005, - 12180374.036660176], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + test_wind_farm = wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[6777087.9658657005, 12180374.036660176], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters['smoothing_order']='turbine_power_curves' - test_wind_farm=wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[6790706.001026006, - 12179417.461328149], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + parameters["smoothing_order"] = "turbine_power_curves" + test_wind_farm = wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[6790706.001026006, 12179417.461328149], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) def test_run_model_turbine_cluster(self): - parameters={'wake_losses_model': 'dena_mean', - 'smoothing': False, - 'standard_deviation_method': 'turbulence_intensity', - 'smoothing_order': 'wind_farm_power_curves'} + parameters = { + "wake_losses_model": "dena_mean", + "smoothing": False, + "standard_deviation_method": "turbulence_intensity", + "smoothing_order": "wind_farm_power_curves", + } # Test modelchain with default values - power_output_exp=pd.Series(data=[10363047.755401008, - 21694496.68221325], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( + power_output_exp = pd.Series( + data=[10363047.755401008, 21694496.68221325], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), - **parameters) + **parameters, + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters['wake_losses_model']='wind_farm_efficiency' - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + parameters["wake_losses_model"] = "wind_farm_efficiency" + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[10920128.570572512, - 21273144.336885825], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[10920128.570572512, 21273144.336885825], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters['smoothing']='True' - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + parameters["smoothing"] = "True" + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[11360309.77979467, - 20328652.64490018], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[11360309.77979467, 20328652.64490018], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[11360309.77979467, - 20328652.64490018], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[11360309.77979467, 20328652.64490018], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters['smoothing_order']='turbine_power_curves' - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + parameters["smoothing_order"] = "turbine_power_curves" + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[11373183.797085874, - 20325877.105744187], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[11373183.797085874, 20325877.105744187], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) @@ -195,80 +246,115 @@ def test_error_raising(self): # Raise ValueError when aggregated wind farm power curve needs to be # calculated but turbine does not have a power curve - test_turbine_data={ - 'hub_height': 100, - 'rotor_diameter': 98, - 'turbine_type': 'V90/2000'} - test_turbine=wt.WindTurbine(**test_turbine_data) - test_turbine.power_curve=True - test_farm={'wind_turbine_fleet': - [{'wind_turbine': - wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': - test_turbine, - 'number_of_turbines': 3}]} - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**test_farm)) + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 98, + "turbine_type": "V90/2000", + } + test_turbine = wt.WindTurbine(**test_turbine_data) + test_turbine.power_curve = True + test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + {"wind_turbine": test_turbine, "number_of_turbines": 3}, + ] + } + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**test_farm) + ) with pytest.raises(ValueError): test_tc_mc.run_model(self.weather_df) # Raise ValueError when neither turbulence intensity nor roughness # length are provided to apply power curve smoothing with standard # deviation method 'turbulence_intensity' - parameters={'smoothing': True, - 'standard_deviation_method': 'turbulence_intensity'} - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**self.test_farm), **parameters) - weather_df=self.weather_df.copy() - weather_df.pop('roughness_length') + parameters = { + "smoothing": True, + "standard_deviation_method": "turbulence_intensity", + } + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**self.test_farm), **parameters + ) + weather_df = self.weather_df.copy() + weather_df.pop("roughness_length") with pytest.raises(ValueError): test_tc_mc.run_model(weather_df) def test_ignore_wake_losses(self): """Run model without wake losses.""" - parameters={'wake_losses_model': None, - 'smoothing': False, - 'standard_deviation_method': 'turbulence_intensity', - 'smoothing_order': 'wind_farm_power_curves'} + parameters = { + "wake_losses_model": None, + "smoothing": False, + "standard_deviation_method": "turbulence_intensity", + "smoothing_order": "wind_farm_power_curves", + } # Test modelchain with default values - test_tc_mc=tc_mc.TurbineClusterModelChain( + test_tc_mc = tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), - **parameters) + **parameters, + ) test_tc_mc.run_model(self.weather_df) def test_wind_turbine_cluster_repr_with_name(self): """Test string representation of WindTurbineCluster with a name.""" - assert 'Wind turbine cluster:' in repr( - wtc.WindTurbineCluster(**self.test_cluster)) + assert "Wind turbine cluster:" in repr( + wtc.WindTurbineCluster(**self.test_cluster) + ) def test_wind_turbine_cluster_repr_without_name(self): """Test string representation of WindTurbineCluster without a name.""" - test_cluster={'wind_farms': [wf.WindFarm(**self.test_farm), - wf.WindFarm(**self.test_farm_2)]} - assert 'Wind turbine cluster with:' in repr( - wtc.WindTurbineCluster(**test_cluster)) + test_cluster = { + "wind_farms": [ + wf.WindFarm(**self.test_farm), + wf.WindFarm(**self.test_farm_2), + ] + } + assert "Wind turbine cluster with:" in repr( + wtc.WindTurbineCluster(**test_cluster) + ) def test_tc_modelchain_with_power_curve_as_dict(self): """Test power curves as dict in TurbineClusterModelChain.run_model()""" - my_turbine={'nominal_power': 3e6, 'hub_height': 105, - 'power_curve': { - 'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - my_farm={'wind_turbine_fleet': - [{'wind_turbine': wt.WindTurbine(**my_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}]} - my_cluster= {'wind_farms': [wf.WindFarm(**my_farm), - wf.WindFarm(**self.test_farm)]} - power_output_exp=pd.Series(data=[10853277.966972714, - 21731814.593688786], - name='feedin_power_plant') + my_turbine = { + "nominal_power": 3e6, + "hub_height": 105, + "power_curve": { + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + } + my_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**my_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + ] + } + my_cluster = { + "wind_farms": [ + wf.WindFarm(**my_farm), + wf.WindFarm(**self.test_farm), + ] + } + power_output_exp = pd.Series( + data=[10853277.966972714, 21731814.593688786], + name="feedin_power_plant", + ) # run model with my_cluster - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wtc.WindTurbineCluster(**my_cluster)) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wtc.WindTurbineCluster(**my_cluster) + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) diff --git a/tests/test_wake_losses.py b/tests/test_wake_losses.py index 951ddcd1..d27fd4a1 100644 --- a/tests/test_wake_losses.py +++ b/tests/test_wake_losses.py @@ -8,49 +8,77 @@ import pytest from pandas.util.testing import assert_series_equal -from windpowerlib.wake_losses import (reduce_wind_speed, - get_wind_efficiency_curve) +from windpowerlib.wake_losses import ( + reduce_wind_speed, + get_wind_efficiency_curve, +) class TestWakeLosses: - def test_reduce_wind_speed(self): - parameters={'wind_speed': pd.Series(np.arange(0, 26, 1.0)), - 'wind_efficiency_curve_name': 'dena_mean'} - wind_speed_exp=pd.Series([ - 0.0, 0.9949534234119396, 1.9897327884892086, 2.9843374545454546, - 3.807636264984227, 4.714931284760845, 5.642507531914893, - 6.607021108049704, 7.592423167192429, 8.59498170212766, - 9.606135658475111, 10.619828799086758, 11.641291957894737, - 12.674012890137966, 13.709490666666666, 14.742508260567297, - 15.773293013157893, 16.794615009724474, 17.817683032858028, - 18.85294996704484, 19.86509539493748, 20.858807854510186, - 21.854369681134507, 22.850700350710902, 23.85962037735849, - 24.958125]) + parameters = { + "wind_speed": pd.Series(np.arange(0, 26, 1.0)), + "wind_efficiency_curve_name": "dena_mean", + } + wind_speed_exp = pd.Series( + [ + 0.0, + 0.9949534234119396, + 1.9897327884892086, + 2.9843374545454546, + 3.807636264984227, + 4.714931284760845, + 5.642507531914893, + 6.607021108049704, + 7.592423167192429, + 8.59498170212766, + 9.606135658475111, + 10.619828799086758, + 11.641291957894737, + 12.674012890137966, + 13.709490666666666, + 14.742508260567297, + 15.773293013157893, + 16.794615009724474, + 17.817683032858028, + 18.85294996704484, + 19.86509539493748, + 20.858807854510186, + 21.854369681134507, + 22.850700350710902, + 23.85962037735849, + 24.958125, + ] + ) assert_series_equal(reduce_wind_speed(**parameters), wind_speed_exp) # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters['wind_efficiency_curve_name']='misspelled' + parameters["wind_efficiency_curve_name"] = "misspelled" reduce_wind_speed(**parameters) with pytest.raises(ValueError): - parameters['wind_efficiency_curve_name']='dena_misspelled' + parameters["wind_efficiency_curve_name"] = "dena_misspelled" reduce_wind_speed(**parameters) def test_get_wind_efficiency_curve_one(self): """Test get_wind_efficiency_curve() for one curve.""" - wec=get_wind_efficiency_curve('dena_mean').sum() - wec_exp=pd.Series({'efficiency': 162.45047, - 'wind_speed': 1915.23620}) + wec = get_wind_efficiency_curve("dena_mean").sum() + wec_exp = pd.Series( + {"efficiency": 162.45047, "wind_speed": 1915.23620} + ) assert_series_equal(wec.sort_index(), wec_exp.sort_index()) def test_get_wind_efficiency_curve_all(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum=int(get_wind_efficiency_curve('all').sum().round().sum()) + wec_all_sum = int(get_wind_efficiency_curve("all").sum().round().sum()) assert wec_all_sum == 12145 def test_get_wind_efficiency_curve_list(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum=int(get_wind_efficiency_curve( - ['dena_mean', 'knorr_mean']).sum().round().sum()) + wec_all_sum = int( + get_wind_efficiency_curve(["dena_mean", "knorr_mean"]) + .sum() + .round() + .sum() + ) assert wec_all_sum == 3568 diff --git a/tests/test_wind_farm.py b/tests/test_wind_farm.py index a2aa4dba..b031abcf 100644 --- a/tests/test_wind_farm.py +++ b/tests/test_wind_farm.py @@ -11,155 +11,211 @@ class TestWindFarm: - @classmethod def setup_class(self): """Setup default values""" - self.test_turbine={'hub_height': 100, - 'turbine_type': 'E-126/4200'} - self.test_turbine_2={'hub_height': 90, - 'turbine_type': 'V90/2000', - 'nominal_power': 2e6} + self.test_turbine = {"hub_height": 100, "turbine_type": "E-126/4200"} + self.test_turbine_2 = { + "hub_height": 90, + "turbine_type": "V90/2000", + "nominal_power": 2e6, + } def test_initialization_list(self): """test simple initialization with wind turbine fleet list""" - wind_turbine_fleet=[ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'number_of_turbines': 2}] - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet = [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "number_of_turbines": 2, + }, + ] + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_list_2(self): """test simple initialization with wind turbine fleet list where once number of turbines and once total capacity is provided""" - wind_turbine_fleet=[ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'total_capacity': 2 * 2e6}] - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet = [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "total_capacity": 2 * 2e6, + }, + ] + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_dataframe(self): """test simple initialization with wind turbine fleet dataframe""" - wind_turbine_fleet=pd.DataFrame( - data={'wind_turbine': [WindTurbine(**self.test_turbine), - WindTurbine(**self.test_turbine_2)], - 'number_of_turbines': [3, 2]}) - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet = pd.DataFrame( + data={ + "wind_turbine": [ + WindTurbine(**self.test_turbine), + WindTurbine(**self.test_turbine_2), + ], + "number_of_turbines": [3, 2], + } + ) + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_1(self): """test catching error when wind_turbine_fleet not provided as list""" - msg='Wind turbine must be provided as WindTurbine object' + msg = "Wind turbine must be provided as WindTurbine object" with pytest.raises(ValueError, match=msg): - WindFarm(wind_turbine_fleet={'wind_turbine': 'turbine', - 'number_of_turbines': 2}, - name='dummy') + WindFarm( + wind_turbine_fleet={ + "wind_turbine": "turbine", + "number_of_turbines": 2, + }, + name="dummy", + ) def test_initialization_2(self): """test catching error when WindTurbine in wind_turbine_fleet not initialized""" - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': None, - 'number_of_turbines': 3}]} - msg='Wind turbine must be provided as WindTurbine object' + test_farm = { + "wind_turbine_fleet": [ + {"wind_turbine": None, "number_of_turbines": 3} + ] + } + msg = "Wind turbine must be provided as WindTurbine object" with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_3(self): """test catching error when wind_turbine not specified in wind_turbine_fleet""" - wind_turbine_fleet=pd.DataFrame( - data={'wind_turbines': [WindTurbine(**self.test_turbine), - WindTurbine(**self.test_turbine_2)], - 'number_of_turbines': [3, 2]}) - msg='Missing wind_turbine key/column in wind_turbine_fleet' + wind_turbine_fleet = pd.DataFrame( + data={ + "wind_turbines": [ + WindTurbine(**self.test_turbine), + WindTurbine(**self.test_turbine_2), + ], + "number_of_turbines": [3, 2], + } + ) + msg = "Missing wind_turbine key/column in wind_turbine_fleet" with pytest.raises(KeyError, match=msg): WindFarm(wind_turbine_fleet=wind_turbine_fleet) def test_initialization_4(self, recwarn): """test overwriting and raising warning when number_of_turbines and total_capacity in wind turbine fleet do not fit""" - wt1=WindTurbine(**self.test_turbine) - wt2=WindTurbine(**self.test_turbine_2) - wind_turbine_fleet=pd.DataFrame( - data={'wind_turbine': [wt1, wt2], - 'number_of_turbines': [3, 2], - 'total_capacity': [3, np.nan]}, - index=[0, 1]) - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) - total_cap_wt1_expected=\ - wt1.nominal_power * wind_turbine_fleet.loc[0, 'number_of_turbines'] - assert windfarm.wind_turbine_fleet.loc[0, 'total_capacity'] == \ - total_cap_wt1_expected - total_cap_wt2_expected=\ - wt2.nominal_power * wind_turbine_fleet.loc[1, 'number_of_turbines'] - assert windfarm.wind_turbine_fleet.loc[1, 'total_capacity'] == \ - total_cap_wt2_expected + wt1 = WindTurbine(**self.test_turbine) + wt2 = WindTurbine(**self.test_turbine_2) + wind_turbine_fleet = pd.DataFrame( + data={ + "wind_turbine": [wt1, wt2], + "number_of_turbines": [3, 2], + "total_capacity": [3, np.nan], + }, + index=[0, 1], + ) + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + total_cap_wt1_expected = ( + wt1.nominal_power * wind_turbine_fleet.loc[0, "number_of_turbines"] + ) + assert ( + windfarm.wind_turbine_fleet.loc[0, "total_capacity"] + == total_cap_wt1_expected + ) + total_cap_wt2_expected = ( + wt2.nominal_power * wind_turbine_fleet.loc[1, "number_of_turbines"] + ) + assert ( + windfarm.wind_turbine_fleet.loc[1, "total_capacity"] + == total_cap_wt2_expected + ) assert recwarn.pop(WindpowerlibUserWarning) def test_initialization_5(self): """test catching error when number of turbines cannot be deduced""" - wt=WindTurbine(**self.test_turbine) - wt.nominal_power=None - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': wt, - 'total_capacity': 3e6}]} - msg='Number of turbines of type' + wt = WindTurbine(**self.test_turbine) + wt.nominal_power = None + test_farm = { + "wind_turbine_fleet": [{"wind_turbine": wt, "total_capacity": 3e6}] + } + msg = "Number of turbines of type" with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_6(self): """test catching error when neither number_of_turbines nor total_capacity is provided""" - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbine': 3e6}]} - msg='Number of turbines of type ' + test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbine": 3e6, + } + ] + } + msg = "Number of turbines of type " with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_7(self): """test catching error when total capacity cannot be deduced""" - wt=WindTurbine(**self.test_turbine) - wt.nominal_power=None - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': wt, - 'number_of_turbines': 3}]} - msg='Total capacity of turbines of type' + wt = WindTurbine(**self.test_turbine) + wt.nominal_power = None + test_farm = { + "wind_turbine_fleet": [ + {"wind_turbine": wt, "number_of_turbines": 3} + ] + } + msg = "Total capacity of turbines of type" with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_mean_hub_height(self): """tests mean_hub_height method""" - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 2}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'total_capacity': 3e6}]} - windfarm=WindFarm(**test_farm) + test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 2, + }, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "total_capacity": 3e6, + }, + ] + } + windfarm = WindFarm(**test_farm) assert 97.265 == pytest.approx( - windfarm.mean_hub_height().hub_height, 1e-3) + windfarm.mean_hub_height().hub_height, 1e-3 + ) def test_repr(self): """Test string representation of WindFarm""" - test_fleet=[{'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 2}] - assert 'E-126/4200' in repr(WindFarm(wind_turbine_fleet=test_fleet)) + test_fleet = [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 2, + } + ] + assert "E-126/4200" in repr(WindFarm(wind_turbine_fleet=test_fleet)) def test_aggregation_of_power_curve_with_missing_power_curve(self): """Test WindFarm.assign_power_curve() with missing power_curve.""" - wt1=WindTurbine(**self.test_turbine) - wt1.power_curve=None - wind_turbine_fleet=[ - {'wind_turbine': wt1, - 'number_of_turbines': 3}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'number_of_turbines': 2}] - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) - msg='For an aggregated wind farm power curve each wind' + wt1 = WindTurbine(**self.test_turbine) + wt1.power_curve = None + wind_turbine_fleet = [ + {"wind_turbine": wt1, "number_of_turbines": 3}, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "number_of_turbines": 2, + }, + ] + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + msg = "For an aggregated wind farm power curve each wind" with pytest.raises(ValueError, match=msg): windfarm.assign_power_curve() diff --git a/tests/test_wind_speed.py b/tests/test_wind_speed.py index 88712a3d..f4af4299 100644 --- a/tests/test_wind_speed.py +++ b/tests/test_wind_speed.py @@ -13,94 +13,104 @@ class TestWindSpeed: - def test_logarithmic_profile(self): - parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), - 'wind_speed_height': 10, - 'hub_height': 100, - 'roughness_length': pd.Series(data=[0.15, 0.15]), - 'obstacle_height': 0} + parameters = { + "wind_speed": pd.Series(data=[5.0, 6.5]), + "wind_speed_height": 10, + "hub_height": 100, + "roughness_length": pd.Series(data=[0.15, 0.15]), + "obstacle_height": 0, + } # Test wind_speed as pd.Series with roughness_length as pd.Series, # np.array and float - v_wind_hub_exp=pd.Series(data=[7.74136523, 10.0637748]) - assert_series_equal(logarithmic_profile(**parameters), - v_wind_hub_exp) - parameters['roughness_length']=np.array( - parameters['roughness_length']) - assert_series_equal(logarithmic_profile(**parameters), - v_wind_hub_exp) - parameters['roughness_length']=parameters['roughness_length'][0] - assert_series_equal(logarithmic_profile(**parameters), - v_wind_hub_exp) + v_wind_hub_exp = pd.Series(data=[7.74136523, 10.0637748]) + assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) + assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) + parameters["roughness_length"] = parameters["roughness_length"][0] + assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) # Test wind_speed as np.array with roughness_length as float, pd.Series # and np.array - v_wind_hub_exp=np.array([7.74136523, 10.0637748]) - parameters['wind_speed']=np.array(parameters['wind_speed']) + v_wind_hub_exp = np.array([7.74136523, 10.0637748]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters['roughness_length']=pd.Series( - data=[parameters['roughness_length'], - parameters['roughness_length']]) + parameters["roughness_length"] = pd.Series( + data=[ + parameters["roughness_length"], + parameters["roughness_length"], + ] + ) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters['roughness_length']=np.array( - parameters['roughness_length']) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) # Test obstacle_height is not zero - v_wind_hub_exp=np.array([13.54925281, 17.61402865]) - parameters['obstacle_height']=12 + v_wind_hub_exp = np.array([13.54925281, 17.61402865]) + parameters["obstacle_height"] = 12 assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) # Raise ValueError due to 0.7 * `obstacle_height` > `wind_speed_height` with pytest.raises(ValueError): - parameters['obstacle_height']=20 + parameters["obstacle_height"] = 20 logarithmic_profile(**parameters) def test_hellman(self): - parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), - 'wind_speed_height': 10, - 'hub_height': 100, - 'roughness_length': pd.Series(data=[0.15, 0.15]), - 'hellman_exponent': None} + parameters = { + "wind_speed": pd.Series(data=[5.0, 6.5]), + "wind_speed_height": 10, + "hub_height": 100, + "roughness_length": pd.Series(data=[0.15, 0.15]), + "hellman_exponent": None, + } # Test wind_speed is pd.Series with roughness_length is pd.Series, # np.array and float - v_wind_hub_exp=pd.Series(data=[7.12462437, 9.26201168]) + v_wind_hub_exp = pd.Series(data=[7.12462437, 9.26201168]) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters['roughness_length']=np.array( - parameters['roughness_length']) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters['roughness_length']=parameters['roughness_length'][0] + parameters["roughness_length"] = parameters["roughness_length"][0] assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test wind_speed as np.array with roughness_length is float, pd.Series # and np.array - v_wind_hub_exp=np.array([7.12462437, 9.26201168]) - parameters['wind_speed']=np.array(parameters['wind_speed']) + v_wind_hub_exp = np.array([7.12462437, 9.26201168]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters['roughness_length']=pd.Series( - data=(parameters['roughness_length'], - parameters['roughness_length'])) + parameters["roughness_length"] = pd.Series( + data=( + parameters["roughness_length"], + parameters["roughness_length"], + ) + ) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters['roughness_length']=np.array( - parameters['roughness_length']) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) # Test roughness_length is None and hellman_exponent is None - v_wind_hub_exp=pd.Series(data=[6.9474774, 9.03172]) - parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) - parameters['roughness_length']=None + v_wind_hub_exp = pd.Series(data=[6.9474774, 9.03172]) + parameters["wind_speed"] = pd.Series(data=parameters["wind_speed"]) + parameters["roughness_length"] = None assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test hellman_exponent is not None - v_wind_hub_exp=pd.Series(data=[7.92446596, 10.30180575]) - parameters['roughness_length']=0.15 - parameters['hellman_exponent']=0.2 + v_wind_hub_exp = pd.Series(data=[7.92446596, 10.30180575]) + parameters["roughness_length"] = 0.15 + parameters["hellman_exponent"] = 0.2 assert_series_equal(hellman(**parameters), v_wind_hub_exp) diff --git a/tests/test_wind_turbine.py b/tests/test_wind_turbine.py index fdcf4472..1f3acfac 100644 --- a/tests/test_wind_turbine.py +++ b/tests/test_wind_turbine.py @@ -9,47 +9,52 @@ import os from windpowerlib.tools import WindpowerlibUserWarning -from windpowerlib.wind_turbine import (get_turbine_data_from_file, WindTurbine, - get_turbine_types, WindTurbineGroup, - load_turbine_data_from_oedb) +from windpowerlib.wind_turbine import ( + get_turbine_data_from_file, + WindTurbine, + get_turbine_types, + WindTurbineGroup, + load_turbine_data_from_oedb, +) class TestWindTurbine: - @classmethod def setup_class(cls): """Setup default values""" - cls.source=os.path.join(os.path.dirname(__file__), '../example/data') + cls.source = os.path.join(os.path.dirname(__file__), "../example/data") def test_warning(self, recwarn): - test_turbine_data={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'turbine_not_in_file', - 'path': self.source} - assert(WindTurbine(**test_turbine_data).power_curve is None) + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "turbine_not_in_file", + "path": self.source, + } + assert WindTurbine(**test_turbine_data).power_curve is None assert recwarn.pop(WindpowerlibUserWarning) def test_get_turbine_data_from_file(self): # Raise FileNotFoundError due to missing with pytest.raises(FileNotFoundError): - get_turbine_data_from_file(turbine_type='...', - path='not_existent') + get_turbine_data_from_file(turbine_type="...", path="not_existent") def test_get_turbine_types(self, capsys): get_turbine_types() - captured=capsys.readouterr() - assert 'Enercon' in captured.out - get_turbine_types('oedb', print_out=False, filter_=False) - msg="`turbine_library` is 'wrong' but must be 'local' or 'oedb'." + captured = capsys.readouterr() + assert "Enercon" in captured.out + get_turbine_types("oedb", print_out=False, filter_=False) + msg = "`turbine_library` is 'wrong' but must be 'local' or 'oedb'." with pytest.raises(ValueError, match=msg): - get_turbine_types('wrong') + get_turbine_types("wrong") def test_wrong_url_load_turbine_data(self): """Load turbine data from oedb.""" - with pytest.raises(ConnectionError, - match="Database connection not successful"): - load_turbine_data_from_oedb('wrong_schema') + with pytest.raises( + ConnectionError, match="Database connection not successful" + ): + load_turbine_data_from_oedb("wrong_schema") @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_string_representation_of_wind_turbine(self): @@ -57,43 +62,51 @@ def test_string_representation_of_wind_turbine(self): def test_power_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_curve.""" - test_turbine_data={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'test_type', - 'power_curve': 'string'} + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "test_type", + "power_curve": "string", + } with pytest.raises(TypeError): WindTurbine(**test_turbine_data) def test_power_coefficient_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_coefficient_curve.""" - test_turbine_data={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'test_type', - 'power_coefficient_curve': 'string'} + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "test_type", + "power_coefficient_curve": "string", + } with pytest.raises(TypeError): WindTurbine(**test_turbine_data) def test_to_group_method(self): - example_turbine={ - 'hub_height': 100, - 'rotor_diameter': 70, - 'turbine_type': 'DUMMY 3', - 'path': self.source} - e_t_1=WindTurbine(**example_turbine) - assert(isinstance(e_t_1.to_group(), WindTurbineGroup)) - assert(e_t_1.to_group(5).number_of_turbines == 5) - assert(e_t_1.to_group(number_turbines=5).number_of_turbines == 5) - assert(e_t_1.to_group(total_capacity=3e6).number_of_turbines == 2.0) + example_turbine = { + "hub_height": 100, + "rotor_diameter": 70, + "turbine_type": "DUMMY 3", + "path": self.source, + } + e_t_1 = WindTurbine(**example_turbine) + assert isinstance(e_t_1.to_group(), WindTurbineGroup) + assert e_t_1.to_group(5).number_of_turbines == 5 + assert e_t_1.to_group(number_turbines=5).number_of_turbines == 5 + assert e_t_1.to_group(total_capacity=3e6).number_of_turbines == 2.0 def test_wrongly_defined_to_group_method(self): - example_turbine={ - 'hub_height': 100, - 'rotor_diameter': 70, - 'turbine_type': 'DUMMY 3', - 'path': self.source} - e_t_1=WindTurbine(**example_turbine) - with pytest.raises(ValueError, - match="The 'number' and the 'total_capacity' " - "parameter are mutually exclusive."): + example_turbine = { + "hub_height": 100, + "rotor_diameter": 70, + "turbine_type": "DUMMY 3", + "path": self.source, + } + e_t_1 = WindTurbine(**example_turbine) + with pytest.raises( + ValueError, + match="The 'number' and the 'total_capacity' " + "parameter are mutually exclusive.", + ): e_t_1.to_group(5, 3000) diff --git a/windpowerlib/__init__.py b/windpowerlib/__init__.py index 7ffd29ce..a206ff5a 100644 --- a/windpowerlib/__init__.py +++ b/windpowerlib/__init__.py @@ -1,6 +1,6 @@ -__copyright__="Copyright oemof developer group" -__license__="MIT" -__version__='0.2.1dev' +__copyright__ = "Copyright oemof developer group" +__license__ = "MIT" +__version__ = "0.2.1dev" from windpowerlib.wind_turbine import WindTurbine from windpowerlib.wind_farm import WindFarm diff --git a/windpowerlib/modelchain.py b/windpowerlib/modelchain.py index e137934a..d87b5ff5 100644 --- a/windpowerlib/modelchain.py +++ b/windpowerlib/modelchain.py @@ -134,24 +134,28 @@ class ModelChain(object): """ - def __init__(self, power_plant, - wind_speed_model='logarithmic', - temperature_model='linear_gradient', - density_model='barometric', - power_output_model='power_curve', - density_correction=False, - obstacle_height=0, - hellman_exp=None, **kwargs): - - self.power_plant=power_plant - self.obstacle_height=obstacle_height - self.wind_speed_model=wind_speed_model - self.temperature_model=temperature_model - self.density_model=density_model - self.power_output_model=power_output_model - self.density_correction=density_correction - self.hellman_exp=hellman_exp - self.power_output=None + def __init__( + self, + power_plant, + wind_speed_model="logarithmic", + temperature_model="linear_gradient", + density_model="barometric", + power_output_model="power_curve", + density_correction=False, + obstacle_height=0, + hellman_exp=None, + **kwargs, + ): + + self.power_plant = power_plant + self.obstacle_height = obstacle_height + self.wind_speed_model = wind_speed_model + self.temperature_model = temperature_model + self.density_model = density_model + self.power_output_model = power_output_model + self.density_correction = density_correction + self.hellman_exp = hellman_exp + self.power_output = None def temperature_hub(self, weather_df): r""" @@ -182,28 +186,42 @@ def temperature_hub(self, weather_df): temperature(s) closest to the hub height are used. """ - if self.power_plant.hub_height in weather_df['temperature']: - temperature_hub=weather_df['temperature'][ - self.power_plant.hub_height] - elif self.temperature_model == 'linear_gradient': - logging.debug('Calculating temperature using temperature ' - 'gradient.') - closest_height=weather_df['temperature'].columns[ - min(range(len(weather_df['temperature'].columns)), - key=lambda i: abs(weather_df['temperature'].columns[i] - - self.power_plant.hub_height))] - temperature_hub=temperature.linear_gradient( - weather_df['temperature'][closest_height], closest_height, - self.power_plant.hub_height) - elif self.temperature_model == 'interpolation_extrapolation': - logging.debug('Calculating temperature using linear inter- or ' - 'extrapolation.') - temperature_hub=tools.linear_interpolation_extrapolation( - weather_df['temperature'], self.power_plant.hub_height) + if self.power_plant.hub_height in weather_df["temperature"]: + temperature_hub = weather_df["temperature"][ + self.power_plant.hub_height + ] + elif self.temperature_model == "linear_gradient": + logging.debug( + "Calculating temperature using temperature " "gradient." + ) + closest_height = weather_df["temperature"].columns[ + min( + range(len(weather_df["temperature"].columns)), + key=lambda i: abs( + weather_df["temperature"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + temperature_hub = temperature.linear_gradient( + weather_df["temperature"][closest_height], + closest_height, + self.power_plant.hub_height, + ) + elif self.temperature_model == "interpolation_extrapolation": + logging.debug( + "Calculating temperature using linear inter- or " + "extrapolation." + ) + temperature_hub = tools.linear_interpolation_extrapolation( + weather_df["temperature"], self.power_plant.hub_height + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.temperature_model) + "`temperature_model` must be " - "'linear_gradient' or 'interpolation_extrapolation'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.temperature_model) + + "`temperature_model` must be " + "'linear_gradient' or 'interpolation_extrapolation'." + ) return temperature_hub def density_hub(self, weather_df): @@ -241,39 +259,60 @@ def density_hub(self, weather_df): hub height, the `weather_df` must contain at least two time series for density. """ - if self.density_model != 'interpolation_extrapolation': - temperature_hub=self.temperature_hub(weather_df) + if self.density_model != "interpolation_extrapolation": + temperature_hub = self.temperature_hub(weather_df) # Calculation of density in kg/m³ at hub height - if self.density_model == 'barometric': - logging.debug('Calculating density using barometric height ' - 'equation.') - closest_height=weather_df['pressure'].columns[ - min(range(len(weather_df['pressure'].columns)), - key=lambda i: abs(weather_df['pressure'].columns[i] - - self.power_plant.hub_height))] - density_hub=density.barometric( - weather_df['pressure'][closest_height], closest_height, - self.power_plant.hub_height, temperature_hub) - elif self.density_model == 'ideal_gas': - logging.debug('Calculating density using ideal gas equation.') - closest_height=weather_df['pressure'].columns[ - min(range(len(weather_df['pressure'].columns)), - key=lambda i: abs(weather_df['pressure'].columns[i] - - self.power_plant.hub_height))] - density_hub=density.ideal_gas( - weather_df['pressure'][closest_height], closest_height, - self.power_plant.hub_height, temperature_hub) - elif self.density_model == 'interpolation_extrapolation': - logging.debug('Calculating density using linear inter- or ' - 'extrapolation.') - density_hub=tools.linear_interpolation_extrapolation( - weather_df['density'], self.power_plant.hub_height) + if self.density_model == "barometric": + logging.debug( + "Calculating density using barometric height " "equation." + ) + closest_height = weather_df["pressure"].columns[ + min( + range(len(weather_df["pressure"].columns)), + key=lambda i: abs( + weather_df["pressure"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + density_hub = density.barometric( + weather_df["pressure"][closest_height], + closest_height, + self.power_plant.hub_height, + temperature_hub, + ) + elif self.density_model == "ideal_gas": + logging.debug("Calculating density using ideal gas equation.") + closest_height = weather_df["pressure"].columns[ + min( + range(len(weather_df["pressure"].columns)), + key=lambda i: abs( + weather_df["pressure"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + density_hub = density.ideal_gas( + weather_df["pressure"][closest_height], + closest_height, + self.power_plant.hub_height, + temperature_hub, + ) + elif self.density_model == "interpolation_extrapolation": + logging.debug( + "Calculating density using linear inter- or " "extrapolation." + ) + density_hub = tools.linear_interpolation_extrapolation( + weather_df["density"], self.power_plant.hub_height + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.density_model) + "`density_model` " + - "must be 'barometric', 'ideal_gas' or " + - "'interpolation_extrapolation'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.density_model) + + "`density_model` " + + "must be 'barometric', 'ideal_gas' or " + + "'interpolation_extrapolation'." + ) return density_hub def wind_speed_hub(self, weather_df): @@ -305,47 +344,71 @@ def wind_speed_hub(self, weather_df): wind speed(s) closest to the hub height are used. """ - if self.power_plant.hub_height in weather_df['wind_speed']: - wind_speed_hub=weather_df['wind_speed'][ - self.power_plant.hub_height] - elif self.wind_speed_model == 'logarithmic': - logging.debug('Calculating wind speed using logarithmic wind ' - 'profile.') - closest_height=weather_df['wind_speed'].columns[ - min(range(len(weather_df['wind_speed'].columns)), - key=lambda i: abs(weather_df['wind_speed'].columns[i] - - self.power_plant.hub_height))] - wind_speed_hub=wind_speed.logarithmic_profile( - weather_df['wind_speed'][closest_height], closest_height, + if self.power_plant.hub_height in weather_df["wind_speed"]: + wind_speed_hub = weather_df["wind_speed"][ + self.power_plant.hub_height + ] + elif self.wind_speed_model == "logarithmic": + logging.debug( + "Calculating wind speed using logarithmic wind " "profile." + ) + closest_height = weather_df["wind_speed"].columns[ + min( + range(len(weather_df["wind_speed"].columns)), + key=lambda i: abs( + weather_df["wind_speed"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + wind_speed_hub = wind_speed.logarithmic_profile( + weather_df["wind_speed"][closest_height], + closest_height, self.power_plant.hub_height, - weather_df['roughness_length'].iloc[:, 0], - self.obstacle_height) - elif self.wind_speed_model == 'hellman': - logging.debug('Calculating wind speed using hellman equation.') - closest_height=weather_df['wind_speed'].columns[ - min(range(len(weather_df['wind_speed'].columns)), - key=lambda i: abs(weather_df['wind_speed'].columns[i] - - self.power_plant.hub_height))] - wind_speed_hub=wind_speed.hellman( - weather_df['wind_speed'][closest_height], closest_height, + weather_df["roughness_length"].iloc[:, 0], + self.obstacle_height, + ) + elif self.wind_speed_model == "hellman": + logging.debug("Calculating wind speed using hellman equation.") + closest_height = weather_df["wind_speed"].columns[ + min( + range(len(weather_df["wind_speed"].columns)), + key=lambda i: abs( + weather_df["wind_speed"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + wind_speed_hub = wind_speed.hellman( + weather_df["wind_speed"][closest_height], + closest_height, self.power_plant.hub_height, - weather_df['roughness_length'].iloc[:, 0], - self.hellman_exp) - elif self.wind_speed_model == 'interpolation_extrapolation': - logging.debug('Calculating wind speed using linear inter- or ' - 'extrapolation.') - wind_speed_hub=tools.linear_interpolation_extrapolation( - weather_df['wind_speed'], self.power_plant.hub_height) - elif self.wind_speed_model == 'log_interpolation_extrapolation': - logging.debug('Calculating wind speed using logarithmic inter- or ' - 'extrapolation.') - wind_speed_hub=tools.logarithmic_interpolation_extrapolation( - weather_df['wind_speed'], self.power_plant.hub_height) + weather_df["roughness_length"].iloc[:, 0], + self.hellman_exp, + ) + elif self.wind_speed_model == "interpolation_extrapolation": + logging.debug( + "Calculating wind speed using linear inter- or " + "extrapolation." + ) + wind_speed_hub = tools.linear_interpolation_extrapolation( + weather_df["wind_speed"], self.power_plant.hub_height + ) + elif self.wind_speed_model == "log_interpolation_extrapolation": + logging.debug( + "Calculating wind speed using logarithmic inter- or " + "extrapolation." + ) + wind_speed_hub = tools.logarithmic_interpolation_extrapolation( + weather_df["wind_speed"], self.power_plant.hub_height + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.wind_speed_model) + "`wind_speed_model` must be " - "'logarithmic', 'hellman', 'interpolation_extrapolation' " + - "or 'log_interpolation_extrapolation'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.wind_speed_model) + + "`wind_speed_model` must be " + "'logarithmic', 'hellman', 'interpolation_extrapolation' " + + "or 'log_interpolation_extrapolation'." + ) return wind_speed_hub def calculate_power_output(self, wind_speed_hub, density_hub): @@ -367,34 +430,43 @@ def calculate_power_output(self, wind_speed_hub, density_hub): Electrical power output of the wind turbine in W. """ - if self.power_output_model == 'power_curve': + if self.power_output_model == "power_curve": if self.power_plant.power_curve is None: - raise TypeError("Power curve values of {} are missing.".format( - self.power_plant)) - logging.debug('Calculating power output using power curve.') - return (power_output.power_curve( - wind_speed_hub, - self.power_plant.power_curve['wind_speed'], - self.power_plant.power_curve['value'], - density_hub, self.density_correction)) - elif self.power_output_model == 'power_coefficient_curve': + raise TypeError( + "Power curve values of {} are missing.".format( + self.power_plant + ) + ) + logging.debug("Calculating power output using power curve.") + return power_output.power_curve( + wind_speed_hub, + self.power_plant.power_curve["wind_speed"], + self.power_plant.power_curve["value"], + density_hub, + self.density_correction, + ) + elif self.power_output_model == "power_coefficient_curve": if self.power_plant.power_coefficient_curve is None: - raise TypeError("Power coefficient curve values of {} are " - "missing.".format(self.power_plant)) - logging.debug('Calculating power output using power coefficient ' - 'curve.') - return (power_output.power_coefficient_curve( - wind_speed_hub, - self.power_plant.power_coefficient_curve[ - 'wind_speed'], - self.power_plant.power_coefficient_curve[ - 'value'], - self.power_plant.rotor_diameter, density_hub)) + raise TypeError( + "Power coefficient curve values of {} are " + "missing.".format(self.power_plant) + ) + logging.debug( + "Calculating power output using power coefficient " "curve." + ) + return power_output.power_coefficient_curve( + wind_speed_hub, + self.power_plant.power_coefficient_curve["wind_speed"], + self.power_plant.power_coefficient_curve["value"], + self.power_plant.rotor_diameter, + density_hub, + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.power_output_model) + - "`power_output_model` must be " + - "'power_curve' or 'power_coefficient_curve'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.power_output_model) + + "`power_output_model` must be " + + "'power_curve' or 'power_coefficient_curve'." + ) def run_model(self, weather_df): r""" @@ -438,10 +510,16 @@ def run_model(self, weather_df): 'wind_speed' """ - wind_speed_hub=self.wind_speed_hub(weather_df) - density_hub=(None if (self.power_output_model == 'power_curve' and - self.density_correction is False) - else self.density_hub(weather_df)) - self.power_output=self.calculate_power_output(wind_speed_hub, - density_hub) + wind_speed_hub = self.wind_speed_hub(weather_df) + density_hub = ( + None + if ( + self.power_output_model == "power_curve" + and self.density_correction is False + ) + else self.density_hub(weather_df) + ) + self.power_output = self.calculate_power_output( + wind_speed_hub, density_hub + ) return self diff --git a/windpowerlib/power_curves.py b/windpowerlib/power_curves.py index 0aa6acaf..ef9eb138 100644 --- a/windpowerlib/power_curves.py +++ b/windpowerlib/power_curves.py @@ -110,70 +110,98 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, """ # Specify normalized standard deviation - if standard_deviation_method == 'turbulence_intensity': - if ('turbulence_intensity' in kwargs and - kwargs['turbulence_intensity'] is not np.nan): - normalized_standard_deviation=kwargs['turbulence_intensity'] + if standard_deviation_method == "turbulence_intensity": + if ( + "turbulence_intensity" in kwargs + and kwargs["turbulence_intensity"] is not np.nan + ): + normalized_standard_deviation = kwargs["turbulence_intensity"] else: - raise ValueError("Turbulence intensity must be defined for " + - "using 'turbulence_intensity' as " + - "`standard_deviation_method`") - elif standard_deviation_method == 'Staffell_Pfenninger': - normalized_standard_deviation=0.2 + raise ValueError( + "Turbulence intensity must be defined for " + + "using 'turbulence_intensity' as " + + "`standard_deviation_method`" + ) + elif standard_deviation_method == "Staffell_Pfenninger": + normalized_standard_deviation = 0.2 else: - raise ValueError("{} is no valid `standard_deviation_method`. Valid " - + "options are 'turbulence_intensity', or " - + "'Staffell_Pfenninger'".format( - standard_deviation_method)) + raise ValueError( + "{} is no valid `standard_deviation_method`. Valid " + + "options are 'turbulence_intensity', or " + + "'Staffell_Pfenninger'".format(standard_deviation_method) + ) # Initialize list for power curve values - smoothed_power_curve_values=[] + smoothed_power_curve_values = [] # Append wind speeds to `power_curve_wind_speeds` - maximum_value=power_curve_wind_speeds.iloc[-1] + wind_speed_range + maximum_value = power_curve_wind_speeds.iloc[-1] + wind_speed_range while power_curve_wind_speeds.values[-1] < maximum_value: - power_curve_wind_speeds=power_curve_wind_speeds.append( - pd.Series(power_curve_wind_speeds.iloc[-1] + - (power_curve_wind_speeds.iloc[5] - - power_curve_wind_speeds.iloc[4]), - index=[power_curve_wind_speeds.index[-1] + 1])) - power_curve_values=power_curve_values.append( - pd.Series(0.0, index=[power_curve_values.index[-1] + 1])) + power_curve_wind_speeds = power_curve_wind_speeds.append( + pd.Series( + power_curve_wind_speeds.iloc[-1] + + ( + power_curve_wind_speeds.iloc[5] + - power_curve_wind_speeds.iloc[4] + ), + index=[power_curve_wind_speeds.index[-1] + 1], + ) + ) + power_curve_values = power_curve_values.append( + pd.Series(0.0, index=[power_curve_values.index[-1] + 1]) + ) for power_curve_wind_speed in power_curve_wind_speeds: # Create array of wind speeds for the sum - wind_speeds_block=(np.arange( - -wind_speed_range, wind_speed_range + block_width, block_width) + - power_curve_wind_speed) + wind_speeds_block = ( + np.arange( + -wind_speed_range, wind_speed_range + block_width, block_width + ) + + power_curve_wind_speed + ) # Get standard deviation for Gauss function - standard_deviation=( + standard_deviation = ( (power_curve_wind_speed * normalized_standard_deviation + 0.6) - if standard_deviation_method is 'Staffell_Pfenninger' - else power_curve_wind_speed * normalized_standard_deviation) + if standard_deviation_method is "Staffell_Pfenninger" + else power_curve_wind_speed * normalized_standard_deviation + ) # Get the smoothed value of the power output if standard_deviation == 0.0: # The gaussian distribution is not defined for a standard deviation # of zero. Smoothed power curve value is set to zero. - smoothed_value=0.0 + smoothed_value = 0.0 else: - smoothed_value=sum( - block_width * np.interp(wind_speed, power_curve_wind_speeds, - power_curve_values, left=0, right=0) * - tools.gauss_distribution( + smoothed_value = sum( + block_width + * np.interp( + wind_speed, + power_curve_wind_speeds, + power_curve_values, + left=0, + right=0, + ) + * tools.gauss_distribution( power_curve_wind_speed - wind_speed, - standard_deviation, mean_gauss) - for wind_speed in wind_speeds_block) + standard_deviation, + mean_gauss, + ) + for wind_speed in wind_speeds_block + ) # Add value to list - add zero if `smoothed_value` is nan as Gauss # distribution for a standard deviation of zero. smoothed_power_curve_values.append(smoothed_value) # Create smoothed power curve data frame - smoothed_power_curve_df=pd.DataFrame( - data=[list(power_curve_wind_speeds.values), - smoothed_power_curve_values]).transpose() + smoothed_power_curve_df = pd.DataFrame( + data=[ + list(power_curve_wind_speeds.values), + smoothed_power_curve_values, + ] + ).transpose() # Rename columns of the data frame - smoothed_power_curve_df.columns=['wind_speed', 'value'] + smoothed_power_curve_df.columns = ["wind_speed", "value"] return smoothed_power_curve_df -def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values, - wind_farm_efficiency): +def wake_losses_to_power_curve( + power_curve_wind_speeds, power_curve_values, wind_farm_efficiency +): r""" Reduces the power values of a power curve by an efficiency (curve). @@ -200,27 +228,36 @@ def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values, """ # Create power curve DataFrame - power_curve_df=pd.DataFrame( - data=[list(power_curve_wind_speeds), - list(power_curve_values)]).transpose() + power_curve_df = pd.DataFrame( + data=[list(power_curve_wind_speeds), list(power_curve_values)] + ).transpose() # Rename columns of DataFrame - power_curve_df.columns=['wind_speed', 'value'] + power_curve_df.columns = ["wind_speed", "value"] if isinstance(wind_farm_efficiency, float): - power_curve_df['value']=power_curve_values * wind_farm_efficiency - elif (isinstance(wind_farm_efficiency, dict) or - isinstance(wind_farm_efficiency, pd.DataFrame)): - df=pd.concat([power_curve_df.set_index('wind_speed'), - wind_farm_efficiency.set_index('wind_speed')], axis=1) + power_curve_df["value"] = power_curve_values * wind_farm_efficiency + elif isinstance(wind_farm_efficiency, dict) or isinstance( + wind_farm_efficiency, pd.DataFrame + ): + df = pd.concat( + [ + power_curve_df.set_index("wind_speed"), + wind_farm_efficiency.set_index("wind_speed"), + ], + axis=1, + ) # Add column with reduced power (nan values of efficiency are # interpolated) - df['reduced_power']=df['value'] * df['efficiency'].interpolate( - method='index') - reduced_power=df['reduced_power'].dropna() - power_curve_df=pd.DataFrame([reduced_power.index, - reduced_power.values]).transpose() - power_curve_df.columns=['wind_speed', 'value'] + df["reduced_power"] = df["value"] * df["efficiency"].interpolate( + method="index" + ) + reduced_power = df["reduced_power"].dropna() + power_curve_df = pd.DataFrame( + [reduced_power.index, reduced_power.values] + ).transpose() + power_curve_df.columns = ["wind_speed", "value"] else: raise TypeError( "'wind_farm_efficiency' must be float, dict or pd.DataFrame " - "but is {}".format(type(wind_farm_efficiency))) + "but is {}".format(type(wind_farm_efficiency)) + ) return power_curve_df diff --git a/windpowerlib/power_output.py b/windpowerlib/power_output.py index ba446e6a..a9554020 100644 --- a/windpowerlib/power_output.py +++ b/windpowerlib/power_output.py @@ -63,23 +63,41 @@ def power_coefficient_curve(wind_speed, power_coefficient_curve_wind_speeds, Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 542 """ - power_coefficient_time_series=np.interp( - wind_speed, power_coefficient_curve_wind_speeds, - power_coefficient_curve_values, left=0, right=0) - power_output=(1 / 8 * density * rotor_diameter ** 2 * np.pi * - np.power(wind_speed, 3) * - power_coefficient_time_series) + power_coefficient_time_series = np.interp( + wind_speed, + power_coefficient_curve_wind_speeds, + power_coefficient_curve_values, + left=0, + right=0, + ) + power_output = ( + 1 + / 8 + * density + * rotor_diameter ** 2 + * np.pi + * np.power(wind_speed, 3) + * power_coefficient_time_series + ) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output=pd.Series(data=power_output, index=wind_speed.index, - name='feedin_power_plant') + power_output = pd.Series( + data=power_output, + index=wind_speed.index, + name="feedin_power_plant", + ) else: - power_output=np.array(power_output) + power_output = np.array(power_output) return power_output -def power_curve(wind_speed, power_curve_wind_speeds, power_curve_values, - density=None, density_correction=False): +def power_curve( + wind_speed, + power_curve_wind_speeds, + power_curve_values, + density=None, + density_correction=False, +): r""" Calculates the turbine power output using a power curve. @@ -120,26 +138,38 @@ def power_curve(wind_speed, power_curve_wind_speeds, power_curve_values, """ if density_correction is False: - power_output=np.interp(wind_speed, power_curve_wind_speeds, - power_curve_values, left=0, right=0) + power_output = np.interp( + wind_speed, + power_curve_wind_speeds, + power_curve_values, + left=0, + right=0, + ) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output=pd.Series(data=power_output, index=wind_speed.index, - name='feedin_power_plant') + power_output = pd.Series( + data=power_output, + index=wind_speed.index, + name="feedin_power_plant", + ) else: - power_output=np.array(power_output) + power_output = np.array(power_output) elif density_correction is True: - power_output=power_curve_density_correction( - wind_speed, power_curve_wind_speeds, power_curve_values, density) + power_output = power_curve_density_correction( + wind_speed, power_curve_wind_speeds, power_curve_values, density + ) else: - raise TypeError("'{0}' is an invalid type. ".format(type( - density_correction)) + "`density_correction` must " + - "be Boolean (True or False).") + raise TypeError( + "'{0}' is an invalid type. ".format(type(density_correction)) + + "`density_correction` must " + + "be Boolean (True or False)." + ) return power_output -def power_curve_density_correction(wind_speed, power_curve_wind_speeds, - power_curve_values, density): +def power_curve_density_correction( + wind_speed, power_curve_wind_speeds, power_curve_values, density +): r""" Calculates the turbine power output using a density corrected power curve. diff --git a/windpowerlib/tools.py b/windpowerlib/tools.py index 3d4c593c..faab0202 100644 --- a/windpowerlib/tools.py +++ b/windpowerlib/tools.py @@ -78,12 +78,15 @@ def linear_interpolation_extrapolation(df, target_height): """ # find closest heights - heights_sorted=df.columns[ - sorted(range(len(df.columns)), - key=lambda i: abs(df.columns[i] - target_height))] - return ((df[heights_sorted[1]] - df[heights_sorted[0]]) / - (heights_sorted[1] - heights_sorted[0]) * - (target_height - heights_sorted[0]) + df[heights_sorted[0]]) + heights_sorted = df.columns[ + sorted( + range(len(df.columns)), + key=lambda i: abs(df.columns[i] - target_height), + ) + ] + return (df[heights_sorted[1]] - df[heights_sorted[0]]) / ( + heights_sorted[1] - heights_sorted[0] + ) * (target_height - heights_sorted[0]) + df[heights_sorted[0]] def logarithmic_interpolation_extrapolation(df, target_height): @@ -132,14 +135,17 @@ def logarithmic_interpolation_extrapolation(df, target_height): """ # find closest heights - heights_sorted=df.columns[ - sorted(range(len(df.columns)), - key=lambda i: abs(df.columns[i] - target_height))] - return ((np.log(target_height) * - (df[heights_sorted[1]] - df[heights_sorted[0]]) - - df[heights_sorted[1]] * np.log(heights_sorted[0]) + - df[heights_sorted[0]] * np.log(heights_sorted[1])) / - (np.log(heights_sorted[1]) - np.log(heights_sorted[0]))) + heights_sorted = df.columns[ + sorted( + range(len(df.columns)), + key=lambda i: abs(df.columns[i] - target_height), + ) + ] + return ( + np.log(target_height) * (df[heights_sorted[1]] - df[heights_sorted[0]]) + - df[heights_sorted[1]] * np.log(heights_sorted[0]) + + df[heights_sorted[0]] * np.log(heights_sorted[1]) + ) / (np.log(heights_sorted[1]) - np.log(heights_sorted[0])) def gauss_distribution(function_variable, standard_deviation, mean=0): diff --git a/windpowerlib/turbine_cluster_modelchain.py b/windpowerlib/turbine_cluster_modelchain.py index 4d978d3a..ed113b81 100644 --- a/windpowerlib/turbine_cluster_modelchain.py +++ b/windpowerlib/turbine_cluster_modelchain.py @@ -142,21 +142,28 @@ class TurbineClusterModelChain(ModelChain): Used to set `hellman_exponent` in :func:`~.wind_speed.hellman`. """ - def __init__(self, power_plant, wake_losses_model='dena_mean', - smoothing=False, block_width=0.5, - standard_deviation_method='turbulence_intensity', - smoothing_order='wind_farm_power_curves', **kwargs): + + def __init__( + self, + power_plant, + wake_losses_model="dena_mean", + smoothing=False, + block_width=0.5, + standard_deviation_method="turbulence_intensity", + smoothing_order="wind_farm_power_curves", + **kwargs, + ): super(TurbineClusterModelChain, self).__init__(power_plant, **kwargs) - self.power_plant=power_plant - self.wake_losses_model=wake_losses_model - self.smoothing=smoothing - self.block_width=block_width - self.standard_deviation_method=standard_deviation_method - self.smoothing_order=smoothing_order + self.power_plant = power_plant + self.wake_losses_model = wake_losses_model + self.smoothing = smoothing + self.block_width = block_width + self.standard_deviation_method = standard_deviation_method + self.smoothing_order = smoothing_order - self.power_curve=None - self.power_output=None + self.power_curve = None + self.power_output = None def assign_power_curve(self, weather_df): r""" @@ -186,40 +193,55 @@ def assign_power_curve(self, weather_df): """ # Get turbulence intensity from weather if existent - turbulence_intensity=( - weather_df['turbulence_intensity'].values.mean() if - 'turbulence_intensity' in - weather_df.columns.get_level_values(0) else None) - roughness_length=( - weather_df['roughness_length'].values.mean() if - 'roughness_length' in weather_df.columns.get_level_values(0) else - None) + turbulence_intensity = ( + weather_df["turbulence_intensity"].values.mean() + if "turbulence_intensity" in weather_df.columns.get_level_values(0) + else None + ) + roughness_length = ( + weather_df["roughness_length"].values.mean() + if "roughness_length" in weather_df.columns.get_level_values(0) + else None + ) # Assign power curve - if (self.wake_losses_model == 'wind_farm_efficiency' or - self.wake_losses_model is None): - wake_losses_model_to_power_curve=self.wake_losses_model + if ( + self.wake_losses_model == "wind_farm_efficiency" + or self.wake_losses_model is None + ): + wake_losses_model_to_power_curve = self.wake_losses_model if self.wake_losses_model is None: - logging.debug('Wake losses in wind farms are not considered.') + logging.debug("Wake losses in wind farms are not considered.") else: - logging.debug('Wake losses considered with {}.'.format( - self.wake_losses_model)) + logging.debug( + "Wake losses considered with {}.".format( + self.wake_losses_model + ) + ) else: - logging.debug('Wake losses considered by {} wind '.format( - self.wake_losses_model) + 'efficiency curve.') - wake_losses_model_to_power_curve=None + logging.debug( + "Wake losses considered by {} wind ".format( + self.wake_losses_model + ) + + "efficiency curve." + ) + wake_losses_model_to_power_curve = None self.power_plant.assign_power_curve( wake_losses_model=wake_losses_model_to_power_curve, - smoothing=self.smoothing, block_width=self.block_width, + smoothing=self.smoothing, + block_width=self.block_width, standard_deviation_method=self.standard_deviation_method, smoothing_order=self.smoothing_order, roughness_length=roughness_length, - turbulence_intensity=turbulence_intensity) + turbulence_intensity=turbulence_intensity, + ) # Further logging messages if self.smoothing is False: - logging.debug('Aggregated power curve not smoothed.') + logging.debug("Aggregated power curve not smoothed.") else: - logging.debug('Aggregated power curve smoothed by method: ' + - self.standard_deviation_method) + logging.debug( + "Aggregated power curve smoothed by method: " + + self.standard_deviation_method + ) return self @@ -269,16 +291,25 @@ def run_model(self, weather_df): self.assign_power_curve(weather_df) self.power_plant.mean_hub_height() - wind_speed_hub=self.wind_speed_hub(weather_df) - density_hub=(None if (self.power_output_model == 'power_curve' and - self.density_correction is False) - else self.density_hub(weather_df)) - if (self.wake_losses_model != 'wind_farm_efficiency' and - self.wake_losses_model is not None): + wind_speed_hub = self.wind_speed_hub(weather_df) + density_hub = ( + None + if ( + self.power_output_model == "power_curve" + and self.density_correction is False + ) + else self.density_hub(weather_df) + ) + if ( + self.wake_losses_model != "wind_farm_efficiency" + and self.wake_losses_model is not None + ): # Reduce wind speed with wind efficiency curve - wind_speed_hub=wake_losses.reduce_wind_speed( + wind_speed_hub = wake_losses.reduce_wind_speed( wind_speed_hub, - wind_efficiency_curve_name=self.wake_losses_model) - self.power_output=self.calculate_power_output(wind_speed_hub, - density_hub) + wind_efficiency_curve_name=self.wake_losses_model, + ) + self.power_output = self.calculate_power_output( + wind_speed_hub, density_hub + ) return self diff --git a/windpowerlib/wake_losses.py b/windpowerlib/wake_losses.py index 59d0ea37..77e46834 100644 --- a/windpowerlib/wake_losses.py +++ b/windpowerlib/wake_losses.py @@ -45,16 +45,19 @@ def reduce_wind_speed(wind_speed, wind_efficiency_curve_name='dena_mean'): """ # Get wind efficiency curve - wind_efficiency_curve=get_wind_efficiency_curve( - curve_name=wind_efficiency_curve_name) + wind_efficiency_curve = get_wind_efficiency_curve( + curve_name=wind_efficiency_curve_name + ) # Reduce wind speed by wind efficiency - reduced_wind_speed=wind_speed * np.interp( - wind_speed, wind_efficiency_curve['wind_speed'], - wind_efficiency_curve['efficiency']) + reduced_wind_speed = wind_speed * np.interp( + wind_speed, + wind_efficiency_curve["wind_speed"], + wind_efficiency_curve["efficiency"], + ) return reduced_wind_speed -def get_wind_efficiency_curve(curve_name='all'): +def get_wind_efficiency_curve(curve_name="all"): r""" Reads wind efficiency curve(s) specified in `curve_name`. @@ -107,45 +110,59 @@ def get_wind_efficiency_curve(curve_name='all'): plt.show() """ - possible_curve_names=['dena_mean', 'knorr_mean', 'dena_extreme1', - 'dena_extreme2', 'knorr_extreme1', - 'knorr_extreme2', 'knorr_extreme3'] - - if curve_name == 'all': - curve_names=possible_curve_names + possible_curve_names = [ + "dena_mean", + "knorr_mean", + "dena_extreme1", + "dena_extreme2", + "knorr_extreme1", + "knorr_extreme2", + "knorr_extreme3", + ] + + if curve_name == "all": + curve_names = possible_curve_names elif isinstance(curve_name, str): - curve_names=[curve_name] + curve_names = [curve_name] else: - curve_names=curve_name + curve_names = curve_name - efficiency_curve=pd.DataFrame() + efficiency_curve = pd.DataFrame() for curve_name in curve_names: - if curve_name.split('_')[0] not in ['dena', 'knorr']: - raise ValueError("`curve_name` must be one of the following: " + - "{} but is {}".format(possible_curve_names, - curve_name)) - path=os.path.join(os.path.dirname(__file__), 'data', - 'wind_efficiency_curves_{}.csv'.format( - curve_name.split('_')[0])) + if curve_name.split("_")[0] not in ["dena", "knorr"]: + raise ValueError( + "`curve_name` must be one of the following: " + + "{} but is {}".format(possible_curve_names, curve_name) + ) + path = os.path.join( + os.path.dirname(__file__), + "data", + "wind_efficiency_curves_{}.csv".format(curve_name.split("_")[0]), + ) # Read wind efficiency curves from file - wind_efficiency_curves=pd.read_csv(path) + wind_efficiency_curves = pd.read_csv(path) # Raise error if wind efficiency curve specified in 'curve_name' does # not exist if curve_name not in list(wind_efficiency_curves): - msg=("Efficiency curve <{0}> does not exist. Must be one of the " - "following: {1}.") + msg = ( + "Efficiency curve <{0}> does not exist. Must be one of the " + "following: {1}." + ) raise ValueError(msg.format(curve_name, *possible_curve_names)) # Get wind efficiency curve and rename column containing efficiency - wec=wind_efficiency_curves[['wind_speed', curve_name]] + wec = wind_efficiency_curves[["wind_speed", curve_name]] if efficiency_curve.empty: - efficiency_curve=pd.DataFrame( - {(curve_name, 'wind_speed'): wec['wind_speed'], - (curve_name, 'efficiency'): wec[curve_name]}) + efficiency_curve = pd.DataFrame( + { + (curve_name, "wind_speed"): wec["wind_speed"], + (curve_name, "efficiency"): wec[curve_name], + } + ) else: - efficiency_curve[(curve_name, 'wind_speed')]=wec['wind_speed'] - efficiency_curve[(curve_name, 'efficiency')]=wec[curve_name] + efficiency_curve[(curve_name, "wind_speed")] = wec["wind_speed"] + efficiency_curve[(curve_name, "efficiency")] = wec[curve_name] if len(curve_names) == 1: return efficiency_curve[curve_names[0]] else: diff --git a/windpowerlib/wind_farm.py b/windpowerlib/wind_farm.py index 8df8c2b8..97f085dd 100644 --- a/windpowerlib/wind_farm.py +++ b/windpowerlib/wind_farm.py @@ -113,15 +113,15 @@ class WindFarm(object): 31200000.0 """ - def __init__(self, wind_turbine_fleet, efficiency=None, name='', **kwargs): + def __init__(self, wind_turbine_fleet, efficiency=None, name="", **kwargs): - self.wind_turbine_fleet=wind_turbine_fleet - self.efficiency=efficiency - self.name=name + self.wind_turbine_fleet = wind_turbine_fleet + self.efficiency = efficiency + self.name = name - self.hub_height=None - self._nominal_power=None - self.power_curve=None + self.hub_height = None + self._nominal_power = None + self.power_curve = None self.check_and_complete_wind_turbine_fleet() @@ -137,80 +137,104 @@ def check_and_complete_wind_turbine_fleet(self): """ # convert list to dataframe if necessary if isinstance(self.wind_turbine_fleet, list): - self.wind_turbine_fleet=pd.DataFrame(self.wind_turbine_fleet) + self.wind_turbine_fleet = pd.DataFrame(self.wind_turbine_fleet) # check wind turbines try: - for turbine in self.wind_turbine_fleet['wind_turbine']: + for turbine in self.wind_turbine_fleet["wind_turbine"]: if not isinstance(turbine, WindTurbine): raise ValueError( - 'Wind turbine must be provided as WindTurbine object ' - 'but was provided as {}.'.format(type(turbine))) + "Wind turbine must be provided as WindTurbine object " + "but was provided as {}.".format(type(turbine)) + ) except KeyError: - raise KeyError('Missing wind_turbine key/column in ' - 'wind_turbine_fleet parameter.') + raise KeyError( + "Missing wind_turbine key/column in " + "wind_turbine_fleet parameter." + ) # add columns for number of turbines and total capacity if they don't # yet exist - if 'number_of_turbines' not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet['number_of_turbines']=np.nan - if 'total_capacity' not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet['total_capacity']=np.nan + if "number_of_turbines" not in self.wind_turbine_fleet.columns: + self.wind_turbine_fleet["number_of_turbines"] = np.nan + if "total_capacity" not in self.wind_turbine_fleet.columns: + self.wind_turbine_fleet["total_capacity"] = np.nan # calculate number of turbines if necessary - number_turbines_not_provided=self.wind_turbine_fleet[ - self.wind_turbine_fleet['number_of_turbines'].isnull()] + number_turbines_not_provided = self.wind_turbine_fleet[ + self.wind_turbine_fleet["number_of_turbines"].isnull() + ] for ix, row in number_turbines_not_provided.iterrows(): - msg='Number of turbines of type {0} can not be deduced ' \ - 'from total capacity. Please either provide ' \ - '`number_of_turbines` in the turbine fleet definition or ' \ - 'set the nominal power of the wind turbine.' + msg = ( + "Number of turbines of type {0} can not be deduced " + "from total capacity. Please either provide " + "`number_of_turbines` in the turbine fleet definition or " + "set the nominal power of the wind turbine." + ) try: - number_of_turbines=row['total_capacity'] / \ - row['wind_turbine'].nominal_power + number_of_turbines = ( + row["total_capacity"] / row["wind_turbine"].nominal_power + ) if np.isnan(number_of_turbines): - raise ValueError(msg.format(row['wind_turbine'])) + raise ValueError(msg.format(row["wind_turbine"])) else: - self.wind_turbine_fleet.loc[ix, 'number_of_turbines']=\ - number_of_turbines + self.wind_turbine_fleet.loc[ + ix, "number_of_turbines" + ] = number_of_turbines except TypeError: - raise ValueError(msg.format(row['wind_turbine'])) + raise ValueError(msg.format(row["wind_turbine"])) # calculate total capacity if necessary and check that total capacity # and number of turbines is consistent if both are provided for ix, row in self.wind_turbine_fleet.iterrows(): - if np.isnan(row['total_capacity']): + if np.isnan(row["total_capacity"]): try: - self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ - row['number_of_turbines'] * \ - row['wind_turbine'].nominal_power + self.wind_turbine_fleet.loc[ix, "total_capacity"] = ( + row["number_of_turbines"] + * row["wind_turbine"].nominal_power + ) except TypeError: raise ValueError( - 'Total capacity of turbines of type {turbine} cannot ' - 'be deduced. Please check if the nominal power of the ' - 'wind turbine is set.'.format( - turbine=row['wind_turbine'])) + "Total capacity of turbines of type {turbine} cannot " + "be deduced. Please check if the nominal power of the " + "wind turbine is set.".format( + turbine=row["wind_turbine"] + ) + ) else: - if not abs(row['total_capacity'] - ( - row['number_of_turbines'] * - row['wind_turbine'].nominal_power)) < 1: - self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ - row['number_of_turbines'] * \ - row['wind_turbine'].nominal_power - msg=( - 'The provided total capacity of WindTurbine {0} has ' - 'been overwritten as it was not consistent with the ' - 'number of turbines provided for this type.') - warnings.warn(msg.format(row['wind_turbine']), - tools.WindpowerlibUserWarning) + if ( + not abs( + row["total_capacity"] + - ( + row["number_of_turbines"] + * row["wind_turbine"].nominal_power + ) + ) + < 1 + ): + self.wind_turbine_fleet.loc[ix, "total_capacity"] = ( + row["number_of_turbines"] + * row["wind_turbine"].nominal_power + ) + msg = ( + "The provided total capacity of WindTurbine {0} has " + "been overwritten as it was not consistent with the " + "number of turbines provided for this type." + ) + warnings.warn( + msg.format(row["wind_turbine"]), + tools.WindpowerlibUserWarning, + ) def __repr__(self): - if self.name is not '': - return 'Wind farm: {name}'.format(name=self.name) + if self.name is not "": + return "Wind farm: {name}".format(name=self.name) else: - return 'Wind farm with turbine fleet: [number, type]\n {}'.format( + return "Wind farm with turbine fleet: [number, type]\n {}".format( self.wind_turbine_fleet.loc[ - :, ['number_of_turbines', 'wind_turbine']].values) + :, ["number_of_turbines", "wind_turbine"] + ].values + ) @property def nominal_power(self): @@ -224,12 +248,12 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power=self.wind_turbine_fleet.total_capacity.sum() + self.nominal_power = self.wind_turbine_fleet.total_capacity.sum() return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power=nominal_power + self._nominal_power = nominal_power def mean_hub_height(self): r""" @@ -267,17 +291,25 @@ def mean_hub_height(self): p. 35 """ - self.hub_height=np.exp( - sum(np.log(row['wind_turbine'].hub_height) * row['total_capacity'] - for ix, row in self.wind_turbine_fleet.iterrows()) / - self.nominal_power) + self.hub_height = np.exp( + sum( + np.log(row["wind_turbine"].hub_height) * row["total_capacity"] + for ix, row in self.wind_turbine_fleet.iterrows() + ) + / self.nominal_power + ) return self - def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', - smoothing=False, block_width=0.5, - standard_deviation_method='turbulence_intensity', - smoothing_order='wind_farm_power_curves', - turbulence_intensity=None, **kwargs): + def assign_power_curve( + self, + wake_losses_model="wind_farm_efficiency", + smoothing=False, + block_width=0.5, + standard_deviation_method="turbulence_intensity", + smoothing_order="wind_farm_power_curves", + turbulence_intensity=None, + **kwargs, + ): r""" Calculates the power curve of a wind farm. @@ -327,83 +359,123 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', """ # Check if all wind turbines have a power curve as attribute - for turbine in self.wind_turbine_fleet['wind_turbine']: + for turbine in self.wind_turbine_fleet["wind_turbine"]: if turbine.power_curve is None: - raise ValueError("For an aggregated wind farm power curve " + - "each wind turbine needs a power curve " + - "but `power_curve` of '{}' is None.".format( - turbine)) + raise ValueError( + "For an aggregated wind farm power curve " + + "each wind turbine needs a power curve " + + "but `power_curve` of '{}' is None.".format(turbine) + ) # Initialize data frame for power curve values - df=pd.DataFrame() + df = pd.DataFrame() for ix, row in self.wind_turbine_fleet.iterrows(): # Check if needed parameters are available and/or assign them if smoothing: - if (standard_deviation_method == 'turbulence_intensity' and - turbulence_intensity is None): - if 'roughness_length' in kwargs and \ - kwargs['roughness_length'] is not None: + if ( + standard_deviation_method == "turbulence_intensity" + and turbulence_intensity is None + ): + if ( + "roughness_length" in kwargs + and kwargs["roughness_length"] is not None + ): # Calculate turbulence intensity and write to kwargs - turbulence_intensity=( - tools.estimate_turbulence_intensity( - row['wind_turbine'].hub_height, - kwargs['roughness_length'])) - kwargs['turbulence_intensity']=turbulence_intensity + turbulence_intensity = tools.estimate_turbulence_intensity( + row["wind_turbine"].hub_height, + kwargs["roughness_length"], + ) + kwargs["turbulence_intensity"] = turbulence_intensity else: raise ValueError( - "`roughness_length` must be defined for using " + - "'turbulence_intensity' as " + - "`standard_deviation_method` if " + - "`turbulence_intensity` is not given") + "`roughness_length` must be defined for using " + + "'turbulence_intensity' as " + + "`standard_deviation_method` if " + + "`turbulence_intensity` is not given" + ) # Get original power curve - power_curve=pd.DataFrame(row['wind_turbine'].power_curve) + power_curve = pd.DataFrame(row["wind_turbine"].power_curve) # Editions to the power curves before the summation - if smoothing and smoothing_order == 'turbine_power_curves': - power_curve=power_curves.smooth_power_curve( - power_curve['wind_speed'], power_curve['value'], + if smoothing and smoothing_order == "turbine_power_curves": + power_curve = power_curves.smooth_power_curve( + power_curve["wind_speed"], + power_curve["value"], standard_deviation_method=standard_deviation_method, - block_width=block_width, **kwargs) + block_width=block_width, + **kwargs, + ) else: # Add value zero to start and end of curve as otherwise # problems can occur during the aggregation - if power_curve.iloc[0]['wind_speed'] != 0.0: - power_curve=pd.concat( - [pd.DataFrame(data={ - 'value': [0.0], 'wind_speed': [0.0]}), - power_curve], join='inner') - if power_curve.iloc[-1]['value'] != 0.0: - power_curve=pd.concat( - [power_curve, pd.DataFrame(data={ - 'wind_speed': [power_curve['wind_speed'].loc[ - power_curve.index[-1]] + 0.5], - 'value': [0.0]})], join='inner') + if power_curve.iloc[0]["wind_speed"] != 0.0: + power_curve = pd.concat( + [ + pd.DataFrame( + data={"value": [0.0], "wind_speed": [0.0]} + ), + power_curve, + ], + join="inner", + ) + if power_curve.iloc[-1]["value"] != 0.0: + power_curve = pd.concat( + [ + power_curve, + pd.DataFrame( + data={ + "wind_speed": [ + power_curve["wind_speed"].loc[ + power_curve.index[-1] + ] + + 0.5 + ], + "value": [0.0], + } + ), + ], + join="inner", + ) # Add power curves of all turbine types to data frame # (multiplied by turbine amount) - df=pd.concat( - [df, pd.DataFrame(power_curve.set_index(['wind_speed']) * - row['number_of_turbines'])], axis=1) + df = pd.concat( + [ + df, + pd.DataFrame( + power_curve.set_index(["wind_speed"]) + * row["number_of_turbines"] + ), + ], + axis=1, + ) # Aggregate all power curves - wind_farm_power_curve=pd.DataFrame( - df.interpolate(method='index').sum(axis=1)) - wind_farm_power_curve.columns=['value'] + wind_farm_power_curve = pd.DataFrame( + df.interpolate(method="index").sum(axis=1) + ) + wind_farm_power_curve.columns = ["value"] wind_farm_power_curve.reset_index(inplace=True) # Apply power curve smoothing and consideration of wake losses # after the summation - if smoothing and smoothing_order == 'wind_farm_power_curves': - wind_farm_power_curve=power_curves.smooth_power_curve( - wind_farm_power_curve['wind_speed'], - wind_farm_power_curve['value'], + if smoothing and smoothing_order == "wind_farm_power_curves": + wind_farm_power_curve = power_curves.smooth_power_curve( + wind_farm_power_curve["wind_speed"], + wind_farm_power_curve["value"], standard_deviation_method=standard_deviation_method, - block_width=block_width, **kwargs) - if wake_losses_model == 'wind_farm_efficiency': + block_width=block_width, + **kwargs, + ) + if wake_losses_model == "wind_farm_efficiency": if self.efficiency is not None: - wind_farm_power_curve=( - power_curves.wake_losses_to_power_curve( - wind_farm_power_curve['wind_speed'].values, - wind_farm_power_curve['value'].values, - wind_farm_efficiency=self.efficiency)) + wind_farm_power_curve = power_curves.wake_losses_to_power_curve( + wind_farm_power_curve["wind_speed"].values, + wind_farm_power_curve["value"].values, + wind_farm_efficiency=self.efficiency, + ) else: - logging.info("`wake_losses_model` is {} but wind farm ".format( - wake_losses_model) + "efficiency is NOT taken into " - "account as it is None.") - self.power_curve=wind_farm_power_curve + logging.info( + "`wake_losses_model` is {} but wind farm ".format( + wake_losses_model + ) + + "efficiency is NOT taken into " + "account as it is None." + ) + self.power_curve = wind_farm_power_curve return self diff --git a/windpowerlib/wind_speed.py b/windpowerlib/wind_speed.py index 60882805..7a1189a5 100644 --- a/windpowerlib/wind_speed.py +++ b/windpowerlib/wind_speed.py @@ -73,22 +73,33 @@ def logarithmic_profile(wind_speed, wind_speed_height, hub_height, """ if 0.7 * obstacle_height > wind_speed_height: - raise ValueError("To take an obstacle height of {0} m ".format( - obstacle_height) + "into consideration, wind " + - "speed data of a greater height is needed.") + raise ValueError( + "To take an obstacle height of {0} m ".format(obstacle_height) + + "into consideration, wind " + + "speed data of a greater height is needed." + ) # Return np.array if wind_speed is np.array - if (isinstance(wind_speed, np.ndarray) and - isinstance(roughness_length, pd.Series)): - roughness_length=np.array(roughness_length) - - return (wind_speed * np.log((hub_height - 0.7 * obstacle_height) / - roughness_length) / - np.log((wind_speed_height - 0.7 * obstacle_height) / - roughness_length)) - - -def hellman(wind_speed, wind_speed_height, hub_height, - roughness_length=None, hellman_exponent=None): + if isinstance(wind_speed, np.ndarray) and isinstance( + roughness_length, pd.Series + ): + roughness_length = np.array(roughness_length) + + return ( + wind_speed + * np.log((hub_height - 0.7 * obstacle_height) / roughness_length) + / np.log( + (wind_speed_height - 0.7 * obstacle_height) / roughness_length + ) + ) + + +def hellman( + wind_speed, + wind_speed_height, + hub_height, + roughness_length=None, + hellman_exponent=None, +): r""" Calculates the wind speed at hub height using the hellman equation. diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index b1ac7fa2..4e2a6af0 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -114,107 +114,131 @@ class WindTurbine(object): 1500000.0 """ - def __init__(self, hub_height, nominal_power=None, path='oedb', - power_curve=None, power_coefficient_curve=None, - rotor_diameter=None, turbine_type=None, **kwargs): - - self.hub_height=hub_height - self.turbine_type=turbine_type - self.rotor_diameter=rotor_diameter - self.nominal_power=nominal_power - self.power_curve=power_curve - self.power_coefficient_curve=power_coefficient_curve - - if path == 'oedb': - path=os.path.join(os.path.dirname(__file__), 'oedb') + def __init__( + self, + hub_height, + nominal_power=None, + path="oedb", + power_curve=None, + power_coefficient_curve=None, + rotor_diameter=None, + turbine_type=None, + **kwargs, + ): + + self.hub_height = hub_height + self.turbine_type = turbine_type + self.rotor_diameter = rotor_diameter + self.nominal_power = nominal_power + self.power_curve = power_curve + self.power_coefficient_curve = power_coefficient_curve + + if path == "oedb": + path = os.path.join(os.path.dirname(__file__), "oedb") if turbine_type is not None and path is not None: if power_curve is None: try: - fn=os.path.join(path, 'power_curves.csv') - self.power_curve=get_turbine_data_from_file( - self.turbine_type, fn) + fn = os.path.join(path, "power_curves.csv") + self.power_curve = get_turbine_data_from_file( + self.turbine_type, fn + ) except KeyError: - msg="No power curve found for {0}" + msg = "No power curve found for {0}" logging.debug(msg.format(self.turbine_type)) if power_coefficient_curve is None: try: - fn=os.path.join(path, 'power_coefficient_curves.csv') - self.power_coefficient_curve=get_turbine_data_from_file( - self.turbine_type, fn) + fn = os.path.join(path, "power_coefficient_curves.csv") + self.power_coefficient_curve = get_turbine_data_from_file( + self.turbine_type, fn + ) except KeyError: - msg="No power coefficient curve found for {0}" + msg = "No power coefficient curve found for {0}" logging.debug(msg.format(self.turbine_type)) if nominal_power is None or ( - rotor_diameter is None and - self.power_coefficient_curve is not None): - turbine_data=None + rotor_diameter is None + and self.power_coefficient_curve is not None + ): + turbine_data = None try: - fn=os.path.join(path, 'turbine_data.csv') - turbine_data=get_turbine_data_from_file( - self.turbine_type, fn) + fn = os.path.join(path, "turbine_data.csv") + turbine_data = get_turbine_data_from_file( + self.turbine_type, fn + ) except KeyError: - msg="No turbine data found for {0}" + msg = "No turbine data found for {0}" logging.debug(msg.format(self.turbine_type)) if self.nominal_power is None and turbine_data is not None: - self.nominal_power=float(turbine_data['nominal_power']) + self.nominal_power = float(turbine_data["nominal_power"]) if self.rotor_diameter is None and turbine_data is not None: - self.rotor_diameter=float(turbine_data['rotor_diameter']) + self.rotor_diameter = float(turbine_data["rotor_diameter"]) if self.power_curve is None and self.power_coefficient_curve is None: - msg=("The WindTurbine has been initialised without a power curve" - " and without a power coefficient curve.\nYou will not be" - " able to calculate the power output.\n" - " Check if the turbine type {0} is in your database file" - " or if you passed a valid curve.") + msg = ( + "The WindTurbine has been initialised without a power curve" + " and without a power coefficient curve.\nYou will not be" + " able to calculate the power output.\n" + " Check if the turbine type {0} is in your database file" + " or if you passed a valid curve." + ) warnings.warn(msg.format(turbine_type), WindpowerlibUserWarning) else: # power (coefficient) curve to pd.DataFrame in case of being dict if isinstance(self.power_curve, dict): - self.power_curve=pd.DataFrame(self.power_curve) + self.power_curve = pd.DataFrame(self.power_curve) if isinstance(self.power_coefficient_curve, dict): - self.power_coefficient_curve=pd.DataFrame( - self.power_coefficient_curve) + self.power_coefficient_curve = pd.DataFrame( + self.power_coefficient_curve + ) # sort power (coefficient) curve by wind speed if isinstance(self.power_curve, pd.DataFrame): - self.power_curve.sort_values(by='wind_speed') + self.power_curve.sort_values(by="wind_speed") elif self.power_curve is not None: - msg="Type of power curve of {} is {} but should be " \ - "pd.DataFrame or dict." - raise TypeError(msg.format(self.__repr__(), - type(self.power_curve))) + msg = ( + "Type of power curve of {} is {} but should be " + "pd.DataFrame or dict." + ) + raise TypeError( + msg.format(self.__repr__(), type(self.power_curve)) + ) if isinstance(self.power_coefficient_curve, pd.DataFrame): - self.power_coefficient_curve.sort_values(by='wind_speed') + self.power_coefficient_curve.sort_values(by="wind_speed") elif self.power_coefficient_curve is not None: - msg="Type of power coefficient curve of {} is {} but " \ - "should be pd.DataFrame or dict." - raise TypeError(msg.format(self.__repr__(), - type(self.power_coefficient_curve))) + msg = ( + "Type of power coefficient curve of {} is {} but " + "should be pd.DataFrame or dict." + ) + raise TypeError( + msg.format( + self.__repr__(), type(self.power_coefficient_curve) + ) + ) def __repr__(self): - info=[] + info = [] if self.nominal_power is not None: - info.append('nominal power={} W'.format(self.nominal_power)) + info.append("nominal power={} W".format(self.nominal_power)) if self.hub_height is not None: - info.append('hub height={} m'.format(self.hub_height)) + info.append("hub height={} m".format(self.hub_height)) if self.rotor_diameter is not None: - info.append('rotor diameter={} m'.format(self.rotor_diameter)) + info.append("rotor diameter={} m".format(self.rotor_diameter)) if self.power_coefficient_curve is not None: - info.append('power_coefficient_curve={}'.format('True')) + info.append("power_coefficient_curve={}".format("True")) else: - info.append('power_coefficient_curve={}'.format('False')) + info.append("power_coefficient_curve={}".format("False")) if self.power_curve is not None: - info.append('power_curve={}'.format('True')) + info.append("power_curve={}".format("True")) else: - info.append('power_curve={}'.format('False')) + info.append("power_curve={}".format("False")) if self.turbine_type is not None: - turbine_repr='Wind turbine: {name} {info}'.format( - name=self.turbine_type, info=info) + turbine_repr = "Wind turbine: {name} {info}".format( + name=self.turbine_type, info=info + ) else: - turbine_repr='Wind turbine: {info}'.format(info=info) + turbine_repr = "Wind turbine: {info}".format(info=info) return turbine_repr @@ -271,22 +295,29 @@ def to_group(self, number_turbines=None, total_capacity=None): """ if number_turbines is not None and total_capacity is not None: - raise ValueError("The 'number' and the 'total_capacity' parameter " - "are mutually exclusive. Use just one of them.") + raise ValueError( + "The 'number' and the 'total_capacity' parameter " + "are mutually exclusive. Use just one of them." + ) elif total_capacity is not None: - number_turbines=total_capacity / self.nominal_power + number_turbines = total_capacity / self.nominal_power elif number_turbines is None: - number_turbines=1 + number_turbines = 1 return WindTurbineGroup( - wind_turbine=self, number_of_turbines=number_turbines) + wind_turbine=self, number_of_turbines=number_turbines + ) # This is working for Python >= 3.5. # There a cleaner solutions for Python >= 3.6, once the support of 3.5 is # dropped: https://stackoverflow.com/a/50038614 -class WindTurbineGroup(NamedTuple('WindTurbineGroup', [ - ('wind_turbine', WindTurbine), ('number_of_turbines', float)])): +class WindTurbineGroup( + NamedTuple( + "WindTurbineGroup", + [("wind_turbine", WindTurbine), ("number_of_turbines", float)], + ) +): """ A simple data container to define more than one turbine of the same type. Use the :func:`~windpowerlib.wind_turbine.WindTurbine.to_group` method to @@ -300,13 +331,16 @@ class WindTurbineGroup(NamedTuple('WindTurbineGroup', [ 'number_of_turbines' : float The number of turbines. The number is not restricted to integer values. """ - __slots__=() + + __slots__ = () -WindTurbineGroup.wind_turbine.__doc__=( - 'A :class:`~windpowerlib.wind_farm.WindTurbine` object.') -WindTurbineGroup.number_of_turbines.__doc__=( - 'Number of turbines of type WindTurbine') +WindTurbineGroup.wind_turbine.__doc__ = ( + "A :class:`~windpowerlib.wind_farm.WindTurbine` object." +) +WindTurbineGroup.number_of_turbines.__doc__ = ( + "Number of turbines of type WindTurbine" +) def get_turbine_data_from_file(turbine_type, path): @@ -349,28 +383,28 @@ def get_turbine_data_from_file(turbine_type, path): """ try: - df=pd.read_csv(path, index_col=0) + df = pd.read_csv(path, index_col=0) except FileNotFoundError: raise FileNotFoundError("The file '{}' was not found.".format(path)) - wpp_df=df[df.index == turbine_type].copy() + wpp_df = df[df.index == turbine_type].copy() # if turbine not in data file if wpp_df.shape[0] == 0: - msg="Wind converter type {0} not provided. Possible types: {1}" + msg = "Wind converter type {0} not provided. Possible types: {1}" raise KeyError(msg.format(turbine_type, list(df.index))) # if turbine in data file # get nominal power or power (coefficient) curve - if 'turbine_data' in path: + if "turbine_data" in path: return wpp_df else: wpp_df.dropna(axis=1, inplace=True) - wpp_df=wpp_df.transpose().reset_index() - wpp_df.columns=['wind_speed', 'value'] + wpp_df = wpp_df.transpose().reset_index() + wpp_df.columns = ["wind_speed", "value"] # transform wind speeds to floats - wpp_df['wind_speed']=wpp_df['wind_speed'].apply(lambda x: float(x)) + wpp_df["wind_speed"] = wpp_df["wind_speed"].apply(lambda x: float(x)) return wpp_df -def load_turbine_data_from_oedb(schema='supply', table='wind_turbine_library'): +def load_turbine_data_from_oedb(schema="supply", table="wind_turbine_library"): r""" Loads turbine library from the OpenEnergy database (oedb). @@ -393,58 +427,82 @@ def load_turbine_data_from_oedb(schema='supply', table='wind_turbine_library'): """ # url of OpenEnergy Platform that contains the oedb - oep_url='http://oep.iks.cs.ovgu.de/' + oep_url = "http://oep.iks.cs.ovgu.de/" # load data - result=requests.get( - oep_url + '/api/v0/schema/{}/tables/{}/rows/?'.format( - schema, table), ) + result = requests.get( + oep_url + "/api/v0/schema/{}/tables/{}/rows/?".format(schema, table), + ) if not result.status_code == 200: - raise ConnectionError("Database connection not successful. " - "Response: [{}]".format(result.status_code)) + raise ConnectionError( + "Database connection not successful. " + "Response: [{}]".format(result.status_code) + ) # extract data to dataframe - turbine_data=pd.DataFrame(result.json()) + turbine_data = pd.DataFrame(result.json()) # standard file name for saving data - filename=os.path.join(os.path.dirname(__file__), 'oedb', - '{}.csv') + filename = os.path.join(os.path.dirname(__file__), "oedb", "{}.csv") # get all power (coefficient) curves and save to file # for curve_type in ['power_curve', 'power_coefficient_curve']: - for curve_type in ['power_curve', 'power_coefficient_curve']: - curves_df=pd.DataFrame(columns=['wind_speed']) + for curve_type in ["power_curve", "power_coefficient_curve"]: + curves_df = pd.DataFrame(columns=["wind_speed"]) for index in turbine_data.index: - if (turbine_data['{}_wind_speeds'.format(curve_type)][index] - and turbine_data['{}_values'.format(curve_type)][index]): - df=pd.DataFrame(data=[ - eval(turbine_data['{}_wind_speeds'.format(curve_type)][ - index]), - eval(turbine_data['{}_values'.format(curve_type)][ - index])]).transpose().rename( - columns={0: 'wind_speed', - 1: turbine_data['turbine_type'][index]}) - curves_df=pd.merge(left=curves_df, right=df, how='outer', - on='wind_speed') - curves_df=curves_df.set_index('wind_speed').sort_index().transpose() + if ( + turbine_data["{}_wind_speeds".format(curve_type)][index] + and turbine_data["{}_values".format(curve_type)][index] + ): + df = ( + pd.DataFrame( + data=[ + eval( + turbine_data[ + "{}_wind_speeds".format(curve_type) + ][index] + ), + eval( + turbine_data["{}_values".format(curve_type)][ + index + ] + ), + ] + ) + .transpose() + .rename( + columns={ + 0: "wind_speed", + 1: turbine_data["turbine_type"][index], + } + ) + ) + curves_df = pd.merge( + left=curves_df, right=df, how="outer", on="wind_speed" + ) + curves_df = curves_df.set_index("wind_speed").sort_index().transpose() # power curve values in W - if curve_type == 'power_curve': + if curve_type == "power_curve": curves_df *= 1000 - curves_df.index.name='turbine_type' - curves_df.to_csv(filename.format('{}s'.format(curve_type))) + curves_df.index.name = "turbine_type" + curves_df.to_csv(filename.format("{}s".format(curve_type))) # get turbine data and save to file (excl. curves) - turbine_data_df=turbine_data.drop( - ['power_curve_wind_speeds', 'power_curve_values', - 'power_coefficient_curve_wind_speeds', - 'power_coefficient_curve_values', - 'thrust_coefficient_curve_wind_speeds', - 'thrust_coefficient_curve_values'], axis=1).set_index('turbine_type') + turbine_data_df = turbine_data.drop( + [ + "power_curve_wind_speeds", + "power_curve_values", + "power_coefficient_curve_wind_speeds", + "power_coefficient_curve_values", + "thrust_coefficient_curve_wind_speeds", + "thrust_coefficient_curve_values", + ], + axis=1, + ).set_index("turbine_type") # nominal power in W - turbine_data_df['nominal_power']=turbine_data_df[ - 'nominal_power'] * 1000 - turbine_data_df.to_csv(filename.format('turbine_data')) + turbine_data_df["nominal_power"] = turbine_data_df["nominal_power"] * 1000 + turbine_data_df.to_csv(filename.format("turbine_data")) return turbine_data -def get_turbine_types(turbine_library='local', print_out=True, filter_=True): +def get_turbine_types(turbine_library="local", print_out=True, filter_=True): r""" Get all provided wind turbine types provided. @@ -506,26 +564,34 @@ def get_turbine_types(turbine_library='local', print_out=True, filter_=True): Name: 1, dtype: object """ - if turbine_library == 'local': - filename=os.path.join(os.path.dirname(__file__), 'oedb', 'turbine_data.csv') - df=pd.read_csv(filename, index_col=0).reset_index() - elif turbine_library == 'oedb': - df=load_turbine_data_from_oedb() + if turbine_library == "local": + filename = os.path.join( + os.path.dirname(__file__), "oedb", "turbine_data.csv" + ) + df = pd.read_csv(filename, index_col=0).reset_index() + elif turbine_library == "oedb": + df = load_turbine_data_from_oedb() else: - raise ValueError("`turbine_library` is '{}' ".format(turbine_library) + - "but must be 'local' or 'oedb'.") + raise ValueError( + "`turbine_library` is '{}' ".format(turbine_library) + + "but must be 'local' or 'oedb'." + ) if filter_: - cp_curves_df=df.loc[df['has_cp_curve']][ - ['manufacturer', 'turbine_type', 'has_cp_curve']] - p_curves_df=df.loc[df['has_power_curve']][ - ['manufacturer', 'turbine_type', 'has_power_curve']] - curves_df=pd.merge(p_curves_df, cp_curves_df, how='outer', - sort=True).fillna(False) + cp_curves_df = df.loc[df["has_cp_curve"]][ + ["manufacturer", "turbine_type", "has_cp_curve"] + ] + p_curves_df = df.loc[df["has_power_curve"]][ + ["manufacturer", "turbine_type", "has_power_curve"] + ] + curves_df = pd.merge( + p_curves_df, cp_curves_df, how="outer", sort=True + ).fillna(False) else: - curves_df=df[['manufacturer', 'turbine_type', 'has_power_curve', - 'has_cp_curve']] + curves_df = df[ + ["manufacturer", "turbine_type", "has_power_curve", "has_cp_curve"] + ] if print_out: - pd.set_option('display.max_rows', len(curves_df)) + pd.set_option("display.max_rows", len(curves_df)) print(curves_df) - pd.reset_option('display.max_rows') + pd.reset_option("display.max_rows") return curves_df diff --git a/windpowerlib/wind_turbine_cluster.py b/windpowerlib/wind_turbine_cluster.py index bb2d2f79..32f10bab 100644 --- a/windpowerlib/wind_turbine_cluster.py +++ b/windpowerlib/wind_turbine_cluster.py @@ -37,23 +37,24 @@ class WindTurbineCluster(object): :py:func:`assign_power_curve` for more information. """ - def __init__(self, wind_farms, name='', **kwargs): - self.wind_farms=wind_farms - self.name=name + def __init__(self, wind_farms, name="", **kwargs): - self.hub_height=None - self._nominal_power=None - self.power_curve=None + self.wind_farms = wind_farms + self.name = name + + self.hub_height = None + self._nominal_power = None + self.power_curve = None def __repr__(self): - if self.name is not '': - wf_repr='Wind turbine cluster: {name}'.format(name=self.name) + if self.name is not "": + wf_repr = "Wind turbine cluster: {name}".format(name=self.name) else: - info=[] + info = [] for wind_farm in self.wind_farms: info.append(wind_farm) - wf_repr=r'Wind turbine cluster with: {info}'.format(info=info) + wf_repr = r"Wind turbine cluster with: {info}".format(info=info) return wf_repr @property @@ -69,13 +70,14 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power=sum(wind_farm.nominal_power - for wind_farm in self.wind_farms) + self.nominal_power = sum( + wind_farm.nominal_power for wind_farm in self.wind_farms + ) return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power=nominal_power + self._nominal_power = nominal_power def mean_hub_height(self): r""" @@ -113,16 +115,25 @@ def mean_hub_height(self): p. 35 """ - self.hub_height=np.exp(sum( - np.log(wind_farm.hub_height) * wind_farm.nominal_power for - wind_farm in self.wind_farms) / self.nominal_power) + self.hub_height = np.exp( + sum( + np.log(wind_farm.hub_height) * wind_farm.nominal_power + for wind_farm in self.wind_farms + ) + / self.nominal_power + ) return self - def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', - smoothing=False, block_width=0.5, - standard_deviation_method='turbulence_intensity', - smoothing_order='wind_farm_power_curves', - turbulence_intensity=None, **kwargs): + def assign_power_curve( + self, + wake_losses_model="wind_farm_efficiency", + smoothing=False, + block_width=0.5, + standard_deviation_method="turbulence_intensity", + smoothing_order="wind_farm_power_curves", + turbulence_intensity=None, + **kwargs, + ): r""" Calculates the power curve of a wind turbine cluster. @@ -180,20 +191,31 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', # Assign wind farm power curve farm.assign_power_curve( wake_losses_model=wake_losses_model, - smoothing=smoothing, block_width=block_width, + smoothing=smoothing, + block_width=block_width, standard_deviation_method=standard_deviation_method, smoothing_order=smoothing_order, - turbulence_intensity=turbulence_intensity, **kwargs) + turbulence_intensity=turbulence_intensity, + **kwargs, + ) # Create data frame from power curves of all wind farms - df=pd.concat([farm.power_curve.set_index(['wind_speed']).rename( - columns={'value': i}) for - farm, i in zip(self.wind_farms, - list(range(len(self.wind_farms))))], axis=1) + df = pd.concat( + [ + farm.power_curve.set_index(["wind_speed"]).rename( + columns={"value": i} + ) + for farm, i in zip( + self.wind_farms, list(range(len(self.wind_farms))) + ) + ], + axis=1, + ) # Sum up power curves - cluster_power_curve=pd.DataFrame( - df.interpolate(method='index').sum(axis=1)) - cluster_power_curve.columns=['value'] + cluster_power_curve = pd.DataFrame( + df.interpolate(method="index").sum(axis=1) + ) + cluster_power_curve.columns = ["value"] # Return wind speed (index) to a column of the data frame cluster_power_curve.reset_index(inplace=True) - self.power_curve=cluster_power_curve + self.power_curve = cluster_power_curve return self From 92f589a95598b76737b52f3d758654aa69ab70f4 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 12 Dec 2019 15:11:07 +0000 Subject: [PATCH 10/16] Fixing style errors. --- windpowerlib/power_output.py | 39 +++++++++++++++++++++++++++--------- windpowerlib/wind_speed.py | 11 +++++----- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/windpowerlib/power_output.py b/windpowerlib/power_output.py index a9554020..4db874b9 100644 --- a/windpowerlib/power_output.py +++ b/windpowerlib/power_output.py @@ -237,18 +237,37 @@ def power_curve_density_correction( """ if density is None: - raise TypeError("`density` is None. For the calculation with a " + - "density corrected power curve density at hub " + - "height is needed.") - power_output=[(np.interp( - wind_speed[i], power_curve_wind_speeds * (1.225 / density[i]) ** ( - np.interp(power_curve_wind_speeds, [7.5, 12.5], [1/3, 2/3])), - power_curve_values, left=0, right=0)) for i in range(len(wind_speed))] + raise TypeError( + "`density` is None. For the calculation with a " + + "density corrected power curve density at hub " + + "height is needed." + ) + power_output = [ + ( + np.interp( + wind_speed[i], + power_curve_wind_speeds + * (1.225 / density[i]) + ** ( + np.interp( + power_curve_wind_speeds, [7.5, 12.5], [1 / 3, 2 / 3] + ) + ), + power_curve_values, + left=0, + right=0, + ) + ) + for i in range(len(wind_speed)) + ] # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output=pd.Series(data=power_output, index=wind_speed.index, - name='feedin_power_plant') + power_output = pd.Series( + data=power_output, + index=wind_speed.index, + name="feedin_power_plant", + ) else: - power_output=np.array(power_output) + power_output = np.array(power_output) return power_output diff --git a/windpowerlib/wind_speed.py b/windpowerlib/wind_speed.py index 7a1189a5..c620dd43 100644 --- a/windpowerlib/wind_speed.py +++ b/windpowerlib/wind_speed.py @@ -171,10 +171,11 @@ def hellman( if hellman_exponent is None: if roughness_length is not None: # Return np.array if wind_speed is np.array - if (isinstance(wind_speed, np.ndarray) and - isinstance(roughness_length, pd.Series)): - roughness_length=np.array(roughness_length) - hellman_exponent=1 / np.log(hub_height / roughness_length) + if isinstance(wind_speed, np.ndarray) and isinstance( + roughness_length, pd.Series + ): + roughness_length = np.array(roughness_length) + hellman_exponent = 1 / np.log(hub_height / roughness_length) else: - hellman_exponent=1/7 + hellman_exponent = 1 / 7 return wind_speed * (hub_height / wind_speed_height) ** hellman_exponent From 9563bd87a5cbbfb2bbe1948e305089664546813f Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:17:54 +0100 Subject: [PATCH 11/16] Make lint happy --- windpowerlib/wind_farm.py | 2 +- windpowerlib/wind_turbine_cluster.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/windpowerlib/wind_farm.py b/windpowerlib/wind_farm.py index 97f085dd..d8432939 100644 --- a/windpowerlib/wind_farm.py +++ b/windpowerlib/wind_farm.py @@ -227,7 +227,7 @@ def check_and_complete_wind_turbine_fleet(self): ) def __repr__(self): - if self.name is not "": + if self.name != "": return "Wind farm: {name}".format(name=self.name) else: return "Wind farm with turbine fleet: [number, type]\n {}".format( diff --git a/windpowerlib/wind_turbine_cluster.py b/windpowerlib/wind_turbine_cluster.py index 32f10bab..3610f9c2 100644 --- a/windpowerlib/wind_turbine_cluster.py +++ b/windpowerlib/wind_turbine_cluster.py @@ -48,7 +48,7 @@ def __init__(self, wind_farms, name="", **kwargs): self.power_curve = None def __repr__(self): - if self.name is not "": + if self.name != "": wf_repr = "Wind turbine cluster: {name}".format(name=self.name) else: info = [] From 5d332339154a66af09eed617fbcca6476042dad6 Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:22:15 +0100 Subject: [PATCH 12/16] Revert "Fixing style errors." This reverts commit 92f589a95598b76737b52f3d758654aa69ab70f4. --- windpowerlib/power_output.py | 39 +++++++++--------------------------- windpowerlib/wind_speed.py | 11 +++++----- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/windpowerlib/power_output.py b/windpowerlib/power_output.py index 4db874b9..a9554020 100644 --- a/windpowerlib/power_output.py +++ b/windpowerlib/power_output.py @@ -237,37 +237,18 @@ def power_curve_density_correction( """ if density is None: - raise TypeError( - "`density` is None. For the calculation with a " - + "density corrected power curve density at hub " - + "height is needed." - ) - power_output = [ - ( - np.interp( - wind_speed[i], - power_curve_wind_speeds - * (1.225 / density[i]) - ** ( - np.interp( - power_curve_wind_speeds, [7.5, 12.5], [1 / 3, 2 / 3] - ) - ), - power_curve_values, - left=0, - right=0, - ) - ) - for i in range(len(wind_speed)) - ] + raise TypeError("`density` is None. For the calculation with a " + + "density corrected power curve density at hub " + + "height is needed.") + power_output=[(np.interp( + wind_speed[i], power_curve_wind_speeds * (1.225 / density[i]) ** ( + np.interp(power_curve_wind_speeds, [7.5, 12.5], [1/3, 2/3])), + power_curve_values, left=0, right=0)) for i in range(len(wind_speed))] # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output = pd.Series( - data=power_output, - index=wind_speed.index, - name="feedin_power_plant", - ) + power_output=pd.Series(data=power_output, index=wind_speed.index, + name='feedin_power_plant') else: - power_output = np.array(power_output) + power_output=np.array(power_output) return power_output diff --git a/windpowerlib/wind_speed.py b/windpowerlib/wind_speed.py index c620dd43..7a1189a5 100644 --- a/windpowerlib/wind_speed.py +++ b/windpowerlib/wind_speed.py @@ -171,11 +171,10 @@ def hellman( if hellman_exponent is None: if roughness_length is not None: # Return np.array if wind_speed is np.array - if isinstance(wind_speed, np.ndarray) and isinstance( - roughness_length, pd.Series - ): - roughness_length = np.array(roughness_length) - hellman_exponent = 1 / np.log(hub_height / roughness_length) + if (isinstance(wind_speed, np.ndarray) and + isinstance(roughness_length, pd.Series)): + roughness_length=np.array(roughness_length) + hellman_exponent=1 / np.log(hub_height / roughness_length) else: - hellman_exponent = 1 / 7 + hellman_exponent=1/7 return wind_speed * (hub_height / wind_speed_height) ** hellman_exponent From 37e68dff9ed62b7c7abfd54735025da61c26e8f6 Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:26:52 +0100 Subject: [PATCH 13/16] Revert "Fixing style errors." This reverts commit b5c3a1eb9f3ac36835dc61b58833745d1cc7734d. --- example/modelchain_example.py | 121 ++--- example/test_examples.py | 90 ++-- example/turbine_cluster_modelchain_example.py | 117 ++--- tests/test_density.py | 63 +-- tests/test_modelchain.py | 490 +++++++----------- tests/test_power_curves.py | 170 ++---- tests/test_power_output.py | 271 +++++----- tests/test_temperature.py | 21 +- tests/test_tools.py | 140 ++--- tests/test_turbine_cluster_modelchain.py | 434 +++++++--------- tests/test_wake_losses.py | 74 +-- tests/test_wind_farm.py | 230 ++++---- tests/test_wind_speed.py | 106 ++-- tests/test_wind_turbine.py | 107 ++-- windpowerlib/__init__.py | 6 +- windpowerlib/modelchain.py | 354 +++++-------- windpowerlib/power_curves.py | 151 ++---- windpowerlib/power_output.py | 76 +-- windpowerlib/tools.py | 34 +- windpowerlib/turbine_cluster_modelchain.py | 119 ++--- windpowerlib/wake_losses.py | 79 ++- windpowerlib/wind_farm.py | 312 +++++------ windpowerlib/wind_speed.py | 41 +- windpowerlib/wind_turbine.py | 330 +++++------- windpowerlib/wind_turbine_cluster.py | 84 ++- 25 files changed, 1595 insertions(+), 2425 deletions(-) diff --git a/example/modelchain_example.py b/example/modelchain_example.py index c4686e61..07149387 100644 --- a/example/modelchain_example.py +++ b/example/modelchain_example.py @@ -19,7 +19,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt = None + plt=None from windpowerlib import ModelChain from windpowerlib import WindTurbine @@ -64,29 +64,24 @@ def get_weather_data(filename='weather.csv', **kwargs): """ - if "datapath" not in kwargs: - kwargs["datapath"] = os.path.join( - os.path.split(os.path.dirname(__file__))[0], "example" - ) - file = os.path.join(kwargs["datapath"], filename) + if 'datapath' not in kwargs: + kwargs['datapath']=os.path.join(os.path.split( + os.path.dirname(__file__))[0], 'example') + file=os.path.join(kwargs['datapath'], filename) # read csv file - weather_df = pd.read_csv( - file, - index_col=0, - header=[0, 1], - date_parser=lambda idx: pd.to_datetime(idx, utc=True), - ) + weather_df=pd.read_csv( + file, index_col=0, header=[0, 1], + date_parser=lambda idx: pd.to_datetime(idx, utc=True)) # change type of index to datetime and set time zone - weather_df.index = pd.to_datetime(weather_df.index).tz_convert( - "Europe/Berlin" - ) + weather_df.index=pd.to_datetime(weather_df.index).tz_convert( + 'Europe/Berlin') # change type of height from str to int by resetting columns - l0 = [_[0] for _ in weather_df.columns] - l1 = [int(_[1]) for _ in weather_df.columns] - weather_df.columns = [l0, l1] + l0=[_[0] for _ in weather_df.columns] + l1=[int(_[1]) for _ in weather_df.columns] + weather_df.columns=[l0, l1] return weather_df @@ -116,42 +111,37 @@ def initialize_wind_turbines(): # specification of wind turbine where data is provided in the oedb # turbine library - enercon_e126 = { - "turbine_type": "E-126/4200", # turbine type as in register - "hub_height": 135, # in m + enercon_e126={ + 'turbine_type': 'E-126/4200', # turbine type as in register + 'hub_height': 135 # in m } # initialize WindTurbine object - e126 = WindTurbine(**enercon_e126) + e126=WindTurbine(**enercon_e126) # specification of own wind turbine (Note: power values and nominal power # have to be in Watt) - my_turbine = { - "nominal_power": 3e6, # in W - "hub_height": 105, # in m - "power_curve": pd.DataFrame( - data={ - "value": [ - p * 1000 - for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] - ], # in W - "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], - } - ), # in m/s + my_turbine={ + 'nominal_power': 3e6, # in W + 'hub_height': 105, # in m + 'power_curve': pd.DataFrame( + data={'value': [p * 1000 for p in [ + 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W + 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}) # in m/s } # initialize WindTurbine object - my_turbine = WindTurbine(**my_turbine) + my_turbine=WindTurbine(**my_turbine) # specification of wind turbine where power coefficient curve and nominal # power is provided in an own csv file - csv_path = os.path.join(os.path.dirname(__file__), "data") - dummy_turbine = { - "turbine_type": "DUMMY 1", - "hub_height": 100, # in m - "rotor_diameter": 70, # in m - "path": csv_path, + csv_path=os.path.join(os.path.dirname(__file__), 'data') + dummy_turbine={ + 'turbine_type': "DUMMY 1", + 'hub_height': 100, # in m + 'rotor_diameter': 70, # in m + 'path': csv_path } # initialize WindTurbine object - dummy_turbine = WindTurbine(**dummy_turbine) + dummy_turbine=WindTurbine(**dummy_turbine) return my_turbine, e126, dummy_turbine @@ -185,38 +175,37 @@ def calculate_power_output(weather, my_turbine, e126, dummy_turbine): # power output calculation for my_turbine # initialize ModelChain with default parameters and use run_model method # to calculate power output - mc_my_turbine = ModelChain(my_turbine).run_model(weather) + mc_my_turbine=ModelChain(my_turbine).run_model(weather) # write power output time series to WindTurbine object - my_turbine.power_output = mc_my_turbine.power_output + my_turbine.power_output=mc_my_turbine.power_output # power output calculation for e126 # own specifications for ModelChain setup - modelchain_data = { - "wind_speed_model": "logarithmic", # 'logarithmic' (default), - # 'hellman' or - # 'interpolation_extrapolation' - "density_model": "ideal_gas", # 'barometric' (default), 'ideal_gas' or - # 'interpolation_extrapolation' - "temperature_model": "linear_gradient", # 'linear_gradient' (def.) or - # 'interpolation_extrapolation' - "power_output_model": "power_curve", # 'power_curve' (default) or - # 'power_coefficient_curve' - "density_correction": True, # False (default) or True - "obstacle_height": 0, # default: 0 - "hellman_exp": None, - } # None (default) or None + modelchain_data={ + 'wind_speed_model': 'logarithmic', # 'logarithmic' (default), + # 'hellman' or + # 'interpolation_extrapolation' + 'density_model': 'ideal_gas', # 'barometric' (default), 'ideal_gas' or + # 'interpolation_extrapolation' + 'temperature_model': 'linear_gradient', # 'linear_gradient' (def.) or + # 'interpolation_extrapolation' + 'power_output_model': 'power_curve', # 'power_curve' (default) or + # 'power_coefficient_curve' + 'density_correction': True, # False (default) or True + 'obstacle_height': 0, # default: 0 + 'hellman_exp': None} # None (default) or None # initialize ModelChain with own specifications and use run_model method # to calculate power output - mc_e126 = ModelChain(e126, **modelchain_data).run_model(weather) + mc_e126=ModelChain(e126, **modelchain_data).run_model(weather) # write power output time series to WindTurbine object - e126.power_output = mc_e126.power_output + e126.power_output=mc_e126.power_output # power output calculation for example_turbine # own specification for 'power_output_model' - mc_example_turbine = ModelChain( - dummy_turbine, power_output_model="power_coefficient_curve" - ).run_model(weather) - dummy_turbine.power_output = mc_example_turbine.power_output + mc_example_turbine=ModelChain( + dummy_turbine, + power_output_model='power_coefficient_curve').run_model(weather) + dummy_turbine.power_output=mc_example_turbine.power_output return @@ -283,8 +272,8 @@ def run_example(): Runs the basic example. """ - weather = get_weather_data("weather.csv") - my_turbine, e126, dummy_turbine = initialize_wind_turbines() + weather=get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=initialize_wind_turbines() calculate_power_output(weather, my_turbine, e126, dummy_turbine) plot_or_print(my_turbine, e126, dummy_turbine) diff --git a/example/test_examples.py b/example/test_examples.py index afa612f4..aed5fd0c 100644 --- a/example/test_examples.py +++ b/example/test_examples.py @@ -15,92 +15,64 @@ class TestExamples: + def test_modelchain_example_flh(self): # tests full load hours - weather = mc_e.get_weather_data("weather.csv") - my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() + weather=mc_e.get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() mc_e.calculate_power_output(weather, my_turbine, e126, dummy_turbine) - assert_allclose( - 2764.194772, (e126.power_output.sum() / e126.nominal_power), 0.01 - ) - assert_allclose( - 1882.7567, - (my_turbine.power_output.sum() / my_turbine.nominal_power), - 0.01, - ) + assert_allclose(2764.194772, (e126.power_output.sum() / + e126.nominal_power), 0.01) + assert_allclose(1882.7567, (my_turbine.power_output.sum() / + my_turbine.nominal_power), 0.01) def test_turbine_cluster_modelchain_example_flh(self): # tests full load hours - weather = mc_e.get_weather_data("weather.csv") - my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() - example_farm, example_farm_2 = tc_mc_e.initialize_wind_farms( - my_turbine, e126 - ) - example_cluster = tc_mc_e.initialize_wind_turbine_cluster( - example_farm, example_farm_2 - ) + weather=mc_e.get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() + example_farm, example_farm_2=tc_mc_e.initialize_wind_farms( + my_turbine, e126) + example_cluster=tc_mc_e.initialize_wind_turbine_cluster( + example_farm, example_farm_2) tc_mc_e.calculate_power_output(weather, example_farm, example_cluster) - assert_allclose( - 1956.164053, - (example_farm.power_output.sum() / example_farm.nominal_power), - 0.01, - ) - assert_allclose( - 2156.794154, - ( - example_cluster.power_output.sum() - / example_cluster.nominal_power - ), - 0.01, - ) + assert_allclose(1956.164053, (example_farm.power_output.sum() / + example_farm.nominal_power), 0.01) + assert_allclose(2156.794154, (example_cluster.power_output.sum() / + example_cluster.nominal_power), 0.01) def _notebook_run(self, path): """ Execute a notebook via nbconvert and collect output. Returns (parsed nb object, execution errors) """ - dirname, __ = os.path.split(path) + dirname, __=os.path.split(path) os.chdir(dirname) with tempfile.NamedTemporaryFile(suffix=".ipynb") as fout: - args = [ - "jupyter", - "nbconvert", - "--to", - "notebook", - "--execute", - "--ExecutePreprocessor.timeout=60", - "--output", - fout.name, - path, - ] + args=["jupyter", "nbconvert", "--to", "notebook", "--execute", + "--ExecutePreprocessor.timeout=60", + "--output", fout.name, path] subprocess.check_call(args) fout.seek(0) - nb = nbformat.read(fout, nbformat.current_nbformat) + nb=nbformat.read(fout, nbformat.current_nbformat) - errors = [ - output - for cell in nb.cells - if "outputs" in cell - for output in cell["outputs"] - if output.output_type == "error" - ] + errors=[output for cell in nb.cells if "outputs" in cell + for output in cell["outputs"] + if output.output_type == "error"] return nb, errors @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_modelchain_example_ipynb(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - nb, errors = self._notebook_run( - os.path.join(dir_path, "modelchain_example.ipynb") - ) + dir_path=os.path.dirname(os.path.realpath(__file__)) + nb, errors=self._notebook_run( + os.path.join(dir_path, 'modelchain_example.ipynb')) assert errors == [] @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_turbine_cluster_modelchain_example_ipynb(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - nb, errors = self._notebook_run( - os.path.join(dir_path, "turbine_cluster_modelchain_example.ipynb") - ) + dir_path=os.path.dirname(os.path.realpath(__file__)) + nb, errors=self._notebook_run( + os.path.join(dir_path, 'turbine_cluster_modelchain_example.ipynb')) assert errors == [] diff --git a/example/turbine_cluster_modelchain_example.py b/example/turbine_cluster_modelchain_example.py index ea0584bd..9903dbf1 100644 --- a/example/turbine_cluster_modelchain_example.py +++ b/example/turbine_cluster_modelchain_example.py @@ -15,7 +15,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt = None + plt=None from example import modelchain_example as mc_e from windpowerlib import WindFarm @@ -58,30 +58,24 @@ def initialize_wind_farms(my_turbine, e126): # for each turbine type you can either specify the number of turbines of # that type in the wind farm (float values are possible as well) or the # total installed capacity of that turbine type in W - wind_turbine_fleet = pd.DataFrame( - { - "wind_turbine": [my_turbine, e126], # as windpowerlib.WindTurbine - "number_of_turbines": [6, None], - "total_capacity": [None, 12.6e6], - } + wind_turbine_fleet=pd.DataFrame( + {'wind_turbine': [my_turbine, e126], # as windpowerlib.WindTurbine + 'number_of_turbines': [6, None], + 'total_capacity': [None, 12.6e6]} ) # initialize WindFarm object - example_farm = WindFarm( - name="example_farm", wind_turbine_fleet=wind_turbine_fleet - ) + example_farm=WindFarm(name='example_farm', + wind_turbine_fleet=wind_turbine_fleet) # specification of wind farm data (2) containing a wind farm efficiency # wind turbine fleet is provided using the to_group function - example_farm_2_data = { - "name": "example_farm_2", - "wind_turbine_fleet": [ - my_turbine.to_group(6), - e126.to_group(total_capacity=12.6e6), - ], - "efficiency": 0.9, - } + example_farm_2_data={ + 'name': 'example_farm_2', + 'wind_turbine_fleet': [my_turbine.to_group(6), + e126.to_group(total_capacity=12.6e6)], + 'efficiency': 0.9} # initialize WindFarm object - example_farm_2 = WindFarm(**example_farm_2_data) + example_farm_2=WindFarm(**example_farm_2_data) return example_farm, example_farm_2 @@ -109,12 +103,11 @@ def initialize_wind_turbine_cluster(example_farm, example_farm_2): """ # specification of cluster data - example_cluster_data = { - "name": "example_cluster", - "wind_farms": [example_farm, example_farm_2], - } + example_cluster_data={ + 'name': 'example_cluster', + 'wind_farms': [example_farm, example_farm_2]} # initialize WindTurbineCluster object - example_cluster = WindTurbineCluster(**example_cluster_data) + example_cluster=WindTurbineCluster(**example_cluster_data) return example_cluster @@ -140,49 +133,48 @@ class that provides all necessary steps to calculate the power output of a WindTurbineCluster object. """ - example_farm.efficiency = 0.9 + example_farm.efficiency=0.9 # power output calculation for example_farm # initialize TurbineClusterModelChain with default parameters and use # run_model method to calculate power output - mc_example_farm = TurbineClusterModelChain(example_farm).run_model(weather) + mc_example_farm=TurbineClusterModelChain(example_farm).run_model(weather) # write power output time series to WindFarm object - example_farm.power_output = mc_example_farm.power_output + example_farm.power_output=mc_example_farm.power_output # power output calculation for turbine_cluster # own specifications for TurbineClusterModelChain setup - modelchain_data = { - "wake_losses_model": "wind_farm_efficiency", # 'dena_mean' (default), None, - # 'wind_farm_efficiency' or name - # of another wind efficiency curve - # see :py:func:`~.wake_losses.get_wind_efficiency_curve` - "smoothing": True, # False (default) or True - "block_width": 0.5, # default: 0.5 - "standard_deviation_method": "Staffell_Pfenninger", # - # 'turbulence_intensity' (default) - # or 'Staffell_Pfenninger' - "smoothing_order": "wind_farm_power_curves", # - # 'wind_farm_power_curves' (default) or - # 'turbine_power_curves' - "wind_speed_model": "logarithmic", # 'logarithmic' (default), - # 'hellman' or - # 'interpolation_extrapolation' - "density_model": "ideal_gas", # 'barometric' (default), 'ideal_gas' or - # 'interpolation_extrapolation' - "temperature_model": "linear_gradient", # 'linear_gradient' (def.) or - # 'interpolation_extrapolation' - "power_output_model": "power_curve", # 'power_curve' (default) or - # 'power_coefficient_curve' - "density_correction": True, # False (default) or True - "obstacle_height": 0, # default: 0 - "hellman_exp": None, - } # None (default) or None + modelchain_data={ + 'wake_losses_model': + 'wind_farm_efficiency', # 'dena_mean' (default), None, + # 'wind_farm_efficiency' or name + # of another wind efficiency curve + # see :py:func:`~.wake_losses.get_wind_efficiency_curve` + 'smoothing': True, # False (default) or True + 'block_width': 0.5, # default: 0.5 + 'standard_deviation_method': 'Staffell_Pfenninger', # + # 'turbulence_intensity' (default) + # or 'Staffell_Pfenninger' + 'smoothing_order': 'wind_farm_power_curves', # + # 'wind_farm_power_curves' (default) or + # 'turbine_power_curves' + 'wind_speed_model': 'logarithmic', # 'logarithmic' (default), + # 'hellman' or + # 'interpolation_extrapolation' + 'density_model': 'ideal_gas', # 'barometric' (default), 'ideal_gas' or + # 'interpolation_extrapolation' + 'temperature_model': 'linear_gradient', # 'linear_gradient' (def.) or + # 'interpolation_extrapolation' + 'power_output_model': 'power_curve', # 'power_curve' (default) or + # 'power_coefficient_curve' + 'density_correction': True, # False (default) or True + 'obstacle_height': 0, # default: 0 + 'hellman_exp': None} # None (default) or None # initialize TurbineClusterModelChain with own specifications and use # run_model method to calculate power output - mc_example_cluster = TurbineClusterModelChain( - example_cluster, **modelchain_data - ).run_model(weather) + mc_example_cluster=TurbineClusterModelChain( + example_cluster, **modelchain_data).run_model(weather) # write power output time series to WindTurbineCluster object - example_cluster.power_output = mc_example_cluster.power_output + example_cluster.power_output=mc_example_cluster.power_output return @@ -217,12 +209,11 @@ def run_example(): Runs the example. """ - weather = mc_e.get_weather_data("weather.csv") - my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() - example_farm, example_farm_2 = initialize_wind_farms(my_turbine, e126) - example_cluster = initialize_wind_turbine_cluster( - example_farm, example_farm_2 - ) + weather=mc_e.get_weather_data('weather.csv') + my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() + example_farm, example_farm_2=initialize_wind_farms(my_turbine, e126) + example_cluster=initialize_wind_turbine_cluster(example_farm, + example_farm_2) calculate_power_output(weather, example_farm, example_cluster) plot_or_print(example_farm, example_cluster) diff --git a/tests/test_density.py b/tests/test_density.py index 68556f4d..67c4b4b5 100644 --- a/tests/test_density.py +++ b/tests/test_density.py @@ -12,66 +12,57 @@ class TestDensity: + def test_barometric(self): - parameters = { - "pressure": pd.Series(data=[101125, 101000]), - "pressure_height": 0, - "hub_height": 100, - "temperature_hub_height": pd.Series(data=[267, 268]), - } + parameters={'pressure': pd.Series(data=[101125, 101000]), + 'pressure_height': 0, + 'hub_height': 100, + 'temperature_hub_height': pd.Series(data=[267, 268])} # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp = pd.Series(data=[1.30305336, 1.29656645]) + rho_exp=pd.Series(data=[1.30305336, 1.29656645]) assert_series_equal(barometric(**parameters), rho_exp) - parameters["temperature_hub_height"] = np.array( - parameters["temperature_hub_height"] - ) + parameters['temperature_hub_height']=np.array( + parameters['temperature_hub_height']) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters["pressure"] = np.array(parameters["pressure"]) - parameters["temperature_hub_height"] = pd.Series( - data=parameters["temperature_hub_height"] - ) + parameters['pressure']=np.array(parameters['pressure']) + parameters['temperature_hub_height']=pd.Series( + data=parameters['temperature_hub_height']) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp = np.array([1.30305336, 1.29656645]) - parameters["temperature_hub_height"] = np.array( - parameters["temperature_hub_height"] - ) + rho_exp=np.array([1.30305336, 1.29656645]) + parameters['temperature_hub_height']=np.array( + parameters['temperature_hub_height']) assert_allclose(barometric(**parameters), rho_exp) assert isinstance(barometric(**parameters), np.ndarray) def test_ideal_gas(self): - parameters = { - "pressure": pd.Series(data=[101125, 101000]), - "pressure_height": 0, - "hub_height": 100, - "temperature_hub_height": pd.Series(data=[267, 268]), - } + parameters={'pressure': pd.Series(data=[101125, 101000]), + 'pressure_height': 0, + 'hub_height': 100, + 'temperature_hub_height': pd.Series(data=[267, 268])} # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp = pd.Series(data=[1.30309439, 1.29660728]) + rho_exp=pd.Series(data=[1.30309439, 1.29660728]) assert_series_equal(ideal_gas(**parameters), rho_exp) - parameters["temperature_hub_height"] = np.array( - parameters["temperature_hub_height"] - ) + parameters['temperature_hub_height']=np.array( + parameters['temperature_hub_height']) assert_series_equal(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters["pressure"] = np.array(parameters["pressure"]) - parameters["temperature_hub_height"] = pd.Series( - data=parameters["temperature_hub_height"] - ) + parameters['pressure']=np.array(parameters['pressure']) + parameters['temperature_hub_height']=pd.Series( + data=parameters['temperature_hub_height']) assert_allclose(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp = np.array([1.30309439, 1.29660728]) - parameters["temperature_hub_height"] = np.array( - parameters["temperature_hub_height"] - ) + rho_exp=np.array([1.30309439, 1.29660728]) + parameters['temperature_hub_height']=np.array( + parameters['temperature_hub_height']) assert_allclose(ideal_gas(**parameters), rho_exp) assert isinstance(ideal_gas(**parameters), np.ndarray) diff --git a/tests/test_modelchain.py b/tests/test_modelchain.py index 8bdac075..2fea51aa 100644 --- a/tests/test_modelchain.py +++ b/tests/test_modelchain.py @@ -14,420 +14,330 @@ class TestModelChain: + @classmethod def setup_class(self): """Setup default values""" - self.test_turbine = { - "hub_height": 100, - "turbine_type": "E-126/4200", - "power_curve": pd.DataFrame( - data={"value": [0.0, 4200 * 1000], "wind_speed": [0.0, 25.0]} - ), - } - - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - pressure_0m = np.array([[101125], [101000]]) - wind_speed_8m = np.array([[4.0], [5.0]]) - wind_speed_10m = np.array([[5.0], [6.5]]) - roughness_length = np.array([[0.15], [0.15]]) - self.weather_df = pd.DataFrame( - np.hstack( - ( - temperature_2m, - temperature_10m, - pressure_0m, - wind_speed_8m, - wind_speed_10m, - roughness_length, - ) - ), + self.test_turbine={'hub_height': 100, + 'turbine_type': 'E-126/4200', + 'power_curve': pd.DataFrame( + data={'value': [0.0, 4200 * 1000], + 'wind_speed': [0.0, 25.0]})} + + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + pressure_0m=np.array([[101125], [101000]]) + wind_speed_8m=np.array([[4.0], [5.0]]) + wind_speed_10m=np.array([[5.0], [6.5]]) + roughness_length=np.array([[0.15], [0.15]]) + self.weather_df=pd.DataFrame( + np.hstack((temperature_2m, temperature_10m, pressure_0m, + wind_speed_8m, wind_speed_10m, roughness_length)), index=[0, 1], - columns=[ - np.array( - [ - "temperature", - "temperature", - "pressure", - "wind_speed", - "wind_speed", - "roughness_length", - ] - ), - np.array([2, 10, 0, 8, 10, 0]), - ], - ) + columns=[np.array(['temperature', 'temperature', 'pressure', + 'wind_speed', 'wind_speed', + 'roughness_length']), + np.array([2, 10, 0, 8, 10, 0])]) def test_temperature_hub(self): # Test modelchain with temperature_model='linear_gradient' - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with temperature_model='interpolation_extrapolation' - test_mc_2 = mc.ModelChain( + test_mc_2=mc.ModelChain( wt.WindTurbine(**self.test_turbine), - temperature_model="interpolation_extrapolation", - ) + temperature_model='interpolation_extrapolation') # Parameters for tests - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - weather_df = pd.DataFrame( - np.hstack((temperature_2m, temperature_10m)), - index=[0, 1], - columns=[ - np.array(["temperature", "temperature"]), - np.array([2, 10]), - ], - ) + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + weather_df=pd.DataFrame(np.hstack((temperature_2m, + temperature_10m)), + index=[0, 1], + columns=[np.array(['temperature', + 'temperature']), + np.array([2, 10])]) # temperature_10m is closer to hub height than temperature_2m - temp_exp = pd.Series(data=[266.415, 265.415], name=10) + temp_exp=pd.Series(data=[266.415, 265.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp = pd.Series(data=[267.0, 243.5]) + temp_exp=pd.Series(data=[267.0, 243.5]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns = [ - np.array(["temperature", "temperature"]), - np.array([10, 200]), - ] - temp_exp = pd.Series(data=[266.415, 267.415], name=10) + weather_df.columns=[np.array(['temperature', 'temperature']), + np.array([10, 200])] + temp_exp=pd.Series(data=[266.415, 267.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp = pd.Series(data=[267.0, 267.052632]) + temp_exp=pd.Series(data=[267.0, 267.052632]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # temperature at hub height - weather_df.columns = [ - np.array(["temperature", "temperature"]), - np.array([100, 10]), - ] - temp_exp = pd.Series(data=[267, 268], name=100) + weather_df.columns=[np.array(['temperature', 'temperature']), + np.array([100, 10])] + temp_exp=pd.Series(data=[267, 268], name=100) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) def test_density_hub(self): # Test modelchain with density_model='barometric' - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with density_model='ideal_gas' - test_mc_2 = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), density_model="ideal_gas" - ) + test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + density_model='ideal_gas') # Test modelchain with density_model='interpolation_extrapolation' - test_mc_3 = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), - density_model="interpolation_extrapolation", - ) + test_mc_3=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + density_model='interpolation_extrapolation') # Parameters for tests - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - pressure_0m = np.array([[101125], [101000]]) - weather_df = pd.DataFrame( - np.hstack((temperature_2m, temperature_10m, pressure_0m)), - index=[0, 1], - columns=[ - np.array(["temperature", "temperature", "pressure"]), - np.array([2, 10, 0]), - ], - ) + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + pressure_0m=np.array([[101125], [101000]]) + weather_df=pd.DataFrame(np.hstack((temperature_2m, + temperature_10m, + pressure_0m)), + index=[0, 1], + columns=[np.array(['temperature', + 'temperature', + 'pressure']), + np.array([2, 10, 0])]) # temperature_10m is closer to hub height than temperature_2m - rho_exp = pd.Series(data=[1.30591, 1.30919]) + rho_exp=pd.Series(data=[1.30591, 1.30919]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp = pd.Series(data=[1.30595575725, 1.30923554056]) + rho_exp=pd.Series(data=[1.30595575725, 1.30923554056]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns = [ - np.array(["temperature", "temperature", "pressure"]), - np.array([10, 200, 0]), - ] - rho_exp = pd.Series(data=[1.30591, 1.29940]) + weather_df.columns=[np.array(['temperature', 'temperature', + 'pressure']), + np.array([10, 200, 0])] + rho_exp=pd.Series(data=[1.30591, 1.29940]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp = pd.Series(data=[1.30595575725, 1.29944375221]) + rho_exp=pd.Series(data=[1.30595575725, 1.29944375221]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # temperature at hub height - weather_df.columns = [ - np.array(["temperature", "temperature", "pressure"]), - np.array([100, 10, 0]), - ] - rho_exp = pd.Series(data=[1.30305, 1.29657]) + weather_df.columns=[np.array(['temperature', 'temperature', + 'pressure']), + np.array([100, 10, 0])] + rho_exp=pd.Series(data=[1.30305, 1.29657]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) # density interpolation - density_10m = np.array([[1.30591], [1.29940]]) - density_150m = np.array([[1.30305], [1.29657]]) - weather_df = pd.DataFrame( - np.hstack((density_10m, density_150m)), - index=[0, 1], - columns=[np.array(["density", "density"]), np.array([10, 150])], - ) - rho_exp = pd.Series(data=[1.304071, 1.297581]) + density_10m=np.array([[1.30591], [1.29940]]) + density_150m=np.array([[1.30305], [1.29657]]) + weather_df=pd.DataFrame(np.hstack((density_10m, + density_150m)), + index=[0, 1], + columns=[np.array(['density', + 'density']), + np.array([10, 150])]) + rho_exp=pd.Series(data=[1.304071, 1.297581]) assert_series_equal(test_mc_3.density_hub(weather_df), rho_exp) def test_wind_speed_hub(self): # Test modelchain with wind_speed_model='logarithmic' - test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with wind_speed_model='hellman' - test_mc_2 = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), wind_speed_model="hellman" - ) + test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + wind_speed_model='hellman') # Test modelchain with wind_speed_model='interpolation_extrapolation' - test_mc_3 = mc.ModelChain( + test_mc_3=mc.ModelChain( wt.WindTurbine(**self.test_turbine), - wind_speed_model="interpolation_extrapolation", - ) + wind_speed_model='interpolation_extrapolation') # Test modelchain with # wind_speed_model='log_interpolation_extrapolation' - test_mc_4 = mc.ModelChain( + test_mc_4=mc.ModelChain( wt.WindTurbine(**self.test_turbine), - wind_speed_model="log_interpolation_extrapolation", - ) + wind_speed_model='log_interpolation_extrapolation') # Parameters for tests - wind_speed_8m = np.array([[4.0], [5.0]]) - wind_speed_10m = np.array([[5.0], [6.5]]) - roughness_length = np.array([[0.15], [0.15]]) - weather_df = pd.DataFrame( - np.hstack((wind_speed_8m, wind_speed_10m, roughness_length)), - index=[0, 1], - columns=[ - np.array(["wind_speed", "wind_speed", "roughness_length"]), - np.array([8, 10, 0]), - ], - ) + wind_speed_8m=np.array([[4.0], [5.0]]) + wind_speed_10m=np.array([[5.0], [6.5]]) + roughness_length=np.array([[0.15], [0.15]]) + weather_df=pd.DataFrame(np.hstack((wind_speed_8m, + wind_speed_10m, + roughness_length)), + index=[0, 1], + columns=[np.array(['wind_speed', + 'wind_speed', + 'roughness_length']), + np.array([8, 10, 0])]) # wind_speed_10m is closer to hub height than wind_speed_8m - v_wind_exp = pd.Series(data=[7.74137, 10.06377]) + v_wind_exp=pd.Series(data=[7.74137, 10.06377]) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp = pd.Series(data=[7.12462, 9.26201]) + v_wind_exp=pd.Series(data=[7.12462, 9.26201]) assert_series_equal(test_mc_2.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp = pd.Series(data=[50.0, 74.0]) + v_wind_exp=pd.Series(data=[50.0, 74.0]) assert_series_equal(test_mc_3.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp = pd.Series(data=[15.3188511585, 21.9782767378]) + v_wind_exp=pd.Series(data=[15.3188511585, 21.9782767378]) assert_series_equal(test_mc_4.wind_speed_hub(weather_df), v_wind_exp) # wind_speed is given at hub height - weather_df.columns = [ - np.array(["wind_speed", "wind_speed", "roughness_length"]), - np.array([10, 100, 0]), - ] - v_wind_exp = pd.Series(data=[5.0, 6.5], name=100) + weather_df.columns=[np.array(['wind_speed', 'wind_speed', + 'roughness_length']), + np.array([10, 100, 0])] + v_wind_exp=pd.Series(data=[5.0, 6.5], name=100) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) # ***** test_run_model ********* def test_with_default_parameter(self): """Test with default parameters of modelchain (power curve)""" - test_turbine = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "E-126/4200", - } - power_output_exp = pd.Series( - data=[1637405.4840444783, 3154438.3894902095], - name="feedin_power_plant", - ) - test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine)) + test_turbine={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'E-126/4200'} + power_output_exp=pd.Series(data=[1637405.4840444783, + 3154438.3894902095], + name='feedin_power_plant') + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_density_corrected_power_curve_and_hellman(self): """Test with density corrected power curve and hellman""" - test_turbine = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "E-126/4200", - } - test_modelchain = { - "wind_speed_model": "hellman", - "power_output_model": "power_curve", - "density_correction": True, - } - power_output_exp = pd.Series( - data=[1366958.544547462, 2823402.837201821], - name="feedin_power_plant", - ) - test_mc = mc.ModelChain( - wt.WindTurbine(**test_turbine), **test_modelchain - ) + test_turbine={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'E-126/4200'} + test_modelchain={'wind_speed_model': 'hellman', + 'power_output_model': 'power_curve', + 'density_correction': True} + power_output_exp=pd.Series(data=[1366958.544547462, + 2823402.837201821], + name='feedin_power_plant') + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_power_coefficient_curve_and_hellman(self): """Test with power coefficient curve and hellman""" - test_turbine = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "E-126/4200", - } - power_output_exp = pd.Series( - data=[534137.5112701517, 1103611.1736067757], - name="feedin_power_plant", - ) - test_modelchain = { - "wind_speed_model": "hellman", - "power_output_model": "power_coefficient_curve", - "density_correction": False, - } - test_mc = mc.ModelChain( - wt.WindTurbine(**test_turbine), **test_modelchain - ) + test_turbine={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'E-126/4200'} + power_output_exp=pd.Series(data=[534137.5112701517, + 1103611.1736067757], + name='feedin_power_plant') + test_modelchain={'wind_speed_model': 'hellman', + 'power_output_model': 'power_coefficient_curve', + 'density_correction': False} + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_wrong_spelling_power_output_model(self): """Raise ValueErrors due to wrong spelling of power_output_model""" with pytest.raises(ValueError): - test_modelchain = { - "wind_speed_model": "hellman", - "power_output_model": "wrong_spelling", - "density_correction": False, - } - test_mc = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), **test_modelchain - ) + test_modelchain={'wind_speed_model': 'hellman', + 'power_output_model': 'wrong_spelling', + 'density_correction': False} + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_spelling_density_model(self): """Raise ValueErrors due to wrong spelling of density_model""" with pytest.raises(ValueError): - test_modelchain = { - "wind_speed_model": "hellman", - "power_output_model": "power_coefficient_curve", - "density_correction": False, - "density_model": "wrong_spelling", - } - test_mc = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), **test_modelchain - ) + test_modelchain={'wind_speed_model': 'hellman', + 'power_output_model': 'power_coefficient_curve', + 'density_correction': False, + 'density_model': 'wrong_spelling'} + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_spelling_temperature_model(self): """Raise ValueErrors due to wrong spelling of temperature_model""" with pytest.raises(ValueError): - test_modelchain = { - "wind_speed_model": "hellman", - "power_output_model": "power_coefficient_curve", - "density_correction": False, - "temperature_model": "wrong_spelling", - } - test_mc = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), **test_modelchain - ) + test_modelchain={'wind_speed_model': 'hellman', + 'power_output_model': 'power_coefficient_curve', + 'density_correction': False, + 'temperature_model': 'wrong_spelling'} + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_spelling_wind_speed_model(self): """Raise ValueErrors due to wrong spelling of wind_speed_model""" with pytest.raises(ValueError): - test_modelchain = { - "wind_speed_model": "wrong_spelling", - "power_output_model": "power_coefficient_curve", - "density_correction": False, - } - test_mc = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), **test_modelchain - ) + test_modelchain={'wind_speed_model': 'wrong_spelling', + 'power_output_model': 'power_coefficient_curve', + 'density_correction': False} + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) def test_wrong_density_correction_type(self): """Raise TypeErrors due to wrong type of `density_correction`""" with pytest.raises(TypeError): - test_modelchain = { - "power_output_model": "power_curve", - "density_correction": "wrong_type", - } - test_mc = mc.ModelChain( - wt.WindTurbine(**self.test_turbine), **test_modelchain - ) + test_modelchain={'power_output_model': 'power_curve', + 'density_correction': 'wrong_type'} + test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_cp_values(self): """Raise TypeErrors due to missing cp-values""" - test_turbine = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "E-126/4201", - } - msg = "Power coefficient curve values of" + test_turbine={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'E-126/4201'} + msg="Power coefficient curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain = { - "power_output_model": "power_coefficient_curve", - "density_correction": True, - } - test_mc = mc.ModelChain( - wt.WindTurbine(**test_turbine), **test_modelchain - ) + test_modelchain={'power_output_model': 'power_coefficient_curve', + 'density_correction': True} + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_p_values(self): """Raise TypeErrors due to missing p-values""" - test_turbine = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "E-126/4205", - } - msg = "Power curve values of" + test_turbine={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'E-126/4205'} + msg="Power curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain = { - "power_output_model": "power_curve", - "density_corr": True, - } - test_mc = mc.ModelChain( - wt.WindTurbine(**test_turbine), **test_modelchain - ) + test_modelchain={'power_output_model': 'power_curve', + 'density_corr': True} + test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), + **test_modelchain) test_mc.run_model(self.weather_df) def test_modelchain_with_power_curve_as_dict(self): """Test power curves as dict""" - my_turbine = { - "nominal_power": 3e6, - "hub_height": 105, - "rotor_diameter": 70, - "power_curve": { - "value": [ - p * 1000 - for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] - ], - "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], - }, - "power_coefficient_curve": { - "value": [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], - "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], - }, - } - power_output_exp = pd.Series( - data=[919055.54840, 1541786.60559], name="feedin_power_plant" - ) - test_mc = mc.ModelChain(wt.WindTurbine(**my_turbine)) + my_turbine={'nominal_power': 3e6, 'hub_height': 105, + 'rotor_diameter': 70, + 'power_curve': { + 'value': [p * 1000 for p in [ + 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], + 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}, + 'power_coefficient_curve': { + 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], + 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} + power_output_exp=pd.Series(data=[919055.54840, + 1541786.60559], + name='feedin_power_plant') + test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_modelchain_with_power_coefficient_curve_as_dict(self): """Test power coefficient curves as dict""" - my_turbine = { - "nominal_power": 3e6, - "hub_height": 105, - "rotor_diameter": 70, - "power_curve": { - "value": [ - p * 1000 - for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] - ], - "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], - }, - "power_coefficient_curve": { - "value": [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], - "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], - }, - } - power_output_exp = pd.Series( - data=[469518.35104, 901794.28532], name="feedin_power_plant" - ) - test_mc = mc.ModelChain( - wt.WindTurbine(**my_turbine), - power_output_model="power_coefficient_curve", - ) + my_turbine={'nominal_power': 3e6, 'hub_height': 105, + 'rotor_diameter': 70, + 'power_curve': { + 'value': [p * 1000 for p in [ + 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], + 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}, + 'power_coefficient_curve': { + 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], + 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} + power_output_exp=pd.Series(data=[469518.35104, + 901794.28532], + name='feedin_power_plant') + test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine), + power_output_model='power_coefficient_curve') test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) diff --git a/tests/test_power_curves.py b/tests/test_power_curves.py index ccf296ab..5814969b 100644 --- a/tests/test_power_curves.py +++ b/tests/test_power_curves.py @@ -8,153 +8,95 @@ import pytest from pandas.util.testing import assert_frame_equal -from windpowerlib.power_curves import ( - smooth_power_curve, - wake_losses_to_power_curve, -) +from windpowerlib.power_curves import (smooth_power_curve, + wake_losses_to_power_curve) import windpowerlib.wind_turbine as wt class TestPowerCurves: + @classmethod def setup_class(self): - self.test_turbine = {"hub_height": 100, "turbine_type": "E-126/4200"} + self.test_turbine={'hub_height': 100, + 'turbine_type': 'E-126/4200'} def test_smooth_power_curve(self): - test_curve = wt.WindTurbine(**self.test_turbine).power_curve - parameters = { - "power_curve_wind_speeds": test_curve["wind_speed"], - "power_curve_values": test_curve["value"], - "standard_deviation_method": "turbulence_intensity", - } + test_curve=wt.WindTurbine(**self.test_turbine).power_curve + parameters={'power_curve_wind_speeds': test_curve['wind_speed'], + 'power_curve_values': test_curve['value'], + 'standard_deviation_method': 'turbulence_intensity'} # Raise ValueError - `turbulence_intensity` missing with pytest.raises(ValueError): - parameters["standard_deviation_method"] = "turbulence_intensity" + parameters['standard_deviation_method']='turbulence_intensity' smooth_power_curve(**parameters) # Test turbulence_intensity method - parameters["turbulence_intensity"] = 0.5 - wind_speed_values_exp = pd.Series( - [6.0, 7.0, 8.0, 9.0, 10.0], name="wind_speed" - ) - power_values_exp = pd.Series( - [ - 1141906.9806766496, - 1577536.8085282773, - 1975480.993355767, - 2314059.4022704284, - 2590216.6802602503, - ], - name="value", - ) - smoothed_curve_exp = pd.DataFrame( - data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1) - ) - smoothed_curve_exp.index = np.arange(5, 10, 1) - assert_frame_equal( - smooth_power_curve(**parameters)[5:10], smoothed_curve_exp - ) + parameters['turbulence_intensity']=0.5 + wind_speed_values_exp=pd.Series([6.0, 7.0, 8.0, 9.0, 10.0], + name='wind_speed') + power_values_exp=pd.Series([ + 1141906.9806766496, 1577536.8085282773, 1975480.993355767, + 2314059.4022704284, 2590216.6802602503], name='value') + smoothed_curve_exp=pd.DataFrame(data=pd.concat([ + wind_speed_values_exp, power_values_exp], axis=1)) + smoothed_curve_exp.index=np.arange(5, 10, 1) + assert_frame_equal(smooth_power_curve(**parameters)[5:10], + smoothed_curve_exp) # Test Staffel_Pfenninger method - parameters["standard_deviation_method"] = "Staffell_Pfenninger" - power_values_exp = pd.Series( - [ - 929405.1348918702, - 1395532.5468724659, - 1904826.6851982325, - 2402659.118305521, - 2844527.1732449625, - ], - name="value", - ) - smoothed_curve_exp = pd.DataFrame( - data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1) - ) - smoothed_curve_exp.index = np.arange(5, 10, 1) - assert_frame_equal( - smooth_power_curve(**parameters)[5:10], smoothed_curve_exp - ) + parameters['standard_deviation_method']='Staffell_Pfenninger' + power_values_exp=pd.Series([ + 929405.1348918702, 1395532.5468724659, 1904826.6851982325, + 2402659.118305521, 2844527.1732449625], name='value') + smoothed_curve_exp=pd.DataFrame( + data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1)) + smoothed_curve_exp.index=np.arange(5, 10, 1) + assert_frame_equal(smooth_power_curve(**parameters)[5:10], + smoothed_curve_exp) # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters["standard_deviation_method"] = "misspelled" + parameters['standard_deviation_method']='misspelled' smooth_power_curve(**parameters) def test_wake_losses_to_power_curve(self): - test_curve = wt.WindTurbine(**self.test_turbine).power_curve - parameters = { - "power_curve_wind_speeds": test_curve["wind_speed"], - "power_curve_values": test_curve["value"], - "wind_farm_efficiency": 0.9, - } + test_curve=wt.WindTurbine(**self.test_turbine).power_curve + parameters={'power_curve_wind_speeds': test_curve['wind_speed'], + 'power_curve_values': test_curve['value'], + 'wind_farm_efficiency': 0.9} # Test constant efficiency - power_curve_exp = test_curve.copy(deep=True) - power_curve_exp["value"] = power_curve_exp["value"].values * 0.9 - assert_frame_equal( - wake_losses_to_power_curve(**parameters), power_curve_exp - ) + power_curve_exp=test_curve.copy(deep=True) + power_curve_exp['value']=power_curve_exp['value'].values * 0.9 + assert_frame_equal(wake_losses_to_power_curve(**parameters), + power_curve_exp) # Test efficiency curve - parameters["wind_farm_efficiency"] = pd.DataFrame( - pd.concat( - [ - pd.Series(np.arange(1, 26, 1)), - pd.Series( - [ - 1.0, - 1.0, - 1.0, - 0.84, - 0.85, - 0.86, - 0.85, - 0.85, - 0.85, - 0.86, - 0.87, - 0.89, - 0.92, - 0.95, - 0.95, - 0.96, - 0.99, - 0.95, - 0.98, - 0.97, - 0.99, - 1.0, - 1.0, - 1.0, - 1.0, - ] - ), - ], - axis=1, - ) - ) - parameters["wind_farm_efficiency"].columns = [ - "wind_speed", - "efficiency", - ] - power_curve_exp = test_curve.copy(deep=True) - power_curve_exp["value"] = ( - power_curve_exp["value"].values - * parameters["wind_farm_efficiency"]["efficiency"] - ) - assert_frame_equal( - wake_losses_to_power_curve(**parameters), power_curve_exp - ) + parameters['wind_farm_efficiency']=pd.DataFrame( + pd.concat([pd.Series(np.arange(1, 26, 1)), + pd.Series([ + 1.0, 1.0, 1.0, 0.84, 0.85, 0.86, 0.85, 0.85, 0.85, + 0.86, 0.87, 0.89, 0.92, 0.95, 0.95, 0.96, 0.99, + 0.95, 0.98, 0.97, 0.99, 1.0, 1.0, 1.0, 1.0])], + axis=1)) + parameters['wind_farm_efficiency'].columns=['wind_speed', + 'efficiency'] + power_curve_exp=test_curve.copy(deep=True) + power_curve_exp['value']=( + power_curve_exp['value'].values * parameters[ + 'wind_farm_efficiency']['efficiency']) + assert_frame_equal(wake_losses_to_power_curve(**parameters), + power_curve_exp) # Raise TypeError if wind farm efficiency is of wrong type with pytest.raises(TypeError): - parameters["wind_farm_efficiency"] = 1 + parameters['wind_farm_efficiency']=1 wake_losses_to_power_curve(**parameters) if __name__ == "__main__": - test = TestPowerCurves() + test=TestPowerCurves() test.setup_class() test.test_smooth_power_curve() test.test_wake_losses_to_power_curve() diff --git a/tests/test_power_output.py b/tests/test_power_output.py index d29d6e35..0a5c6f84 100644 --- a/tests/test_power_output.py +++ b/tests/test_power_output.py @@ -9,214 +9,187 @@ from numpy.testing import assert_allclose from pandas.util.testing import assert_series_equal -from windpowerlib.power_output import ( - power_coefficient_curve, - power_curve, - power_curve_density_correction, -) +from windpowerlib.power_output import (power_coefficient_curve, + power_curve, + power_curve_density_correction) class TestPowerOutput: + def test_power_coefficient_curve(self): - parameters = { - "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), - "density": pd.Series(data=[1.3, 1.3, 1.3]), - "rotor_diameter": 80, - "power_coefficient_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), - "power_coefficient_curve_values": pd.Series([0.3, 0.4, 0.5]), - } + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + 'density': pd.Series(data=[1.3, 1.3, 1.3]), + 'rotor_diameter': 80, + 'power_coefficient_curve_wind_speeds': + pd.Series([4.0, 5.0, 6.0]), + 'power_coefficient_curve_values': + pd.Series([0.3, 0.4, 0.5])} # Test wind_speed as pd.Series with density and power_coefficient_curve # as pd.Series and np.array - power_output_exp = pd.Series( - data=[0.0, 244615.399, 0.0], name="feedin_power_plant" - ) - assert_series_equal( - power_coefficient_curve(**parameters), power_output_exp - ) - parameters["density"] = np.array(parameters["density"]) - assert_series_equal( - power_coefficient_curve(**parameters), power_output_exp - ) - parameters["power_coefficient_curve_values"] = np.array( - parameters["power_coefficient_curve_values"] - ) - parameters["power_coefficient_curve_wind_speeds"] = np.array( - parameters["power_coefficient_curve_wind_speeds"] - ) - assert_series_equal( - power_coefficient_curve(**parameters), power_output_exp - ) + power_output_exp=pd.Series(data=[0.0, 244615.399, 0.0], + name='feedin_power_plant') + assert_series_equal(power_coefficient_curve(**parameters), + power_output_exp) + parameters['density']=np.array(parameters['density']) + assert_series_equal(power_coefficient_curve(**parameters), + power_output_exp) + parameters['power_coefficient_curve_values']=np.array( + parameters['power_coefficient_curve_values']) + parameters['power_coefficient_curve_wind_speeds']=np.array( + parameters['power_coefficient_curve_wind_speeds']) + assert_series_equal(power_coefficient_curve(**parameters), + power_output_exp) # Test wind_speed as np.array with density and power_coefficient_curve # as np.array and pd.Series - power_output_exp = np.array([0.0, 244615.399, 0.0]) - parameters["wind_speed"] = np.array(parameters["wind_speed"]) - assert_allclose( - power_coefficient_curve(**parameters), power_output_exp - ) + power_output_exp=np.array([0.0, 244615.399, 0.0]) + parameters['wind_speed']=np.array(parameters['wind_speed']) + assert_allclose(power_coefficient_curve(**parameters), + power_output_exp) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters["density"] = pd.Series(data=parameters["density"]) - assert_allclose( - power_coefficient_curve(**parameters), power_output_exp - ) + parameters['density']=pd.Series(data=parameters['density']) + assert_allclose(power_coefficient_curve(**parameters), + power_output_exp) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters["power_coefficient_curve_wind_speeds"] = pd.Series( - data=parameters["power_coefficient_curve_wind_speeds"] - ) - parameters["power_coefficient_curve_values"] = pd.Series( - data=parameters["power_coefficient_curve_values"] - ) - assert_allclose( - power_coefficient_curve(**parameters), power_output_exp - ) + parameters['power_coefficient_curve_wind_speeds']=pd.Series( + data=parameters['power_coefficient_curve_wind_speeds']) + parameters['power_coefficient_curve_values']=pd.Series( + data=parameters['power_coefficient_curve_values']) + assert_allclose(power_coefficient_curve(**parameters), + power_output_exp) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) def test_power_curve(self): - parameters = { - "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), - "density": pd.Series(data=[1.3, 1.3, 1.3]), - "density_correction": False, - "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), - "power_curve_values": pd.Series([300, 400, 500]), - } + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + 'density': pd.Series(data=[1.3, 1.3, 1.3]), + 'density_correction': False, + 'power_curve_wind_speeds': + pd.Series([4.0, 5.0, 6.0]), + 'power_curve_values': + pd.Series([300, 400, 500]) + } # Tests without density correction: # Test wind_speed as pd.Series and power_curve as pd.Series and # np.array - power_output_exp = pd.Series( - data=[0.0, 450.0, 0.0], name="feedin_power_plant" - ) - assert_series_equal(power_curve(**parameters), power_output_exp) - parameters["power_curve_values"] = np.array( - parameters["power_curve_values"] - ) - parameters["power_curve_wind_speeds"] = np.array( - parameters["power_curve_wind_speeds"] - ) + power_output_exp=pd.Series(data=[0.0, 450.0, 0.0], + name='feedin_power_plant') assert_series_equal(power_curve(**parameters), power_output_exp) + parameters['power_curve_values']=np.array( + parameters['power_curve_values']) + parameters['power_curve_wind_speeds']=np.array( + parameters['power_curve_wind_speeds']) + assert_series_equal(power_curve(**parameters), + power_output_exp) # Test wind_speed as np.array and power_curve as pd.Series and np.array - power_output_exp = np.array([0.0, 450.0, 0.0]) - parameters["wind_speed"] = np.array(parameters["wind_speed"]) + power_output_exp=np.array([0.0, 450.0, 0.0]) + parameters['wind_speed']=np.array(parameters['wind_speed']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters["power_curve_wind_speeds"] = pd.Series( - data=parameters["power_curve_wind_speeds"] - ) - parameters["power_curve_values"] = pd.Series( - data=parameters["power_curve_values"] - ) + parameters['power_curve_wind_speeds']=pd.Series( + data=parameters['power_curve_wind_speeds']) + parameters['power_curve_values']=pd.Series( + data=parameters['power_curve_values']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Tests with density correction: # Test wind_speed as np.array with density and power_curve as pd.Series # and np.array - power_output_exp = np.array([0.0, 461.00290572, 0.0]) - parameters["density_correction"] = True + power_output_exp=np.array([0.0, 461.00290572, 0.0]) + parameters['density_correction']=True assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters["density"] = np.array(parameters["density"]) + parameters['density']=np.array(parameters['density']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters["power_curve_values"] = np.array( - parameters["power_curve_values"] - ) - parameters["power_curve_wind_speeds"] = np.array( - parameters["power_curve_wind_speeds"] - ) + parameters['power_curve_values']=np.array( + parameters['power_curve_values']) + parameters['power_curve_wind_speeds']=np.array( + parameters['power_curve_wind_speeds']) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Test wind_speed as pd.Series with density and power_curve as # np. array and pd.Series - power_output_exp = pd.Series( - data=[0.0, 461.00290572, 0.0], name="feedin_power_plant" - ) - parameters["wind_speed"] = pd.Series(data=parameters["wind_speed"]) - assert_series_equal(power_curve(**parameters), power_output_exp) - parameters["density"] = pd.Series(data=parameters["density"]) - assert_series_equal(power_curve(**parameters), power_output_exp) - parameters["power_curve_wind_speeds"] = pd.Series( - data=parameters["power_curve_wind_speeds"] - ) - parameters["power_curve_values"] = pd.Series( - data=parameters["power_curve_values"] - ) + power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], + name='feedin_power_plant') + parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) assert_series_equal(power_curve(**parameters), power_output_exp) + parameters['density']=pd.Series(data=parameters['density']) + assert_series_equal(power_curve(**parameters), + power_output_exp) + parameters['power_curve_wind_speeds']=pd.Series( + data=parameters['power_curve_wind_speeds']) + parameters['power_curve_values']=pd.Series( + data=parameters['power_curve_values']) + assert_series_equal(power_curve(**parameters), + power_output_exp) # Raise TypeErrors due to wrong type of `density_correction` with pytest.raises(TypeError): - parameters["density"] = "wrong_type" + parameters['density']='wrong_type' power_curve(**parameters) def test_power_curve_density_correction(self): - parameters = { - "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), - "density": pd.Series(data=[1.3, 1.3, 1.3]), - "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), - "power_curve_values": pd.Series([300, 400, 500]), - } + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + 'density': pd.Series(data=[1.3, 1.3, 1.3]), + 'power_curve_wind_speeds': + pd.Series([4.0, 5.0, 6.0]), + 'power_curve_values': + pd.Series([300, 400, 500]) + } # Test wind_speed as pd.Series with density and power_curve as # pd.Series and np.array - power_output_exp = pd.Series( - data=[0.0, 461.00290572, 0.0], name="feedin_power_plant" - ) - assert_series_equal( - power_curve_density_correction(**parameters), power_output_exp - ) - parameters["density"] = np.array(parameters["density"]) - assert_series_equal( - power_curve_density_correction(**parameters), power_output_exp - ) - parameters["power_curve_values"] = np.array( - parameters["power_curve_values"] - ) - parameters["power_curve_wind_speeds"] = np.array( - parameters["power_curve_wind_speeds"] - ) - assert_series_equal( - power_curve_density_correction(**parameters), power_output_exp - ) + power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], + name='feedin_power_plant') + assert_series_equal(power_curve_density_correction(**parameters), + power_output_exp) + parameters['density']=np.array(parameters['density']) + assert_series_equal(power_curve_density_correction(**parameters), + power_output_exp) + parameters['power_curve_values']=np.array( + parameters['power_curve_values']) + parameters['power_curve_wind_speeds']=np.array( + parameters['power_curve_wind_speeds']) + assert_series_equal(power_curve_density_correction(**parameters), + power_output_exp) # Test wind_speed as np.array with density and power_curve as np.array # and pd.Series - parameters["wind_speed"] = np.array(parameters["wind_speed"]) - power_output_exp = np.array([0.0, 461.00290572, 0.0]) - assert_allclose( - power_curve_density_correction(**parameters), power_output_exp - ) + parameters['wind_speed']=np.array(parameters['wind_speed']) + power_output_exp=np.array([0.0, 461.00290572, 0.0]) + assert_allclose(power_curve_density_correction(**parameters), + power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters["density"] = pd.Series(data=parameters["density"]) - assert_allclose( - power_curve_density_correction(**parameters), power_output_exp - ) + parameters['density']=pd.Series(data=parameters['density']) + assert_allclose(power_curve_density_correction(**parameters), + power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters["power_curve_wind_speeds"] = pd.Series( - data=parameters["power_curve_wind_speeds"] - ) - parameters["power_curve_values"] = pd.Series( - data=parameters["power_curve_values"] - ) - assert_allclose( - power_curve_density_correction(**parameters), power_output_exp - ) + parameters['power_curve_wind_speeds']=pd.Series( + data=parameters['power_curve_wind_speeds']) + parameters['power_curve_values']=pd.Series( + data=parameters['power_curve_values']) + assert_allclose(power_curve_density_correction(**parameters), + power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Raise TypeError due to density is None with pytest.raises(TypeError): - parameters["density"] = None + parameters['density']=None power_curve_density_correction(**parameters) def test_wrong_spelling_density_correction(self): - parameters = { - "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), - "density": pd.Series(data=[1.3, 1.3, 1.3]), - "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), - "power_curve_values": pd.Series([300, 400, 500]), - } - msg = "is an invalid type. `density_correction` must be Boolean" + parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), + 'density': pd.Series(data=[1.3, 1.3, 1.3]), + 'power_curve_wind_speeds': + pd.Series([4.0, 5.0, 6.0]), + 'power_curve_values': + pd.Series([300, 400, 500]) + } + msg="is an invalid type. `density_correction` must be Boolean" with pytest.raises(TypeError, match=msg): - parameters["density_correction"] = None + parameters['density_correction']=None power_curve(**parameters) diff --git a/tests/test_temperature.py b/tests/test_temperature.py index d0e2ba4b..59070069 100644 --- a/tests/test_temperature.py +++ b/tests/test_temperature.py @@ -12,23 +12,20 @@ class TestTemperature: + def test_linear_gradient(self): """Test temperature as pd.Series""" - parameters = { - "temperature": pd.Series(data=[267, 268]), - "temperature_height": 2, - "hub_height": 100, - } - temp_hub_exp = pd.Series(data=[266.363, 267.36300]) + parameters={'temperature': pd.Series(data=[267, 268]), + 'temperature_height': 2, + 'hub_height': 100} + temp_hub_exp=pd.Series(data=[266.363, 267.36300]) assert_series_equal(linear_gradient(**parameters), temp_hub_exp) def test_temperature_as_np_array(self): """Test temperature as np.array""" - parameters = { - "temperature": np.array([267, 268]), - "temperature_height": 2, - "hub_height": 100, - } - temp_hub_exp = np.array([266.363, 267.36300]) + parameters={'temperature': np.array([267, 268]), + 'temperature_height': 2, + 'hub_height': 100} + temp_hub_exp=np.array([266.363, 267.36300]) assert_array_equal(linear_gradient(**parameters), temp_hub_exp) assert isinstance(linear_gradient(**parameters), np.ndarray) diff --git a/tests/test_tools.py b/tests/test_tools.py index 2392d89d..91d87223 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -6,128 +6,96 @@ import pandas as pd from pandas.util.testing import assert_series_equal -from windpowerlib.tools import ( - linear_interpolation_extrapolation, - logarithmic_interpolation_extrapolation, -) +from windpowerlib.tools import (linear_interpolation_extrapolation, + logarithmic_interpolation_extrapolation) class TestTools: + @classmethod def setup_class(cls): - cls.parameters = {"target_height": 80} - cls.df = pd.DataFrame( - data={ - 10: [2.0, 2.0, 3.0], - 80: [4.0, 5.0, 6.0], - 200: [5.0, 8.0, 10.0], - }, - index=[0, 1, 2], - ) + cls.parameters={'target_height': 80} + cls.df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], + 80: [4.0, 5.0, 6.0], + 200: [5.0, 8.0, 10.0]}, + index=[0, 1, 2]) def test_linear_target_height_is_equal_to_given_height(self): """ Test linear interpolation and extrapolation if target_height is equal to height given in a column of the DataFrame. """ - exp_output = pd.Series(data=[4.0, 5.0, 6.0]) - assert_series_equal( - linear_interpolation_extrapolation(self.df, **self.parameters), - exp_output, - ) + exp_output=pd.Series(data=[4.0, 5.0, 6.0]) + assert_series_equal(linear_interpolation_extrapolation( + self.df, **self.parameters), exp_output) def test_linear_target_height_is_between_given_heights(self): """ Test linear interpolation and extrapolation if target_height is between heights given in the columns of the DataFrame """ - exp_output = pd.Series(data=[4.5, 6.5, 8.0]) - self.parameters["target_height"] = 140 - assert_series_equal( - linear_interpolation_extrapolation(self.df, **self.parameters), - exp_output, - ) + exp_output=pd.Series(data=[4.5, 6.5, 8.0]) + self.parameters['target_height']=140 + assert_series_equal(linear_interpolation_extrapolation( + self.df, **self.parameters), exp_output) - exp_output = pd.Series(data=[4.285714, 5.428571, 6.428571]) - self.parameters["target_height"] = 90 - assert_series_equal( - linear_interpolation_extrapolation(self.df, **self.parameters), - exp_output, - ) + exp_output=pd.Series(data=[4.285714, 5.428571, 6.428571]) + self.parameters['target_height']=90 + assert_series_equal(linear_interpolation_extrapolation( + self.df, **self.parameters), exp_output) def test_linear_target_height_is_greater_than_the_given_heights(self): """ Test linear interpolation and extrapolation if target_height is greater than the heights given in the columns of the DataFrame """ - exp_output = pd.Series(data=[5.333333, 9.0, 11.333333]) - self.parameters["target_height"] = 240 - assert_series_equal( - linear_interpolation_extrapolation(self.df, **self.parameters), - exp_output, - ) + exp_output=pd.Series(data=[5.333333, 9.0, 11.333333]) + self.parameters['target_height']=240 + assert_series_equal(linear_interpolation_extrapolation( + self.df, **self.parameters), exp_output) def test_linear_target_height_is_smaller_than_the_given_heights(self): """ Test linear interpolation and extrapolation if target_height is smaller than the heights given in the columns of the DataFrame """ - exp_output = pd.Series(data=[1.857143, 1.785714, 2.785714]) - self.parameters["target_height"] = 5 - assert_series_equal( - linear_interpolation_extrapolation(self.df, **self.parameters), - exp_output, - ) + exp_output=pd.Series(data=[1.857143, 1.785714, 2.785714]) + self.parameters['target_height']=5 + assert_series_equal(linear_interpolation_extrapolation( + self.df, **self.parameters), exp_output) def test_logarithmic_interpolation_extrapolation(self): - parameters = {"target_height": 80} - df = pd.DataFrame( - data={ - 10: [2.0, 2.0, 3.0], - 80: [4.0, 5.0, 6.0], - 200: [5.0, 8.0, 10.0], - }, - index=[0, 1, 2], - ) + parameters={'target_height': 80} + df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], + 80: [4.0, 5.0, 6.0], + 200: [5.0, 8.0, 10.0]}, + index=[0, 1, 2]) # target_height is equal to height given in a column of the DataFrame - exp_output = pd.Series(data=[4.0, 5.0, 6.0]) - assert_series_equal( - logarithmic_interpolation_extrapolation(df, **parameters), - exp_output, - ) + exp_output=pd.Series(data=[4.0, 5.0, 6.0]) + assert_series_equal(logarithmic_interpolation_extrapolation( + df, **parameters), exp_output) # target_height is between heights given in the columns of the # DataFrame - exp_output = pd.Series( - data=[4.61074042165, 6.83222126494, 8.44296168659] - ) - parameters["target_height"] = 140 - assert_series_equal( - logarithmic_interpolation_extrapolation(df, **parameters), - exp_output, - ) - exp_output = pd.Series( - data=[4.11328333429, 5.16992500144, 6.16992500144] - ) - parameters["target_height"] = 90 - assert_series_equal( - logarithmic_interpolation_extrapolation(df, **parameters), - exp_output, - ) + exp_output=pd.Series( + data=[4.61074042165, 6.83222126494, 8.44296168659]) + parameters['target_height']=140 + assert_series_equal(logarithmic_interpolation_extrapolation( + df, **parameters), exp_output) + exp_output=pd.Series( + data=[4.11328333429, 5.16992500144, 6.16992500144]) + parameters['target_height']=90 + assert_series_equal(logarithmic_interpolation_extrapolation( + df, **parameters), exp_output) # target_height is greater than the heights given in the columns of the # DataFrame - exp_output = pd.Series( - data=[5.19897784672, 8.59693354015, 10.7959113869] - ) - parameters["target_height"] = 240 - assert_series_equal( - logarithmic_interpolation_extrapolation(df, **parameters), - exp_output, - ) + exp_output=pd.Series( + data=[5.19897784672, 8.59693354015, 10.7959113869]) + parameters['target_height']=240 + assert_series_equal(logarithmic_interpolation_extrapolation( + df, **parameters), exp_output) # target_height is smaller than the heights given in the columns of the # DataFrame - exp_output = pd.Series(data=[1.33333333333, 1.0, 2.0]) - parameters["target_height"] = 5 - assert_series_equal( - logarithmic_interpolation_extrapolation(df, **parameters), - exp_output, - ) + exp_output=pd.Series(data=[1.33333333333, 1.0, 2.0]) + parameters['target_height']=5 + assert_series_equal(logarithmic_interpolation_extrapolation( + df, **parameters), exp_output) diff --git a/tests/test_turbine_cluster_modelchain.py b/tests/test_turbine_cluster_modelchain.py index 2b20e151..80f9bcfd 100644 --- a/tests/test_turbine_cluster_modelchain.py +++ b/tests/test_turbine_cluster_modelchain.py @@ -15,230 +15,179 @@ class TestTurbineClusterModelChain: + @classmethod def setup_class(self): - temperature_2m = np.array([[267], [268]]) - temperature_10m = np.array([[267], [266]]) - pressure_0m = np.array([[101125], [101000]]) - wind_speed_8m = np.array([[4.0], [5.0]]) - wind_speed_10m = np.array([[5.0], [6.5]]) - roughness_length = np.array([[0.15], [0.15]]) - self.weather_df = pd.DataFrame( - np.hstack( - ( - temperature_2m, - temperature_10m, - pressure_0m, - wind_speed_8m, - wind_speed_10m, - roughness_length, - ) - ), - index=[0, 1], - columns=[ - np.array( - [ - "temperature", - "temperature", - "pressure", - "wind_speed", - "wind_speed", - "roughness_length", - ] - ), - np.array([2, 10, 0, 8, 10, 0]), - ], - ) - self.test_turbine = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "E-126/4200", - } - self.test_turbine_2 = { - "hub_height": 90, - "rotor_diameter": 60, - "turbine_type": "V90/2000", - "nominal_power": 2000000.0, - } - self.test_farm = { - "wind_turbine_fleet": [ - { - "wind_turbine": wt.WindTurbine(**self.test_turbine), - "number_of_turbines": 3, - } - ] - } - self.test_farm_2 = { - "name": "test farm", - "wind_turbine_fleet": [ - { - "wind_turbine": wt.WindTurbine(**self.test_turbine), - "number_of_turbines": 3, - }, - { - "wind_turbine": wt.WindTurbine(**self.test_turbine_2), - "number_of_turbines": 3, - }, - ], - } - self.test_cluster = { - "name": "example_cluster", - "wind_farms": [ - wf.WindFarm(**self.test_farm), - wf.WindFarm(**self.test_farm_2), - ], - } + temperature_2m=np.array([[267], [268]]) + temperature_10m=np.array([[267], [266]]) + pressure_0m=np.array([[101125], [101000]]) + wind_speed_8m=np.array([[4.0], [5.0]]) + wind_speed_10m=np.array([[5.0], [6.5]]) + roughness_length=np.array([[0.15], [0.15]]) + self.weather_df=pd.DataFrame( + np.hstack((temperature_2m, + temperature_10m, + pressure_0m, + wind_speed_8m, + wind_speed_10m, + roughness_length)), + index=[0, 1], + columns=[np.array(['temperature', + 'temperature', + 'pressure', + 'wind_speed', + 'wind_speed', + 'roughness_length']), + np.array([2, 10, 0, 8, 10, 0])]) + self.test_turbine={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'E-126/4200'} + self.test_turbine_2={'hub_height': 90, + 'rotor_diameter': 60, + 'turbine_type': 'V90/2000', + 'nominal_power': 2000000.0} + self.test_farm={'wind_turbine_fleet': [ + {'wind_turbine': + wt.WindTurbine(**self.test_turbine), + 'number_of_turbines': 3}]} + self.test_farm_2={'name': 'test farm', + 'wind_turbine_fleet': + [{'wind_turbine': + wt.WindTurbine(**self.test_turbine), + 'number_of_turbines': 3}, + {'wind_turbine': + wt.WindTurbine(**self.test_turbine_2), + 'number_of_turbines': 3}]} + self.test_cluster={'name': 'example_cluster', + 'wind_farms': [wf.WindFarm(**self.test_farm), + wf.WindFarm(**self.test_farm_2)]} def test_run_model(self): - parameters = { - "wake_losses_model": "dena_mean", - "smoothing": False, - "standard_deviation_method": "turbulence_intensity", - "smoothing_order": "wind_farm_power_curves", - } + parameters={'wake_losses_model': 'dena_mean', + 'smoothing': False, + 'standard_deviation_method': 'turbulence_intensity', + 'smoothing_order': 'wind_farm_power_curves'} # Test modelchain with default values - power_output_exp = pd.Series( - data=[4198361.4830405945, 8697966.121234536], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**self.test_farm), **parameters - ) + power_output_exp=pd.Series(data=[4198361.4830405945, + 8697966.121234536], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**self.test_farm), **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters["wake_losses_model"] = "wind_farm_efficiency" - test_wind_farm = wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[4420994.806920091, 8516983.651623568], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters - ) + parameters['wake_losses_model']='wind_farm_efficiency' + test_wind_farm=wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[4420994.806920091, + 8516983.651623568], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters["smoothing"] = "True" - test_wind_farm = wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[4581109.03847444, 8145581.914240712], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters - ) + parameters['smoothing']='True' + test_wind_farm=wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[4581109.03847444, + 8145581.914240712], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_wind_farm = wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[6777087.9658657005, 12180374.036660176], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters - ) + test_wind_farm=wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[6777087.9658657005, + 12180374.036660176], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters["smoothing_order"] = "turbine_power_curves" - test_wind_farm = wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[6790706.001026006, 12179417.461328149], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters - ) + parameters['smoothing_order']='turbine_power_curves' + test_wind_farm=wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency=0.9 + power_output_exp=pd.Series(data=[6790706.001026006, + 12179417.461328149], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) def test_run_model_turbine_cluster(self): - parameters = { - "wake_losses_model": "dena_mean", - "smoothing": False, - "standard_deviation_method": "turbulence_intensity", - "smoothing_order": "wind_farm_power_curves", - } + parameters={'wake_losses_model': 'dena_mean', + 'smoothing': False, + 'standard_deviation_method': 'turbulence_intensity', + 'smoothing_order': 'wind_farm_power_curves'} # Test modelchain with default values - power_output_exp = pd.Series( - data=[10363047.755401008, 21694496.68221325], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( + power_output_exp=pd.Series(data=[10363047.755401008, + 21694496.68221325], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), - **parameters, - ) + **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters["wake_losses_model"] = "wind_farm_efficiency" - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + parameters['wake_losses_model']='wind_farm_efficiency' + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[10920128.570572512, 21273144.336885825], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters - ) + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[10920128.570572512, + 21273144.336885825], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters["smoothing"] = "True" - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + parameters['smoothing']='True' + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[11360309.77979467, 20328652.64490018], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters - ) + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[11360309.77979467, + 20328652.64490018], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[11360309.77979467, 20328652.64490018], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters - ) + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[11360309.77979467, + 20328652.64490018], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters["smoothing_order"] = "turbine_power_curves" - test_cluster = wtc.WindTurbineCluster(**self.test_cluster) + parameters['smoothing_order']='turbine_power_curves' + test_cluster=wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency = 0.9 - power_output_exp = pd.Series( - data=[11373183.797085874, 20325877.105744187], - name="feedin_power_plant", - ) - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters - ) + farm.efficiency=0.9 + power_output_exp=pd.Series(data=[11373183.797085874, + 20325877.105744187], + name='feedin_power_plant') + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) @@ -246,115 +195,80 @@ def test_error_raising(self): # Raise ValueError when aggregated wind farm power curve needs to be # calculated but turbine does not have a power curve - test_turbine_data = { - "hub_height": 100, - "rotor_diameter": 98, - "turbine_type": "V90/2000", - } - test_turbine = wt.WindTurbine(**test_turbine_data) - test_turbine.power_curve = True - test_farm = { - "wind_turbine_fleet": [ - { - "wind_turbine": wt.WindTurbine(**self.test_turbine), - "number_of_turbines": 3, - }, - {"wind_turbine": test_turbine, "number_of_turbines": 3}, - ] - } - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**test_farm) - ) + test_turbine_data={ + 'hub_height': 100, + 'rotor_diameter': 98, + 'turbine_type': 'V90/2000'} + test_turbine=wt.WindTurbine(**test_turbine_data) + test_turbine.power_curve=True + test_farm={'wind_turbine_fleet': + [{'wind_turbine': + wt.WindTurbine(**self.test_turbine), + 'number_of_turbines': 3}, + {'wind_turbine': + test_turbine, + 'number_of_turbines': 3}]} + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**test_farm)) with pytest.raises(ValueError): test_tc_mc.run_model(self.weather_df) # Raise ValueError when neither turbulence intensity nor roughness # length are provided to apply power curve smoothing with standard # deviation method 'turbulence_intensity' - parameters = { - "smoothing": True, - "standard_deviation_method": "turbulence_intensity", - } - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**self.test_farm), **parameters - ) - weather_df = self.weather_df.copy() - weather_df.pop("roughness_length") + parameters={'smoothing': True, + 'standard_deviation_method': 'turbulence_intensity'} + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**self.test_farm), **parameters) + weather_df=self.weather_df.copy() + weather_df.pop('roughness_length') with pytest.raises(ValueError): test_tc_mc.run_model(weather_df) def test_ignore_wake_losses(self): """Run model without wake losses.""" - parameters = { - "wake_losses_model": None, - "smoothing": False, - "standard_deviation_method": "turbulence_intensity", - "smoothing_order": "wind_farm_power_curves", - } + parameters={'wake_losses_model': None, + 'smoothing': False, + 'standard_deviation_method': 'turbulence_intensity', + 'smoothing_order': 'wind_farm_power_curves'} # Test modelchain with default values - test_tc_mc = tc_mc.TurbineClusterModelChain( + test_tc_mc=tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), - **parameters, - ) + **parameters) test_tc_mc.run_model(self.weather_df) def test_wind_turbine_cluster_repr_with_name(self): """Test string representation of WindTurbineCluster with a name.""" - assert "Wind turbine cluster:" in repr( - wtc.WindTurbineCluster(**self.test_cluster) - ) + assert 'Wind turbine cluster:' in repr( + wtc.WindTurbineCluster(**self.test_cluster)) def test_wind_turbine_cluster_repr_without_name(self): """Test string representation of WindTurbineCluster without a name.""" - test_cluster = { - "wind_farms": [ - wf.WindFarm(**self.test_farm), - wf.WindFarm(**self.test_farm_2), - ] - } - assert "Wind turbine cluster with:" in repr( - wtc.WindTurbineCluster(**test_cluster) - ) + test_cluster={'wind_farms': [wf.WindFarm(**self.test_farm), + wf.WindFarm(**self.test_farm_2)]} + assert 'Wind turbine cluster with:' in repr( + wtc.WindTurbineCluster(**test_cluster)) def test_tc_modelchain_with_power_curve_as_dict(self): """Test power curves as dict in TurbineClusterModelChain.run_model()""" - my_turbine = { - "nominal_power": 3e6, - "hub_height": 105, - "power_curve": { - "value": [ - p * 1000 - for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] - ], - "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], - }, - } - my_farm = { - "wind_turbine_fleet": [ - { - "wind_turbine": wt.WindTurbine(**my_turbine), - "number_of_turbines": 3, - }, - { - "wind_turbine": wt.WindTurbine(**self.test_turbine), - "number_of_turbines": 3, - }, - ] - } - my_cluster = { - "wind_farms": [ - wf.WindFarm(**my_farm), - wf.WindFarm(**self.test_farm), - ] - } - power_output_exp = pd.Series( - data=[10853277.966972714, 21731814.593688786], - name="feedin_power_plant", - ) + my_turbine={'nominal_power': 3e6, 'hub_height': 105, + 'power_curve': { + 'value': [p * 1000 for p in [ + 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], + 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} + my_farm={'wind_turbine_fleet': + [{'wind_turbine': wt.WindTurbine(**my_turbine), + 'number_of_turbines': 3}, + {'wind_turbine': wt.WindTurbine(**self.test_turbine), + 'number_of_turbines': 3}]} + my_cluster= {'wind_farms': [wf.WindFarm(**my_farm), + wf.WindFarm(**self.test_farm)]} + power_output_exp=pd.Series(data=[10853277.966972714, + 21731814.593688786], + name='feedin_power_plant') # run model with my_cluster - test_tc_mc = tc_mc.TurbineClusterModelChain( - power_plant=wtc.WindTurbineCluster(**my_cluster) - ) + test_tc_mc=tc_mc.TurbineClusterModelChain( + power_plant=wtc.WindTurbineCluster(**my_cluster)) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) diff --git a/tests/test_wake_losses.py b/tests/test_wake_losses.py index d27fd4a1..951ddcd1 100644 --- a/tests/test_wake_losses.py +++ b/tests/test_wake_losses.py @@ -8,77 +8,49 @@ import pytest from pandas.util.testing import assert_series_equal -from windpowerlib.wake_losses import ( - reduce_wind_speed, - get_wind_efficiency_curve, -) +from windpowerlib.wake_losses import (reduce_wind_speed, + get_wind_efficiency_curve) class TestWakeLosses: + def test_reduce_wind_speed(self): - parameters = { - "wind_speed": pd.Series(np.arange(0, 26, 1.0)), - "wind_efficiency_curve_name": "dena_mean", - } - wind_speed_exp = pd.Series( - [ - 0.0, - 0.9949534234119396, - 1.9897327884892086, - 2.9843374545454546, - 3.807636264984227, - 4.714931284760845, - 5.642507531914893, - 6.607021108049704, - 7.592423167192429, - 8.59498170212766, - 9.606135658475111, - 10.619828799086758, - 11.641291957894737, - 12.674012890137966, - 13.709490666666666, - 14.742508260567297, - 15.773293013157893, - 16.794615009724474, - 17.817683032858028, - 18.85294996704484, - 19.86509539493748, - 20.858807854510186, - 21.854369681134507, - 22.850700350710902, - 23.85962037735849, - 24.958125, - ] - ) + parameters={'wind_speed': pd.Series(np.arange(0, 26, 1.0)), + 'wind_efficiency_curve_name': 'dena_mean'} + wind_speed_exp=pd.Series([ + 0.0, 0.9949534234119396, 1.9897327884892086, 2.9843374545454546, + 3.807636264984227, 4.714931284760845, 5.642507531914893, + 6.607021108049704, 7.592423167192429, 8.59498170212766, + 9.606135658475111, 10.619828799086758, 11.641291957894737, + 12.674012890137966, 13.709490666666666, 14.742508260567297, + 15.773293013157893, 16.794615009724474, 17.817683032858028, + 18.85294996704484, 19.86509539493748, 20.858807854510186, + 21.854369681134507, 22.850700350710902, 23.85962037735849, + 24.958125]) assert_series_equal(reduce_wind_speed(**parameters), wind_speed_exp) # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters["wind_efficiency_curve_name"] = "misspelled" + parameters['wind_efficiency_curve_name']='misspelled' reduce_wind_speed(**parameters) with pytest.raises(ValueError): - parameters["wind_efficiency_curve_name"] = "dena_misspelled" + parameters['wind_efficiency_curve_name']='dena_misspelled' reduce_wind_speed(**parameters) def test_get_wind_efficiency_curve_one(self): """Test get_wind_efficiency_curve() for one curve.""" - wec = get_wind_efficiency_curve("dena_mean").sum() - wec_exp = pd.Series( - {"efficiency": 162.45047, "wind_speed": 1915.23620} - ) + wec=get_wind_efficiency_curve('dena_mean').sum() + wec_exp=pd.Series({'efficiency': 162.45047, + 'wind_speed': 1915.23620}) assert_series_equal(wec.sort_index(), wec_exp.sort_index()) def test_get_wind_efficiency_curve_all(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum = int(get_wind_efficiency_curve("all").sum().round().sum()) + wec_all_sum=int(get_wind_efficiency_curve('all').sum().round().sum()) assert wec_all_sum == 12145 def test_get_wind_efficiency_curve_list(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum = int( - get_wind_efficiency_curve(["dena_mean", "knorr_mean"]) - .sum() - .round() - .sum() - ) + wec_all_sum=int(get_wind_efficiency_curve( + ['dena_mean', 'knorr_mean']).sum().round().sum()) assert wec_all_sum == 3568 diff --git a/tests/test_wind_farm.py b/tests/test_wind_farm.py index b031abcf..a2aa4dba 100644 --- a/tests/test_wind_farm.py +++ b/tests/test_wind_farm.py @@ -11,211 +11,155 @@ class TestWindFarm: + @classmethod def setup_class(self): """Setup default values""" - self.test_turbine = {"hub_height": 100, "turbine_type": "E-126/4200"} - self.test_turbine_2 = { - "hub_height": 90, - "turbine_type": "V90/2000", - "nominal_power": 2e6, - } + self.test_turbine={'hub_height': 100, + 'turbine_type': 'E-126/4200'} + self.test_turbine_2={'hub_height': 90, + 'turbine_type': 'V90/2000', + 'nominal_power': 2e6} def test_initialization_list(self): """test simple initialization with wind turbine fleet list""" - wind_turbine_fleet = [ - { - "wind_turbine": WindTurbine(**self.test_turbine), - "number_of_turbines": 3, - }, - { - "wind_turbine": WindTurbine(**self.test_turbine_2), - "number_of_turbines": 2, - }, - ] - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet=[ + {'wind_turbine': WindTurbine(**self.test_turbine), + 'number_of_turbines': 3}, + {'wind_turbine': WindTurbine(**self.test_turbine_2), + 'number_of_turbines': 2}] + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_list_2(self): """test simple initialization with wind turbine fleet list where once number of turbines and once total capacity is provided""" - wind_turbine_fleet = [ - { - "wind_turbine": WindTurbine(**self.test_turbine), - "number_of_turbines": 3, - }, - { - "wind_turbine": WindTurbine(**self.test_turbine_2), - "total_capacity": 2 * 2e6, - }, - ] - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet=[ + {'wind_turbine': WindTurbine(**self.test_turbine), + 'number_of_turbines': 3}, + {'wind_turbine': WindTurbine(**self.test_turbine_2), + 'total_capacity': 2 * 2e6}] + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_dataframe(self): """test simple initialization with wind turbine fleet dataframe""" - wind_turbine_fleet = pd.DataFrame( - data={ - "wind_turbine": [ - WindTurbine(**self.test_turbine), - WindTurbine(**self.test_turbine_2), - ], - "number_of_turbines": [3, 2], - } - ) - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet=pd.DataFrame( + data={'wind_turbine': [WindTurbine(**self.test_turbine), + WindTurbine(**self.test_turbine_2)], + 'number_of_turbines': [3, 2]}) + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_1(self): """test catching error when wind_turbine_fleet not provided as list""" - msg = "Wind turbine must be provided as WindTurbine object" + msg='Wind turbine must be provided as WindTurbine object' with pytest.raises(ValueError, match=msg): - WindFarm( - wind_turbine_fleet={ - "wind_turbine": "turbine", - "number_of_turbines": 2, - }, - name="dummy", - ) + WindFarm(wind_turbine_fleet={'wind_turbine': 'turbine', + 'number_of_turbines': 2}, + name='dummy') def test_initialization_2(self): """test catching error when WindTurbine in wind_turbine_fleet not initialized""" - test_farm = { - "wind_turbine_fleet": [ - {"wind_turbine": None, "number_of_turbines": 3} - ] - } - msg = "Wind turbine must be provided as WindTurbine object" + test_farm={'wind_turbine_fleet': [ + {'wind_turbine': None, + 'number_of_turbines': 3}]} + msg='Wind turbine must be provided as WindTurbine object' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_3(self): """test catching error when wind_turbine not specified in wind_turbine_fleet""" - wind_turbine_fleet = pd.DataFrame( - data={ - "wind_turbines": [ - WindTurbine(**self.test_turbine), - WindTurbine(**self.test_turbine_2), - ], - "number_of_turbines": [3, 2], - } - ) - msg = "Missing wind_turbine key/column in wind_turbine_fleet" + wind_turbine_fleet=pd.DataFrame( + data={'wind_turbines': [WindTurbine(**self.test_turbine), + WindTurbine(**self.test_turbine_2)], + 'number_of_turbines': [3, 2]}) + msg='Missing wind_turbine key/column in wind_turbine_fleet' with pytest.raises(KeyError, match=msg): WindFarm(wind_turbine_fleet=wind_turbine_fleet) def test_initialization_4(self, recwarn): """test overwriting and raising warning when number_of_turbines and total_capacity in wind turbine fleet do not fit""" - wt1 = WindTurbine(**self.test_turbine) - wt2 = WindTurbine(**self.test_turbine_2) - wind_turbine_fleet = pd.DataFrame( - data={ - "wind_turbine": [wt1, wt2], - "number_of_turbines": [3, 2], - "total_capacity": [3, np.nan], - }, - index=[0, 1], - ) - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) - total_cap_wt1_expected = ( - wt1.nominal_power * wind_turbine_fleet.loc[0, "number_of_turbines"] - ) - assert ( - windfarm.wind_turbine_fleet.loc[0, "total_capacity"] - == total_cap_wt1_expected - ) - total_cap_wt2_expected = ( - wt2.nominal_power * wind_turbine_fleet.loc[1, "number_of_turbines"] - ) - assert ( - windfarm.wind_turbine_fleet.loc[1, "total_capacity"] - == total_cap_wt2_expected - ) + wt1=WindTurbine(**self.test_turbine) + wt2=WindTurbine(**self.test_turbine_2) + wind_turbine_fleet=pd.DataFrame( + data={'wind_turbine': [wt1, wt2], + 'number_of_turbines': [3, 2], + 'total_capacity': [3, np.nan]}, + index=[0, 1]) + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + total_cap_wt1_expected=\ + wt1.nominal_power * wind_turbine_fleet.loc[0, 'number_of_turbines'] + assert windfarm.wind_turbine_fleet.loc[0, 'total_capacity'] == \ + total_cap_wt1_expected + total_cap_wt2_expected=\ + wt2.nominal_power * wind_turbine_fleet.loc[1, 'number_of_turbines'] + assert windfarm.wind_turbine_fleet.loc[1, 'total_capacity'] == \ + total_cap_wt2_expected assert recwarn.pop(WindpowerlibUserWarning) def test_initialization_5(self): """test catching error when number of turbines cannot be deduced""" - wt = WindTurbine(**self.test_turbine) - wt.nominal_power = None - test_farm = { - "wind_turbine_fleet": [{"wind_turbine": wt, "total_capacity": 3e6}] - } - msg = "Number of turbines of type" + wt=WindTurbine(**self.test_turbine) + wt.nominal_power=None + test_farm={'wind_turbine_fleet': [ + {'wind_turbine': wt, + 'total_capacity': 3e6}]} + msg='Number of turbines of type' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_6(self): """test catching error when neither number_of_turbines nor total_capacity is provided""" - test_farm = { - "wind_turbine_fleet": [ - { - "wind_turbine": WindTurbine(**self.test_turbine), - "number_of_turbine": 3e6, - } - ] - } - msg = "Number of turbines of type " + test_farm={'wind_turbine_fleet': [ + {'wind_turbine': WindTurbine(**self.test_turbine), + 'number_of_turbine': 3e6}]} + msg='Number of turbines of type ' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_7(self): """test catching error when total capacity cannot be deduced""" - wt = WindTurbine(**self.test_turbine) - wt.nominal_power = None - test_farm = { - "wind_turbine_fleet": [ - {"wind_turbine": wt, "number_of_turbines": 3} - ] - } - msg = "Total capacity of turbines of type" + wt=WindTurbine(**self.test_turbine) + wt.nominal_power=None + test_farm={'wind_turbine_fleet': [ + {'wind_turbine': wt, + 'number_of_turbines': 3}]} + msg='Total capacity of turbines of type' with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_mean_hub_height(self): """tests mean_hub_height method""" - test_farm = { - "wind_turbine_fleet": [ - { - "wind_turbine": WindTurbine(**self.test_turbine), - "number_of_turbines": 2, - }, - { - "wind_turbine": WindTurbine(**self.test_turbine_2), - "total_capacity": 3e6, - }, - ] - } - windfarm = WindFarm(**test_farm) + test_farm={'wind_turbine_fleet': [ + {'wind_turbine': WindTurbine(**self.test_turbine), + 'number_of_turbines': 2}, + {'wind_turbine': WindTurbine(**self.test_turbine_2), + 'total_capacity': 3e6}]} + windfarm=WindFarm(**test_farm) assert 97.265 == pytest.approx( - windfarm.mean_hub_height().hub_height, 1e-3 - ) + windfarm.mean_hub_height().hub_height, 1e-3) def test_repr(self): """Test string representation of WindFarm""" - test_fleet = [ - { - "wind_turbine": WindTurbine(**self.test_turbine), - "number_of_turbines": 2, - } - ] - assert "E-126/4200" in repr(WindFarm(wind_turbine_fleet=test_fleet)) + test_fleet=[{'wind_turbine': WindTurbine(**self.test_turbine), + 'number_of_turbines': 2}] + assert 'E-126/4200' in repr(WindFarm(wind_turbine_fleet=test_fleet)) def test_aggregation_of_power_curve_with_missing_power_curve(self): """Test WindFarm.assign_power_curve() with missing power_curve.""" - wt1 = WindTurbine(**self.test_turbine) - wt1.power_curve = None - wind_turbine_fleet = [ - {"wind_turbine": wt1, "number_of_turbines": 3}, - { - "wind_turbine": WindTurbine(**self.test_turbine_2), - "number_of_turbines": 2, - }, - ] - windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) - msg = "For an aggregated wind farm power curve each wind" + wt1=WindTurbine(**self.test_turbine) + wt1.power_curve=None + wind_turbine_fleet=[ + {'wind_turbine': wt1, + 'number_of_turbines': 3}, + {'wind_turbine': WindTurbine(**self.test_turbine_2), + 'number_of_turbines': 2}] + windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + msg='For an aggregated wind farm power curve each wind' with pytest.raises(ValueError, match=msg): windfarm.assign_power_curve() diff --git a/tests/test_wind_speed.py b/tests/test_wind_speed.py index f4af4299..88712a3d 100644 --- a/tests/test_wind_speed.py +++ b/tests/test_wind_speed.py @@ -13,104 +13,94 @@ class TestWindSpeed: + def test_logarithmic_profile(self): - parameters = { - "wind_speed": pd.Series(data=[5.0, 6.5]), - "wind_speed_height": 10, - "hub_height": 100, - "roughness_length": pd.Series(data=[0.15, 0.15]), - "obstacle_height": 0, - } + parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), + 'wind_speed_height': 10, + 'hub_height': 100, + 'roughness_length': pd.Series(data=[0.15, 0.15]), + 'obstacle_height': 0} # Test wind_speed as pd.Series with roughness_length as pd.Series, # np.array and float - v_wind_hub_exp = pd.Series(data=[7.74136523, 10.0637748]) - assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) - parameters["roughness_length"] = np.array( - parameters["roughness_length"] - ) - assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) - parameters["roughness_length"] = parameters["roughness_length"][0] - assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) + v_wind_hub_exp=pd.Series(data=[7.74136523, 10.0637748]) + assert_series_equal(logarithmic_profile(**parameters), + v_wind_hub_exp) + parameters['roughness_length']=np.array( + parameters['roughness_length']) + assert_series_equal(logarithmic_profile(**parameters), + v_wind_hub_exp) + parameters['roughness_length']=parameters['roughness_length'][0] + assert_series_equal(logarithmic_profile(**parameters), + v_wind_hub_exp) # Test wind_speed as np.array with roughness_length as float, pd.Series # and np.array - v_wind_hub_exp = np.array([7.74136523, 10.0637748]) - parameters["wind_speed"] = np.array(parameters["wind_speed"]) + v_wind_hub_exp=np.array([7.74136523, 10.0637748]) + parameters['wind_speed']=np.array(parameters['wind_speed']) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters["roughness_length"] = pd.Series( - data=[ - parameters["roughness_length"], - parameters["roughness_length"], - ] - ) + parameters['roughness_length']=pd.Series( + data=[parameters['roughness_length'], + parameters['roughness_length']]) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters["roughness_length"] = np.array( - parameters["roughness_length"] - ) + parameters['roughness_length']=np.array( + parameters['roughness_length']) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) # Test obstacle_height is not zero - v_wind_hub_exp = np.array([13.54925281, 17.61402865]) - parameters["obstacle_height"] = 12 + v_wind_hub_exp=np.array([13.54925281, 17.61402865]) + parameters['obstacle_height']=12 assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) # Raise ValueError due to 0.7 * `obstacle_height` > `wind_speed_height` with pytest.raises(ValueError): - parameters["obstacle_height"] = 20 + parameters['obstacle_height']=20 logarithmic_profile(**parameters) def test_hellman(self): - parameters = { - "wind_speed": pd.Series(data=[5.0, 6.5]), - "wind_speed_height": 10, - "hub_height": 100, - "roughness_length": pd.Series(data=[0.15, 0.15]), - "hellman_exponent": None, - } + parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), + 'wind_speed_height': 10, + 'hub_height': 100, + 'roughness_length': pd.Series(data=[0.15, 0.15]), + 'hellman_exponent': None} # Test wind_speed is pd.Series with roughness_length is pd.Series, # np.array and float - v_wind_hub_exp = pd.Series(data=[7.12462437, 9.26201168]) + v_wind_hub_exp=pd.Series(data=[7.12462437, 9.26201168]) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters["roughness_length"] = np.array( - parameters["roughness_length"] - ) + parameters['roughness_length']=np.array( + parameters['roughness_length']) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters["roughness_length"] = parameters["roughness_length"][0] + parameters['roughness_length']=parameters['roughness_length'][0] assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test wind_speed as np.array with roughness_length is float, pd.Series # and np.array - v_wind_hub_exp = np.array([7.12462437, 9.26201168]) - parameters["wind_speed"] = np.array(parameters["wind_speed"]) + v_wind_hub_exp=np.array([7.12462437, 9.26201168]) + parameters['wind_speed']=np.array(parameters['wind_speed']) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters["roughness_length"] = pd.Series( - data=( - parameters["roughness_length"], - parameters["roughness_length"], - ) - ) + parameters['roughness_length']=pd.Series( + data=(parameters['roughness_length'], + parameters['roughness_length'])) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters["roughness_length"] = np.array( - parameters["roughness_length"] - ) + parameters['roughness_length']=np.array( + parameters['roughness_length']) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) # Test roughness_length is None and hellman_exponent is None - v_wind_hub_exp = pd.Series(data=[6.9474774, 9.03172]) - parameters["wind_speed"] = pd.Series(data=parameters["wind_speed"]) - parameters["roughness_length"] = None + v_wind_hub_exp=pd.Series(data=[6.9474774, 9.03172]) + parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) + parameters['roughness_length']=None assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test hellman_exponent is not None - v_wind_hub_exp = pd.Series(data=[7.92446596, 10.30180575]) - parameters["roughness_length"] = 0.15 - parameters["hellman_exponent"] = 0.2 + v_wind_hub_exp=pd.Series(data=[7.92446596, 10.30180575]) + parameters['roughness_length']=0.15 + parameters['hellman_exponent']=0.2 assert_series_equal(hellman(**parameters), v_wind_hub_exp) diff --git a/tests/test_wind_turbine.py b/tests/test_wind_turbine.py index 1f3acfac..fdcf4472 100644 --- a/tests/test_wind_turbine.py +++ b/tests/test_wind_turbine.py @@ -9,52 +9,47 @@ import os from windpowerlib.tools import WindpowerlibUserWarning -from windpowerlib.wind_turbine import ( - get_turbine_data_from_file, - WindTurbine, - get_turbine_types, - WindTurbineGroup, - load_turbine_data_from_oedb, -) +from windpowerlib.wind_turbine import (get_turbine_data_from_file, WindTurbine, + get_turbine_types, WindTurbineGroup, + load_turbine_data_from_oedb) class TestWindTurbine: + @classmethod def setup_class(cls): """Setup default values""" - cls.source = os.path.join(os.path.dirname(__file__), "../example/data") + cls.source=os.path.join(os.path.dirname(__file__), '../example/data') def test_warning(self, recwarn): - test_turbine_data = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "turbine_not_in_file", - "path": self.source, - } - assert WindTurbine(**test_turbine_data).power_curve is None + test_turbine_data={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'turbine_not_in_file', + 'path': self.source} + assert(WindTurbine(**test_turbine_data).power_curve is None) assert recwarn.pop(WindpowerlibUserWarning) def test_get_turbine_data_from_file(self): # Raise FileNotFoundError due to missing with pytest.raises(FileNotFoundError): - get_turbine_data_from_file(turbine_type="...", path="not_existent") + get_turbine_data_from_file(turbine_type='...', + path='not_existent') def test_get_turbine_types(self, capsys): get_turbine_types() - captured = capsys.readouterr() - assert "Enercon" in captured.out - get_turbine_types("oedb", print_out=False, filter_=False) - msg = "`turbine_library` is 'wrong' but must be 'local' or 'oedb'." + captured=capsys.readouterr() + assert 'Enercon' in captured.out + get_turbine_types('oedb', print_out=False, filter_=False) + msg="`turbine_library` is 'wrong' but must be 'local' or 'oedb'." with pytest.raises(ValueError, match=msg): - get_turbine_types("wrong") + get_turbine_types('wrong') def test_wrong_url_load_turbine_data(self): """Load turbine data from oedb.""" - with pytest.raises( - ConnectionError, match="Database connection not successful" - ): - load_turbine_data_from_oedb("wrong_schema") + with pytest.raises(ConnectionError, + match="Database connection not successful"): + load_turbine_data_from_oedb('wrong_schema') @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_string_representation_of_wind_turbine(self): @@ -62,51 +57,43 @@ def test_string_representation_of_wind_turbine(self): def test_power_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_curve.""" - test_turbine_data = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "test_type", - "power_curve": "string", - } + test_turbine_data={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'test_type', + 'power_curve': 'string'} with pytest.raises(TypeError): WindTurbine(**test_turbine_data) def test_power_coefficient_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_coefficient_curve.""" - test_turbine_data = { - "hub_height": 100, - "rotor_diameter": 80, - "turbine_type": "test_type", - "power_coefficient_curve": "string", - } + test_turbine_data={'hub_height': 100, + 'rotor_diameter': 80, + 'turbine_type': 'test_type', + 'power_coefficient_curve': 'string'} with pytest.raises(TypeError): WindTurbine(**test_turbine_data) def test_to_group_method(self): - example_turbine = { - "hub_height": 100, - "rotor_diameter": 70, - "turbine_type": "DUMMY 3", - "path": self.source, - } - e_t_1 = WindTurbine(**example_turbine) - assert isinstance(e_t_1.to_group(), WindTurbineGroup) - assert e_t_1.to_group(5).number_of_turbines == 5 - assert e_t_1.to_group(number_turbines=5).number_of_turbines == 5 - assert e_t_1.to_group(total_capacity=3e6).number_of_turbines == 2.0 + example_turbine={ + 'hub_height': 100, + 'rotor_diameter': 70, + 'turbine_type': 'DUMMY 3', + 'path': self.source} + e_t_1=WindTurbine(**example_turbine) + assert(isinstance(e_t_1.to_group(), WindTurbineGroup)) + assert(e_t_1.to_group(5).number_of_turbines == 5) + assert(e_t_1.to_group(number_turbines=5).number_of_turbines == 5) + assert(e_t_1.to_group(total_capacity=3e6).number_of_turbines == 2.0) def test_wrongly_defined_to_group_method(self): - example_turbine = { - "hub_height": 100, - "rotor_diameter": 70, - "turbine_type": "DUMMY 3", - "path": self.source, - } - e_t_1 = WindTurbine(**example_turbine) - with pytest.raises( - ValueError, - match="The 'number' and the 'total_capacity' " - "parameter are mutually exclusive.", - ): + example_turbine={ + 'hub_height': 100, + 'rotor_diameter': 70, + 'turbine_type': 'DUMMY 3', + 'path': self.source} + e_t_1=WindTurbine(**example_turbine) + with pytest.raises(ValueError, + match="The 'number' and the 'total_capacity' " + "parameter are mutually exclusive."): e_t_1.to_group(5, 3000) diff --git a/windpowerlib/__init__.py b/windpowerlib/__init__.py index a206ff5a..7ffd29ce 100644 --- a/windpowerlib/__init__.py +++ b/windpowerlib/__init__.py @@ -1,6 +1,6 @@ -__copyright__ = "Copyright oemof developer group" -__license__ = "MIT" -__version__ = "0.2.1dev" +__copyright__="Copyright oemof developer group" +__license__="MIT" +__version__='0.2.1dev' from windpowerlib.wind_turbine import WindTurbine from windpowerlib.wind_farm import WindFarm diff --git a/windpowerlib/modelchain.py b/windpowerlib/modelchain.py index d87b5ff5..e137934a 100644 --- a/windpowerlib/modelchain.py +++ b/windpowerlib/modelchain.py @@ -134,28 +134,24 @@ class ModelChain(object): """ - def __init__( - self, - power_plant, - wind_speed_model="logarithmic", - temperature_model="linear_gradient", - density_model="barometric", - power_output_model="power_curve", - density_correction=False, - obstacle_height=0, - hellman_exp=None, - **kwargs, - ): - - self.power_plant = power_plant - self.obstacle_height = obstacle_height - self.wind_speed_model = wind_speed_model - self.temperature_model = temperature_model - self.density_model = density_model - self.power_output_model = power_output_model - self.density_correction = density_correction - self.hellman_exp = hellman_exp - self.power_output = None + def __init__(self, power_plant, + wind_speed_model='logarithmic', + temperature_model='linear_gradient', + density_model='barometric', + power_output_model='power_curve', + density_correction=False, + obstacle_height=0, + hellman_exp=None, **kwargs): + + self.power_plant=power_plant + self.obstacle_height=obstacle_height + self.wind_speed_model=wind_speed_model + self.temperature_model=temperature_model + self.density_model=density_model + self.power_output_model=power_output_model + self.density_correction=density_correction + self.hellman_exp=hellman_exp + self.power_output=None def temperature_hub(self, weather_df): r""" @@ -186,42 +182,28 @@ def temperature_hub(self, weather_df): temperature(s) closest to the hub height are used. """ - if self.power_plant.hub_height in weather_df["temperature"]: - temperature_hub = weather_df["temperature"][ - self.power_plant.hub_height - ] - elif self.temperature_model == "linear_gradient": - logging.debug( - "Calculating temperature using temperature " "gradient." - ) - closest_height = weather_df["temperature"].columns[ - min( - range(len(weather_df["temperature"].columns)), - key=lambda i: abs( - weather_df["temperature"].columns[i] - - self.power_plant.hub_height - ), - ) - ] - temperature_hub = temperature.linear_gradient( - weather_df["temperature"][closest_height], - closest_height, - self.power_plant.hub_height, - ) - elif self.temperature_model == "interpolation_extrapolation": - logging.debug( - "Calculating temperature using linear inter- or " - "extrapolation." - ) - temperature_hub = tools.linear_interpolation_extrapolation( - weather_df["temperature"], self.power_plant.hub_height - ) + if self.power_plant.hub_height in weather_df['temperature']: + temperature_hub=weather_df['temperature'][ + self.power_plant.hub_height] + elif self.temperature_model == 'linear_gradient': + logging.debug('Calculating temperature using temperature ' + 'gradient.') + closest_height=weather_df['temperature'].columns[ + min(range(len(weather_df['temperature'].columns)), + key=lambda i: abs(weather_df['temperature'].columns[i] - + self.power_plant.hub_height))] + temperature_hub=temperature.linear_gradient( + weather_df['temperature'][closest_height], closest_height, + self.power_plant.hub_height) + elif self.temperature_model == 'interpolation_extrapolation': + logging.debug('Calculating temperature using linear inter- or ' + 'extrapolation.') + temperature_hub=tools.linear_interpolation_extrapolation( + weather_df['temperature'], self.power_plant.hub_height) else: - raise ValueError( - "'{0}' is an invalid value. ".format(self.temperature_model) - + "`temperature_model` must be " - "'linear_gradient' or 'interpolation_extrapolation'." - ) + raise ValueError("'{0}' is an invalid value. ".format( + self.temperature_model) + "`temperature_model` must be " + "'linear_gradient' or 'interpolation_extrapolation'.") return temperature_hub def density_hub(self, weather_df): @@ -259,60 +241,39 @@ def density_hub(self, weather_df): hub height, the `weather_df` must contain at least two time series for density. """ - if self.density_model != "interpolation_extrapolation": - temperature_hub = self.temperature_hub(weather_df) + if self.density_model != 'interpolation_extrapolation': + temperature_hub=self.temperature_hub(weather_df) # Calculation of density in kg/m³ at hub height - if self.density_model == "barometric": - logging.debug( - "Calculating density using barometric height " "equation." - ) - closest_height = weather_df["pressure"].columns[ - min( - range(len(weather_df["pressure"].columns)), - key=lambda i: abs( - weather_df["pressure"].columns[i] - - self.power_plant.hub_height - ), - ) - ] - density_hub = density.barometric( - weather_df["pressure"][closest_height], - closest_height, - self.power_plant.hub_height, - temperature_hub, - ) - elif self.density_model == "ideal_gas": - logging.debug("Calculating density using ideal gas equation.") - closest_height = weather_df["pressure"].columns[ - min( - range(len(weather_df["pressure"].columns)), - key=lambda i: abs( - weather_df["pressure"].columns[i] - - self.power_plant.hub_height - ), - ) - ] - density_hub = density.ideal_gas( - weather_df["pressure"][closest_height], - closest_height, - self.power_plant.hub_height, - temperature_hub, - ) - elif self.density_model == "interpolation_extrapolation": - logging.debug( - "Calculating density using linear inter- or " "extrapolation." - ) - density_hub = tools.linear_interpolation_extrapolation( - weather_df["density"], self.power_plant.hub_height - ) + if self.density_model == 'barometric': + logging.debug('Calculating density using barometric height ' + 'equation.') + closest_height=weather_df['pressure'].columns[ + min(range(len(weather_df['pressure'].columns)), + key=lambda i: abs(weather_df['pressure'].columns[i] - + self.power_plant.hub_height))] + density_hub=density.barometric( + weather_df['pressure'][closest_height], closest_height, + self.power_plant.hub_height, temperature_hub) + elif self.density_model == 'ideal_gas': + logging.debug('Calculating density using ideal gas equation.') + closest_height=weather_df['pressure'].columns[ + min(range(len(weather_df['pressure'].columns)), + key=lambda i: abs(weather_df['pressure'].columns[i] - + self.power_plant.hub_height))] + density_hub=density.ideal_gas( + weather_df['pressure'][closest_height], closest_height, + self.power_plant.hub_height, temperature_hub) + elif self.density_model == 'interpolation_extrapolation': + logging.debug('Calculating density using linear inter- or ' + 'extrapolation.') + density_hub=tools.linear_interpolation_extrapolation( + weather_df['density'], self.power_plant.hub_height) else: - raise ValueError( - "'{0}' is an invalid value. ".format(self.density_model) - + "`density_model` " - + "must be 'barometric', 'ideal_gas' or " - + "'interpolation_extrapolation'." - ) + raise ValueError("'{0}' is an invalid value. ".format( + self.density_model) + "`density_model` " + + "must be 'barometric', 'ideal_gas' or " + + "'interpolation_extrapolation'.") return density_hub def wind_speed_hub(self, weather_df): @@ -344,71 +305,47 @@ def wind_speed_hub(self, weather_df): wind speed(s) closest to the hub height are used. """ - if self.power_plant.hub_height in weather_df["wind_speed"]: - wind_speed_hub = weather_df["wind_speed"][ - self.power_plant.hub_height - ] - elif self.wind_speed_model == "logarithmic": - logging.debug( - "Calculating wind speed using logarithmic wind " "profile." - ) - closest_height = weather_df["wind_speed"].columns[ - min( - range(len(weather_df["wind_speed"].columns)), - key=lambda i: abs( - weather_df["wind_speed"].columns[i] - - self.power_plant.hub_height - ), - ) - ] - wind_speed_hub = wind_speed.logarithmic_profile( - weather_df["wind_speed"][closest_height], - closest_height, + if self.power_plant.hub_height in weather_df['wind_speed']: + wind_speed_hub=weather_df['wind_speed'][ + self.power_plant.hub_height] + elif self.wind_speed_model == 'logarithmic': + logging.debug('Calculating wind speed using logarithmic wind ' + 'profile.') + closest_height=weather_df['wind_speed'].columns[ + min(range(len(weather_df['wind_speed'].columns)), + key=lambda i: abs(weather_df['wind_speed'].columns[i] - + self.power_plant.hub_height))] + wind_speed_hub=wind_speed.logarithmic_profile( + weather_df['wind_speed'][closest_height], closest_height, self.power_plant.hub_height, - weather_df["roughness_length"].iloc[:, 0], - self.obstacle_height, - ) - elif self.wind_speed_model == "hellman": - logging.debug("Calculating wind speed using hellman equation.") - closest_height = weather_df["wind_speed"].columns[ - min( - range(len(weather_df["wind_speed"].columns)), - key=lambda i: abs( - weather_df["wind_speed"].columns[i] - - self.power_plant.hub_height - ), - ) - ] - wind_speed_hub = wind_speed.hellman( - weather_df["wind_speed"][closest_height], - closest_height, + weather_df['roughness_length'].iloc[:, 0], + self.obstacle_height) + elif self.wind_speed_model == 'hellman': + logging.debug('Calculating wind speed using hellman equation.') + closest_height=weather_df['wind_speed'].columns[ + min(range(len(weather_df['wind_speed'].columns)), + key=lambda i: abs(weather_df['wind_speed'].columns[i] - + self.power_plant.hub_height))] + wind_speed_hub=wind_speed.hellman( + weather_df['wind_speed'][closest_height], closest_height, self.power_plant.hub_height, - weather_df["roughness_length"].iloc[:, 0], - self.hellman_exp, - ) - elif self.wind_speed_model == "interpolation_extrapolation": - logging.debug( - "Calculating wind speed using linear inter- or " - "extrapolation." - ) - wind_speed_hub = tools.linear_interpolation_extrapolation( - weather_df["wind_speed"], self.power_plant.hub_height - ) - elif self.wind_speed_model == "log_interpolation_extrapolation": - logging.debug( - "Calculating wind speed using logarithmic inter- or " - "extrapolation." - ) - wind_speed_hub = tools.logarithmic_interpolation_extrapolation( - weather_df["wind_speed"], self.power_plant.hub_height - ) + weather_df['roughness_length'].iloc[:, 0], + self.hellman_exp) + elif self.wind_speed_model == 'interpolation_extrapolation': + logging.debug('Calculating wind speed using linear inter- or ' + 'extrapolation.') + wind_speed_hub=tools.linear_interpolation_extrapolation( + weather_df['wind_speed'], self.power_plant.hub_height) + elif self.wind_speed_model == 'log_interpolation_extrapolation': + logging.debug('Calculating wind speed using logarithmic inter- or ' + 'extrapolation.') + wind_speed_hub=tools.logarithmic_interpolation_extrapolation( + weather_df['wind_speed'], self.power_plant.hub_height) else: - raise ValueError( - "'{0}' is an invalid value. ".format(self.wind_speed_model) - + "`wind_speed_model` must be " - "'logarithmic', 'hellman', 'interpolation_extrapolation' " - + "or 'log_interpolation_extrapolation'." - ) + raise ValueError("'{0}' is an invalid value. ".format( + self.wind_speed_model) + "`wind_speed_model` must be " + "'logarithmic', 'hellman', 'interpolation_extrapolation' " + + "or 'log_interpolation_extrapolation'.") return wind_speed_hub def calculate_power_output(self, wind_speed_hub, density_hub): @@ -430,43 +367,34 @@ def calculate_power_output(self, wind_speed_hub, density_hub): Electrical power output of the wind turbine in W. """ - if self.power_output_model == "power_curve": + if self.power_output_model == 'power_curve': if self.power_plant.power_curve is None: - raise TypeError( - "Power curve values of {} are missing.".format( - self.power_plant - ) - ) - logging.debug("Calculating power output using power curve.") - return power_output.power_curve( - wind_speed_hub, - self.power_plant.power_curve["wind_speed"], - self.power_plant.power_curve["value"], - density_hub, - self.density_correction, - ) - elif self.power_output_model == "power_coefficient_curve": + raise TypeError("Power curve values of {} are missing.".format( + self.power_plant)) + logging.debug('Calculating power output using power curve.') + return (power_output.power_curve( + wind_speed_hub, + self.power_plant.power_curve['wind_speed'], + self.power_plant.power_curve['value'], + density_hub, self.density_correction)) + elif self.power_output_model == 'power_coefficient_curve': if self.power_plant.power_coefficient_curve is None: - raise TypeError( - "Power coefficient curve values of {} are " - "missing.".format(self.power_plant) - ) - logging.debug( - "Calculating power output using power coefficient " "curve." - ) - return power_output.power_coefficient_curve( - wind_speed_hub, - self.power_plant.power_coefficient_curve["wind_speed"], - self.power_plant.power_coefficient_curve["value"], - self.power_plant.rotor_diameter, - density_hub, - ) + raise TypeError("Power coefficient curve values of {} are " + "missing.".format(self.power_plant)) + logging.debug('Calculating power output using power coefficient ' + 'curve.') + return (power_output.power_coefficient_curve( + wind_speed_hub, + self.power_plant.power_coefficient_curve[ + 'wind_speed'], + self.power_plant.power_coefficient_curve[ + 'value'], + self.power_plant.rotor_diameter, density_hub)) else: - raise ValueError( - "'{0}' is an invalid value. ".format(self.power_output_model) - + "`power_output_model` must be " - + "'power_curve' or 'power_coefficient_curve'." - ) + raise ValueError("'{0}' is an invalid value. ".format( + self.power_output_model) + + "`power_output_model` must be " + + "'power_curve' or 'power_coefficient_curve'.") def run_model(self, weather_df): r""" @@ -510,16 +438,10 @@ def run_model(self, weather_df): 'wind_speed' """ - wind_speed_hub = self.wind_speed_hub(weather_df) - density_hub = ( - None - if ( - self.power_output_model == "power_curve" - and self.density_correction is False - ) - else self.density_hub(weather_df) - ) - self.power_output = self.calculate_power_output( - wind_speed_hub, density_hub - ) + wind_speed_hub=self.wind_speed_hub(weather_df) + density_hub=(None if (self.power_output_model == 'power_curve' and + self.density_correction is False) + else self.density_hub(weather_df)) + self.power_output=self.calculate_power_output(wind_speed_hub, + density_hub) return self diff --git a/windpowerlib/power_curves.py b/windpowerlib/power_curves.py index ef9eb138..0aa6acaf 100644 --- a/windpowerlib/power_curves.py +++ b/windpowerlib/power_curves.py @@ -110,98 +110,70 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, """ # Specify normalized standard deviation - if standard_deviation_method == "turbulence_intensity": - if ( - "turbulence_intensity" in kwargs - and kwargs["turbulence_intensity"] is not np.nan - ): - normalized_standard_deviation = kwargs["turbulence_intensity"] + if standard_deviation_method == 'turbulence_intensity': + if ('turbulence_intensity' in kwargs and + kwargs['turbulence_intensity'] is not np.nan): + normalized_standard_deviation=kwargs['turbulence_intensity'] else: - raise ValueError( - "Turbulence intensity must be defined for " - + "using 'turbulence_intensity' as " - + "`standard_deviation_method`" - ) - elif standard_deviation_method == "Staffell_Pfenninger": - normalized_standard_deviation = 0.2 + raise ValueError("Turbulence intensity must be defined for " + + "using 'turbulence_intensity' as " + + "`standard_deviation_method`") + elif standard_deviation_method == 'Staffell_Pfenninger': + normalized_standard_deviation=0.2 else: - raise ValueError( - "{} is no valid `standard_deviation_method`. Valid " - + "options are 'turbulence_intensity', or " - + "'Staffell_Pfenninger'".format(standard_deviation_method) - ) + raise ValueError("{} is no valid `standard_deviation_method`. Valid " + + "options are 'turbulence_intensity', or " + + "'Staffell_Pfenninger'".format( + standard_deviation_method)) # Initialize list for power curve values - smoothed_power_curve_values = [] + smoothed_power_curve_values=[] # Append wind speeds to `power_curve_wind_speeds` - maximum_value = power_curve_wind_speeds.iloc[-1] + wind_speed_range + maximum_value=power_curve_wind_speeds.iloc[-1] + wind_speed_range while power_curve_wind_speeds.values[-1] < maximum_value: - power_curve_wind_speeds = power_curve_wind_speeds.append( - pd.Series( - power_curve_wind_speeds.iloc[-1] - + ( - power_curve_wind_speeds.iloc[5] - - power_curve_wind_speeds.iloc[4] - ), - index=[power_curve_wind_speeds.index[-1] + 1], - ) - ) - power_curve_values = power_curve_values.append( - pd.Series(0.0, index=[power_curve_values.index[-1] + 1]) - ) + power_curve_wind_speeds=power_curve_wind_speeds.append( + pd.Series(power_curve_wind_speeds.iloc[-1] + + (power_curve_wind_speeds.iloc[5] - + power_curve_wind_speeds.iloc[4]), + index=[power_curve_wind_speeds.index[-1] + 1])) + power_curve_values=power_curve_values.append( + pd.Series(0.0, index=[power_curve_values.index[-1] + 1])) for power_curve_wind_speed in power_curve_wind_speeds: # Create array of wind speeds for the sum - wind_speeds_block = ( - np.arange( - -wind_speed_range, wind_speed_range + block_width, block_width - ) - + power_curve_wind_speed - ) + wind_speeds_block=(np.arange( + -wind_speed_range, wind_speed_range + block_width, block_width) + + power_curve_wind_speed) # Get standard deviation for Gauss function - standard_deviation = ( + standard_deviation=( (power_curve_wind_speed * normalized_standard_deviation + 0.6) - if standard_deviation_method is "Staffell_Pfenninger" - else power_curve_wind_speed * normalized_standard_deviation - ) + if standard_deviation_method is 'Staffell_Pfenninger' + else power_curve_wind_speed * normalized_standard_deviation) # Get the smoothed value of the power output if standard_deviation == 0.0: # The gaussian distribution is not defined for a standard deviation # of zero. Smoothed power curve value is set to zero. - smoothed_value = 0.0 + smoothed_value=0.0 else: - smoothed_value = sum( - block_width - * np.interp( - wind_speed, - power_curve_wind_speeds, - power_curve_values, - left=0, - right=0, - ) - * tools.gauss_distribution( + smoothed_value=sum( + block_width * np.interp(wind_speed, power_curve_wind_speeds, + power_curve_values, left=0, right=0) * + tools.gauss_distribution( power_curve_wind_speed - wind_speed, - standard_deviation, - mean_gauss, - ) - for wind_speed in wind_speeds_block - ) + standard_deviation, mean_gauss) + for wind_speed in wind_speeds_block) # Add value to list - add zero if `smoothed_value` is nan as Gauss # distribution for a standard deviation of zero. smoothed_power_curve_values.append(smoothed_value) # Create smoothed power curve data frame - smoothed_power_curve_df = pd.DataFrame( - data=[ - list(power_curve_wind_speeds.values), - smoothed_power_curve_values, - ] - ).transpose() + smoothed_power_curve_df=pd.DataFrame( + data=[list(power_curve_wind_speeds.values), + smoothed_power_curve_values]).transpose() # Rename columns of the data frame - smoothed_power_curve_df.columns = ["wind_speed", "value"] + smoothed_power_curve_df.columns=['wind_speed', 'value'] return smoothed_power_curve_df -def wake_losses_to_power_curve( - power_curve_wind_speeds, power_curve_values, wind_farm_efficiency -): +def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values, + wind_farm_efficiency): r""" Reduces the power values of a power curve by an efficiency (curve). @@ -228,36 +200,27 @@ def wake_losses_to_power_curve( """ # Create power curve DataFrame - power_curve_df = pd.DataFrame( - data=[list(power_curve_wind_speeds), list(power_curve_values)] - ).transpose() + power_curve_df=pd.DataFrame( + data=[list(power_curve_wind_speeds), + list(power_curve_values)]).transpose() # Rename columns of DataFrame - power_curve_df.columns = ["wind_speed", "value"] + power_curve_df.columns=['wind_speed', 'value'] if isinstance(wind_farm_efficiency, float): - power_curve_df["value"] = power_curve_values * wind_farm_efficiency - elif isinstance(wind_farm_efficiency, dict) or isinstance( - wind_farm_efficiency, pd.DataFrame - ): - df = pd.concat( - [ - power_curve_df.set_index("wind_speed"), - wind_farm_efficiency.set_index("wind_speed"), - ], - axis=1, - ) + power_curve_df['value']=power_curve_values * wind_farm_efficiency + elif (isinstance(wind_farm_efficiency, dict) or + isinstance(wind_farm_efficiency, pd.DataFrame)): + df=pd.concat([power_curve_df.set_index('wind_speed'), + wind_farm_efficiency.set_index('wind_speed')], axis=1) # Add column with reduced power (nan values of efficiency are # interpolated) - df["reduced_power"] = df["value"] * df["efficiency"].interpolate( - method="index" - ) - reduced_power = df["reduced_power"].dropna() - power_curve_df = pd.DataFrame( - [reduced_power.index, reduced_power.values] - ).transpose() - power_curve_df.columns = ["wind_speed", "value"] + df['reduced_power']=df['value'] * df['efficiency'].interpolate( + method='index') + reduced_power=df['reduced_power'].dropna() + power_curve_df=pd.DataFrame([reduced_power.index, + reduced_power.values]).transpose() + power_curve_df.columns=['wind_speed', 'value'] else: raise TypeError( "'wind_farm_efficiency' must be float, dict or pd.DataFrame " - "but is {}".format(type(wind_farm_efficiency)) - ) + "but is {}".format(type(wind_farm_efficiency))) return power_curve_df diff --git a/windpowerlib/power_output.py b/windpowerlib/power_output.py index a9554020..ba446e6a 100644 --- a/windpowerlib/power_output.py +++ b/windpowerlib/power_output.py @@ -63,41 +63,23 @@ def power_coefficient_curve(wind_speed, power_coefficient_curve_wind_speeds, Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 542 """ - power_coefficient_time_series = np.interp( - wind_speed, - power_coefficient_curve_wind_speeds, - power_coefficient_curve_values, - left=0, - right=0, - ) - power_output = ( - 1 - / 8 - * density - * rotor_diameter ** 2 - * np.pi - * np.power(wind_speed, 3) - * power_coefficient_time_series - ) + power_coefficient_time_series=np.interp( + wind_speed, power_coefficient_curve_wind_speeds, + power_coefficient_curve_values, left=0, right=0) + power_output=(1 / 8 * density * rotor_diameter ** 2 * np.pi * + np.power(wind_speed, 3) * + power_coefficient_time_series) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output = pd.Series( - data=power_output, - index=wind_speed.index, - name="feedin_power_plant", - ) + power_output=pd.Series(data=power_output, index=wind_speed.index, + name='feedin_power_plant') else: - power_output = np.array(power_output) + power_output=np.array(power_output) return power_output -def power_curve( - wind_speed, - power_curve_wind_speeds, - power_curve_values, - density=None, - density_correction=False, -): +def power_curve(wind_speed, power_curve_wind_speeds, power_curve_values, + density=None, density_correction=False): r""" Calculates the turbine power output using a power curve. @@ -138,38 +120,26 @@ def power_curve( """ if density_correction is False: - power_output = np.interp( - wind_speed, - power_curve_wind_speeds, - power_curve_values, - left=0, - right=0, - ) + power_output=np.interp(wind_speed, power_curve_wind_speeds, + power_curve_values, left=0, right=0) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output = pd.Series( - data=power_output, - index=wind_speed.index, - name="feedin_power_plant", - ) + power_output=pd.Series(data=power_output, index=wind_speed.index, + name='feedin_power_plant') else: - power_output = np.array(power_output) + power_output=np.array(power_output) elif density_correction is True: - power_output = power_curve_density_correction( - wind_speed, power_curve_wind_speeds, power_curve_values, density - ) + power_output=power_curve_density_correction( + wind_speed, power_curve_wind_speeds, power_curve_values, density) else: - raise TypeError( - "'{0}' is an invalid type. ".format(type(density_correction)) - + "`density_correction` must " - + "be Boolean (True or False)." - ) + raise TypeError("'{0}' is an invalid type. ".format(type( + density_correction)) + "`density_correction` must " + + "be Boolean (True or False).") return power_output -def power_curve_density_correction( - wind_speed, power_curve_wind_speeds, power_curve_values, density -): +def power_curve_density_correction(wind_speed, power_curve_wind_speeds, + power_curve_values, density): r""" Calculates the turbine power output using a density corrected power curve. diff --git a/windpowerlib/tools.py b/windpowerlib/tools.py index faab0202..3d4c593c 100644 --- a/windpowerlib/tools.py +++ b/windpowerlib/tools.py @@ -78,15 +78,12 @@ def linear_interpolation_extrapolation(df, target_height): """ # find closest heights - heights_sorted = df.columns[ - sorted( - range(len(df.columns)), - key=lambda i: abs(df.columns[i] - target_height), - ) - ] - return (df[heights_sorted[1]] - df[heights_sorted[0]]) / ( - heights_sorted[1] - heights_sorted[0] - ) * (target_height - heights_sorted[0]) + df[heights_sorted[0]] + heights_sorted=df.columns[ + sorted(range(len(df.columns)), + key=lambda i: abs(df.columns[i] - target_height))] + return ((df[heights_sorted[1]] - df[heights_sorted[0]]) / + (heights_sorted[1] - heights_sorted[0]) * + (target_height - heights_sorted[0]) + df[heights_sorted[0]]) def logarithmic_interpolation_extrapolation(df, target_height): @@ -135,17 +132,14 @@ def logarithmic_interpolation_extrapolation(df, target_height): """ # find closest heights - heights_sorted = df.columns[ - sorted( - range(len(df.columns)), - key=lambda i: abs(df.columns[i] - target_height), - ) - ] - return ( - np.log(target_height) * (df[heights_sorted[1]] - df[heights_sorted[0]]) - - df[heights_sorted[1]] * np.log(heights_sorted[0]) - + df[heights_sorted[0]] * np.log(heights_sorted[1]) - ) / (np.log(heights_sorted[1]) - np.log(heights_sorted[0])) + heights_sorted=df.columns[ + sorted(range(len(df.columns)), + key=lambda i: abs(df.columns[i] - target_height))] + return ((np.log(target_height) * + (df[heights_sorted[1]] - df[heights_sorted[0]]) - + df[heights_sorted[1]] * np.log(heights_sorted[0]) + + df[heights_sorted[0]] * np.log(heights_sorted[1])) / + (np.log(heights_sorted[1]) - np.log(heights_sorted[0]))) def gauss_distribution(function_variable, standard_deviation, mean=0): diff --git a/windpowerlib/turbine_cluster_modelchain.py b/windpowerlib/turbine_cluster_modelchain.py index ed113b81..4d978d3a 100644 --- a/windpowerlib/turbine_cluster_modelchain.py +++ b/windpowerlib/turbine_cluster_modelchain.py @@ -142,28 +142,21 @@ class TurbineClusterModelChain(ModelChain): Used to set `hellman_exponent` in :func:`~.wind_speed.hellman`. """ - - def __init__( - self, - power_plant, - wake_losses_model="dena_mean", - smoothing=False, - block_width=0.5, - standard_deviation_method="turbulence_intensity", - smoothing_order="wind_farm_power_curves", - **kwargs, - ): + def __init__(self, power_plant, wake_losses_model='dena_mean', + smoothing=False, block_width=0.5, + standard_deviation_method='turbulence_intensity', + smoothing_order='wind_farm_power_curves', **kwargs): super(TurbineClusterModelChain, self).__init__(power_plant, **kwargs) - self.power_plant = power_plant - self.wake_losses_model = wake_losses_model - self.smoothing = smoothing - self.block_width = block_width - self.standard_deviation_method = standard_deviation_method - self.smoothing_order = smoothing_order + self.power_plant=power_plant + self.wake_losses_model=wake_losses_model + self.smoothing=smoothing + self.block_width=block_width + self.standard_deviation_method=standard_deviation_method + self.smoothing_order=smoothing_order - self.power_curve = None - self.power_output = None + self.power_curve=None + self.power_output=None def assign_power_curve(self, weather_df): r""" @@ -193,55 +186,40 @@ def assign_power_curve(self, weather_df): """ # Get turbulence intensity from weather if existent - turbulence_intensity = ( - weather_df["turbulence_intensity"].values.mean() - if "turbulence_intensity" in weather_df.columns.get_level_values(0) - else None - ) - roughness_length = ( - weather_df["roughness_length"].values.mean() - if "roughness_length" in weather_df.columns.get_level_values(0) - else None - ) + turbulence_intensity=( + weather_df['turbulence_intensity'].values.mean() if + 'turbulence_intensity' in + weather_df.columns.get_level_values(0) else None) + roughness_length=( + weather_df['roughness_length'].values.mean() if + 'roughness_length' in weather_df.columns.get_level_values(0) else + None) # Assign power curve - if ( - self.wake_losses_model == "wind_farm_efficiency" - or self.wake_losses_model is None - ): - wake_losses_model_to_power_curve = self.wake_losses_model + if (self.wake_losses_model == 'wind_farm_efficiency' or + self.wake_losses_model is None): + wake_losses_model_to_power_curve=self.wake_losses_model if self.wake_losses_model is None: - logging.debug("Wake losses in wind farms are not considered.") + logging.debug('Wake losses in wind farms are not considered.') else: - logging.debug( - "Wake losses considered with {}.".format( - self.wake_losses_model - ) - ) + logging.debug('Wake losses considered with {}.'.format( + self.wake_losses_model)) else: - logging.debug( - "Wake losses considered by {} wind ".format( - self.wake_losses_model - ) - + "efficiency curve." - ) - wake_losses_model_to_power_curve = None + logging.debug('Wake losses considered by {} wind '.format( + self.wake_losses_model) + 'efficiency curve.') + wake_losses_model_to_power_curve=None self.power_plant.assign_power_curve( wake_losses_model=wake_losses_model_to_power_curve, - smoothing=self.smoothing, - block_width=self.block_width, + smoothing=self.smoothing, block_width=self.block_width, standard_deviation_method=self.standard_deviation_method, smoothing_order=self.smoothing_order, roughness_length=roughness_length, - turbulence_intensity=turbulence_intensity, - ) + turbulence_intensity=turbulence_intensity) # Further logging messages if self.smoothing is False: - logging.debug("Aggregated power curve not smoothed.") + logging.debug('Aggregated power curve not smoothed.') else: - logging.debug( - "Aggregated power curve smoothed by method: " - + self.standard_deviation_method - ) + logging.debug('Aggregated power curve smoothed by method: ' + + self.standard_deviation_method) return self @@ -291,25 +269,16 @@ def run_model(self, weather_df): self.assign_power_curve(weather_df) self.power_plant.mean_hub_height() - wind_speed_hub = self.wind_speed_hub(weather_df) - density_hub = ( - None - if ( - self.power_output_model == "power_curve" - and self.density_correction is False - ) - else self.density_hub(weather_df) - ) - if ( - self.wake_losses_model != "wind_farm_efficiency" - and self.wake_losses_model is not None - ): + wind_speed_hub=self.wind_speed_hub(weather_df) + density_hub=(None if (self.power_output_model == 'power_curve' and + self.density_correction is False) + else self.density_hub(weather_df)) + if (self.wake_losses_model != 'wind_farm_efficiency' and + self.wake_losses_model is not None): # Reduce wind speed with wind efficiency curve - wind_speed_hub = wake_losses.reduce_wind_speed( + wind_speed_hub=wake_losses.reduce_wind_speed( wind_speed_hub, - wind_efficiency_curve_name=self.wake_losses_model, - ) - self.power_output = self.calculate_power_output( - wind_speed_hub, density_hub - ) + wind_efficiency_curve_name=self.wake_losses_model) + self.power_output=self.calculate_power_output(wind_speed_hub, + density_hub) return self diff --git a/windpowerlib/wake_losses.py b/windpowerlib/wake_losses.py index 77e46834..59d0ea37 100644 --- a/windpowerlib/wake_losses.py +++ b/windpowerlib/wake_losses.py @@ -45,19 +45,16 @@ def reduce_wind_speed(wind_speed, wind_efficiency_curve_name='dena_mean'): """ # Get wind efficiency curve - wind_efficiency_curve = get_wind_efficiency_curve( - curve_name=wind_efficiency_curve_name - ) + wind_efficiency_curve=get_wind_efficiency_curve( + curve_name=wind_efficiency_curve_name) # Reduce wind speed by wind efficiency - reduced_wind_speed = wind_speed * np.interp( - wind_speed, - wind_efficiency_curve["wind_speed"], - wind_efficiency_curve["efficiency"], - ) + reduced_wind_speed=wind_speed * np.interp( + wind_speed, wind_efficiency_curve['wind_speed'], + wind_efficiency_curve['efficiency']) return reduced_wind_speed -def get_wind_efficiency_curve(curve_name="all"): +def get_wind_efficiency_curve(curve_name='all'): r""" Reads wind efficiency curve(s) specified in `curve_name`. @@ -110,59 +107,45 @@ def get_wind_efficiency_curve(curve_name="all"): plt.show() """ - possible_curve_names = [ - "dena_mean", - "knorr_mean", - "dena_extreme1", - "dena_extreme2", - "knorr_extreme1", - "knorr_extreme2", - "knorr_extreme3", - ] - - if curve_name == "all": - curve_names = possible_curve_names + possible_curve_names=['dena_mean', 'knorr_mean', 'dena_extreme1', + 'dena_extreme2', 'knorr_extreme1', + 'knorr_extreme2', 'knorr_extreme3'] + + if curve_name == 'all': + curve_names=possible_curve_names elif isinstance(curve_name, str): - curve_names = [curve_name] + curve_names=[curve_name] else: - curve_names = curve_name + curve_names=curve_name - efficiency_curve = pd.DataFrame() + efficiency_curve=pd.DataFrame() for curve_name in curve_names: - if curve_name.split("_")[0] not in ["dena", "knorr"]: - raise ValueError( - "`curve_name` must be one of the following: " - + "{} but is {}".format(possible_curve_names, curve_name) - ) - path = os.path.join( - os.path.dirname(__file__), - "data", - "wind_efficiency_curves_{}.csv".format(curve_name.split("_")[0]), - ) + if curve_name.split('_')[0] not in ['dena', 'knorr']: + raise ValueError("`curve_name` must be one of the following: " + + "{} but is {}".format(possible_curve_names, + curve_name)) + path=os.path.join(os.path.dirname(__file__), 'data', + 'wind_efficiency_curves_{}.csv'.format( + curve_name.split('_')[0])) # Read wind efficiency curves from file - wind_efficiency_curves = pd.read_csv(path) + wind_efficiency_curves=pd.read_csv(path) # Raise error if wind efficiency curve specified in 'curve_name' does # not exist if curve_name not in list(wind_efficiency_curves): - msg = ( - "Efficiency curve <{0}> does not exist. Must be one of the " - "following: {1}." - ) + msg=("Efficiency curve <{0}> does not exist. Must be one of the " + "following: {1}.") raise ValueError(msg.format(curve_name, *possible_curve_names)) # Get wind efficiency curve and rename column containing efficiency - wec = wind_efficiency_curves[["wind_speed", curve_name]] + wec=wind_efficiency_curves[['wind_speed', curve_name]] if efficiency_curve.empty: - efficiency_curve = pd.DataFrame( - { - (curve_name, "wind_speed"): wec["wind_speed"], - (curve_name, "efficiency"): wec[curve_name], - } - ) + efficiency_curve=pd.DataFrame( + {(curve_name, 'wind_speed'): wec['wind_speed'], + (curve_name, 'efficiency'): wec[curve_name]}) else: - efficiency_curve[(curve_name, "wind_speed")] = wec["wind_speed"] - efficiency_curve[(curve_name, "efficiency")] = wec[curve_name] + efficiency_curve[(curve_name, 'wind_speed')]=wec['wind_speed'] + efficiency_curve[(curve_name, 'efficiency')]=wec[curve_name] if len(curve_names) == 1: return efficiency_curve[curve_names[0]] else: diff --git a/windpowerlib/wind_farm.py b/windpowerlib/wind_farm.py index d8432939..b2342690 100644 --- a/windpowerlib/wind_farm.py +++ b/windpowerlib/wind_farm.py @@ -113,15 +113,15 @@ class WindFarm(object): 31200000.0 """ - def __init__(self, wind_turbine_fleet, efficiency=None, name="", **kwargs): + def __init__(self, wind_turbine_fleet, efficiency=None, name='', **kwargs): - self.wind_turbine_fleet = wind_turbine_fleet - self.efficiency = efficiency - self.name = name + self.wind_turbine_fleet=wind_turbine_fleet + self.efficiency=efficiency + self.name=name - self.hub_height = None - self._nominal_power = None - self.power_curve = None + self.hub_height=None + self._nominal_power=None + self.power_curve=None self.check_and_complete_wind_turbine_fleet() @@ -137,104 +137,80 @@ def check_and_complete_wind_turbine_fleet(self): """ # convert list to dataframe if necessary if isinstance(self.wind_turbine_fleet, list): - self.wind_turbine_fleet = pd.DataFrame(self.wind_turbine_fleet) + self.wind_turbine_fleet=pd.DataFrame(self.wind_turbine_fleet) # check wind turbines try: - for turbine in self.wind_turbine_fleet["wind_turbine"]: + for turbine in self.wind_turbine_fleet['wind_turbine']: if not isinstance(turbine, WindTurbine): raise ValueError( - "Wind turbine must be provided as WindTurbine object " - "but was provided as {}.".format(type(turbine)) - ) + 'Wind turbine must be provided as WindTurbine object ' + 'but was provided as {}.'.format(type(turbine))) except KeyError: - raise KeyError( - "Missing wind_turbine key/column in " - "wind_turbine_fleet parameter." - ) + raise KeyError('Missing wind_turbine key/column in ' + 'wind_turbine_fleet parameter.') # add columns for number of turbines and total capacity if they don't # yet exist - if "number_of_turbines" not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet["number_of_turbines"] = np.nan - if "total_capacity" not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet["total_capacity"] = np.nan + if 'number_of_turbines' not in self.wind_turbine_fleet.columns: + self.wind_turbine_fleet['number_of_turbines']=np.nan + if 'total_capacity' not in self.wind_turbine_fleet.columns: + self.wind_turbine_fleet['total_capacity']=np.nan # calculate number of turbines if necessary - number_turbines_not_provided = self.wind_turbine_fleet[ - self.wind_turbine_fleet["number_of_turbines"].isnull() - ] + number_turbines_not_provided=self.wind_turbine_fleet[ + self.wind_turbine_fleet['number_of_turbines'].isnull()] for ix, row in number_turbines_not_provided.iterrows(): - msg = ( - "Number of turbines of type {0} can not be deduced " - "from total capacity. Please either provide " - "`number_of_turbines` in the turbine fleet definition or " - "set the nominal power of the wind turbine." - ) + msg='Number of turbines of type {0} can not be deduced ' \ + 'from total capacity. Please either provide ' \ + '`number_of_turbines` in the turbine fleet definition or ' \ + 'set the nominal power of the wind turbine.' try: - number_of_turbines = ( - row["total_capacity"] / row["wind_turbine"].nominal_power - ) + number_of_turbines=row['total_capacity'] / \ + row['wind_turbine'].nominal_power if np.isnan(number_of_turbines): - raise ValueError(msg.format(row["wind_turbine"])) + raise ValueError(msg.format(row['wind_turbine'])) else: - self.wind_turbine_fleet.loc[ - ix, "number_of_turbines" - ] = number_of_turbines + self.wind_turbine_fleet.loc[ix, 'number_of_turbines']=\ + number_of_turbines except TypeError: - raise ValueError(msg.format(row["wind_turbine"])) + raise ValueError(msg.format(row['wind_turbine'])) # calculate total capacity if necessary and check that total capacity # and number of turbines is consistent if both are provided for ix, row in self.wind_turbine_fleet.iterrows(): - if np.isnan(row["total_capacity"]): + if np.isnan(row['total_capacity']): try: - self.wind_turbine_fleet.loc[ix, "total_capacity"] = ( - row["number_of_turbines"] - * row["wind_turbine"].nominal_power - ) + self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ + row['number_of_turbines'] * \ + row['wind_turbine'].nominal_power except TypeError: raise ValueError( - "Total capacity of turbines of type {turbine} cannot " - "be deduced. Please check if the nominal power of the " - "wind turbine is set.".format( - turbine=row["wind_turbine"] - ) - ) + 'Total capacity of turbines of type {turbine} cannot ' + 'be deduced. Please check if the nominal power of the ' + 'wind turbine is set.'.format( + turbine=row['wind_turbine'])) else: - if ( - not abs( - row["total_capacity"] - - ( - row["number_of_turbines"] - * row["wind_turbine"].nominal_power - ) - ) - < 1 - ): - self.wind_turbine_fleet.loc[ix, "total_capacity"] = ( - row["number_of_turbines"] - * row["wind_turbine"].nominal_power - ) - msg = ( - "The provided total capacity of WindTurbine {0} has " - "been overwritten as it was not consistent with the " - "number of turbines provided for this type." - ) - warnings.warn( - msg.format(row["wind_turbine"]), - tools.WindpowerlibUserWarning, - ) + if not abs(row['total_capacity'] - ( + row['number_of_turbines'] * + row['wind_turbine'].nominal_power)) < 1: + self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ + row['number_of_turbines'] * \ + row['wind_turbine'].nominal_power + msg=( + 'The provided total capacity of WindTurbine {0} has ' + 'been overwritten as it was not consistent with the ' + 'number of turbines provided for this type.') + warnings.warn(msg.format(row['wind_turbine']), + tools.WindpowerlibUserWarning) def __repr__(self): - if self.name != "": - return "Wind farm: {name}".format(name=self.name) + if self.name != '': + return 'Wind farm: {name}'.format(name=self.name) else: - return "Wind farm with turbine fleet: [number, type]\n {}".format( + return 'Wind farm with turbine fleet: [number, type]\n {}'.format( self.wind_turbine_fleet.loc[ - :, ["number_of_turbines", "wind_turbine"] - ].values - ) + :, ['number_of_turbines', 'wind_turbine']].values) @property def nominal_power(self): @@ -248,12 +224,12 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power = self.wind_turbine_fleet.total_capacity.sum() + self.nominal_power=self.wind_turbine_fleet.total_capacity.sum() return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power = nominal_power + self._nominal_power=nominal_power def mean_hub_height(self): r""" @@ -291,25 +267,17 @@ def mean_hub_height(self): p. 35 """ - self.hub_height = np.exp( - sum( - np.log(row["wind_turbine"].hub_height) * row["total_capacity"] - for ix, row in self.wind_turbine_fleet.iterrows() - ) - / self.nominal_power - ) + self.hub_height=np.exp( + sum(np.log(row['wind_turbine'].hub_height) * row['total_capacity'] + for ix, row in self.wind_turbine_fleet.iterrows()) / + self.nominal_power) return self - def assign_power_curve( - self, - wake_losses_model="wind_farm_efficiency", - smoothing=False, - block_width=0.5, - standard_deviation_method="turbulence_intensity", - smoothing_order="wind_farm_power_curves", - turbulence_intensity=None, - **kwargs, - ): + def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', + smoothing=False, block_width=0.5, + standard_deviation_method='turbulence_intensity', + smoothing_order='wind_farm_power_curves', + turbulence_intensity=None, **kwargs): r""" Calculates the power curve of a wind farm. @@ -359,123 +327,83 @@ def assign_power_curve( """ # Check if all wind turbines have a power curve as attribute - for turbine in self.wind_turbine_fleet["wind_turbine"]: + for turbine in self.wind_turbine_fleet['wind_turbine']: if turbine.power_curve is None: - raise ValueError( - "For an aggregated wind farm power curve " - + "each wind turbine needs a power curve " - + "but `power_curve` of '{}' is None.".format(turbine) - ) + raise ValueError("For an aggregated wind farm power curve " + + "each wind turbine needs a power curve " + + "but `power_curve` of '{}' is None.".format( + turbine)) # Initialize data frame for power curve values - df = pd.DataFrame() + df=pd.DataFrame() for ix, row in self.wind_turbine_fleet.iterrows(): # Check if needed parameters are available and/or assign them if smoothing: - if ( - standard_deviation_method == "turbulence_intensity" - and turbulence_intensity is None - ): - if ( - "roughness_length" in kwargs - and kwargs["roughness_length"] is not None - ): + if (standard_deviation_method == 'turbulence_intensity' and + turbulence_intensity is None): + if 'roughness_length' in kwargs and \ + kwargs['roughness_length'] is not None: # Calculate turbulence intensity and write to kwargs - turbulence_intensity = tools.estimate_turbulence_intensity( - row["wind_turbine"].hub_height, - kwargs["roughness_length"], - ) - kwargs["turbulence_intensity"] = turbulence_intensity + turbulence_intensity=( + tools.estimate_turbulence_intensity( + row['wind_turbine'].hub_height, + kwargs['roughness_length'])) + kwargs['turbulence_intensity']=turbulence_intensity else: raise ValueError( - "`roughness_length` must be defined for using " - + "'turbulence_intensity' as " - + "`standard_deviation_method` if " - + "`turbulence_intensity` is not given" - ) + "`roughness_length` must be defined for using " + + "'turbulence_intensity' as " + + "`standard_deviation_method` if " + + "`turbulence_intensity` is not given") # Get original power curve - power_curve = pd.DataFrame(row["wind_turbine"].power_curve) + power_curve=pd.DataFrame(row['wind_turbine'].power_curve) # Editions to the power curves before the summation - if smoothing and smoothing_order == "turbine_power_curves": - power_curve = power_curves.smooth_power_curve( - power_curve["wind_speed"], - power_curve["value"], + if smoothing and smoothing_order == 'turbine_power_curves': + power_curve=power_curves.smooth_power_curve( + power_curve['wind_speed'], power_curve['value'], standard_deviation_method=standard_deviation_method, - block_width=block_width, - **kwargs, - ) + block_width=block_width, **kwargs) else: # Add value zero to start and end of curve as otherwise # problems can occur during the aggregation - if power_curve.iloc[0]["wind_speed"] != 0.0: - power_curve = pd.concat( - [ - pd.DataFrame( - data={"value": [0.0], "wind_speed": [0.0]} - ), - power_curve, - ], - join="inner", - ) - if power_curve.iloc[-1]["value"] != 0.0: - power_curve = pd.concat( - [ - power_curve, - pd.DataFrame( - data={ - "wind_speed": [ - power_curve["wind_speed"].loc[ - power_curve.index[-1] - ] - + 0.5 - ], - "value": [0.0], - } - ), - ], - join="inner", - ) + if power_curve.iloc[0]['wind_speed'] != 0.0: + power_curve=pd.concat( + [pd.DataFrame(data={ + 'value': [0.0], 'wind_speed': [0.0]}), + power_curve], join='inner') + if power_curve.iloc[-1]['value'] != 0.0: + power_curve=pd.concat( + [power_curve, pd.DataFrame(data={ + 'wind_speed': [power_curve['wind_speed'].loc[ + power_curve.index[-1]] + 0.5], + 'value': [0.0]})], join='inner') # Add power curves of all turbine types to data frame # (multiplied by turbine amount) - df = pd.concat( - [ - df, - pd.DataFrame( - power_curve.set_index(["wind_speed"]) - * row["number_of_turbines"] - ), - ], - axis=1, - ) + df=pd.concat( + [df, pd.DataFrame(power_curve.set_index(['wind_speed']) * + row['number_of_turbines'])], axis=1) # Aggregate all power curves - wind_farm_power_curve = pd.DataFrame( - df.interpolate(method="index").sum(axis=1) - ) - wind_farm_power_curve.columns = ["value"] + wind_farm_power_curve=pd.DataFrame( + df.interpolate(method='index').sum(axis=1)) + wind_farm_power_curve.columns=['value'] wind_farm_power_curve.reset_index(inplace=True) # Apply power curve smoothing and consideration of wake losses # after the summation - if smoothing and smoothing_order == "wind_farm_power_curves": - wind_farm_power_curve = power_curves.smooth_power_curve( - wind_farm_power_curve["wind_speed"], - wind_farm_power_curve["value"], + if smoothing and smoothing_order == 'wind_farm_power_curves': + wind_farm_power_curve=power_curves.smooth_power_curve( + wind_farm_power_curve['wind_speed'], + wind_farm_power_curve['value'], standard_deviation_method=standard_deviation_method, - block_width=block_width, - **kwargs, - ) - if wake_losses_model == "wind_farm_efficiency": + block_width=block_width, **kwargs) + if wake_losses_model == 'wind_farm_efficiency': if self.efficiency is not None: - wind_farm_power_curve = power_curves.wake_losses_to_power_curve( - wind_farm_power_curve["wind_speed"].values, - wind_farm_power_curve["value"].values, - wind_farm_efficiency=self.efficiency, - ) + wind_farm_power_curve=( + power_curves.wake_losses_to_power_curve( + wind_farm_power_curve['wind_speed'].values, + wind_farm_power_curve['value'].values, + wind_farm_efficiency=self.efficiency)) else: - logging.info( - "`wake_losses_model` is {} but wind farm ".format( - wake_losses_model - ) - + "efficiency is NOT taken into " - "account as it is None." - ) - self.power_curve = wind_farm_power_curve + logging.info("`wake_losses_model` is {} but wind farm ".format( + wake_losses_model) + "efficiency is NOT taken into " + "account as it is None.") + self.power_curve=wind_farm_power_curve return self diff --git a/windpowerlib/wind_speed.py b/windpowerlib/wind_speed.py index 7a1189a5..60882805 100644 --- a/windpowerlib/wind_speed.py +++ b/windpowerlib/wind_speed.py @@ -73,33 +73,22 @@ def logarithmic_profile(wind_speed, wind_speed_height, hub_height, """ if 0.7 * obstacle_height > wind_speed_height: - raise ValueError( - "To take an obstacle height of {0} m ".format(obstacle_height) - + "into consideration, wind " - + "speed data of a greater height is needed." - ) + raise ValueError("To take an obstacle height of {0} m ".format( + obstacle_height) + "into consideration, wind " + + "speed data of a greater height is needed.") # Return np.array if wind_speed is np.array - if isinstance(wind_speed, np.ndarray) and isinstance( - roughness_length, pd.Series - ): - roughness_length = np.array(roughness_length) - - return ( - wind_speed - * np.log((hub_height - 0.7 * obstacle_height) / roughness_length) - / np.log( - (wind_speed_height - 0.7 * obstacle_height) / roughness_length - ) - ) - - -def hellman( - wind_speed, - wind_speed_height, - hub_height, - roughness_length=None, - hellman_exponent=None, -): + if (isinstance(wind_speed, np.ndarray) and + isinstance(roughness_length, pd.Series)): + roughness_length=np.array(roughness_length) + + return (wind_speed * np.log((hub_height - 0.7 * obstacle_height) / + roughness_length) / + np.log((wind_speed_height - 0.7 * obstacle_height) / + roughness_length)) + + +def hellman(wind_speed, wind_speed_height, hub_height, + roughness_length=None, hellman_exponent=None): r""" Calculates the wind speed at hub height using the hellman equation. diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 4e2a6af0..b1ac7fa2 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -114,131 +114,107 @@ class WindTurbine(object): 1500000.0 """ - def __init__( - self, - hub_height, - nominal_power=None, - path="oedb", - power_curve=None, - power_coefficient_curve=None, - rotor_diameter=None, - turbine_type=None, - **kwargs, - ): - - self.hub_height = hub_height - self.turbine_type = turbine_type - self.rotor_diameter = rotor_diameter - self.nominal_power = nominal_power - self.power_curve = power_curve - self.power_coefficient_curve = power_coefficient_curve - - if path == "oedb": - path = os.path.join(os.path.dirname(__file__), "oedb") + def __init__(self, hub_height, nominal_power=None, path='oedb', + power_curve=None, power_coefficient_curve=None, + rotor_diameter=None, turbine_type=None, **kwargs): + + self.hub_height=hub_height + self.turbine_type=turbine_type + self.rotor_diameter=rotor_diameter + self.nominal_power=nominal_power + self.power_curve=power_curve + self.power_coefficient_curve=power_coefficient_curve + + if path == 'oedb': + path=os.path.join(os.path.dirname(__file__), 'oedb') if turbine_type is not None and path is not None: if power_curve is None: try: - fn = os.path.join(path, "power_curves.csv") - self.power_curve = get_turbine_data_from_file( - self.turbine_type, fn - ) + fn=os.path.join(path, 'power_curves.csv') + self.power_curve=get_turbine_data_from_file( + self.turbine_type, fn) except KeyError: - msg = "No power curve found for {0}" + msg="No power curve found for {0}" logging.debug(msg.format(self.turbine_type)) if power_coefficient_curve is None: try: - fn = os.path.join(path, "power_coefficient_curves.csv") - self.power_coefficient_curve = get_turbine_data_from_file( - self.turbine_type, fn - ) + fn=os.path.join(path, 'power_coefficient_curves.csv') + self.power_coefficient_curve=get_turbine_data_from_file( + self.turbine_type, fn) except KeyError: - msg = "No power coefficient curve found for {0}" + msg="No power coefficient curve found for {0}" logging.debug(msg.format(self.turbine_type)) if nominal_power is None or ( - rotor_diameter is None - and self.power_coefficient_curve is not None - ): - turbine_data = None + rotor_diameter is None and + self.power_coefficient_curve is not None): + turbine_data=None try: - fn = os.path.join(path, "turbine_data.csv") - turbine_data = get_turbine_data_from_file( - self.turbine_type, fn - ) + fn=os.path.join(path, 'turbine_data.csv') + turbine_data=get_turbine_data_from_file( + self.turbine_type, fn) except KeyError: - msg = "No turbine data found for {0}" + msg="No turbine data found for {0}" logging.debug(msg.format(self.turbine_type)) if self.nominal_power is None and turbine_data is not None: - self.nominal_power = float(turbine_data["nominal_power"]) + self.nominal_power=float(turbine_data['nominal_power']) if self.rotor_diameter is None and turbine_data is not None: - self.rotor_diameter = float(turbine_data["rotor_diameter"]) + self.rotor_diameter=float(turbine_data['rotor_diameter']) if self.power_curve is None and self.power_coefficient_curve is None: - msg = ( - "The WindTurbine has been initialised without a power curve" - " and without a power coefficient curve.\nYou will not be" - " able to calculate the power output.\n" - " Check if the turbine type {0} is in your database file" - " or if you passed a valid curve." - ) + msg=("The WindTurbine has been initialised without a power curve" + " and without a power coefficient curve.\nYou will not be" + " able to calculate the power output.\n" + " Check if the turbine type {0} is in your database file" + " or if you passed a valid curve.") warnings.warn(msg.format(turbine_type), WindpowerlibUserWarning) else: # power (coefficient) curve to pd.DataFrame in case of being dict if isinstance(self.power_curve, dict): - self.power_curve = pd.DataFrame(self.power_curve) + self.power_curve=pd.DataFrame(self.power_curve) if isinstance(self.power_coefficient_curve, dict): - self.power_coefficient_curve = pd.DataFrame( - self.power_coefficient_curve - ) + self.power_coefficient_curve=pd.DataFrame( + self.power_coefficient_curve) # sort power (coefficient) curve by wind speed if isinstance(self.power_curve, pd.DataFrame): - self.power_curve.sort_values(by="wind_speed") + self.power_curve.sort_values(by='wind_speed') elif self.power_curve is not None: - msg = ( - "Type of power curve of {} is {} but should be " - "pd.DataFrame or dict." - ) - raise TypeError( - msg.format(self.__repr__(), type(self.power_curve)) - ) + msg="Type of power curve of {} is {} but should be " \ + "pd.DataFrame or dict." + raise TypeError(msg.format(self.__repr__(), + type(self.power_curve))) if isinstance(self.power_coefficient_curve, pd.DataFrame): - self.power_coefficient_curve.sort_values(by="wind_speed") + self.power_coefficient_curve.sort_values(by='wind_speed') elif self.power_coefficient_curve is not None: - msg = ( - "Type of power coefficient curve of {} is {} but " - "should be pd.DataFrame or dict." - ) - raise TypeError( - msg.format( - self.__repr__(), type(self.power_coefficient_curve) - ) - ) + msg="Type of power coefficient curve of {} is {} but " \ + "should be pd.DataFrame or dict." + raise TypeError(msg.format(self.__repr__(), + type(self.power_coefficient_curve))) def __repr__(self): - info = [] + info=[] if self.nominal_power is not None: - info.append("nominal power={} W".format(self.nominal_power)) + info.append('nominal power={} W'.format(self.nominal_power)) if self.hub_height is not None: - info.append("hub height={} m".format(self.hub_height)) + info.append('hub height={} m'.format(self.hub_height)) if self.rotor_diameter is not None: - info.append("rotor diameter={} m".format(self.rotor_diameter)) + info.append('rotor diameter={} m'.format(self.rotor_diameter)) if self.power_coefficient_curve is not None: - info.append("power_coefficient_curve={}".format("True")) + info.append('power_coefficient_curve={}'.format('True')) else: - info.append("power_coefficient_curve={}".format("False")) + info.append('power_coefficient_curve={}'.format('False')) if self.power_curve is not None: - info.append("power_curve={}".format("True")) + info.append('power_curve={}'.format('True')) else: - info.append("power_curve={}".format("False")) + info.append('power_curve={}'.format('False')) if self.turbine_type is not None: - turbine_repr = "Wind turbine: {name} {info}".format( - name=self.turbine_type, info=info - ) + turbine_repr='Wind turbine: {name} {info}'.format( + name=self.turbine_type, info=info) else: - turbine_repr = "Wind turbine: {info}".format(info=info) + turbine_repr='Wind turbine: {info}'.format(info=info) return turbine_repr @@ -295,29 +271,22 @@ def to_group(self, number_turbines=None, total_capacity=None): """ if number_turbines is not None and total_capacity is not None: - raise ValueError( - "The 'number' and the 'total_capacity' parameter " - "are mutually exclusive. Use just one of them." - ) + raise ValueError("The 'number' and the 'total_capacity' parameter " + "are mutually exclusive. Use just one of them.") elif total_capacity is not None: - number_turbines = total_capacity / self.nominal_power + number_turbines=total_capacity / self.nominal_power elif number_turbines is None: - number_turbines = 1 + number_turbines=1 return WindTurbineGroup( - wind_turbine=self, number_of_turbines=number_turbines - ) + wind_turbine=self, number_of_turbines=number_turbines) # This is working for Python >= 3.5. # There a cleaner solutions for Python >= 3.6, once the support of 3.5 is # dropped: https://stackoverflow.com/a/50038614 -class WindTurbineGroup( - NamedTuple( - "WindTurbineGroup", - [("wind_turbine", WindTurbine), ("number_of_turbines", float)], - ) -): +class WindTurbineGroup(NamedTuple('WindTurbineGroup', [ + ('wind_turbine', WindTurbine), ('number_of_turbines', float)])): """ A simple data container to define more than one turbine of the same type. Use the :func:`~windpowerlib.wind_turbine.WindTurbine.to_group` method to @@ -331,16 +300,13 @@ class WindTurbineGroup( 'number_of_turbines' : float The number of turbines. The number is not restricted to integer values. """ - - __slots__ = () + __slots__=() -WindTurbineGroup.wind_turbine.__doc__ = ( - "A :class:`~windpowerlib.wind_farm.WindTurbine` object." -) -WindTurbineGroup.number_of_turbines.__doc__ = ( - "Number of turbines of type WindTurbine" -) +WindTurbineGroup.wind_turbine.__doc__=( + 'A :class:`~windpowerlib.wind_farm.WindTurbine` object.') +WindTurbineGroup.number_of_turbines.__doc__=( + 'Number of turbines of type WindTurbine') def get_turbine_data_from_file(turbine_type, path): @@ -383,28 +349,28 @@ def get_turbine_data_from_file(turbine_type, path): """ try: - df = pd.read_csv(path, index_col=0) + df=pd.read_csv(path, index_col=0) except FileNotFoundError: raise FileNotFoundError("The file '{}' was not found.".format(path)) - wpp_df = df[df.index == turbine_type].copy() + wpp_df=df[df.index == turbine_type].copy() # if turbine not in data file if wpp_df.shape[0] == 0: - msg = "Wind converter type {0} not provided. Possible types: {1}" + msg="Wind converter type {0} not provided. Possible types: {1}" raise KeyError(msg.format(turbine_type, list(df.index))) # if turbine in data file # get nominal power or power (coefficient) curve - if "turbine_data" in path: + if 'turbine_data' in path: return wpp_df else: wpp_df.dropna(axis=1, inplace=True) - wpp_df = wpp_df.transpose().reset_index() - wpp_df.columns = ["wind_speed", "value"] + wpp_df=wpp_df.transpose().reset_index() + wpp_df.columns=['wind_speed', 'value'] # transform wind speeds to floats - wpp_df["wind_speed"] = wpp_df["wind_speed"].apply(lambda x: float(x)) + wpp_df['wind_speed']=wpp_df['wind_speed'].apply(lambda x: float(x)) return wpp_df -def load_turbine_data_from_oedb(schema="supply", table="wind_turbine_library"): +def load_turbine_data_from_oedb(schema='supply', table='wind_turbine_library'): r""" Loads turbine library from the OpenEnergy database (oedb). @@ -427,82 +393,58 @@ def load_turbine_data_from_oedb(schema="supply", table="wind_turbine_library"): """ # url of OpenEnergy Platform that contains the oedb - oep_url = "http://oep.iks.cs.ovgu.de/" + oep_url='http://oep.iks.cs.ovgu.de/' # load data - result = requests.get( - oep_url + "/api/v0/schema/{}/tables/{}/rows/?".format(schema, table), - ) + result=requests.get( + oep_url + '/api/v0/schema/{}/tables/{}/rows/?'.format( + schema, table), ) if not result.status_code == 200: - raise ConnectionError( - "Database connection not successful. " - "Response: [{}]".format(result.status_code) - ) + raise ConnectionError("Database connection not successful. " + "Response: [{}]".format(result.status_code)) # extract data to dataframe - turbine_data = pd.DataFrame(result.json()) + turbine_data=pd.DataFrame(result.json()) # standard file name for saving data - filename = os.path.join(os.path.dirname(__file__), "oedb", "{}.csv") + filename=os.path.join(os.path.dirname(__file__), 'oedb', + '{}.csv') # get all power (coefficient) curves and save to file # for curve_type in ['power_curve', 'power_coefficient_curve']: - for curve_type in ["power_curve", "power_coefficient_curve"]: - curves_df = pd.DataFrame(columns=["wind_speed"]) + for curve_type in ['power_curve', 'power_coefficient_curve']: + curves_df=pd.DataFrame(columns=['wind_speed']) for index in turbine_data.index: - if ( - turbine_data["{}_wind_speeds".format(curve_type)][index] - and turbine_data["{}_values".format(curve_type)][index] - ): - df = ( - pd.DataFrame( - data=[ - eval( - turbine_data[ - "{}_wind_speeds".format(curve_type) - ][index] - ), - eval( - turbine_data["{}_values".format(curve_type)][ - index - ] - ), - ] - ) - .transpose() - .rename( - columns={ - 0: "wind_speed", - 1: turbine_data["turbine_type"][index], - } - ) - ) - curves_df = pd.merge( - left=curves_df, right=df, how="outer", on="wind_speed" - ) - curves_df = curves_df.set_index("wind_speed").sort_index().transpose() + if (turbine_data['{}_wind_speeds'.format(curve_type)][index] + and turbine_data['{}_values'.format(curve_type)][index]): + df=pd.DataFrame(data=[ + eval(turbine_data['{}_wind_speeds'.format(curve_type)][ + index]), + eval(turbine_data['{}_values'.format(curve_type)][ + index])]).transpose().rename( + columns={0: 'wind_speed', + 1: turbine_data['turbine_type'][index]}) + curves_df=pd.merge(left=curves_df, right=df, how='outer', + on='wind_speed') + curves_df=curves_df.set_index('wind_speed').sort_index().transpose() # power curve values in W - if curve_type == "power_curve": + if curve_type == 'power_curve': curves_df *= 1000 - curves_df.index.name = "turbine_type" - curves_df.to_csv(filename.format("{}s".format(curve_type))) + curves_df.index.name='turbine_type' + curves_df.to_csv(filename.format('{}s'.format(curve_type))) # get turbine data and save to file (excl. curves) - turbine_data_df = turbine_data.drop( - [ - "power_curve_wind_speeds", - "power_curve_values", - "power_coefficient_curve_wind_speeds", - "power_coefficient_curve_values", - "thrust_coefficient_curve_wind_speeds", - "thrust_coefficient_curve_values", - ], - axis=1, - ).set_index("turbine_type") + turbine_data_df=turbine_data.drop( + ['power_curve_wind_speeds', 'power_curve_values', + 'power_coefficient_curve_wind_speeds', + 'power_coefficient_curve_values', + 'thrust_coefficient_curve_wind_speeds', + 'thrust_coefficient_curve_values'], axis=1).set_index('turbine_type') # nominal power in W - turbine_data_df["nominal_power"] = turbine_data_df["nominal_power"] * 1000 - turbine_data_df.to_csv(filename.format("turbine_data")) + turbine_data_df['nominal_power']=turbine_data_df[ + 'nominal_power'] * 1000 + turbine_data_df.to_csv(filename.format('turbine_data')) return turbine_data -def get_turbine_types(turbine_library="local", print_out=True, filter_=True): +def get_turbine_types(turbine_library='local', print_out=True, filter_=True): r""" Get all provided wind turbine types provided. @@ -564,34 +506,26 @@ def get_turbine_types(turbine_library="local", print_out=True, filter_=True): Name: 1, dtype: object """ - if turbine_library == "local": - filename = os.path.join( - os.path.dirname(__file__), "oedb", "turbine_data.csv" - ) - df = pd.read_csv(filename, index_col=0).reset_index() - elif turbine_library == "oedb": - df = load_turbine_data_from_oedb() + if turbine_library == 'local': + filename=os.path.join(os.path.dirname(__file__), 'oedb', 'turbine_data.csv') + df=pd.read_csv(filename, index_col=0).reset_index() + elif turbine_library == 'oedb': + df=load_turbine_data_from_oedb() else: - raise ValueError( - "`turbine_library` is '{}' ".format(turbine_library) - + "but must be 'local' or 'oedb'." - ) + raise ValueError("`turbine_library` is '{}' ".format(turbine_library) + + "but must be 'local' or 'oedb'.") if filter_: - cp_curves_df = df.loc[df["has_cp_curve"]][ - ["manufacturer", "turbine_type", "has_cp_curve"] - ] - p_curves_df = df.loc[df["has_power_curve"]][ - ["manufacturer", "turbine_type", "has_power_curve"] - ] - curves_df = pd.merge( - p_curves_df, cp_curves_df, how="outer", sort=True - ).fillna(False) + cp_curves_df=df.loc[df['has_cp_curve']][ + ['manufacturer', 'turbine_type', 'has_cp_curve']] + p_curves_df=df.loc[df['has_power_curve']][ + ['manufacturer', 'turbine_type', 'has_power_curve']] + curves_df=pd.merge(p_curves_df, cp_curves_df, how='outer', + sort=True).fillna(False) else: - curves_df = df[ - ["manufacturer", "turbine_type", "has_power_curve", "has_cp_curve"] - ] + curves_df=df[['manufacturer', 'turbine_type', 'has_power_curve', + 'has_cp_curve']] if print_out: - pd.set_option("display.max_rows", len(curves_df)) + pd.set_option('display.max_rows', len(curves_df)) print(curves_df) - pd.reset_option("display.max_rows") + pd.reset_option('display.max_rows') return curves_df diff --git a/windpowerlib/wind_turbine_cluster.py b/windpowerlib/wind_turbine_cluster.py index 3610f9c2..74d2ecb8 100644 --- a/windpowerlib/wind_turbine_cluster.py +++ b/windpowerlib/wind_turbine_cluster.py @@ -37,24 +37,23 @@ class WindTurbineCluster(object): :py:func:`assign_power_curve` for more information. """ + def __init__(self, wind_farms, name='', **kwargs): - def __init__(self, wind_farms, name="", **kwargs): + self.wind_farms=wind_farms + self.name=name - self.wind_farms = wind_farms - self.name = name - - self.hub_height = None - self._nominal_power = None - self.power_curve = None + self.hub_height=None + self._nominal_power=None + self.power_curve=None def __repr__(self): - if self.name != "": - wf_repr = "Wind turbine cluster: {name}".format(name=self.name) + if self.name != '': + wf_repr='Wind turbine cluster: {name}'.format(name=self.name) else: - info = [] + info=[] for wind_farm in self.wind_farms: info.append(wind_farm) - wf_repr = r"Wind turbine cluster with: {info}".format(info=info) + wf_repr=r'Wind turbine cluster with: {info}'.format(info=info) return wf_repr @property @@ -70,14 +69,13 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power = sum( - wind_farm.nominal_power for wind_farm in self.wind_farms - ) + self.nominal_power=sum(wind_farm.nominal_power + for wind_farm in self.wind_farms) return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power = nominal_power + self._nominal_power=nominal_power def mean_hub_height(self): r""" @@ -115,25 +113,16 @@ def mean_hub_height(self): p. 35 """ - self.hub_height = np.exp( - sum( - np.log(wind_farm.hub_height) * wind_farm.nominal_power - for wind_farm in self.wind_farms - ) - / self.nominal_power - ) + self.hub_height=np.exp(sum( + np.log(wind_farm.hub_height) * wind_farm.nominal_power for + wind_farm in self.wind_farms) / self.nominal_power) return self - def assign_power_curve( - self, - wake_losses_model="wind_farm_efficiency", - smoothing=False, - block_width=0.5, - standard_deviation_method="turbulence_intensity", - smoothing_order="wind_farm_power_curves", - turbulence_intensity=None, - **kwargs, - ): + def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', + smoothing=False, block_width=0.5, + standard_deviation_method='turbulence_intensity', + smoothing_order='wind_farm_power_curves', + turbulence_intensity=None, **kwargs): r""" Calculates the power curve of a wind turbine cluster. @@ -191,31 +180,20 @@ def assign_power_curve( # Assign wind farm power curve farm.assign_power_curve( wake_losses_model=wake_losses_model, - smoothing=smoothing, - block_width=block_width, + smoothing=smoothing, block_width=block_width, standard_deviation_method=standard_deviation_method, smoothing_order=smoothing_order, - turbulence_intensity=turbulence_intensity, - **kwargs, - ) + turbulence_intensity=turbulence_intensity, **kwargs) # Create data frame from power curves of all wind farms - df = pd.concat( - [ - farm.power_curve.set_index(["wind_speed"]).rename( - columns={"value": i} - ) - for farm, i in zip( - self.wind_farms, list(range(len(self.wind_farms))) - ) - ], - axis=1, - ) + df=pd.concat([farm.power_curve.set_index(['wind_speed']).rename( + columns={'value': i}) for + farm, i in zip(self.wind_farms, + list(range(len(self.wind_farms))))], axis=1) # Sum up power curves - cluster_power_curve = pd.DataFrame( - df.interpolate(method="index").sum(axis=1) - ) - cluster_power_curve.columns = ["value"] + cluster_power_curve=pd.DataFrame( + df.interpolate(method='index').sum(axis=1)) + cluster_power_curve.columns=['value'] # Return wind speed (index) to a column of the data frame cluster_power_curve.reset_index(inplace=True) - self.power_curve = cluster_power_curve + self.power_curve=cluster_power_curve return self From a4a4eb8540e5dbc7e3ce6ace0c9a6719bc06103f Mon Sep 17 00:00:00 2001 From: uvchik Date: Thu, 12 Dec 2019 16:27:17 +0100 Subject: [PATCH 14/16] Allow versions from 3.5 to 3.8 --- .travis.yml | 3 +-- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9fb5c8f3..84ad58b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,7 @@ matrix: - python: 3.5 - python: 3.6 - python: 3.7 - dist: xenial - sudo: true + - python: 3.8 # command to install dependencies #before_install: diff --git a/pyproject.toml b/pyproject.toml index 3dbb3802..27913c1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.black] line-length = 79 -target-version = ['py36', 'py37', 'py38'] +target-version = ['py35', 'py36', 'py37', 'py38'] include = '\.pyi?$' exclude = ''' /( From dda3b457d29b389369791183df2ddf0e291164f5 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 12 Dec 2019 15:27:36 +0000 Subject: [PATCH 15/16] Fixing style errors. --- example/modelchain_example.py | 121 +++-- example/test_examples.py | 90 ++-- example/turbine_cluster_modelchain_example.py | 117 +++-- tests/test_density.py | 63 ++- tests/test_modelchain.py | 490 +++++++++++------- tests/test_power_curves.py | 170 ++++-- tests/test_power_output.py | 271 +++++----- tests/test_temperature.py | 21 +- tests/test_tools.py | 140 +++-- tests/test_turbine_cluster_modelchain.py | 434 +++++++++------- tests/test_wake_losses.py | 74 ++- tests/test_wind_farm.py | 230 ++++---- tests/test_wind_speed.py | 106 ++-- tests/test_wind_turbine.py | 107 ++-- windpowerlib/__init__.py | 6 +- windpowerlib/modelchain.py | 354 ++++++++----- windpowerlib/power_curves.py | 151 ++++-- windpowerlib/power_output.py | 76 ++- windpowerlib/tools.py | 34 +- windpowerlib/turbine_cluster_modelchain.py | 119 +++-- windpowerlib/wake_losses.py | 79 +-- windpowerlib/wind_farm.py | 312 ++++++----- windpowerlib/wind_speed.py | 41 +- windpowerlib/wind_turbine.py | 330 +++++++----- windpowerlib/wind_turbine_cluster.py | 84 +-- 25 files changed, 2425 insertions(+), 1595 deletions(-) diff --git a/example/modelchain_example.py b/example/modelchain_example.py index 07149387..c4686e61 100644 --- a/example/modelchain_example.py +++ b/example/modelchain_example.py @@ -19,7 +19,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt=None + plt = None from windpowerlib import ModelChain from windpowerlib import WindTurbine @@ -64,24 +64,29 @@ def get_weather_data(filename='weather.csv', **kwargs): """ - if 'datapath' not in kwargs: - kwargs['datapath']=os.path.join(os.path.split( - os.path.dirname(__file__))[0], 'example') - file=os.path.join(kwargs['datapath'], filename) + if "datapath" not in kwargs: + kwargs["datapath"] = os.path.join( + os.path.split(os.path.dirname(__file__))[0], "example" + ) + file = os.path.join(kwargs["datapath"], filename) # read csv file - weather_df=pd.read_csv( - file, index_col=0, header=[0, 1], - date_parser=lambda idx: pd.to_datetime(idx, utc=True)) + weather_df = pd.read_csv( + file, + index_col=0, + header=[0, 1], + date_parser=lambda idx: pd.to_datetime(idx, utc=True), + ) # change type of index to datetime and set time zone - weather_df.index=pd.to_datetime(weather_df.index).tz_convert( - 'Europe/Berlin') + weather_df.index = pd.to_datetime(weather_df.index).tz_convert( + "Europe/Berlin" + ) # change type of height from str to int by resetting columns - l0=[_[0] for _ in weather_df.columns] - l1=[int(_[1]) for _ in weather_df.columns] - weather_df.columns=[l0, l1] + l0 = [_[0] for _ in weather_df.columns] + l1 = [int(_[1]) for _ in weather_df.columns] + weather_df.columns = [l0, l1] return weather_df @@ -111,37 +116,42 @@ def initialize_wind_turbines(): # specification of wind turbine where data is provided in the oedb # turbine library - enercon_e126={ - 'turbine_type': 'E-126/4200', # turbine type as in register - 'hub_height': 135 # in m + enercon_e126 = { + "turbine_type": "E-126/4200", # turbine type as in register + "hub_height": 135, # in m } # initialize WindTurbine object - e126=WindTurbine(**enercon_e126) + e126 = WindTurbine(**enercon_e126) # specification of own wind turbine (Note: power values and nominal power # have to be in Watt) - my_turbine={ - 'nominal_power': 3e6, # in W - 'hub_height': 105, # in m - 'power_curve': pd.DataFrame( - data={'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], # in W - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}) # in m/s + my_turbine = { + "nominal_power": 3e6, # in W + "hub_height": 105, # in m + "power_curve": pd.DataFrame( + data={ + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], # in W + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + } + ), # in m/s } # initialize WindTurbine object - my_turbine=WindTurbine(**my_turbine) + my_turbine = WindTurbine(**my_turbine) # specification of wind turbine where power coefficient curve and nominal # power is provided in an own csv file - csv_path=os.path.join(os.path.dirname(__file__), 'data') - dummy_turbine={ - 'turbine_type': "DUMMY 1", - 'hub_height': 100, # in m - 'rotor_diameter': 70, # in m - 'path': csv_path + csv_path = os.path.join(os.path.dirname(__file__), "data") + dummy_turbine = { + "turbine_type": "DUMMY 1", + "hub_height": 100, # in m + "rotor_diameter": 70, # in m + "path": csv_path, } # initialize WindTurbine object - dummy_turbine=WindTurbine(**dummy_turbine) + dummy_turbine = WindTurbine(**dummy_turbine) return my_turbine, e126, dummy_turbine @@ -175,37 +185,38 @@ def calculate_power_output(weather, my_turbine, e126, dummy_turbine): # power output calculation for my_turbine # initialize ModelChain with default parameters and use run_model method # to calculate power output - mc_my_turbine=ModelChain(my_turbine).run_model(weather) + mc_my_turbine = ModelChain(my_turbine).run_model(weather) # write power output time series to WindTurbine object - my_turbine.power_output=mc_my_turbine.power_output + my_turbine.power_output = mc_my_turbine.power_output # power output calculation for e126 # own specifications for ModelChain setup - modelchain_data={ - 'wind_speed_model': 'logarithmic', # 'logarithmic' (default), - # 'hellman' or - # 'interpolation_extrapolation' - 'density_model': 'ideal_gas', # 'barometric' (default), 'ideal_gas' or - # 'interpolation_extrapolation' - 'temperature_model': 'linear_gradient', # 'linear_gradient' (def.) or - # 'interpolation_extrapolation' - 'power_output_model': 'power_curve', # 'power_curve' (default) or - # 'power_coefficient_curve' - 'density_correction': True, # False (default) or True - 'obstacle_height': 0, # default: 0 - 'hellman_exp': None} # None (default) or None + modelchain_data = { + "wind_speed_model": "logarithmic", # 'logarithmic' (default), + # 'hellman' or + # 'interpolation_extrapolation' + "density_model": "ideal_gas", # 'barometric' (default), 'ideal_gas' or + # 'interpolation_extrapolation' + "temperature_model": "linear_gradient", # 'linear_gradient' (def.) or + # 'interpolation_extrapolation' + "power_output_model": "power_curve", # 'power_curve' (default) or + # 'power_coefficient_curve' + "density_correction": True, # False (default) or True + "obstacle_height": 0, # default: 0 + "hellman_exp": None, + } # None (default) or None # initialize ModelChain with own specifications and use run_model method # to calculate power output - mc_e126=ModelChain(e126, **modelchain_data).run_model(weather) + mc_e126 = ModelChain(e126, **modelchain_data).run_model(weather) # write power output time series to WindTurbine object - e126.power_output=mc_e126.power_output + e126.power_output = mc_e126.power_output # power output calculation for example_turbine # own specification for 'power_output_model' - mc_example_turbine=ModelChain( - dummy_turbine, - power_output_model='power_coefficient_curve').run_model(weather) - dummy_turbine.power_output=mc_example_turbine.power_output + mc_example_turbine = ModelChain( + dummy_turbine, power_output_model="power_coefficient_curve" + ).run_model(weather) + dummy_turbine.power_output = mc_example_turbine.power_output return @@ -272,8 +283,8 @@ def run_example(): Runs the basic example. """ - weather=get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=initialize_wind_turbines() + weather = get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = initialize_wind_turbines() calculate_power_output(weather, my_turbine, e126, dummy_turbine) plot_or_print(my_turbine, e126, dummy_turbine) diff --git a/example/test_examples.py b/example/test_examples.py index aed5fd0c..afa612f4 100644 --- a/example/test_examples.py +++ b/example/test_examples.py @@ -15,64 +15,92 @@ class TestExamples: - def test_modelchain_example_flh(self): # tests full load hours - weather=mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() + weather = mc_e.get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() mc_e.calculate_power_output(weather, my_turbine, e126, dummy_turbine) - assert_allclose(2764.194772, (e126.power_output.sum() / - e126.nominal_power), 0.01) - assert_allclose(1882.7567, (my_turbine.power_output.sum() / - my_turbine.nominal_power), 0.01) + assert_allclose( + 2764.194772, (e126.power_output.sum() / e126.nominal_power), 0.01 + ) + assert_allclose( + 1882.7567, + (my_turbine.power_output.sum() / my_turbine.nominal_power), + 0.01, + ) def test_turbine_cluster_modelchain_example_flh(self): # tests full load hours - weather=mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() - example_farm, example_farm_2=tc_mc_e.initialize_wind_farms( - my_turbine, e126) - example_cluster=tc_mc_e.initialize_wind_turbine_cluster( - example_farm, example_farm_2) + weather = mc_e.get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() + example_farm, example_farm_2 = tc_mc_e.initialize_wind_farms( + my_turbine, e126 + ) + example_cluster = tc_mc_e.initialize_wind_turbine_cluster( + example_farm, example_farm_2 + ) tc_mc_e.calculate_power_output(weather, example_farm, example_cluster) - assert_allclose(1956.164053, (example_farm.power_output.sum() / - example_farm.nominal_power), 0.01) - assert_allclose(2156.794154, (example_cluster.power_output.sum() / - example_cluster.nominal_power), 0.01) + assert_allclose( + 1956.164053, + (example_farm.power_output.sum() / example_farm.nominal_power), + 0.01, + ) + assert_allclose( + 2156.794154, + ( + example_cluster.power_output.sum() + / example_cluster.nominal_power + ), + 0.01, + ) def _notebook_run(self, path): """ Execute a notebook via nbconvert and collect output. Returns (parsed nb object, execution errors) """ - dirname, __=os.path.split(path) + dirname, __ = os.path.split(path) os.chdir(dirname) with tempfile.NamedTemporaryFile(suffix=".ipynb") as fout: - args=["jupyter", "nbconvert", "--to", "notebook", "--execute", - "--ExecutePreprocessor.timeout=60", - "--output", fout.name, path] + args = [ + "jupyter", + "nbconvert", + "--to", + "notebook", + "--execute", + "--ExecutePreprocessor.timeout=60", + "--output", + fout.name, + path, + ] subprocess.check_call(args) fout.seek(0) - nb=nbformat.read(fout, nbformat.current_nbformat) + nb = nbformat.read(fout, nbformat.current_nbformat) - errors=[output for cell in nb.cells if "outputs" in cell - for output in cell["outputs"] - if output.output_type == "error"] + errors = [ + output + for cell in nb.cells + if "outputs" in cell + for output in cell["outputs"] + if output.output_type == "error" + ] return nb, errors @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_modelchain_example_ipynb(self): - dir_path=os.path.dirname(os.path.realpath(__file__)) - nb, errors=self._notebook_run( - os.path.join(dir_path, 'modelchain_example.ipynb')) + dir_path = os.path.dirname(os.path.realpath(__file__)) + nb, errors = self._notebook_run( + os.path.join(dir_path, "modelchain_example.ipynb") + ) assert errors == [] @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6") def test_turbine_cluster_modelchain_example_ipynb(self): - dir_path=os.path.dirname(os.path.realpath(__file__)) - nb, errors=self._notebook_run( - os.path.join(dir_path, 'turbine_cluster_modelchain_example.ipynb')) + dir_path = os.path.dirname(os.path.realpath(__file__)) + nb, errors = self._notebook_run( + os.path.join(dir_path, "turbine_cluster_modelchain_example.ipynb") + ) assert errors == [] diff --git a/example/turbine_cluster_modelchain_example.py b/example/turbine_cluster_modelchain_example.py index 9903dbf1..ea0584bd 100644 --- a/example/turbine_cluster_modelchain_example.py +++ b/example/turbine_cluster_modelchain_example.py @@ -15,7 +15,7 @@ try: from matplotlib import pyplot as plt except ImportError: - plt=None + plt = None from example import modelchain_example as mc_e from windpowerlib import WindFarm @@ -58,24 +58,30 @@ def initialize_wind_farms(my_turbine, e126): # for each turbine type you can either specify the number of turbines of # that type in the wind farm (float values are possible as well) or the # total installed capacity of that turbine type in W - wind_turbine_fleet=pd.DataFrame( - {'wind_turbine': [my_turbine, e126], # as windpowerlib.WindTurbine - 'number_of_turbines': [6, None], - 'total_capacity': [None, 12.6e6]} + wind_turbine_fleet = pd.DataFrame( + { + "wind_turbine": [my_turbine, e126], # as windpowerlib.WindTurbine + "number_of_turbines": [6, None], + "total_capacity": [None, 12.6e6], + } ) # initialize WindFarm object - example_farm=WindFarm(name='example_farm', - wind_turbine_fleet=wind_turbine_fleet) + example_farm = WindFarm( + name="example_farm", wind_turbine_fleet=wind_turbine_fleet + ) # specification of wind farm data (2) containing a wind farm efficiency # wind turbine fleet is provided using the to_group function - example_farm_2_data={ - 'name': 'example_farm_2', - 'wind_turbine_fleet': [my_turbine.to_group(6), - e126.to_group(total_capacity=12.6e6)], - 'efficiency': 0.9} + example_farm_2_data = { + "name": "example_farm_2", + "wind_turbine_fleet": [ + my_turbine.to_group(6), + e126.to_group(total_capacity=12.6e6), + ], + "efficiency": 0.9, + } # initialize WindFarm object - example_farm_2=WindFarm(**example_farm_2_data) + example_farm_2 = WindFarm(**example_farm_2_data) return example_farm, example_farm_2 @@ -103,11 +109,12 @@ def initialize_wind_turbine_cluster(example_farm, example_farm_2): """ # specification of cluster data - example_cluster_data={ - 'name': 'example_cluster', - 'wind_farms': [example_farm, example_farm_2]} + example_cluster_data = { + "name": "example_cluster", + "wind_farms": [example_farm, example_farm_2], + } # initialize WindTurbineCluster object - example_cluster=WindTurbineCluster(**example_cluster_data) + example_cluster = WindTurbineCluster(**example_cluster_data) return example_cluster @@ -133,48 +140,49 @@ class that provides all necessary steps to calculate the power output of a WindTurbineCluster object. """ - example_farm.efficiency=0.9 + example_farm.efficiency = 0.9 # power output calculation for example_farm # initialize TurbineClusterModelChain with default parameters and use # run_model method to calculate power output - mc_example_farm=TurbineClusterModelChain(example_farm).run_model(weather) + mc_example_farm = TurbineClusterModelChain(example_farm).run_model(weather) # write power output time series to WindFarm object - example_farm.power_output=mc_example_farm.power_output + example_farm.power_output = mc_example_farm.power_output # power output calculation for turbine_cluster # own specifications for TurbineClusterModelChain setup - modelchain_data={ - 'wake_losses_model': - 'wind_farm_efficiency', # 'dena_mean' (default), None, - # 'wind_farm_efficiency' or name - # of another wind efficiency curve - # see :py:func:`~.wake_losses.get_wind_efficiency_curve` - 'smoothing': True, # False (default) or True - 'block_width': 0.5, # default: 0.5 - 'standard_deviation_method': 'Staffell_Pfenninger', # - # 'turbulence_intensity' (default) - # or 'Staffell_Pfenninger' - 'smoothing_order': 'wind_farm_power_curves', # - # 'wind_farm_power_curves' (default) or - # 'turbine_power_curves' - 'wind_speed_model': 'logarithmic', # 'logarithmic' (default), - # 'hellman' or - # 'interpolation_extrapolation' - 'density_model': 'ideal_gas', # 'barometric' (default), 'ideal_gas' or - # 'interpolation_extrapolation' - 'temperature_model': 'linear_gradient', # 'linear_gradient' (def.) or - # 'interpolation_extrapolation' - 'power_output_model': 'power_curve', # 'power_curve' (default) or - # 'power_coefficient_curve' - 'density_correction': True, # False (default) or True - 'obstacle_height': 0, # default: 0 - 'hellman_exp': None} # None (default) or None + modelchain_data = { + "wake_losses_model": "wind_farm_efficiency", # 'dena_mean' (default), None, + # 'wind_farm_efficiency' or name + # of another wind efficiency curve + # see :py:func:`~.wake_losses.get_wind_efficiency_curve` + "smoothing": True, # False (default) or True + "block_width": 0.5, # default: 0.5 + "standard_deviation_method": "Staffell_Pfenninger", # + # 'turbulence_intensity' (default) + # or 'Staffell_Pfenninger' + "smoothing_order": "wind_farm_power_curves", # + # 'wind_farm_power_curves' (default) or + # 'turbine_power_curves' + "wind_speed_model": "logarithmic", # 'logarithmic' (default), + # 'hellman' or + # 'interpolation_extrapolation' + "density_model": "ideal_gas", # 'barometric' (default), 'ideal_gas' or + # 'interpolation_extrapolation' + "temperature_model": "linear_gradient", # 'linear_gradient' (def.) or + # 'interpolation_extrapolation' + "power_output_model": "power_curve", # 'power_curve' (default) or + # 'power_coefficient_curve' + "density_correction": True, # False (default) or True + "obstacle_height": 0, # default: 0 + "hellman_exp": None, + } # None (default) or None # initialize TurbineClusterModelChain with own specifications and use # run_model method to calculate power output - mc_example_cluster=TurbineClusterModelChain( - example_cluster, **modelchain_data).run_model(weather) + mc_example_cluster = TurbineClusterModelChain( + example_cluster, **modelchain_data + ).run_model(weather) # write power output time series to WindTurbineCluster object - example_cluster.power_output=mc_example_cluster.power_output + example_cluster.power_output = mc_example_cluster.power_output return @@ -209,11 +217,12 @@ def run_example(): Runs the example. """ - weather=mc_e.get_weather_data('weather.csv') - my_turbine, e126, dummy_turbine=mc_e.initialize_wind_turbines() - example_farm, example_farm_2=initialize_wind_farms(my_turbine, e126) - example_cluster=initialize_wind_turbine_cluster(example_farm, - example_farm_2) + weather = mc_e.get_weather_data("weather.csv") + my_turbine, e126, dummy_turbine = mc_e.initialize_wind_turbines() + example_farm, example_farm_2 = initialize_wind_farms(my_turbine, e126) + example_cluster = initialize_wind_turbine_cluster( + example_farm, example_farm_2 + ) calculate_power_output(weather, example_farm, example_cluster) plot_or_print(example_farm, example_cluster) diff --git a/tests/test_density.py b/tests/test_density.py index 67c4b4b5..68556f4d 100644 --- a/tests/test_density.py +++ b/tests/test_density.py @@ -12,57 +12,66 @@ class TestDensity: - def test_barometric(self): - parameters={'pressure': pd.Series(data=[101125, 101000]), - 'pressure_height': 0, - 'hub_height': 100, - 'temperature_hub_height': pd.Series(data=[267, 268])} + parameters = { + "pressure": pd.Series(data=[101125, 101000]), + "pressure_height": 0, + "hub_height": 100, + "temperature_hub_height": pd.Series(data=[267, 268]), + } # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp=pd.Series(data=[1.30305336, 1.29656645]) + rho_exp = pd.Series(data=[1.30305336, 1.29656645]) assert_series_equal(barometric(**parameters), rho_exp) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters['pressure']=np.array(parameters['pressure']) - parameters['temperature_hub_height']=pd.Series( - data=parameters['temperature_hub_height']) + parameters["pressure"] = np.array(parameters["pressure"]) + parameters["temperature_hub_height"] = pd.Series( + data=parameters["temperature_hub_height"] + ) assert_series_equal(barometric(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp=np.array([1.30305336, 1.29656645]) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + rho_exp = np.array([1.30305336, 1.29656645]) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_allclose(barometric(**parameters), rho_exp) assert isinstance(barometric(**parameters), np.ndarray) def test_ideal_gas(self): - parameters={'pressure': pd.Series(data=[101125, 101000]), - 'pressure_height': 0, - 'hub_height': 100, - 'temperature_hub_height': pd.Series(data=[267, 268])} + parameters = { + "pressure": pd.Series(data=[101125, 101000]), + "pressure_height": 0, + "hub_height": 100, + "temperature_hub_height": pd.Series(data=[267, 268]), + } # Test pressure as pd.Series and temperature_hub_height as pd.Series # and np.array - rho_exp=pd.Series(data=[1.30309439, 1.29660728]) + rho_exp = pd.Series(data=[1.30309439, 1.29660728]) assert_series_equal(ideal_gas(**parameters), rho_exp) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_series_equal(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as pd.Series - parameters['pressure']=np.array(parameters['pressure']) - parameters['temperature_hub_height']=pd.Series( - data=parameters['temperature_hub_height']) + parameters["pressure"] = np.array(parameters["pressure"]) + parameters["temperature_hub_height"] = pd.Series( + data=parameters["temperature_hub_height"] + ) assert_allclose(ideal_gas(**parameters), rho_exp) # Test pressure as np.array and temperature_hub_height as np.array - rho_exp=np.array([1.30309439, 1.29660728]) - parameters['temperature_hub_height']=np.array( - parameters['temperature_hub_height']) + rho_exp = np.array([1.30309439, 1.29660728]) + parameters["temperature_hub_height"] = np.array( + parameters["temperature_hub_height"] + ) assert_allclose(ideal_gas(**parameters), rho_exp) assert isinstance(ideal_gas(**parameters), np.ndarray) diff --git a/tests/test_modelchain.py b/tests/test_modelchain.py index 2fea51aa..8bdac075 100644 --- a/tests/test_modelchain.py +++ b/tests/test_modelchain.py @@ -14,330 +14,420 @@ class TestModelChain: - @classmethod def setup_class(self): """Setup default values""" - self.test_turbine={'hub_height': 100, - 'turbine_type': 'E-126/4200', - 'power_curve': pd.DataFrame( - data={'value': [0.0, 4200 * 1000], - 'wind_speed': [0.0, 25.0]})} - - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - pressure_0m=np.array([[101125], [101000]]) - wind_speed_8m=np.array([[4.0], [5.0]]) - wind_speed_10m=np.array([[5.0], [6.5]]) - roughness_length=np.array([[0.15], [0.15]]) - self.weather_df=pd.DataFrame( - np.hstack((temperature_2m, temperature_10m, pressure_0m, - wind_speed_8m, wind_speed_10m, roughness_length)), + self.test_turbine = { + "hub_height": 100, + "turbine_type": "E-126/4200", + "power_curve": pd.DataFrame( + data={"value": [0.0, 4200 * 1000], "wind_speed": [0.0, 25.0]} + ), + } + + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + pressure_0m = np.array([[101125], [101000]]) + wind_speed_8m = np.array([[4.0], [5.0]]) + wind_speed_10m = np.array([[5.0], [6.5]]) + roughness_length = np.array([[0.15], [0.15]]) + self.weather_df = pd.DataFrame( + np.hstack( + ( + temperature_2m, + temperature_10m, + pressure_0m, + wind_speed_8m, + wind_speed_10m, + roughness_length, + ) + ), index=[0, 1], - columns=[np.array(['temperature', 'temperature', 'pressure', - 'wind_speed', 'wind_speed', - 'roughness_length']), - np.array([2, 10, 0, 8, 10, 0])]) + columns=[ + np.array( + [ + "temperature", + "temperature", + "pressure", + "wind_speed", + "wind_speed", + "roughness_length", + ] + ), + np.array([2, 10, 0, 8, 10, 0]), + ], + ) def test_temperature_hub(self): # Test modelchain with temperature_model='linear_gradient' - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with temperature_model='interpolation_extrapolation' - test_mc_2=mc.ModelChain( + test_mc_2 = mc.ModelChain( wt.WindTurbine(**self.test_turbine), - temperature_model='interpolation_extrapolation') + temperature_model="interpolation_extrapolation", + ) # Parameters for tests - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - weather_df=pd.DataFrame(np.hstack((temperature_2m, - temperature_10m)), - index=[0, 1], - columns=[np.array(['temperature', - 'temperature']), - np.array([2, 10])]) + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + weather_df = pd.DataFrame( + np.hstack((temperature_2m, temperature_10m)), + index=[0, 1], + columns=[ + np.array(["temperature", "temperature"]), + np.array([2, 10]), + ], + ) # temperature_10m is closer to hub height than temperature_2m - temp_exp=pd.Series(data=[266.415, 265.415], name=10) + temp_exp = pd.Series(data=[266.415, 265.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp=pd.Series(data=[267.0, 243.5]) + temp_exp = pd.Series(data=[267.0, 243.5]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns=[np.array(['temperature', 'temperature']), - np.array([10, 200])] - temp_exp=pd.Series(data=[266.415, 267.415], name=10) + weather_df.columns = [ + np.array(["temperature", "temperature"]), + np.array([10, 200]), + ] + temp_exp = pd.Series(data=[266.415, 267.415], name=10) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) - temp_exp=pd.Series(data=[267.0, 267.052632]) + temp_exp = pd.Series(data=[267.0, 267.052632]) assert_series_equal(test_mc_2.temperature_hub(weather_df), temp_exp) # temperature at hub height - weather_df.columns=[np.array(['temperature', 'temperature']), - np.array([100, 10])] - temp_exp=pd.Series(data=[267, 268], name=100) + weather_df.columns = [ + np.array(["temperature", "temperature"]), + np.array([100, 10]), + ] + temp_exp = pd.Series(data=[267, 268], name=100) assert_series_equal(test_mc.temperature_hub(weather_df), temp_exp) def test_density_hub(self): # Test modelchain with density_model='barometric' - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with density_model='ideal_gas' - test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - density_model='ideal_gas') + test_mc_2 = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), density_model="ideal_gas" + ) # Test modelchain with density_model='interpolation_extrapolation' - test_mc_3=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - density_model='interpolation_extrapolation') + test_mc_3 = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), + density_model="interpolation_extrapolation", + ) # Parameters for tests - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - pressure_0m=np.array([[101125], [101000]]) - weather_df=pd.DataFrame(np.hstack((temperature_2m, - temperature_10m, - pressure_0m)), - index=[0, 1], - columns=[np.array(['temperature', - 'temperature', - 'pressure']), - np.array([2, 10, 0])]) + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + pressure_0m = np.array([[101125], [101000]]) + weather_df = pd.DataFrame( + np.hstack((temperature_2m, temperature_10m, pressure_0m)), + index=[0, 1], + columns=[ + np.array(["temperature", "temperature", "pressure"]), + np.array([2, 10, 0]), + ], + ) # temperature_10m is closer to hub height than temperature_2m - rho_exp=pd.Series(data=[1.30591, 1.30919]) + rho_exp = pd.Series(data=[1.30591, 1.30919]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp=pd.Series(data=[1.30595575725, 1.30923554056]) + rho_exp = pd.Series(data=[1.30595575725, 1.30923554056]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # change heights of temperatures so that old temperature_2m is now used - weather_df.columns=[np.array(['temperature', 'temperature', - 'pressure']), - np.array([10, 200, 0])] - rho_exp=pd.Series(data=[1.30591, 1.29940]) + weather_df.columns = [ + np.array(["temperature", "temperature", "pressure"]), + np.array([10, 200, 0]), + ] + rho_exp = pd.Series(data=[1.30591, 1.29940]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) - rho_exp=pd.Series(data=[1.30595575725, 1.29944375221]) + rho_exp = pd.Series(data=[1.30595575725, 1.29944375221]) assert_series_equal(test_mc_2.density_hub(weather_df), rho_exp) # temperature at hub height - weather_df.columns=[np.array(['temperature', 'temperature', - 'pressure']), - np.array([100, 10, 0])] - rho_exp=pd.Series(data=[1.30305, 1.29657]) + weather_df.columns = [ + np.array(["temperature", "temperature", "pressure"]), + np.array([100, 10, 0]), + ] + rho_exp = pd.Series(data=[1.30305, 1.29657]) assert_series_equal(test_mc.density_hub(weather_df), rho_exp) # density interpolation - density_10m=np.array([[1.30591], [1.29940]]) - density_150m=np.array([[1.30305], [1.29657]]) - weather_df=pd.DataFrame(np.hstack((density_10m, - density_150m)), - index=[0, 1], - columns=[np.array(['density', - 'density']), - np.array([10, 150])]) - rho_exp=pd.Series(data=[1.304071, 1.297581]) + density_10m = np.array([[1.30591], [1.29940]]) + density_150m = np.array([[1.30305], [1.29657]]) + weather_df = pd.DataFrame( + np.hstack((density_10m, density_150m)), + index=[0, 1], + columns=[np.array(["density", "density"]), np.array([10, 150])], + ) + rho_exp = pd.Series(data=[1.304071, 1.297581]) assert_series_equal(test_mc_3.density_hub(weather_df), rho_exp) def test_wind_speed_hub(self): # Test modelchain with wind_speed_model='logarithmic' - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine)) + test_mc = mc.ModelChain(wt.WindTurbine(**self.test_turbine)) # Test modelchain with wind_speed_model='hellman' - test_mc_2=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - wind_speed_model='hellman') + test_mc_2 = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), wind_speed_model="hellman" + ) # Test modelchain with wind_speed_model='interpolation_extrapolation' - test_mc_3=mc.ModelChain( + test_mc_3 = mc.ModelChain( wt.WindTurbine(**self.test_turbine), - wind_speed_model='interpolation_extrapolation') + wind_speed_model="interpolation_extrapolation", + ) # Test modelchain with # wind_speed_model='log_interpolation_extrapolation' - test_mc_4=mc.ModelChain( + test_mc_4 = mc.ModelChain( wt.WindTurbine(**self.test_turbine), - wind_speed_model='log_interpolation_extrapolation') + wind_speed_model="log_interpolation_extrapolation", + ) # Parameters for tests - wind_speed_8m=np.array([[4.0], [5.0]]) - wind_speed_10m=np.array([[5.0], [6.5]]) - roughness_length=np.array([[0.15], [0.15]]) - weather_df=pd.DataFrame(np.hstack((wind_speed_8m, - wind_speed_10m, - roughness_length)), - index=[0, 1], - columns=[np.array(['wind_speed', - 'wind_speed', - 'roughness_length']), - np.array([8, 10, 0])]) + wind_speed_8m = np.array([[4.0], [5.0]]) + wind_speed_10m = np.array([[5.0], [6.5]]) + roughness_length = np.array([[0.15], [0.15]]) + weather_df = pd.DataFrame( + np.hstack((wind_speed_8m, wind_speed_10m, roughness_length)), + index=[0, 1], + columns=[ + np.array(["wind_speed", "wind_speed", "roughness_length"]), + np.array([8, 10, 0]), + ], + ) # wind_speed_10m is closer to hub height than wind_speed_8m - v_wind_exp=pd.Series(data=[7.74137, 10.06377]) + v_wind_exp = pd.Series(data=[7.74137, 10.06377]) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp=pd.Series(data=[7.12462, 9.26201]) + v_wind_exp = pd.Series(data=[7.12462, 9.26201]) assert_series_equal(test_mc_2.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp=pd.Series(data=[50.0, 74.0]) + v_wind_exp = pd.Series(data=[50.0, 74.0]) assert_series_equal(test_mc_3.wind_speed_hub(weather_df), v_wind_exp) - v_wind_exp=pd.Series(data=[15.3188511585, 21.9782767378]) + v_wind_exp = pd.Series(data=[15.3188511585, 21.9782767378]) assert_series_equal(test_mc_4.wind_speed_hub(weather_df), v_wind_exp) # wind_speed is given at hub height - weather_df.columns=[np.array(['wind_speed', 'wind_speed', - 'roughness_length']), - np.array([10, 100, 0])] - v_wind_exp=pd.Series(data=[5.0, 6.5], name=100) + weather_df.columns = [ + np.array(["wind_speed", "wind_speed", "roughness_length"]), + np.array([10, 100, 0]), + ] + v_wind_exp = pd.Series(data=[5.0, 6.5], name=100) assert_series_equal(test_mc.wind_speed_hub(weather_df), v_wind_exp) # ***** test_run_model ********* def test_with_default_parameter(self): """Test with default parameters of modelchain (power curve)""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - power_output_exp=pd.Series(data=[1637405.4840444783, - 3154438.3894902095], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine)) + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + power_output_exp = pd.Series( + data=[1637405.4840444783, 3154438.3894902095], + name="feedin_power_plant", + ) + test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_density_corrected_power_curve_and_hellman(self): """Test with density corrected power curve and hellman""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_curve', - 'density_correction': True} - power_output_exp=pd.Series(data=[1366958.544547462, - 2823402.837201821], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_curve", + "density_correction": True, + } + power_output_exp = pd.Series( + data=[1366958.544547462, 2823402.837201821], + name="feedin_power_plant", + ) + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_with_power_coefficient_curve_and_hellman(self): """Test with power coefficient curve and hellman""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - power_output_exp=pd.Series(data=[534137.5112701517, - 1103611.1736067757], - name='feedin_power_plant') - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False} - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + power_output_exp = pd.Series( + data=[534137.5112701517, 1103611.1736067757], + name="feedin_power_plant", + ) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_wrong_spelling_power_output_model(self): """Raise ValueErrors due to wrong spelling of power_output_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'wrong_spelling', - 'density_correction': False} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "wrong_spelling", + "density_correction": False, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_spelling_density_model(self): """Raise ValueErrors due to wrong spelling of density_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False, - 'density_model': 'wrong_spelling'} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + "density_model": "wrong_spelling", + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_spelling_temperature_model(self): """Raise ValueErrors due to wrong spelling of temperature_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'hellman', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False, - 'temperature_model': 'wrong_spelling'} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "hellman", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + "temperature_model": "wrong_spelling", + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_spelling_wind_speed_model(self): """Raise ValueErrors due to wrong spelling of wind_speed_model""" with pytest.raises(ValueError): - test_modelchain={'wind_speed_model': 'wrong_spelling', - 'power_output_model': 'power_coefficient_curve', - 'density_correction': False} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "wind_speed_model": "wrong_spelling", + "power_output_model": "power_coefficient_curve", + "density_correction": False, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_wrong_density_correction_type(self): """Raise TypeErrors due to wrong type of `density_correction`""" with pytest.raises(TypeError): - test_modelchain={'power_output_model': 'power_curve', - 'density_correction': 'wrong_type'} - test_mc=mc.ModelChain(wt.WindTurbine(**self.test_turbine), - **test_modelchain) + test_modelchain = { + "power_output_model": "power_curve", + "density_correction": "wrong_type", + } + test_mc = mc.ModelChain( + wt.WindTurbine(**self.test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_cp_values(self): """Raise TypeErrors due to missing cp-values""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4201'} - msg="Power coefficient curve values of" + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4201", + } + msg = "Power coefficient curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain={'power_output_model': 'power_coefficient_curve', - 'density_correction': True} - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_modelchain = { + "power_output_model": "power_coefficient_curve", + "density_correction": True, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_missing_p_values(self): """Raise TypeErrors due to missing p-values""" - test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4205'} - msg="Power curve values of" + test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4205", + } + msg = "Power curve values of" with pytest.raises(TypeError, match=msg): - test_modelchain={'power_output_model': 'power_curve', - 'density_corr': True} - test_mc=mc.ModelChain(wt.WindTurbine(**test_turbine), - **test_modelchain) + test_modelchain = { + "power_output_model": "power_curve", + "density_corr": True, + } + test_mc = mc.ModelChain( + wt.WindTurbine(**test_turbine), **test_modelchain + ) test_mc.run_model(self.weather_df) def test_modelchain_with_power_curve_as_dict(self): """Test power curves as dict""" - my_turbine={'nominal_power': 3e6, 'hub_height': 105, - 'rotor_diameter': 70, - 'power_curve': { - 'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}, - 'power_coefficient_curve': { - 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - power_output_exp=pd.Series(data=[919055.54840, - 1541786.60559], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine)) + my_turbine = { + "nominal_power": 3e6, + "hub_height": 105, + "rotor_diameter": 70, + "power_curve": { + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + "power_coefficient_curve": { + "value": [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + } + power_output_exp = pd.Series( + data=[919055.54840, 1541786.60559], name="feedin_power_plant" + ) + test_mc = mc.ModelChain(wt.WindTurbine(**my_turbine)) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) def test_modelchain_with_power_coefficient_curve_as_dict(self): """Test power coefficient curves as dict""" - my_turbine={'nominal_power': 3e6, 'hub_height': 105, - 'rotor_diameter': 70, - 'power_curve': { - 'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}, - 'power_coefficient_curve': { - 'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - power_output_exp=pd.Series(data=[469518.35104, - 901794.28532], - name='feedin_power_plant') - test_mc=mc.ModelChain(wt.WindTurbine(**my_turbine), - power_output_model='power_coefficient_curve') + my_turbine = { + "nominal_power": 3e6, + "hub_height": 105, + "rotor_diameter": 70, + "power_curve": { + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + "power_coefficient_curve": { + "value": [0.0, 0.43, 0.45, 0.35, 0.12, 0.03], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + } + power_output_exp = pd.Series( + data=[469518.35104, 901794.28532], name="feedin_power_plant" + ) + test_mc = mc.ModelChain( + wt.WindTurbine(**my_turbine), + power_output_model="power_coefficient_curve", + ) test_mc.run_model(self.weather_df) assert_series_equal(test_mc.power_output, power_output_exp) diff --git a/tests/test_power_curves.py b/tests/test_power_curves.py index 5814969b..ccf296ab 100644 --- a/tests/test_power_curves.py +++ b/tests/test_power_curves.py @@ -8,95 +8,153 @@ import pytest from pandas.util.testing import assert_frame_equal -from windpowerlib.power_curves import (smooth_power_curve, - wake_losses_to_power_curve) +from windpowerlib.power_curves import ( + smooth_power_curve, + wake_losses_to_power_curve, +) import windpowerlib.wind_turbine as wt class TestPowerCurves: - @classmethod def setup_class(self): - self.test_turbine={'hub_height': 100, - 'turbine_type': 'E-126/4200'} + self.test_turbine = {"hub_height": 100, "turbine_type": "E-126/4200"} def test_smooth_power_curve(self): - test_curve=wt.WindTurbine(**self.test_turbine).power_curve - parameters={'power_curve_wind_speeds': test_curve['wind_speed'], - 'power_curve_values': test_curve['value'], - 'standard_deviation_method': 'turbulence_intensity'} + test_curve = wt.WindTurbine(**self.test_turbine).power_curve + parameters = { + "power_curve_wind_speeds": test_curve["wind_speed"], + "power_curve_values": test_curve["value"], + "standard_deviation_method": "turbulence_intensity", + } # Raise ValueError - `turbulence_intensity` missing with pytest.raises(ValueError): - parameters['standard_deviation_method']='turbulence_intensity' + parameters["standard_deviation_method"] = "turbulence_intensity" smooth_power_curve(**parameters) # Test turbulence_intensity method - parameters['turbulence_intensity']=0.5 - wind_speed_values_exp=pd.Series([6.0, 7.0, 8.0, 9.0, 10.0], - name='wind_speed') - power_values_exp=pd.Series([ - 1141906.9806766496, 1577536.8085282773, 1975480.993355767, - 2314059.4022704284, 2590216.6802602503], name='value') - smoothed_curve_exp=pd.DataFrame(data=pd.concat([ - wind_speed_values_exp, power_values_exp], axis=1)) - smoothed_curve_exp.index=np.arange(5, 10, 1) - assert_frame_equal(smooth_power_curve(**parameters)[5:10], - smoothed_curve_exp) + parameters["turbulence_intensity"] = 0.5 + wind_speed_values_exp = pd.Series( + [6.0, 7.0, 8.0, 9.0, 10.0], name="wind_speed" + ) + power_values_exp = pd.Series( + [ + 1141906.9806766496, + 1577536.8085282773, + 1975480.993355767, + 2314059.4022704284, + 2590216.6802602503, + ], + name="value", + ) + smoothed_curve_exp = pd.DataFrame( + data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1) + ) + smoothed_curve_exp.index = np.arange(5, 10, 1) + assert_frame_equal( + smooth_power_curve(**parameters)[5:10], smoothed_curve_exp + ) # Test Staffel_Pfenninger method - parameters['standard_deviation_method']='Staffell_Pfenninger' - power_values_exp=pd.Series([ - 929405.1348918702, 1395532.5468724659, 1904826.6851982325, - 2402659.118305521, 2844527.1732449625], name='value') - smoothed_curve_exp=pd.DataFrame( - data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1)) - smoothed_curve_exp.index=np.arange(5, 10, 1) - assert_frame_equal(smooth_power_curve(**parameters)[5:10], - smoothed_curve_exp) + parameters["standard_deviation_method"] = "Staffell_Pfenninger" + power_values_exp = pd.Series( + [ + 929405.1348918702, + 1395532.5468724659, + 1904826.6851982325, + 2402659.118305521, + 2844527.1732449625, + ], + name="value", + ) + smoothed_curve_exp = pd.DataFrame( + data=pd.concat([wind_speed_values_exp, power_values_exp], axis=1) + ) + smoothed_curve_exp.index = np.arange(5, 10, 1) + assert_frame_equal( + smooth_power_curve(**parameters)[5:10], smoothed_curve_exp + ) # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters['standard_deviation_method']='misspelled' + parameters["standard_deviation_method"] = "misspelled" smooth_power_curve(**parameters) def test_wake_losses_to_power_curve(self): - test_curve=wt.WindTurbine(**self.test_turbine).power_curve - parameters={'power_curve_wind_speeds': test_curve['wind_speed'], - 'power_curve_values': test_curve['value'], - 'wind_farm_efficiency': 0.9} + test_curve = wt.WindTurbine(**self.test_turbine).power_curve + parameters = { + "power_curve_wind_speeds": test_curve["wind_speed"], + "power_curve_values": test_curve["value"], + "wind_farm_efficiency": 0.9, + } # Test constant efficiency - power_curve_exp=test_curve.copy(deep=True) - power_curve_exp['value']=power_curve_exp['value'].values * 0.9 - assert_frame_equal(wake_losses_to_power_curve(**parameters), - power_curve_exp) + power_curve_exp = test_curve.copy(deep=True) + power_curve_exp["value"] = power_curve_exp["value"].values * 0.9 + assert_frame_equal( + wake_losses_to_power_curve(**parameters), power_curve_exp + ) # Test efficiency curve - parameters['wind_farm_efficiency']=pd.DataFrame( - pd.concat([pd.Series(np.arange(1, 26, 1)), - pd.Series([ - 1.0, 1.0, 1.0, 0.84, 0.85, 0.86, 0.85, 0.85, 0.85, - 0.86, 0.87, 0.89, 0.92, 0.95, 0.95, 0.96, 0.99, - 0.95, 0.98, 0.97, 0.99, 1.0, 1.0, 1.0, 1.0])], - axis=1)) - parameters['wind_farm_efficiency'].columns=['wind_speed', - 'efficiency'] - power_curve_exp=test_curve.copy(deep=True) - power_curve_exp['value']=( - power_curve_exp['value'].values * parameters[ - 'wind_farm_efficiency']['efficiency']) - assert_frame_equal(wake_losses_to_power_curve(**parameters), - power_curve_exp) + parameters["wind_farm_efficiency"] = pd.DataFrame( + pd.concat( + [ + pd.Series(np.arange(1, 26, 1)), + pd.Series( + [ + 1.0, + 1.0, + 1.0, + 0.84, + 0.85, + 0.86, + 0.85, + 0.85, + 0.85, + 0.86, + 0.87, + 0.89, + 0.92, + 0.95, + 0.95, + 0.96, + 0.99, + 0.95, + 0.98, + 0.97, + 0.99, + 1.0, + 1.0, + 1.0, + 1.0, + ] + ), + ], + axis=1, + ) + ) + parameters["wind_farm_efficiency"].columns = [ + "wind_speed", + "efficiency", + ] + power_curve_exp = test_curve.copy(deep=True) + power_curve_exp["value"] = ( + power_curve_exp["value"].values + * parameters["wind_farm_efficiency"]["efficiency"] + ) + assert_frame_equal( + wake_losses_to_power_curve(**parameters), power_curve_exp + ) # Raise TypeError if wind farm efficiency is of wrong type with pytest.raises(TypeError): - parameters['wind_farm_efficiency']=1 + parameters["wind_farm_efficiency"] = 1 wake_losses_to_power_curve(**parameters) if __name__ == "__main__": - test=TestPowerCurves() + test = TestPowerCurves() test.setup_class() test.test_smooth_power_curve() test.test_wake_losses_to_power_curve() diff --git a/tests/test_power_output.py b/tests/test_power_output.py index 0a5c6f84..d29d6e35 100644 --- a/tests/test_power_output.py +++ b/tests/test_power_output.py @@ -9,187 +9,214 @@ from numpy.testing import assert_allclose from pandas.util.testing import assert_series_equal -from windpowerlib.power_output import (power_coefficient_curve, - power_curve, - power_curve_density_correction) +from windpowerlib.power_output import ( + power_coefficient_curve, + power_curve, + power_curve_density_correction, +) class TestPowerOutput: - def test_power_coefficient_curve(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'rotor_diameter': 80, - 'power_coefficient_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_coefficient_curve_values': - pd.Series([0.3, 0.4, 0.5])} + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "rotor_diameter": 80, + "power_coefficient_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_coefficient_curve_values": pd.Series([0.3, 0.4, 0.5]), + } # Test wind_speed as pd.Series with density and power_coefficient_curve # as pd.Series and np.array - power_output_exp=pd.Series(data=[0.0, 244615.399, 0.0], - name='feedin_power_plant') - assert_series_equal(power_coefficient_curve(**parameters), - power_output_exp) - parameters['density']=np.array(parameters['density']) - assert_series_equal(power_coefficient_curve(**parameters), - power_output_exp) - parameters['power_coefficient_curve_values']=np.array( - parameters['power_coefficient_curve_values']) - parameters['power_coefficient_curve_wind_speeds']=np.array( - parameters['power_coefficient_curve_wind_speeds']) - assert_series_equal(power_coefficient_curve(**parameters), - power_output_exp) + power_output_exp = pd.Series( + data=[0.0, 244615.399, 0.0], name="feedin_power_plant" + ) + assert_series_equal( + power_coefficient_curve(**parameters), power_output_exp + ) + parameters["density"] = np.array(parameters["density"]) + assert_series_equal( + power_coefficient_curve(**parameters), power_output_exp + ) + parameters["power_coefficient_curve_values"] = np.array( + parameters["power_coefficient_curve_values"] + ) + parameters["power_coefficient_curve_wind_speeds"] = np.array( + parameters["power_coefficient_curve_wind_speeds"] + ) + assert_series_equal( + power_coefficient_curve(**parameters), power_output_exp + ) # Test wind_speed as np.array with density and power_coefficient_curve # as np.array and pd.Series - power_output_exp=np.array([0.0, 244615.399, 0.0]) - parameters['wind_speed']=np.array(parameters['wind_speed']) - assert_allclose(power_coefficient_curve(**parameters), - power_output_exp) + power_output_exp = np.array([0.0, 244615.399, 0.0]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) + assert_allclose( + power_coefficient_curve(**parameters), power_output_exp + ) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters['density']=pd.Series(data=parameters['density']) - assert_allclose(power_coefficient_curve(**parameters), - power_output_exp) + parameters["density"] = pd.Series(data=parameters["density"]) + assert_allclose( + power_coefficient_curve(**parameters), power_output_exp + ) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) - parameters['power_coefficient_curve_wind_speeds']=pd.Series( - data=parameters['power_coefficient_curve_wind_speeds']) - parameters['power_coefficient_curve_values']=pd.Series( - data=parameters['power_coefficient_curve_values']) - assert_allclose(power_coefficient_curve(**parameters), - power_output_exp) + parameters["power_coefficient_curve_wind_speeds"] = pd.Series( + data=parameters["power_coefficient_curve_wind_speeds"] + ) + parameters["power_coefficient_curve_values"] = pd.Series( + data=parameters["power_coefficient_curve_values"] + ) + assert_allclose( + power_coefficient_curve(**parameters), power_output_exp + ) assert isinstance(power_coefficient_curve(**parameters), np.ndarray) def test_power_curve(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'density_correction': False, - 'power_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_curve_values': - pd.Series([300, 400, 500]) - } + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "density_correction": False, + "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_curve_values": pd.Series([300, 400, 500]), + } # Tests without density correction: # Test wind_speed as pd.Series and power_curve as pd.Series and # np.array - power_output_exp=pd.Series(data=[0.0, 450.0, 0.0], - name='feedin_power_plant') + power_output_exp = pd.Series( + data=[0.0, 450.0, 0.0], name="feedin_power_plant" + ) + assert_series_equal(power_curve(**parameters), power_output_exp) + parameters["power_curve_values"] = np.array( + parameters["power_curve_values"] + ) + parameters["power_curve_wind_speeds"] = np.array( + parameters["power_curve_wind_speeds"] + ) assert_series_equal(power_curve(**parameters), power_output_exp) - parameters['power_curve_values']=np.array( - parameters['power_curve_values']) - parameters['power_curve_wind_speeds']=np.array( - parameters['power_curve_wind_speeds']) - assert_series_equal(power_curve(**parameters), - power_output_exp) # Test wind_speed as np.array and power_curve as pd.Series and np.array - power_output_exp=np.array([0.0, 450.0, 0.0]) - parameters['wind_speed']=np.array(parameters['wind_speed']) + power_output_exp = np.array([0.0, 450.0, 0.0]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_wind_speeds']=pd.Series( - data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values']=pd.Series( - data=parameters['power_curve_values']) + parameters["power_curve_wind_speeds"] = pd.Series( + data=parameters["power_curve_wind_speeds"] + ) + parameters["power_curve_values"] = pd.Series( + data=parameters["power_curve_values"] + ) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Tests with density correction: # Test wind_speed as np.array with density and power_curve as pd.Series # and np.array - power_output_exp=np.array([0.0, 461.00290572, 0.0]) - parameters['density_correction']=True + power_output_exp = np.array([0.0, 461.00290572, 0.0]) + parameters["density_correction"] = True assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['density']=np.array(parameters['density']) + parameters["density"] = np.array(parameters["density"]) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_values']=np.array( - parameters['power_curve_values']) - parameters['power_curve_wind_speeds']=np.array( - parameters['power_curve_wind_speeds']) + parameters["power_curve_values"] = np.array( + parameters["power_curve_values"] + ) + parameters["power_curve_wind_speeds"] = np.array( + parameters["power_curve_wind_speeds"] + ) assert_allclose(power_curve(**parameters), power_output_exp) assert isinstance(power_curve(**parameters), np.ndarray) # Test wind_speed as pd.Series with density and power_curve as # np. array and pd.Series - power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], - name='feedin_power_plant') - parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) + power_output_exp = pd.Series( + data=[0.0, 461.00290572, 0.0], name="feedin_power_plant" + ) + parameters["wind_speed"] = pd.Series(data=parameters["wind_speed"]) + assert_series_equal(power_curve(**parameters), power_output_exp) + parameters["density"] = pd.Series(data=parameters["density"]) + assert_series_equal(power_curve(**parameters), power_output_exp) + parameters["power_curve_wind_speeds"] = pd.Series( + data=parameters["power_curve_wind_speeds"] + ) + parameters["power_curve_values"] = pd.Series( + data=parameters["power_curve_values"] + ) assert_series_equal(power_curve(**parameters), power_output_exp) - parameters['density']=pd.Series(data=parameters['density']) - assert_series_equal(power_curve(**parameters), - power_output_exp) - parameters['power_curve_wind_speeds']=pd.Series( - data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values']=pd.Series( - data=parameters['power_curve_values']) - assert_series_equal(power_curve(**parameters), - power_output_exp) # Raise TypeErrors due to wrong type of `density_correction` with pytest.raises(TypeError): - parameters['density']='wrong_type' + parameters["density"] = "wrong_type" power_curve(**parameters) def test_power_curve_density_correction(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'power_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_curve_values': - pd.Series([300, 400, 500]) - } + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_curve_values": pd.Series([300, 400, 500]), + } # Test wind_speed as pd.Series with density and power_curve as # pd.Series and np.array - power_output_exp=pd.Series(data=[0.0, 461.00290572, 0.0], - name='feedin_power_plant') - assert_series_equal(power_curve_density_correction(**parameters), - power_output_exp) - parameters['density']=np.array(parameters['density']) - assert_series_equal(power_curve_density_correction(**parameters), - power_output_exp) - parameters['power_curve_values']=np.array( - parameters['power_curve_values']) - parameters['power_curve_wind_speeds']=np.array( - parameters['power_curve_wind_speeds']) - assert_series_equal(power_curve_density_correction(**parameters), - power_output_exp) + power_output_exp = pd.Series( + data=[0.0, 461.00290572, 0.0], name="feedin_power_plant" + ) + assert_series_equal( + power_curve_density_correction(**parameters), power_output_exp + ) + parameters["density"] = np.array(parameters["density"]) + assert_series_equal( + power_curve_density_correction(**parameters), power_output_exp + ) + parameters["power_curve_values"] = np.array( + parameters["power_curve_values"] + ) + parameters["power_curve_wind_speeds"] = np.array( + parameters["power_curve_wind_speeds"] + ) + assert_series_equal( + power_curve_density_correction(**parameters), power_output_exp + ) # Test wind_speed as np.array with density and power_curve as np.array # and pd.Series - parameters['wind_speed']=np.array(parameters['wind_speed']) - power_output_exp=np.array([0.0, 461.00290572, 0.0]) - assert_allclose(power_curve_density_correction(**parameters), - power_output_exp) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) + power_output_exp = np.array([0.0, 461.00290572, 0.0]) + assert_allclose( + power_curve_density_correction(**parameters), power_output_exp + ) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['density']=pd.Series(data=parameters['density']) - assert_allclose(power_curve_density_correction(**parameters), - power_output_exp) + parameters["density"] = pd.Series(data=parameters["density"]) + assert_allclose( + power_curve_density_correction(**parameters), power_output_exp + ) assert isinstance(power_curve(**parameters), np.ndarray) - parameters['power_curve_wind_speeds']=pd.Series( - data=parameters['power_curve_wind_speeds']) - parameters['power_curve_values']=pd.Series( - data=parameters['power_curve_values']) - assert_allclose(power_curve_density_correction(**parameters), - power_output_exp) + parameters["power_curve_wind_speeds"] = pd.Series( + data=parameters["power_curve_wind_speeds"] + ) + parameters["power_curve_values"] = pd.Series( + data=parameters["power_curve_values"] + ) + assert_allclose( + power_curve_density_correction(**parameters), power_output_exp + ) assert isinstance(power_curve(**parameters), np.ndarray) # Raise TypeError due to density is None with pytest.raises(TypeError): - parameters['density']=None + parameters["density"] = None power_curve_density_correction(**parameters) def test_wrong_spelling_density_correction(self): - parameters={'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]), - 'density': pd.Series(data=[1.3, 1.3, 1.3]), - 'power_curve_wind_speeds': - pd.Series([4.0, 5.0, 6.0]), - 'power_curve_values': - pd.Series([300, 400, 500]) - } - msg="is an invalid type. `density_correction` must be Boolean" + parameters = { + "wind_speed": pd.Series(data=[2.0, 5.5, 7.0]), + "density": pd.Series(data=[1.3, 1.3, 1.3]), + "power_curve_wind_speeds": pd.Series([4.0, 5.0, 6.0]), + "power_curve_values": pd.Series([300, 400, 500]), + } + msg = "is an invalid type. `density_correction` must be Boolean" with pytest.raises(TypeError, match=msg): - parameters['density_correction']=None + parameters["density_correction"] = None power_curve(**parameters) diff --git a/tests/test_temperature.py b/tests/test_temperature.py index 59070069..d0e2ba4b 100644 --- a/tests/test_temperature.py +++ b/tests/test_temperature.py @@ -12,20 +12,23 @@ class TestTemperature: - def test_linear_gradient(self): """Test temperature as pd.Series""" - parameters={'temperature': pd.Series(data=[267, 268]), - 'temperature_height': 2, - 'hub_height': 100} - temp_hub_exp=pd.Series(data=[266.363, 267.36300]) + parameters = { + "temperature": pd.Series(data=[267, 268]), + "temperature_height": 2, + "hub_height": 100, + } + temp_hub_exp = pd.Series(data=[266.363, 267.36300]) assert_series_equal(linear_gradient(**parameters), temp_hub_exp) def test_temperature_as_np_array(self): """Test temperature as np.array""" - parameters={'temperature': np.array([267, 268]), - 'temperature_height': 2, - 'hub_height': 100} - temp_hub_exp=np.array([266.363, 267.36300]) + parameters = { + "temperature": np.array([267, 268]), + "temperature_height": 2, + "hub_height": 100, + } + temp_hub_exp = np.array([266.363, 267.36300]) assert_array_equal(linear_gradient(**parameters), temp_hub_exp) assert isinstance(linear_gradient(**parameters), np.ndarray) diff --git a/tests/test_tools.py b/tests/test_tools.py index 91d87223..2392d89d 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -6,96 +6,128 @@ import pandas as pd from pandas.util.testing import assert_series_equal -from windpowerlib.tools import (linear_interpolation_extrapolation, - logarithmic_interpolation_extrapolation) +from windpowerlib.tools import ( + linear_interpolation_extrapolation, + logarithmic_interpolation_extrapolation, +) class TestTools: - @classmethod def setup_class(cls): - cls.parameters={'target_height': 80} - cls.df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], - 80: [4.0, 5.0, 6.0], - 200: [5.0, 8.0, 10.0]}, - index=[0, 1, 2]) + cls.parameters = {"target_height": 80} + cls.df = pd.DataFrame( + data={ + 10: [2.0, 2.0, 3.0], + 80: [4.0, 5.0, 6.0], + 200: [5.0, 8.0, 10.0], + }, + index=[0, 1, 2], + ) def test_linear_target_height_is_equal_to_given_height(self): """ Test linear interpolation and extrapolation if target_height is equal to height given in a column of the DataFrame. """ - exp_output=pd.Series(data=[4.0, 5.0, 6.0]) - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[4.0, 5.0, 6.0]) + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_linear_target_height_is_between_given_heights(self): """ Test linear interpolation and extrapolation if target_height is between heights given in the columns of the DataFrame """ - exp_output=pd.Series(data=[4.5, 6.5, 8.0]) - self.parameters['target_height']=140 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[4.5, 6.5, 8.0]) + self.parameters["target_height"] = 140 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) - exp_output=pd.Series(data=[4.285714, 5.428571, 6.428571]) - self.parameters['target_height']=90 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[4.285714, 5.428571, 6.428571]) + self.parameters["target_height"] = 90 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_linear_target_height_is_greater_than_the_given_heights(self): """ Test linear interpolation and extrapolation if target_height is greater than the heights given in the columns of the DataFrame """ - exp_output=pd.Series(data=[5.333333, 9.0, 11.333333]) - self.parameters['target_height']=240 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[5.333333, 9.0, 11.333333]) + self.parameters["target_height"] = 240 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_linear_target_height_is_smaller_than_the_given_heights(self): """ Test linear interpolation and extrapolation if target_height is smaller than the heights given in the columns of the DataFrame """ - exp_output=pd.Series(data=[1.857143, 1.785714, 2.785714]) - self.parameters['target_height']=5 - assert_series_equal(linear_interpolation_extrapolation( - self.df, **self.parameters), exp_output) + exp_output = pd.Series(data=[1.857143, 1.785714, 2.785714]) + self.parameters["target_height"] = 5 + assert_series_equal( + linear_interpolation_extrapolation(self.df, **self.parameters), + exp_output, + ) def test_logarithmic_interpolation_extrapolation(self): - parameters={'target_height': 80} - df=pd.DataFrame(data={10: [2.0, 2.0, 3.0], - 80: [4.0, 5.0, 6.0], - 200: [5.0, 8.0, 10.0]}, - index=[0, 1, 2]) + parameters = {"target_height": 80} + df = pd.DataFrame( + data={ + 10: [2.0, 2.0, 3.0], + 80: [4.0, 5.0, 6.0], + 200: [5.0, 8.0, 10.0], + }, + index=[0, 1, 2], + ) # target_height is equal to height given in a column of the DataFrame - exp_output=pd.Series(data=[4.0, 5.0, 6.0]) - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series(data=[4.0, 5.0, 6.0]) + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) # target_height is between heights given in the columns of the # DataFrame - exp_output=pd.Series( - data=[4.61074042165, 6.83222126494, 8.44296168659]) - parameters['target_height']=140 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) - exp_output=pd.Series( - data=[4.11328333429, 5.16992500144, 6.16992500144]) - parameters['target_height']=90 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series( + data=[4.61074042165, 6.83222126494, 8.44296168659] + ) + parameters["target_height"] = 140 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) + exp_output = pd.Series( + data=[4.11328333429, 5.16992500144, 6.16992500144] + ) + parameters["target_height"] = 90 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) # target_height is greater than the heights given in the columns of the # DataFrame - exp_output=pd.Series( - data=[5.19897784672, 8.59693354015, 10.7959113869]) - parameters['target_height']=240 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series( + data=[5.19897784672, 8.59693354015, 10.7959113869] + ) + parameters["target_height"] = 240 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) # target_height is smaller than the heights given in the columns of the # DataFrame - exp_output=pd.Series(data=[1.33333333333, 1.0, 2.0]) - parameters['target_height']=5 - assert_series_equal(logarithmic_interpolation_extrapolation( - df, **parameters), exp_output) + exp_output = pd.Series(data=[1.33333333333, 1.0, 2.0]) + parameters["target_height"] = 5 + assert_series_equal( + logarithmic_interpolation_extrapolation(df, **parameters), + exp_output, + ) diff --git a/tests/test_turbine_cluster_modelchain.py b/tests/test_turbine_cluster_modelchain.py index 80f9bcfd..2b20e151 100644 --- a/tests/test_turbine_cluster_modelchain.py +++ b/tests/test_turbine_cluster_modelchain.py @@ -15,179 +15,230 @@ class TestTurbineClusterModelChain: - @classmethod def setup_class(self): - temperature_2m=np.array([[267], [268]]) - temperature_10m=np.array([[267], [266]]) - pressure_0m=np.array([[101125], [101000]]) - wind_speed_8m=np.array([[4.0], [5.0]]) - wind_speed_10m=np.array([[5.0], [6.5]]) - roughness_length=np.array([[0.15], [0.15]]) - self.weather_df=pd.DataFrame( - np.hstack((temperature_2m, - temperature_10m, - pressure_0m, - wind_speed_8m, - wind_speed_10m, - roughness_length)), - index=[0, 1], - columns=[np.array(['temperature', - 'temperature', - 'pressure', - 'wind_speed', - 'wind_speed', - 'roughness_length']), - np.array([2, 10, 0, 8, 10, 0])]) - self.test_turbine={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'E-126/4200'} - self.test_turbine_2={'hub_height': 90, - 'rotor_diameter': 60, - 'turbine_type': 'V90/2000', - 'nominal_power': 2000000.0} - self.test_farm={'wind_turbine_fleet': [ - {'wind_turbine': - wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}]} - self.test_farm_2={'name': 'test farm', - 'wind_turbine_fleet': - [{'wind_turbine': - wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': - wt.WindTurbine(**self.test_turbine_2), - 'number_of_turbines': 3}]} - self.test_cluster={'name': 'example_cluster', - 'wind_farms': [wf.WindFarm(**self.test_farm), - wf.WindFarm(**self.test_farm_2)]} + temperature_2m = np.array([[267], [268]]) + temperature_10m = np.array([[267], [266]]) + pressure_0m = np.array([[101125], [101000]]) + wind_speed_8m = np.array([[4.0], [5.0]]) + wind_speed_10m = np.array([[5.0], [6.5]]) + roughness_length = np.array([[0.15], [0.15]]) + self.weather_df = pd.DataFrame( + np.hstack( + ( + temperature_2m, + temperature_10m, + pressure_0m, + wind_speed_8m, + wind_speed_10m, + roughness_length, + ) + ), + index=[0, 1], + columns=[ + np.array( + [ + "temperature", + "temperature", + "pressure", + "wind_speed", + "wind_speed", + "roughness_length", + ] + ), + np.array([2, 10, 0, 8, 10, 0]), + ], + ) + self.test_turbine = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "E-126/4200", + } + self.test_turbine_2 = { + "hub_height": 90, + "rotor_diameter": 60, + "turbine_type": "V90/2000", + "nominal_power": 2000000.0, + } + self.test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + } + ] + } + self.test_farm_2 = { + "name": "test farm", + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": wt.WindTurbine(**self.test_turbine_2), + "number_of_turbines": 3, + }, + ], + } + self.test_cluster = { + "name": "example_cluster", + "wind_farms": [ + wf.WindFarm(**self.test_farm), + wf.WindFarm(**self.test_farm_2), + ], + } def test_run_model(self): - parameters={'wake_losses_model': 'dena_mean', - 'smoothing': False, - 'standard_deviation_method': 'turbulence_intensity', - 'smoothing_order': 'wind_farm_power_curves'} + parameters = { + "wake_losses_model": "dena_mean", + "smoothing": False, + "standard_deviation_method": "turbulence_intensity", + "smoothing_order": "wind_farm_power_curves", + } # Test modelchain with default values - power_output_exp=pd.Series(data=[4198361.4830405945, - 8697966.121234536], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**self.test_farm), **parameters) + power_output_exp = pd.Series( + data=[4198361.4830405945, 8697966.121234536], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**self.test_farm), **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters['wake_losses_model']='wind_farm_efficiency' - test_wind_farm=wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[4420994.806920091, - 8516983.651623568], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + parameters["wake_losses_model"] = "wind_farm_efficiency" + test_wind_farm = wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[4420994.806920091, 8516983.651623568], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters['smoothing']='True' - test_wind_farm=wf.WindFarm(**self.test_farm) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[4581109.03847444, - 8145581.914240712], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + parameters["smoothing"] = "True" + test_wind_farm = wf.WindFarm(**self.test_farm) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[4581109.03847444, 8145581.914240712], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_wind_farm=wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[6777087.9658657005, - 12180374.036660176], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + test_wind_farm = wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[6777087.9658657005, 12180374.036660176], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters['smoothing_order']='turbine_power_curves' - test_wind_farm=wf.WindFarm(**self.test_farm_2) - test_wind_farm.efficiency=0.9 - power_output_exp=pd.Series(data=[6790706.001026006, - 12179417.461328149], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_wind_farm, **parameters) + parameters["smoothing_order"] = "turbine_power_curves" + test_wind_farm = wf.WindFarm(**self.test_farm_2) + test_wind_farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[6790706.001026006, 12179417.461328149], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_wind_farm, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) def test_run_model_turbine_cluster(self): - parameters={'wake_losses_model': 'dena_mean', - 'smoothing': False, - 'standard_deviation_method': 'turbulence_intensity', - 'smoothing_order': 'wind_farm_power_curves'} + parameters = { + "wake_losses_model": "dena_mean", + "smoothing": False, + "standard_deviation_method": "turbulence_intensity", + "smoothing_order": "wind_farm_power_curves", + } # Test modelchain with default values - power_output_exp=pd.Series(data=[10363047.755401008, - 21694496.68221325], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( + power_output_exp = pd.Series( + data=[10363047.755401008, 21694496.68221325], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), - **parameters) + **parameters, + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test constant efficiency - parameters['wake_losses_model']='wind_farm_efficiency' - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + parameters["wake_losses_model"] = "wind_farm_efficiency" + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[10920128.570572512, - 21273144.336885825], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[10920128.570572512, 21273144.336885825], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test smoothing - parameters['smoothing']='True' - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + parameters["smoothing"] = "True" + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[11360309.77979467, - 20328652.64490018], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[11360309.77979467, 20328652.64490018], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test wind farm with different turbine types (smoothing) - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[11360309.77979467, - 20328652.64490018], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[11360309.77979467, 20328652.64490018], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) # Test other smoothing order - parameters['smoothing_order']='turbine_power_curves' - test_cluster=wtc.WindTurbineCluster(**self.test_cluster) + parameters["smoothing_order"] = "turbine_power_curves" + test_cluster = wtc.WindTurbineCluster(**self.test_cluster) for farm in test_cluster.wind_farms: - farm.efficiency=0.9 - power_output_exp=pd.Series(data=[11373183.797085874, - 20325877.105744187], - name='feedin_power_plant') - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=test_cluster, **parameters) + farm.efficiency = 0.9 + power_output_exp = pd.Series( + data=[11373183.797085874, 20325877.105744187], + name="feedin_power_plant", + ) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=test_cluster, **parameters + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) @@ -195,80 +246,115 @@ def test_error_raising(self): # Raise ValueError when aggregated wind farm power curve needs to be # calculated but turbine does not have a power curve - test_turbine_data={ - 'hub_height': 100, - 'rotor_diameter': 98, - 'turbine_type': 'V90/2000'} - test_turbine=wt.WindTurbine(**test_turbine_data) - test_turbine.power_curve=True - test_farm={'wind_turbine_fleet': - [{'wind_turbine': - wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': - test_turbine, - 'number_of_turbines': 3}]} - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**test_farm)) + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 98, + "turbine_type": "V90/2000", + } + test_turbine = wt.WindTurbine(**test_turbine_data) + test_turbine.power_curve = True + test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + {"wind_turbine": test_turbine, "number_of_turbines": 3}, + ] + } + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**test_farm) + ) with pytest.raises(ValueError): test_tc_mc.run_model(self.weather_df) # Raise ValueError when neither turbulence intensity nor roughness # length are provided to apply power curve smoothing with standard # deviation method 'turbulence_intensity' - parameters={'smoothing': True, - 'standard_deviation_method': 'turbulence_intensity'} - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wf.WindFarm(**self.test_farm), **parameters) - weather_df=self.weather_df.copy() - weather_df.pop('roughness_length') + parameters = { + "smoothing": True, + "standard_deviation_method": "turbulence_intensity", + } + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wf.WindFarm(**self.test_farm), **parameters + ) + weather_df = self.weather_df.copy() + weather_df.pop("roughness_length") with pytest.raises(ValueError): test_tc_mc.run_model(weather_df) def test_ignore_wake_losses(self): """Run model without wake losses.""" - parameters={'wake_losses_model': None, - 'smoothing': False, - 'standard_deviation_method': 'turbulence_intensity', - 'smoothing_order': 'wind_farm_power_curves'} + parameters = { + "wake_losses_model": None, + "smoothing": False, + "standard_deviation_method": "turbulence_intensity", + "smoothing_order": "wind_farm_power_curves", + } # Test modelchain with default values - test_tc_mc=tc_mc.TurbineClusterModelChain( + test_tc_mc = tc_mc.TurbineClusterModelChain( power_plant=wtc.WindTurbineCluster(**self.test_cluster), - **parameters) + **parameters, + ) test_tc_mc.run_model(self.weather_df) def test_wind_turbine_cluster_repr_with_name(self): """Test string representation of WindTurbineCluster with a name.""" - assert 'Wind turbine cluster:' in repr( - wtc.WindTurbineCluster(**self.test_cluster)) + assert "Wind turbine cluster:" in repr( + wtc.WindTurbineCluster(**self.test_cluster) + ) def test_wind_turbine_cluster_repr_without_name(self): """Test string representation of WindTurbineCluster without a name.""" - test_cluster={'wind_farms': [wf.WindFarm(**self.test_farm), - wf.WindFarm(**self.test_farm_2)]} - assert 'Wind turbine cluster with:' in repr( - wtc.WindTurbineCluster(**test_cluster)) + test_cluster = { + "wind_farms": [ + wf.WindFarm(**self.test_farm), + wf.WindFarm(**self.test_farm_2), + ] + } + assert "Wind turbine cluster with:" in repr( + wtc.WindTurbineCluster(**test_cluster) + ) def test_tc_modelchain_with_power_curve_as_dict(self): """Test power curves as dict in TurbineClusterModelChain.run_model()""" - my_turbine={'nominal_power': 3e6, 'hub_height': 105, - 'power_curve': { - 'value': [p * 1000 for p in [ - 0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]], - 'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}} - my_farm={'wind_turbine_fleet': - [{'wind_turbine': wt.WindTurbine(**my_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': wt.WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}]} - my_cluster= {'wind_farms': [wf.WindFarm(**my_farm), - wf.WindFarm(**self.test_farm)]} - power_output_exp=pd.Series(data=[10853277.966972714, - 21731814.593688786], - name='feedin_power_plant') + my_turbine = { + "nominal_power": 3e6, + "hub_height": 105, + "power_curve": { + "value": [ + p * 1000 + for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0] + ], + "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0], + }, + } + my_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": wt.WindTurbine(**my_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": wt.WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + ] + } + my_cluster = { + "wind_farms": [ + wf.WindFarm(**my_farm), + wf.WindFarm(**self.test_farm), + ] + } + power_output_exp = pd.Series( + data=[10853277.966972714, 21731814.593688786], + name="feedin_power_plant", + ) # run model with my_cluster - test_tc_mc=tc_mc.TurbineClusterModelChain( - power_plant=wtc.WindTurbineCluster(**my_cluster)) + test_tc_mc = tc_mc.TurbineClusterModelChain( + power_plant=wtc.WindTurbineCluster(**my_cluster) + ) test_tc_mc.run_model(self.weather_df) assert_series_equal(test_tc_mc.power_output, power_output_exp) diff --git a/tests/test_wake_losses.py b/tests/test_wake_losses.py index 951ddcd1..d27fd4a1 100644 --- a/tests/test_wake_losses.py +++ b/tests/test_wake_losses.py @@ -8,49 +8,77 @@ import pytest from pandas.util.testing import assert_series_equal -from windpowerlib.wake_losses import (reduce_wind_speed, - get_wind_efficiency_curve) +from windpowerlib.wake_losses import ( + reduce_wind_speed, + get_wind_efficiency_curve, +) class TestWakeLosses: - def test_reduce_wind_speed(self): - parameters={'wind_speed': pd.Series(np.arange(0, 26, 1.0)), - 'wind_efficiency_curve_name': 'dena_mean'} - wind_speed_exp=pd.Series([ - 0.0, 0.9949534234119396, 1.9897327884892086, 2.9843374545454546, - 3.807636264984227, 4.714931284760845, 5.642507531914893, - 6.607021108049704, 7.592423167192429, 8.59498170212766, - 9.606135658475111, 10.619828799086758, 11.641291957894737, - 12.674012890137966, 13.709490666666666, 14.742508260567297, - 15.773293013157893, 16.794615009724474, 17.817683032858028, - 18.85294996704484, 19.86509539493748, 20.858807854510186, - 21.854369681134507, 22.850700350710902, 23.85962037735849, - 24.958125]) + parameters = { + "wind_speed": pd.Series(np.arange(0, 26, 1.0)), + "wind_efficiency_curve_name": "dena_mean", + } + wind_speed_exp = pd.Series( + [ + 0.0, + 0.9949534234119396, + 1.9897327884892086, + 2.9843374545454546, + 3.807636264984227, + 4.714931284760845, + 5.642507531914893, + 6.607021108049704, + 7.592423167192429, + 8.59498170212766, + 9.606135658475111, + 10.619828799086758, + 11.641291957894737, + 12.674012890137966, + 13.709490666666666, + 14.742508260567297, + 15.773293013157893, + 16.794615009724474, + 17.817683032858028, + 18.85294996704484, + 19.86509539493748, + 20.858807854510186, + 21.854369681134507, + 22.850700350710902, + 23.85962037735849, + 24.958125, + ] + ) assert_series_equal(reduce_wind_speed(**parameters), wind_speed_exp) # Raise ValueError - misspelling with pytest.raises(ValueError): - parameters['wind_efficiency_curve_name']='misspelled' + parameters["wind_efficiency_curve_name"] = "misspelled" reduce_wind_speed(**parameters) with pytest.raises(ValueError): - parameters['wind_efficiency_curve_name']='dena_misspelled' + parameters["wind_efficiency_curve_name"] = "dena_misspelled" reduce_wind_speed(**parameters) def test_get_wind_efficiency_curve_one(self): """Test get_wind_efficiency_curve() for one curve.""" - wec=get_wind_efficiency_curve('dena_mean').sum() - wec_exp=pd.Series({'efficiency': 162.45047, - 'wind_speed': 1915.23620}) + wec = get_wind_efficiency_curve("dena_mean").sum() + wec_exp = pd.Series( + {"efficiency": 162.45047, "wind_speed": 1915.23620} + ) assert_series_equal(wec.sort_index(), wec_exp.sort_index()) def test_get_wind_efficiency_curve_all(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum=int(get_wind_efficiency_curve('all').sum().round().sum()) + wec_all_sum = int(get_wind_efficiency_curve("all").sum().round().sum()) assert wec_all_sum == 12145 def test_get_wind_efficiency_curve_list(self): """Test get_wind_efficiency_curve() for all curves.""" - wec_all_sum=int(get_wind_efficiency_curve( - ['dena_mean', 'knorr_mean']).sum().round().sum()) + wec_all_sum = int( + get_wind_efficiency_curve(["dena_mean", "knorr_mean"]) + .sum() + .round() + .sum() + ) assert wec_all_sum == 3568 diff --git a/tests/test_wind_farm.py b/tests/test_wind_farm.py index a2aa4dba..b031abcf 100644 --- a/tests/test_wind_farm.py +++ b/tests/test_wind_farm.py @@ -11,155 +11,211 @@ class TestWindFarm: - @classmethod def setup_class(self): """Setup default values""" - self.test_turbine={'hub_height': 100, - 'turbine_type': 'E-126/4200'} - self.test_turbine_2={'hub_height': 90, - 'turbine_type': 'V90/2000', - 'nominal_power': 2e6} + self.test_turbine = {"hub_height": 100, "turbine_type": "E-126/4200"} + self.test_turbine_2 = { + "hub_height": 90, + "turbine_type": "V90/2000", + "nominal_power": 2e6, + } def test_initialization_list(self): """test simple initialization with wind turbine fleet list""" - wind_turbine_fleet=[ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'number_of_turbines': 2}] - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet = [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "number_of_turbines": 2, + }, + ] + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_list_2(self): """test simple initialization with wind turbine fleet list where once number of turbines and once total capacity is provided""" - wind_turbine_fleet=[ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 3}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'total_capacity': 2 * 2e6}] - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet = [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 3, + }, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "total_capacity": 2 * 2e6, + }, + ] + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_dataframe(self): """test simple initialization with wind turbine fleet dataframe""" - wind_turbine_fleet=pd.DataFrame( - data={'wind_turbine': [WindTurbine(**self.test_turbine), - WindTurbine(**self.test_turbine_2)], - 'number_of_turbines': [3, 2]}) - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) + wind_turbine_fleet = pd.DataFrame( + data={ + "wind_turbine": [ + WindTurbine(**self.test_turbine), + WindTurbine(**self.test_turbine_2), + ], + "number_of_turbines": [3, 2], + } + ) + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) assert 3 * 4.2e6 + 2 * 2e6 == windfarm.nominal_power def test_initialization_1(self): """test catching error when wind_turbine_fleet not provided as list""" - msg='Wind turbine must be provided as WindTurbine object' + msg = "Wind turbine must be provided as WindTurbine object" with pytest.raises(ValueError, match=msg): - WindFarm(wind_turbine_fleet={'wind_turbine': 'turbine', - 'number_of_turbines': 2}, - name='dummy') + WindFarm( + wind_turbine_fleet={ + "wind_turbine": "turbine", + "number_of_turbines": 2, + }, + name="dummy", + ) def test_initialization_2(self): """test catching error when WindTurbine in wind_turbine_fleet not initialized""" - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': None, - 'number_of_turbines': 3}]} - msg='Wind turbine must be provided as WindTurbine object' + test_farm = { + "wind_turbine_fleet": [ + {"wind_turbine": None, "number_of_turbines": 3} + ] + } + msg = "Wind turbine must be provided as WindTurbine object" with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_3(self): """test catching error when wind_turbine not specified in wind_turbine_fleet""" - wind_turbine_fleet=pd.DataFrame( - data={'wind_turbines': [WindTurbine(**self.test_turbine), - WindTurbine(**self.test_turbine_2)], - 'number_of_turbines': [3, 2]}) - msg='Missing wind_turbine key/column in wind_turbine_fleet' + wind_turbine_fleet = pd.DataFrame( + data={ + "wind_turbines": [ + WindTurbine(**self.test_turbine), + WindTurbine(**self.test_turbine_2), + ], + "number_of_turbines": [3, 2], + } + ) + msg = "Missing wind_turbine key/column in wind_turbine_fleet" with pytest.raises(KeyError, match=msg): WindFarm(wind_turbine_fleet=wind_turbine_fleet) def test_initialization_4(self, recwarn): """test overwriting and raising warning when number_of_turbines and total_capacity in wind turbine fleet do not fit""" - wt1=WindTurbine(**self.test_turbine) - wt2=WindTurbine(**self.test_turbine_2) - wind_turbine_fleet=pd.DataFrame( - data={'wind_turbine': [wt1, wt2], - 'number_of_turbines': [3, 2], - 'total_capacity': [3, np.nan]}, - index=[0, 1]) - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) - total_cap_wt1_expected=\ - wt1.nominal_power * wind_turbine_fleet.loc[0, 'number_of_turbines'] - assert windfarm.wind_turbine_fleet.loc[0, 'total_capacity'] == \ - total_cap_wt1_expected - total_cap_wt2_expected=\ - wt2.nominal_power * wind_turbine_fleet.loc[1, 'number_of_turbines'] - assert windfarm.wind_turbine_fleet.loc[1, 'total_capacity'] == \ - total_cap_wt2_expected + wt1 = WindTurbine(**self.test_turbine) + wt2 = WindTurbine(**self.test_turbine_2) + wind_turbine_fleet = pd.DataFrame( + data={ + "wind_turbine": [wt1, wt2], + "number_of_turbines": [3, 2], + "total_capacity": [3, np.nan], + }, + index=[0, 1], + ) + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + total_cap_wt1_expected = ( + wt1.nominal_power * wind_turbine_fleet.loc[0, "number_of_turbines"] + ) + assert ( + windfarm.wind_turbine_fleet.loc[0, "total_capacity"] + == total_cap_wt1_expected + ) + total_cap_wt2_expected = ( + wt2.nominal_power * wind_turbine_fleet.loc[1, "number_of_turbines"] + ) + assert ( + windfarm.wind_turbine_fleet.loc[1, "total_capacity"] + == total_cap_wt2_expected + ) assert recwarn.pop(WindpowerlibUserWarning) def test_initialization_5(self): """test catching error when number of turbines cannot be deduced""" - wt=WindTurbine(**self.test_turbine) - wt.nominal_power=None - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': wt, - 'total_capacity': 3e6}]} - msg='Number of turbines of type' + wt = WindTurbine(**self.test_turbine) + wt.nominal_power = None + test_farm = { + "wind_turbine_fleet": [{"wind_turbine": wt, "total_capacity": 3e6}] + } + msg = "Number of turbines of type" with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_6(self): """test catching error when neither number_of_turbines nor total_capacity is provided""" - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbine': 3e6}]} - msg='Number of turbines of type ' + test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbine": 3e6, + } + ] + } + msg = "Number of turbines of type " with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_initialization_7(self): """test catching error when total capacity cannot be deduced""" - wt=WindTurbine(**self.test_turbine) - wt.nominal_power=None - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': wt, - 'number_of_turbines': 3}]} - msg='Total capacity of turbines of type' + wt = WindTurbine(**self.test_turbine) + wt.nominal_power = None + test_farm = { + "wind_turbine_fleet": [ + {"wind_turbine": wt, "number_of_turbines": 3} + ] + } + msg = "Total capacity of turbines of type" with pytest.raises(ValueError, match=msg): WindFarm(**test_farm) def test_mean_hub_height(self): """tests mean_hub_height method""" - test_farm={'wind_turbine_fleet': [ - {'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 2}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'total_capacity': 3e6}]} - windfarm=WindFarm(**test_farm) + test_farm = { + "wind_turbine_fleet": [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 2, + }, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "total_capacity": 3e6, + }, + ] + } + windfarm = WindFarm(**test_farm) assert 97.265 == pytest.approx( - windfarm.mean_hub_height().hub_height, 1e-3) + windfarm.mean_hub_height().hub_height, 1e-3 + ) def test_repr(self): """Test string representation of WindFarm""" - test_fleet=[{'wind_turbine': WindTurbine(**self.test_turbine), - 'number_of_turbines': 2}] - assert 'E-126/4200' in repr(WindFarm(wind_turbine_fleet=test_fleet)) + test_fleet = [ + { + "wind_turbine": WindTurbine(**self.test_turbine), + "number_of_turbines": 2, + } + ] + assert "E-126/4200" in repr(WindFarm(wind_turbine_fleet=test_fleet)) def test_aggregation_of_power_curve_with_missing_power_curve(self): """Test WindFarm.assign_power_curve() with missing power_curve.""" - wt1=WindTurbine(**self.test_turbine) - wt1.power_curve=None - wind_turbine_fleet=[ - {'wind_turbine': wt1, - 'number_of_turbines': 3}, - {'wind_turbine': WindTurbine(**self.test_turbine_2), - 'number_of_turbines': 2}] - windfarm=WindFarm(wind_turbine_fleet=wind_turbine_fleet) - msg='For an aggregated wind farm power curve each wind' + wt1 = WindTurbine(**self.test_turbine) + wt1.power_curve = None + wind_turbine_fleet = [ + {"wind_turbine": wt1, "number_of_turbines": 3}, + { + "wind_turbine": WindTurbine(**self.test_turbine_2), + "number_of_turbines": 2, + }, + ] + windfarm = WindFarm(wind_turbine_fleet=wind_turbine_fleet) + msg = "For an aggregated wind farm power curve each wind" with pytest.raises(ValueError, match=msg): windfarm.assign_power_curve() diff --git a/tests/test_wind_speed.py b/tests/test_wind_speed.py index 88712a3d..f4af4299 100644 --- a/tests/test_wind_speed.py +++ b/tests/test_wind_speed.py @@ -13,94 +13,104 @@ class TestWindSpeed: - def test_logarithmic_profile(self): - parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), - 'wind_speed_height': 10, - 'hub_height': 100, - 'roughness_length': pd.Series(data=[0.15, 0.15]), - 'obstacle_height': 0} + parameters = { + "wind_speed": pd.Series(data=[5.0, 6.5]), + "wind_speed_height": 10, + "hub_height": 100, + "roughness_length": pd.Series(data=[0.15, 0.15]), + "obstacle_height": 0, + } # Test wind_speed as pd.Series with roughness_length as pd.Series, # np.array and float - v_wind_hub_exp=pd.Series(data=[7.74136523, 10.0637748]) - assert_series_equal(logarithmic_profile(**parameters), - v_wind_hub_exp) - parameters['roughness_length']=np.array( - parameters['roughness_length']) - assert_series_equal(logarithmic_profile(**parameters), - v_wind_hub_exp) - parameters['roughness_length']=parameters['roughness_length'][0] - assert_series_equal(logarithmic_profile(**parameters), - v_wind_hub_exp) + v_wind_hub_exp = pd.Series(data=[7.74136523, 10.0637748]) + assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) + assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) + parameters["roughness_length"] = parameters["roughness_length"][0] + assert_series_equal(logarithmic_profile(**parameters), v_wind_hub_exp) # Test wind_speed as np.array with roughness_length as float, pd.Series # and np.array - v_wind_hub_exp=np.array([7.74136523, 10.0637748]) - parameters['wind_speed']=np.array(parameters['wind_speed']) + v_wind_hub_exp = np.array([7.74136523, 10.0637748]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters['roughness_length']=pd.Series( - data=[parameters['roughness_length'], - parameters['roughness_length']]) + parameters["roughness_length"] = pd.Series( + data=[ + parameters["roughness_length"], + parameters["roughness_length"], + ] + ) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) - parameters['roughness_length']=np.array( - parameters['roughness_length']) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) assert isinstance(logarithmic_profile(**parameters), np.ndarray) # Test obstacle_height is not zero - v_wind_hub_exp=np.array([13.54925281, 17.61402865]) - parameters['obstacle_height']=12 + v_wind_hub_exp = np.array([13.54925281, 17.61402865]) + parameters["obstacle_height"] = 12 assert_allclose(logarithmic_profile(**parameters), v_wind_hub_exp) # Raise ValueError due to 0.7 * `obstacle_height` > `wind_speed_height` with pytest.raises(ValueError): - parameters['obstacle_height']=20 + parameters["obstacle_height"] = 20 logarithmic_profile(**parameters) def test_hellman(self): - parameters={'wind_speed': pd.Series(data=[5.0, 6.5]), - 'wind_speed_height': 10, - 'hub_height': 100, - 'roughness_length': pd.Series(data=[0.15, 0.15]), - 'hellman_exponent': None} + parameters = { + "wind_speed": pd.Series(data=[5.0, 6.5]), + "wind_speed_height": 10, + "hub_height": 100, + "roughness_length": pd.Series(data=[0.15, 0.15]), + "hellman_exponent": None, + } # Test wind_speed is pd.Series with roughness_length is pd.Series, # np.array and float - v_wind_hub_exp=pd.Series(data=[7.12462437, 9.26201168]) + v_wind_hub_exp = pd.Series(data=[7.12462437, 9.26201168]) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters['roughness_length']=np.array( - parameters['roughness_length']) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) assert_series_equal(hellman(**parameters), v_wind_hub_exp) - parameters['roughness_length']=parameters['roughness_length'][0] + parameters["roughness_length"] = parameters["roughness_length"][0] assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test wind_speed as np.array with roughness_length is float, pd.Series # and np.array - v_wind_hub_exp=np.array([7.12462437, 9.26201168]) - parameters['wind_speed']=np.array(parameters['wind_speed']) + v_wind_hub_exp = np.array([7.12462437, 9.26201168]) + parameters["wind_speed"] = np.array(parameters["wind_speed"]) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters['roughness_length']=pd.Series( - data=(parameters['roughness_length'], - parameters['roughness_length'])) + parameters["roughness_length"] = pd.Series( + data=( + parameters["roughness_length"], + parameters["roughness_length"], + ) + ) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) - parameters['roughness_length']=np.array( - parameters['roughness_length']) + parameters["roughness_length"] = np.array( + parameters["roughness_length"] + ) assert_allclose(hellman(**parameters), v_wind_hub_exp) assert isinstance(hellman(**parameters), np.ndarray) # Test roughness_length is None and hellman_exponent is None - v_wind_hub_exp=pd.Series(data=[6.9474774, 9.03172]) - parameters['wind_speed']=pd.Series(data=parameters['wind_speed']) - parameters['roughness_length']=None + v_wind_hub_exp = pd.Series(data=[6.9474774, 9.03172]) + parameters["wind_speed"] = pd.Series(data=parameters["wind_speed"]) + parameters["roughness_length"] = None assert_series_equal(hellman(**parameters), v_wind_hub_exp) # Test hellman_exponent is not None - v_wind_hub_exp=pd.Series(data=[7.92446596, 10.30180575]) - parameters['roughness_length']=0.15 - parameters['hellman_exponent']=0.2 + v_wind_hub_exp = pd.Series(data=[7.92446596, 10.30180575]) + parameters["roughness_length"] = 0.15 + parameters["hellman_exponent"] = 0.2 assert_series_equal(hellman(**parameters), v_wind_hub_exp) diff --git a/tests/test_wind_turbine.py b/tests/test_wind_turbine.py index fdcf4472..1f3acfac 100644 --- a/tests/test_wind_turbine.py +++ b/tests/test_wind_turbine.py @@ -9,47 +9,52 @@ import os from windpowerlib.tools import WindpowerlibUserWarning -from windpowerlib.wind_turbine import (get_turbine_data_from_file, WindTurbine, - get_turbine_types, WindTurbineGroup, - load_turbine_data_from_oedb) +from windpowerlib.wind_turbine import ( + get_turbine_data_from_file, + WindTurbine, + get_turbine_types, + WindTurbineGroup, + load_turbine_data_from_oedb, +) class TestWindTurbine: - @classmethod def setup_class(cls): """Setup default values""" - cls.source=os.path.join(os.path.dirname(__file__), '../example/data') + cls.source = os.path.join(os.path.dirname(__file__), "../example/data") def test_warning(self, recwarn): - test_turbine_data={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'turbine_not_in_file', - 'path': self.source} - assert(WindTurbine(**test_turbine_data).power_curve is None) + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "turbine_not_in_file", + "path": self.source, + } + assert WindTurbine(**test_turbine_data).power_curve is None assert recwarn.pop(WindpowerlibUserWarning) def test_get_turbine_data_from_file(self): # Raise FileNotFoundError due to missing with pytest.raises(FileNotFoundError): - get_turbine_data_from_file(turbine_type='...', - path='not_existent') + get_turbine_data_from_file(turbine_type="...", path="not_existent") def test_get_turbine_types(self, capsys): get_turbine_types() - captured=capsys.readouterr() - assert 'Enercon' in captured.out - get_turbine_types('oedb', print_out=False, filter_=False) - msg="`turbine_library` is 'wrong' but must be 'local' or 'oedb'." + captured = capsys.readouterr() + assert "Enercon" in captured.out + get_turbine_types("oedb", print_out=False, filter_=False) + msg = "`turbine_library` is 'wrong' but must be 'local' or 'oedb'." with pytest.raises(ValueError, match=msg): - get_turbine_types('wrong') + get_turbine_types("wrong") def test_wrong_url_load_turbine_data(self): """Load turbine data from oedb.""" - with pytest.raises(ConnectionError, - match="Database connection not successful"): - load_turbine_data_from_oedb('wrong_schema') + with pytest.raises( + ConnectionError, match="Database connection not successful" + ): + load_turbine_data_from_oedb("wrong_schema") @pytest.mark.filterwarnings("ignore:The WindTurbine") def test_string_representation_of_wind_turbine(self): @@ -57,43 +62,51 @@ def test_string_representation_of_wind_turbine(self): def test_power_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_curve.""" - test_turbine_data={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'test_type', - 'power_curve': 'string'} + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "test_type", + "power_curve": "string", + } with pytest.raises(TypeError): WindTurbine(**test_turbine_data) def test_power_coefficient_curve_is_of_wrong_type(self): """Error raising due to wrong type of WindTurbine.power_coefficient_curve.""" - test_turbine_data={'hub_height': 100, - 'rotor_diameter': 80, - 'turbine_type': 'test_type', - 'power_coefficient_curve': 'string'} + test_turbine_data = { + "hub_height": 100, + "rotor_diameter": 80, + "turbine_type": "test_type", + "power_coefficient_curve": "string", + } with pytest.raises(TypeError): WindTurbine(**test_turbine_data) def test_to_group_method(self): - example_turbine={ - 'hub_height': 100, - 'rotor_diameter': 70, - 'turbine_type': 'DUMMY 3', - 'path': self.source} - e_t_1=WindTurbine(**example_turbine) - assert(isinstance(e_t_1.to_group(), WindTurbineGroup)) - assert(e_t_1.to_group(5).number_of_turbines == 5) - assert(e_t_1.to_group(number_turbines=5).number_of_turbines == 5) - assert(e_t_1.to_group(total_capacity=3e6).number_of_turbines == 2.0) + example_turbine = { + "hub_height": 100, + "rotor_diameter": 70, + "turbine_type": "DUMMY 3", + "path": self.source, + } + e_t_1 = WindTurbine(**example_turbine) + assert isinstance(e_t_1.to_group(), WindTurbineGroup) + assert e_t_1.to_group(5).number_of_turbines == 5 + assert e_t_1.to_group(number_turbines=5).number_of_turbines == 5 + assert e_t_1.to_group(total_capacity=3e6).number_of_turbines == 2.0 def test_wrongly_defined_to_group_method(self): - example_turbine={ - 'hub_height': 100, - 'rotor_diameter': 70, - 'turbine_type': 'DUMMY 3', - 'path': self.source} - e_t_1=WindTurbine(**example_turbine) - with pytest.raises(ValueError, - match="The 'number' and the 'total_capacity' " - "parameter are mutually exclusive."): + example_turbine = { + "hub_height": 100, + "rotor_diameter": 70, + "turbine_type": "DUMMY 3", + "path": self.source, + } + e_t_1 = WindTurbine(**example_turbine) + with pytest.raises( + ValueError, + match="The 'number' and the 'total_capacity' " + "parameter are mutually exclusive.", + ): e_t_1.to_group(5, 3000) diff --git a/windpowerlib/__init__.py b/windpowerlib/__init__.py index 7ffd29ce..a206ff5a 100644 --- a/windpowerlib/__init__.py +++ b/windpowerlib/__init__.py @@ -1,6 +1,6 @@ -__copyright__="Copyright oemof developer group" -__license__="MIT" -__version__='0.2.1dev' +__copyright__ = "Copyright oemof developer group" +__license__ = "MIT" +__version__ = "0.2.1dev" from windpowerlib.wind_turbine import WindTurbine from windpowerlib.wind_farm import WindFarm diff --git a/windpowerlib/modelchain.py b/windpowerlib/modelchain.py index e137934a..7553006e 100644 --- a/windpowerlib/modelchain.py +++ b/windpowerlib/modelchain.py @@ -134,24 +134,28 @@ class ModelChain(object): """ - def __init__(self, power_plant, - wind_speed_model='logarithmic', - temperature_model='linear_gradient', - density_model='barometric', - power_output_model='power_curve', - density_correction=False, - obstacle_height=0, - hellman_exp=None, **kwargs): - - self.power_plant=power_plant - self.obstacle_height=obstacle_height - self.wind_speed_model=wind_speed_model - self.temperature_model=temperature_model - self.density_model=density_model - self.power_output_model=power_output_model - self.density_correction=density_correction - self.hellman_exp=hellman_exp - self.power_output=None + def __init__( + self, + power_plant, + wind_speed_model="logarithmic", + temperature_model="linear_gradient", + density_model="barometric", + power_output_model="power_curve", + density_correction=False, + obstacle_height=0, + hellman_exp=None, + **kwargs + ): + + self.power_plant = power_plant + self.obstacle_height = obstacle_height + self.wind_speed_model = wind_speed_model + self.temperature_model = temperature_model + self.density_model = density_model + self.power_output_model = power_output_model + self.density_correction = density_correction + self.hellman_exp = hellman_exp + self.power_output = None def temperature_hub(self, weather_df): r""" @@ -182,28 +186,42 @@ def temperature_hub(self, weather_df): temperature(s) closest to the hub height are used. """ - if self.power_plant.hub_height in weather_df['temperature']: - temperature_hub=weather_df['temperature'][ - self.power_plant.hub_height] - elif self.temperature_model == 'linear_gradient': - logging.debug('Calculating temperature using temperature ' - 'gradient.') - closest_height=weather_df['temperature'].columns[ - min(range(len(weather_df['temperature'].columns)), - key=lambda i: abs(weather_df['temperature'].columns[i] - - self.power_plant.hub_height))] - temperature_hub=temperature.linear_gradient( - weather_df['temperature'][closest_height], closest_height, - self.power_plant.hub_height) - elif self.temperature_model == 'interpolation_extrapolation': - logging.debug('Calculating temperature using linear inter- or ' - 'extrapolation.') - temperature_hub=tools.linear_interpolation_extrapolation( - weather_df['temperature'], self.power_plant.hub_height) + if self.power_plant.hub_height in weather_df["temperature"]: + temperature_hub = weather_df["temperature"][ + self.power_plant.hub_height + ] + elif self.temperature_model == "linear_gradient": + logging.debug( + "Calculating temperature using temperature " "gradient." + ) + closest_height = weather_df["temperature"].columns[ + min( + range(len(weather_df["temperature"].columns)), + key=lambda i: abs( + weather_df["temperature"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + temperature_hub = temperature.linear_gradient( + weather_df["temperature"][closest_height], + closest_height, + self.power_plant.hub_height, + ) + elif self.temperature_model == "interpolation_extrapolation": + logging.debug( + "Calculating temperature using linear inter- or " + "extrapolation." + ) + temperature_hub = tools.linear_interpolation_extrapolation( + weather_df["temperature"], self.power_plant.hub_height + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.temperature_model) + "`temperature_model` must be " - "'linear_gradient' or 'interpolation_extrapolation'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.temperature_model) + + "`temperature_model` must be " + "'linear_gradient' or 'interpolation_extrapolation'." + ) return temperature_hub def density_hub(self, weather_df): @@ -241,39 +259,60 @@ def density_hub(self, weather_df): hub height, the `weather_df` must contain at least two time series for density. """ - if self.density_model != 'interpolation_extrapolation': - temperature_hub=self.temperature_hub(weather_df) + if self.density_model != "interpolation_extrapolation": + temperature_hub = self.temperature_hub(weather_df) # Calculation of density in kg/m³ at hub height - if self.density_model == 'barometric': - logging.debug('Calculating density using barometric height ' - 'equation.') - closest_height=weather_df['pressure'].columns[ - min(range(len(weather_df['pressure'].columns)), - key=lambda i: abs(weather_df['pressure'].columns[i] - - self.power_plant.hub_height))] - density_hub=density.barometric( - weather_df['pressure'][closest_height], closest_height, - self.power_plant.hub_height, temperature_hub) - elif self.density_model == 'ideal_gas': - logging.debug('Calculating density using ideal gas equation.') - closest_height=weather_df['pressure'].columns[ - min(range(len(weather_df['pressure'].columns)), - key=lambda i: abs(weather_df['pressure'].columns[i] - - self.power_plant.hub_height))] - density_hub=density.ideal_gas( - weather_df['pressure'][closest_height], closest_height, - self.power_plant.hub_height, temperature_hub) - elif self.density_model == 'interpolation_extrapolation': - logging.debug('Calculating density using linear inter- or ' - 'extrapolation.') - density_hub=tools.linear_interpolation_extrapolation( - weather_df['density'], self.power_plant.hub_height) + if self.density_model == "barometric": + logging.debug( + "Calculating density using barometric height " "equation." + ) + closest_height = weather_df["pressure"].columns[ + min( + range(len(weather_df["pressure"].columns)), + key=lambda i: abs( + weather_df["pressure"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + density_hub = density.barometric( + weather_df["pressure"][closest_height], + closest_height, + self.power_plant.hub_height, + temperature_hub, + ) + elif self.density_model == "ideal_gas": + logging.debug("Calculating density using ideal gas equation.") + closest_height = weather_df["pressure"].columns[ + min( + range(len(weather_df["pressure"].columns)), + key=lambda i: abs( + weather_df["pressure"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + density_hub = density.ideal_gas( + weather_df["pressure"][closest_height], + closest_height, + self.power_plant.hub_height, + temperature_hub, + ) + elif self.density_model == "interpolation_extrapolation": + logging.debug( + "Calculating density using linear inter- or " "extrapolation." + ) + density_hub = tools.linear_interpolation_extrapolation( + weather_df["density"], self.power_plant.hub_height + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.density_model) + "`density_model` " + - "must be 'barometric', 'ideal_gas' or " + - "'interpolation_extrapolation'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.density_model) + + "`density_model` " + + "must be 'barometric', 'ideal_gas' or " + + "'interpolation_extrapolation'." + ) return density_hub def wind_speed_hub(self, weather_df): @@ -305,47 +344,71 @@ def wind_speed_hub(self, weather_df): wind speed(s) closest to the hub height are used. """ - if self.power_plant.hub_height in weather_df['wind_speed']: - wind_speed_hub=weather_df['wind_speed'][ - self.power_plant.hub_height] - elif self.wind_speed_model == 'logarithmic': - logging.debug('Calculating wind speed using logarithmic wind ' - 'profile.') - closest_height=weather_df['wind_speed'].columns[ - min(range(len(weather_df['wind_speed'].columns)), - key=lambda i: abs(weather_df['wind_speed'].columns[i] - - self.power_plant.hub_height))] - wind_speed_hub=wind_speed.logarithmic_profile( - weather_df['wind_speed'][closest_height], closest_height, + if self.power_plant.hub_height in weather_df["wind_speed"]: + wind_speed_hub = weather_df["wind_speed"][ + self.power_plant.hub_height + ] + elif self.wind_speed_model == "logarithmic": + logging.debug( + "Calculating wind speed using logarithmic wind " "profile." + ) + closest_height = weather_df["wind_speed"].columns[ + min( + range(len(weather_df["wind_speed"].columns)), + key=lambda i: abs( + weather_df["wind_speed"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + wind_speed_hub = wind_speed.logarithmic_profile( + weather_df["wind_speed"][closest_height], + closest_height, self.power_plant.hub_height, - weather_df['roughness_length'].iloc[:, 0], - self.obstacle_height) - elif self.wind_speed_model == 'hellman': - logging.debug('Calculating wind speed using hellman equation.') - closest_height=weather_df['wind_speed'].columns[ - min(range(len(weather_df['wind_speed'].columns)), - key=lambda i: abs(weather_df['wind_speed'].columns[i] - - self.power_plant.hub_height))] - wind_speed_hub=wind_speed.hellman( - weather_df['wind_speed'][closest_height], closest_height, + weather_df["roughness_length"].iloc[:, 0], + self.obstacle_height, + ) + elif self.wind_speed_model == "hellman": + logging.debug("Calculating wind speed using hellman equation.") + closest_height = weather_df["wind_speed"].columns[ + min( + range(len(weather_df["wind_speed"].columns)), + key=lambda i: abs( + weather_df["wind_speed"].columns[i] + - self.power_plant.hub_height + ), + ) + ] + wind_speed_hub = wind_speed.hellman( + weather_df["wind_speed"][closest_height], + closest_height, self.power_plant.hub_height, - weather_df['roughness_length'].iloc[:, 0], - self.hellman_exp) - elif self.wind_speed_model == 'interpolation_extrapolation': - logging.debug('Calculating wind speed using linear inter- or ' - 'extrapolation.') - wind_speed_hub=tools.linear_interpolation_extrapolation( - weather_df['wind_speed'], self.power_plant.hub_height) - elif self.wind_speed_model == 'log_interpolation_extrapolation': - logging.debug('Calculating wind speed using logarithmic inter- or ' - 'extrapolation.') - wind_speed_hub=tools.logarithmic_interpolation_extrapolation( - weather_df['wind_speed'], self.power_plant.hub_height) + weather_df["roughness_length"].iloc[:, 0], + self.hellman_exp, + ) + elif self.wind_speed_model == "interpolation_extrapolation": + logging.debug( + "Calculating wind speed using linear inter- or " + "extrapolation." + ) + wind_speed_hub = tools.linear_interpolation_extrapolation( + weather_df["wind_speed"], self.power_plant.hub_height + ) + elif self.wind_speed_model == "log_interpolation_extrapolation": + logging.debug( + "Calculating wind speed using logarithmic inter- or " + "extrapolation." + ) + wind_speed_hub = tools.logarithmic_interpolation_extrapolation( + weather_df["wind_speed"], self.power_plant.hub_height + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.wind_speed_model) + "`wind_speed_model` must be " - "'logarithmic', 'hellman', 'interpolation_extrapolation' " + - "or 'log_interpolation_extrapolation'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.wind_speed_model) + + "`wind_speed_model` must be " + "'logarithmic', 'hellman', 'interpolation_extrapolation' " + + "or 'log_interpolation_extrapolation'." + ) return wind_speed_hub def calculate_power_output(self, wind_speed_hub, density_hub): @@ -367,34 +430,43 @@ def calculate_power_output(self, wind_speed_hub, density_hub): Electrical power output of the wind turbine in W. """ - if self.power_output_model == 'power_curve': + if self.power_output_model == "power_curve": if self.power_plant.power_curve is None: - raise TypeError("Power curve values of {} are missing.".format( - self.power_plant)) - logging.debug('Calculating power output using power curve.') - return (power_output.power_curve( - wind_speed_hub, - self.power_plant.power_curve['wind_speed'], - self.power_plant.power_curve['value'], - density_hub, self.density_correction)) - elif self.power_output_model == 'power_coefficient_curve': + raise TypeError( + "Power curve values of {} are missing.".format( + self.power_plant + ) + ) + logging.debug("Calculating power output using power curve.") + return power_output.power_curve( + wind_speed_hub, + self.power_plant.power_curve["wind_speed"], + self.power_plant.power_curve["value"], + density_hub, + self.density_correction, + ) + elif self.power_output_model == "power_coefficient_curve": if self.power_plant.power_coefficient_curve is None: - raise TypeError("Power coefficient curve values of {} are " - "missing.".format(self.power_plant)) - logging.debug('Calculating power output using power coefficient ' - 'curve.') - return (power_output.power_coefficient_curve( - wind_speed_hub, - self.power_plant.power_coefficient_curve[ - 'wind_speed'], - self.power_plant.power_coefficient_curve[ - 'value'], - self.power_plant.rotor_diameter, density_hub)) + raise TypeError( + "Power coefficient curve values of {} are " + "missing.".format(self.power_plant) + ) + logging.debug( + "Calculating power output using power coefficient " "curve." + ) + return power_output.power_coefficient_curve( + wind_speed_hub, + self.power_plant.power_coefficient_curve["wind_speed"], + self.power_plant.power_coefficient_curve["value"], + self.power_plant.rotor_diameter, + density_hub, + ) else: - raise ValueError("'{0}' is an invalid value. ".format( - self.power_output_model) + - "`power_output_model` must be " + - "'power_curve' or 'power_coefficient_curve'.") + raise ValueError( + "'{0}' is an invalid value. ".format(self.power_output_model) + + "`power_output_model` must be " + + "'power_curve' or 'power_coefficient_curve'." + ) def run_model(self, weather_df): r""" @@ -438,10 +510,16 @@ def run_model(self, weather_df): 'wind_speed' """ - wind_speed_hub=self.wind_speed_hub(weather_df) - density_hub=(None if (self.power_output_model == 'power_curve' and - self.density_correction is False) - else self.density_hub(weather_df)) - self.power_output=self.calculate_power_output(wind_speed_hub, - density_hub) + wind_speed_hub = self.wind_speed_hub(weather_df) + density_hub = ( + None + if ( + self.power_output_model == "power_curve" + and self.density_correction is False + ) + else self.density_hub(weather_df) + ) + self.power_output = self.calculate_power_output( + wind_speed_hub, density_hub + ) return self diff --git a/windpowerlib/power_curves.py b/windpowerlib/power_curves.py index 0aa6acaf..ef9eb138 100644 --- a/windpowerlib/power_curves.py +++ b/windpowerlib/power_curves.py @@ -110,70 +110,98 @@ def smooth_power_curve(power_curve_wind_speeds, power_curve_values, """ # Specify normalized standard deviation - if standard_deviation_method == 'turbulence_intensity': - if ('turbulence_intensity' in kwargs and - kwargs['turbulence_intensity'] is not np.nan): - normalized_standard_deviation=kwargs['turbulence_intensity'] + if standard_deviation_method == "turbulence_intensity": + if ( + "turbulence_intensity" in kwargs + and kwargs["turbulence_intensity"] is not np.nan + ): + normalized_standard_deviation = kwargs["turbulence_intensity"] else: - raise ValueError("Turbulence intensity must be defined for " + - "using 'turbulence_intensity' as " + - "`standard_deviation_method`") - elif standard_deviation_method == 'Staffell_Pfenninger': - normalized_standard_deviation=0.2 + raise ValueError( + "Turbulence intensity must be defined for " + + "using 'turbulence_intensity' as " + + "`standard_deviation_method`" + ) + elif standard_deviation_method == "Staffell_Pfenninger": + normalized_standard_deviation = 0.2 else: - raise ValueError("{} is no valid `standard_deviation_method`. Valid " - + "options are 'turbulence_intensity', or " - + "'Staffell_Pfenninger'".format( - standard_deviation_method)) + raise ValueError( + "{} is no valid `standard_deviation_method`. Valid " + + "options are 'turbulence_intensity', or " + + "'Staffell_Pfenninger'".format(standard_deviation_method) + ) # Initialize list for power curve values - smoothed_power_curve_values=[] + smoothed_power_curve_values = [] # Append wind speeds to `power_curve_wind_speeds` - maximum_value=power_curve_wind_speeds.iloc[-1] + wind_speed_range + maximum_value = power_curve_wind_speeds.iloc[-1] + wind_speed_range while power_curve_wind_speeds.values[-1] < maximum_value: - power_curve_wind_speeds=power_curve_wind_speeds.append( - pd.Series(power_curve_wind_speeds.iloc[-1] + - (power_curve_wind_speeds.iloc[5] - - power_curve_wind_speeds.iloc[4]), - index=[power_curve_wind_speeds.index[-1] + 1])) - power_curve_values=power_curve_values.append( - pd.Series(0.0, index=[power_curve_values.index[-1] + 1])) + power_curve_wind_speeds = power_curve_wind_speeds.append( + pd.Series( + power_curve_wind_speeds.iloc[-1] + + ( + power_curve_wind_speeds.iloc[5] + - power_curve_wind_speeds.iloc[4] + ), + index=[power_curve_wind_speeds.index[-1] + 1], + ) + ) + power_curve_values = power_curve_values.append( + pd.Series(0.0, index=[power_curve_values.index[-1] + 1]) + ) for power_curve_wind_speed in power_curve_wind_speeds: # Create array of wind speeds for the sum - wind_speeds_block=(np.arange( - -wind_speed_range, wind_speed_range + block_width, block_width) + - power_curve_wind_speed) + wind_speeds_block = ( + np.arange( + -wind_speed_range, wind_speed_range + block_width, block_width + ) + + power_curve_wind_speed + ) # Get standard deviation for Gauss function - standard_deviation=( + standard_deviation = ( (power_curve_wind_speed * normalized_standard_deviation + 0.6) - if standard_deviation_method is 'Staffell_Pfenninger' - else power_curve_wind_speed * normalized_standard_deviation) + if standard_deviation_method is "Staffell_Pfenninger" + else power_curve_wind_speed * normalized_standard_deviation + ) # Get the smoothed value of the power output if standard_deviation == 0.0: # The gaussian distribution is not defined for a standard deviation # of zero. Smoothed power curve value is set to zero. - smoothed_value=0.0 + smoothed_value = 0.0 else: - smoothed_value=sum( - block_width * np.interp(wind_speed, power_curve_wind_speeds, - power_curve_values, left=0, right=0) * - tools.gauss_distribution( + smoothed_value = sum( + block_width + * np.interp( + wind_speed, + power_curve_wind_speeds, + power_curve_values, + left=0, + right=0, + ) + * tools.gauss_distribution( power_curve_wind_speed - wind_speed, - standard_deviation, mean_gauss) - for wind_speed in wind_speeds_block) + standard_deviation, + mean_gauss, + ) + for wind_speed in wind_speeds_block + ) # Add value to list - add zero if `smoothed_value` is nan as Gauss # distribution for a standard deviation of zero. smoothed_power_curve_values.append(smoothed_value) # Create smoothed power curve data frame - smoothed_power_curve_df=pd.DataFrame( - data=[list(power_curve_wind_speeds.values), - smoothed_power_curve_values]).transpose() + smoothed_power_curve_df = pd.DataFrame( + data=[ + list(power_curve_wind_speeds.values), + smoothed_power_curve_values, + ] + ).transpose() # Rename columns of the data frame - smoothed_power_curve_df.columns=['wind_speed', 'value'] + smoothed_power_curve_df.columns = ["wind_speed", "value"] return smoothed_power_curve_df -def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values, - wind_farm_efficiency): +def wake_losses_to_power_curve( + power_curve_wind_speeds, power_curve_values, wind_farm_efficiency +): r""" Reduces the power values of a power curve by an efficiency (curve). @@ -200,27 +228,36 @@ def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values, """ # Create power curve DataFrame - power_curve_df=pd.DataFrame( - data=[list(power_curve_wind_speeds), - list(power_curve_values)]).transpose() + power_curve_df = pd.DataFrame( + data=[list(power_curve_wind_speeds), list(power_curve_values)] + ).transpose() # Rename columns of DataFrame - power_curve_df.columns=['wind_speed', 'value'] + power_curve_df.columns = ["wind_speed", "value"] if isinstance(wind_farm_efficiency, float): - power_curve_df['value']=power_curve_values * wind_farm_efficiency - elif (isinstance(wind_farm_efficiency, dict) or - isinstance(wind_farm_efficiency, pd.DataFrame)): - df=pd.concat([power_curve_df.set_index('wind_speed'), - wind_farm_efficiency.set_index('wind_speed')], axis=1) + power_curve_df["value"] = power_curve_values * wind_farm_efficiency + elif isinstance(wind_farm_efficiency, dict) or isinstance( + wind_farm_efficiency, pd.DataFrame + ): + df = pd.concat( + [ + power_curve_df.set_index("wind_speed"), + wind_farm_efficiency.set_index("wind_speed"), + ], + axis=1, + ) # Add column with reduced power (nan values of efficiency are # interpolated) - df['reduced_power']=df['value'] * df['efficiency'].interpolate( - method='index') - reduced_power=df['reduced_power'].dropna() - power_curve_df=pd.DataFrame([reduced_power.index, - reduced_power.values]).transpose() - power_curve_df.columns=['wind_speed', 'value'] + df["reduced_power"] = df["value"] * df["efficiency"].interpolate( + method="index" + ) + reduced_power = df["reduced_power"].dropna() + power_curve_df = pd.DataFrame( + [reduced_power.index, reduced_power.values] + ).transpose() + power_curve_df.columns = ["wind_speed", "value"] else: raise TypeError( "'wind_farm_efficiency' must be float, dict or pd.DataFrame " - "but is {}".format(type(wind_farm_efficiency))) + "but is {}".format(type(wind_farm_efficiency)) + ) return power_curve_df diff --git a/windpowerlib/power_output.py b/windpowerlib/power_output.py index ba446e6a..a9554020 100644 --- a/windpowerlib/power_output.py +++ b/windpowerlib/power_output.py @@ -63,23 +63,41 @@ def power_coefficient_curve(wind_speed, power_coefficient_curve_wind_speeds, Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 542 """ - power_coefficient_time_series=np.interp( - wind_speed, power_coefficient_curve_wind_speeds, - power_coefficient_curve_values, left=0, right=0) - power_output=(1 / 8 * density * rotor_diameter ** 2 * np.pi * - np.power(wind_speed, 3) * - power_coefficient_time_series) + power_coefficient_time_series = np.interp( + wind_speed, + power_coefficient_curve_wind_speeds, + power_coefficient_curve_values, + left=0, + right=0, + ) + power_output = ( + 1 + / 8 + * density + * rotor_diameter ** 2 + * np.pi + * np.power(wind_speed, 3) + * power_coefficient_time_series + ) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output=pd.Series(data=power_output, index=wind_speed.index, - name='feedin_power_plant') + power_output = pd.Series( + data=power_output, + index=wind_speed.index, + name="feedin_power_plant", + ) else: - power_output=np.array(power_output) + power_output = np.array(power_output) return power_output -def power_curve(wind_speed, power_curve_wind_speeds, power_curve_values, - density=None, density_correction=False): +def power_curve( + wind_speed, + power_curve_wind_speeds, + power_curve_values, + density=None, + density_correction=False, +): r""" Calculates the turbine power output using a power curve. @@ -120,26 +138,38 @@ def power_curve(wind_speed, power_curve_wind_speeds, power_curve_values, """ if density_correction is False: - power_output=np.interp(wind_speed, power_curve_wind_speeds, - power_curve_values, left=0, right=0) + power_output = np.interp( + wind_speed, + power_curve_wind_speeds, + power_curve_values, + left=0, + right=0, + ) # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output=pd.Series(data=power_output, index=wind_speed.index, - name='feedin_power_plant') + power_output = pd.Series( + data=power_output, + index=wind_speed.index, + name="feedin_power_plant", + ) else: - power_output=np.array(power_output) + power_output = np.array(power_output) elif density_correction is True: - power_output=power_curve_density_correction( - wind_speed, power_curve_wind_speeds, power_curve_values, density) + power_output = power_curve_density_correction( + wind_speed, power_curve_wind_speeds, power_curve_values, density + ) else: - raise TypeError("'{0}' is an invalid type. ".format(type( - density_correction)) + "`density_correction` must " + - "be Boolean (True or False).") + raise TypeError( + "'{0}' is an invalid type. ".format(type(density_correction)) + + "`density_correction` must " + + "be Boolean (True or False)." + ) return power_output -def power_curve_density_correction(wind_speed, power_curve_wind_speeds, - power_curve_values, density): +def power_curve_density_correction( + wind_speed, power_curve_wind_speeds, power_curve_values, density +): r""" Calculates the turbine power output using a density corrected power curve. diff --git a/windpowerlib/tools.py b/windpowerlib/tools.py index 3d4c593c..faab0202 100644 --- a/windpowerlib/tools.py +++ b/windpowerlib/tools.py @@ -78,12 +78,15 @@ def linear_interpolation_extrapolation(df, target_height): """ # find closest heights - heights_sorted=df.columns[ - sorted(range(len(df.columns)), - key=lambda i: abs(df.columns[i] - target_height))] - return ((df[heights_sorted[1]] - df[heights_sorted[0]]) / - (heights_sorted[1] - heights_sorted[0]) * - (target_height - heights_sorted[0]) + df[heights_sorted[0]]) + heights_sorted = df.columns[ + sorted( + range(len(df.columns)), + key=lambda i: abs(df.columns[i] - target_height), + ) + ] + return (df[heights_sorted[1]] - df[heights_sorted[0]]) / ( + heights_sorted[1] - heights_sorted[0] + ) * (target_height - heights_sorted[0]) + df[heights_sorted[0]] def logarithmic_interpolation_extrapolation(df, target_height): @@ -132,14 +135,17 @@ def logarithmic_interpolation_extrapolation(df, target_height): """ # find closest heights - heights_sorted=df.columns[ - sorted(range(len(df.columns)), - key=lambda i: abs(df.columns[i] - target_height))] - return ((np.log(target_height) * - (df[heights_sorted[1]] - df[heights_sorted[0]]) - - df[heights_sorted[1]] * np.log(heights_sorted[0]) + - df[heights_sorted[0]] * np.log(heights_sorted[1])) / - (np.log(heights_sorted[1]) - np.log(heights_sorted[0]))) + heights_sorted = df.columns[ + sorted( + range(len(df.columns)), + key=lambda i: abs(df.columns[i] - target_height), + ) + ] + return ( + np.log(target_height) * (df[heights_sorted[1]] - df[heights_sorted[0]]) + - df[heights_sorted[1]] * np.log(heights_sorted[0]) + + df[heights_sorted[0]] * np.log(heights_sorted[1]) + ) / (np.log(heights_sorted[1]) - np.log(heights_sorted[0])) def gauss_distribution(function_variable, standard_deviation, mean=0): diff --git a/windpowerlib/turbine_cluster_modelchain.py b/windpowerlib/turbine_cluster_modelchain.py index 4d978d3a..5e0eeba1 100644 --- a/windpowerlib/turbine_cluster_modelchain.py +++ b/windpowerlib/turbine_cluster_modelchain.py @@ -142,21 +142,28 @@ class TurbineClusterModelChain(ModelChain): Used to set `hellman_exponent` in :func:`~.wind_speed.hellman`. """ - def __init__(self, power_plant, wake_losses_model='dena_mean', - smoothing=False, block_width=0.5, - standard_deviation_method='turbulence_intensity', - smoothing_order='wind_farm_power_curves', **kwargs): + + def __init__( + self, + power_plant, + wake_losses_model="dena_mean", + smoothing=False, + block_width=0.5, + standard_deviation_method="turbulence_intensity", + smoothing_order="wind_farm_power_curves", + **kwargs + ): super(TurbineClusterModelChain, self).__init__(power_plant, **kwargs) - self.power_plant=power_plant - self.wake_losses_model=wake_losses_model - self.smoothing=smoothing - self.block_width=block_width - self.standard_deviation_method=standard_deviation_method - self.smoothing_order=smoothing_order + self.power_plant = power_plant + self.wake_losses_model = wake_losses_model + self.smoothing = smoothing + self.block_width = block_width + self.standard_deviation_method = standard_deviation_method + self.smoothing_order = smoothing_order - self.power_curve=None - self.power_output=None + self.power_curve = None + self.power_output = None def assign_power_curve(self, weather_df): r""" @@ -186,40 +193,55 @@ def assign_power_curve(self, weather_df): """ # Get turbulence intensity from weather if existent - turbulence_intensity=( - weather_df['turbulence_intensity'].values.mean() if - 'turbulence_intensity' in - weather_df.columns.get_level_values(0) else None) - roughness_length=( - weather_df['roughness_length'].values.mean() if - 'roughness_length' in weather_df.columns.get_level_values(0) else - None) + turbulence_intensity = ( + weather_df["turbulence_intensity"].values.mean() + if "turbulence_intensity" in weather_df.columns.get_level_values(0) + else None + ) + roughness_length = ( + weather_df["roughness_length"].values.mean() + if "roughness_length" in weather_df.columns.get_level_values(0) + else None + ) # Assign power curve - if (self.wake_losses_model == 'wind_farm_efficiency' or - self.wake_losses_model is None): - wake_losses_model_to_power_curve=self.wake_losses_model + if ( + self.wake_losses_model == "wind_farm_efficiency" + or self.wake_losses_model is None + ): + wake_losses_model_to_power_curve = self.wake_losses_model if self.wake_losses_model is None: - logging.debug('Wake losses in wind farms are not considered.') + logging.debug("Wake losses in wind farms are not considered.") else: - logging.debug('Wake losses considered with {}.'.format( - self.wake_losses_model)) + logging.debug( + "Wake losses considered with {}.".format( + self.wake_losses_model + ) + ) else: - logging.debug('Wake losses considered by {} wind '.format( - self.wake_losses_model) + 'efficiency curve.') - wake_losses_model_to_power_curve=None + logging.debug( + "Wake losses considered by {} wind ".format( + self.wake_losses_model + ) + + "efficiency curve." + ) + wake_losses_model_to_power_curve = None self.power_plant.assign_power_curve( wake_losses_model=wake_losses_model_to_power_curve, - smoothing=self.smoothing, block_width=self.block_width, + smoothing=self.smoothing, + block_width=self.block_width, standard_deviation_method=self.standard_deviation_method, smoothing_order=self.smoothing_order, roughness_length=roughness_length, - turbulence_intensity=turbulence_intensity) + turbulence_intensity=turbulence_intensity, + ) # Further logging messages if self.smoothing is False: - logging.debug('Aggregated power curve not smoothed.') + logging.debug("Aggregated power curve not smoothed.") else: - logging.debug('Aggregated power curve smoothed by method: ' + - self.standard_deviation_method) + logging.debug( + "Aggregated power curve smoothed by method: " + + self.standard_deviation_method + ) return self @@ -269,16 +291,25 @@ def run_model(self, weather_df): self.assign_power_curve(weather_df) self.power_plant.mean_hub_height() - wind_speed_hub=self.wind_speed_hub(weather_df) - density_hub=(None if (self.power_output_model == 'power_curve' and - self.density_correction is False) - else self.density_hub(weather_df)) - if (self.wake_losses_model != 'wind_farm_efficiency' and - self.wake_losses_model is not None): + wind_speed_hub = self.wind_speed_hub(weather_df) + density_hub = ( + None + if ( + self.power_output_model == "power_curve" + and self.density_correction is False + ) + else self.density_hub(weather_df) + ) + if ( + self.wake_losses_model != "wind_farm_efficiency" + and self.wake_losses_model is not None + ): # Reduce wind speed with wind efficiency curve - wind_speed_hub=wake_losses.reduce_wind_speed( + wind_speed_hub = wake_losses.reduce_wind_speed( wind_speed_hub, - wind_efficiency_curve_name=self.wake_losses_model) - self.power_output=self.calculate_power_output(wind_speed_hub, - density_hub) + wind_efficiency_curve_name=self.wake_losses_model, + ) + self.power_output = self.calculate_power_output( + wind_speed_hub, density_hub + ) return self diff --git a/windpowerlib/wake_losses.py b/windpowerlib/wake_losses.py index 59d0ea37..77e46834 100644 --- a/windpowerlib/wake_losses.py +++ b/windpowerlib/wake_losses.py @@ -45,16 +45,19 @@ def reduce_wind_speed(wind_speed, wind_efficiency_curve_name='dena_mean'): """ # Get wind efficiency curve - wind_efficiency_curve=get_wind_efficiency_curve( - curve_name=wind_efficiency_curve_name) + wind_efficiency_curve = get_wind_efficiency_curve( + curve_name=wind_efficiency_curve_name + ) # Reduce wind speed by wind efficiency - reduced_wind_speed=wind_speed * np.interp( - wind_speed, wind_efficiency_curve['wind_speed'], - wind_efficiency_curve['efficiency']) + reduced_wind_speed = wind_speed * np.interp( + wind_speed, + wind_efficiency_curve["wind_speed"], + wind_efficiency_curve["efficiency"], + ) return reduced_wind_speed -def get_wind_efficiency_curve(curve_name='all'): +def get_wind_efficiency_curve(curve_name="all"): r""" Reads wind efficiency curve(s) specified in `curve_name`. @@ -107,45 +110,59 @@ def get_wind_efficiency_curve(curve_name='all'): plt.show() """ - possible_curve_names=['dena_mean', 'knorr_mean', 'dena_extreme1', - 'dena_extreme2', 'knorr_extreme1', - 'knorr_extreme2', 'knorr_extreme3'] - - if curve_name == 'all': - curve_names=possible_curve_names + possible_curve_names = [ + "dena_mean", + "knorr_mean", + "dena_extreme1", + "dena_extreme2", + "knorr_extreme1", + "knorr_extreme2", + "knorr_extreme3", + ] + + if curve_name == "all": + curve_names = possible_curve_names elif isinstance(curve_name, str): - curve_names=[curve_name] + curve_names = [curve_name] else: - curve_names=curve_name + curve_names = curve_name - efficiency_curve=pd.DataFrame() + efficiency_curve = pd.DataFrame() for curve_name in curve_names: - if curve_name.split('_')[0] not in ['dena', 'knorr']: - raise ValueError("`curve_name` must be one of the following: " + - "{} but is {}".format(possible_curve_names, - curve_name)) - path=os.path.join(os.path.dirname(__file__), 'data', - 'wind_efficiency_curves_{}.csv'.format( - curve_name.split('_')[0])) + if curve_name.split("_")[0] not in ["dena", "knorr"]: + raise ValueError( + "`curve_name` must be one of the following: " + + "{} but is {}".format(possible_curve_names, curve_name) + ) + path = os.path.join( + os.path.dirname(__file__), + "data", + "wind_efficiency_curves_{}.csv".format(curve_name.split("_")[0]), + ) # Read wind efficiency curves from file - wind_efficiency_curves=pd.read_csv(path) + wind_efficiency_curves = pd.read_csv(path) # Raise error if wind efficiency curve specified in 'curve_name' does # not exist if curve_name not in list(wind_efficiency_curves): - msg=("Efficiency curve <{0}> does not exist. Must be one of the " - "following: {1}.") + msg = ( + "Efficiency curve <{0}> does not exist. Must be one of the " + "following: {1}." + ) raise ValueError(msg.format(curve_name, *possible_curve_names)) # Get wind efficiency curve and rename column containing efficiency - wec=wind_efficiency_curves[['wind_speed', curve_name]] + wec = wind_efficiency_curves[["wind_speed", curve_name]] if efficiency_curve.empty: - efficiency_curve=pd.DataFrame( - {(curve_name, 'wind_speed'): wec['wind_speed'], - (curve_name, 'efficiency'): wec[curve_name]}) + efficiency_curve = pd.DataFrame( + { + (curve_name, "wind_speed"): wec["wind_speed"], + (curve_name, "efficiency"): wec[curve_name], + } + ) else: - efficiency_curve[(curve_name, 'wind_speed')]=wec['wind_speed'] - efficiency_curve[(curve_name, 'efficiency')]=wec[curve_name] + efficiency_curve[(curve_name, "wind_speed")] = wec["wind_speed"] + efficiency_curve[(curve_name, "efficiency")] = wec[curve_name] if len(curve_names) == 1: return efficiency_curve[curve_names[0]] else: diff --git a/windpowerlib/wind_farm.py b/windpowerlib/wind_farm.py index b2342690..3bb387a1 100644 --- a/windpowerlib/wind_farm.py +++ b/windpowerlib/wind_farm.py @@ -113,15 +113,15 @@ class WindFarm(object): 31200000.0 """ - def __init__(self, wind_turbine_fleet, efficiency=None, name='', **kwargs): + def __init__(self, wind_turbine_fleet, efficiency=None, name="", **kwargs): - self.wind_turbine_fleet=wind_turbine_fleet - self.efficiency=efficiency - self.name=name + self.wind_turbine_fleet = wind_turbine_fleet + self.efficiency = efficiency + self.name = name - self.hub_height=None - self._nominal_power=None - self.power_curve=None + self.hub_height = None + self._nominal_power = None + self.power_curve = None self.check_and_complete_wind_turbine_fleet() @@ -137,80 +137,104 @@ def check_and_complete_wind_turbine_fleet(self): """ # convert list to dataframe if necessary if isinstance(self.wind_turbine_fleet, list): - self.wind_turbine_fleet=pd.DataFrame(self.wind_turbine_fleet) + self.wind_turbine_fleet = pd.DataFrame(self.wind_turbine_fleet) # check wind turbines try: - for turbine in self.wind_turbine_fleet['wind_turbine']: + for turbine in self.wind_turbine_fleet["wind_turbine"]: if not isinstance(turbine, WindTurbine): raise ValueError( - 'Wind turbine must be provided as WindTurbine object ' - 'but was provided as {}.'.format(type(turbine))) + "Wind turbine must be provided as WindTurbine object " + "but was provided as {}.".format(type(turbine)) + ) except KeyError: - raise KeyError('Missing wind_turbine key/column in ' - 'wind_turbine_fleet parameter.') + raise KeyError( + "Missing wind_turbine key/column in " + "wind_turbine_fleet parameter." + ) # add columns for number of turbines and total capacity if they don't # yet exist - if 'number_of_turbines' not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet['number_of_turbines']=np.nan - if 'total_capacity' not in self.wind_turbine_fleet.columns: - self.wind_turbine_fleet['total_capacity']=np.nan + if "number_of_turbines" not in self.wind_turbine_fleet.columns: + self.wind_turbine_fleet["number_of_turbines"] = np.nan + if "total_capacity" not in self.wind_turbine_fleet.columns: + self.wind_turbine_fleet["total_capacity"] = np.nan # calculate number of turbines if necessary - number_turbines_not_provided=self.wind_turbine_fleet[ - self.wind_turbine_fleet['number_of_turbines'].isnull()] + number_turbines_not_provided = self.wind_turbine_fleet[ + self.wind_turbine_fleet["number_of_turbines"].isnull() + ] for ix, row in number_turbines_not_provided.iterrows(): - msg='Number of turbines of type {0} can not be deduced ' \ - 'from total capacity. Please either provide ' \ - '`number_of_turbines` in the turbine fleet definition or ' \ - 'set the nominal power of the wind turbine.' + msg = ( + "Number of turbines of type {0} can not be deduced " + "from total capacity. Please either provide " + "`number_of_turbines` in the turbine fleet definition or " + "set the nominal power of the wind turbine." + ) try: - number_of_turbines=row['total_capacity'] / \ - row['wind_turbine'].nominal_power + number_of_turbines = ( + row["total_capacity"] / row["wind_turbine"].nominal_power + ) if np.isnan(number_of_turbines): - raise ValueError(msg.format(row['wind_turbine'])) + raise ValueError(msg.format(row["wind_turbine"])) else: - self.wind_turbine_fleet.loc[ix, 'number_of_turbines']=\ - number_of_turbines + self.wind_turbine_fleet.loc[ + ix, "number_of_turbines" + ] = number_of_turbines except TypeError: - raise ValueError(msg.format(row['wind_turbine'])) + raise ValueError(msg.format(row["wind_turbine"])) # calculate total capacity if necessary and check that total capacity # and number of turbines is consistent if both are provided for ix, row in self.wind_turbine_fleet.iterrows(): - if np.isnan(row['total_capacity']): + if np.isnan(row["total_capacity"]): try: - self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ - row['number_of_turbines'] * \ - row['wind_turbine'].nominal_power + self.wind_turbine_fleet.loc[ix, "total_capacity"] = ( + row["number_of_turbines"] + * row["wind_turbine"].nominal_power + ) except TypeError: raise ValueError( - 'Total capacity of turbines of type {turbine} cannot ' - 'be deduced. Please check if the nominal power of the ' - 'wind turbine is set.'.format( - turbine=row['wind_turbine'])) + "Total capacity of turbines of type {turbine} cannot " + "be deduced. Please check if the nominal power of the " + "wind turbine is set.".format( + turbine=row["wind_turbine"] + ) + ) else: - if not abs(row['total_capacity'] - ( - row['number_of_turbines'] * - row['wind_turbine'].nominal_power)) < 1: - self.wind_turbine_fleet.loc[ix, 'total_capacity']=\ - row['number_of_turbines'] * \ - row['wind_turbine'].nominal_power - msg=( - 'The provided total capacity of WindTurbine {0} has ' - 'been overwritten as it was not consistent with the ' - 'number of turbines provided for this type.') - warnings.warn(msg.format(row['wind_turbine']), - tools.WindpowerlibUserWarning) + if ( + not abs( + row["total_capacity"] + - ( + row["number_of_turbines"] + * row["wind_turbine"].nominal_power + ) + ) + < 1 + ): + self.wind_turbine_fleet.loc[ix, "total_capacity"] = ( + row["number_of_turbines"] + * row["wind_turbine"].nominal_power + ) + msg = ( + "The provided total capacity of WindTurbine {0} has " + "been overwritten as it was not consistent with the " + "number of turbines provided for this type." + ) + warnings.warn( + msg.format(row["wind_turbine"]), + tools.WindpowerlibUserWarning, + ) def __repr__(self): - if self.name != '': - return 'Wind farm: {name}'.format(name=self.name) + if self.name != "": + return "Wind farm: {name}".format(name=self.name) else: - return 'Wind farm with turbine fleet: [number, type]\n {}'.format( + return "Wind farm with turbine fleet: [number, type]\n {}".format( self.wind_turbine_fleet.loc[ - :, ['number_of_turbines', 'wind_turbine']].values) + :, ["number_of_turbines", "wind_turbine"] + ].values + ) @property def nominal_power(self): @@ -224,12 +248,12 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power=self.wind_turbine_fleet.total_capacity.sum() + self.nominal_power = self.wind_turbine_fleet.total_capacity.sum() return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power=nominal_power + self._nominal_power = nominal_power def mean_hub_height(self): r""" @@ -267,17 +291,25 @@ def mean_hub_height(self): p. 35 """ - self.hub_height=np.exp( - sum(np.log(row['wind_turbine'].hub_height) * row['total_capacity'] - for ix, row in self.wind_turbine_fleet.iterrows()) / - self.nominal_power) + self.hub_height = np.exp( + sum( + np.log(row["wind_turbine"].hub_height) * row["total_capacity"] + for ix, row in self.wind_turbine_fleet.iterrows() + ) + / self.nominal_power + ) return self - def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', - smoothing=False, block_width=0.5, - standard_deviation_method='turbulence_intensity', - smoothing_order='wind_farm_power_curves', - turbulence_intensity=None, **kwargs): + def assign_power_curve( + self, + wake_losses_model="wind_farm_efficiency", + smoothing=False, + block_width=0.5, + standard_deviation_method="turbulence_intensity", + smoothing_order="wind_farm_power_curves", + turbulence_intensity=None, + **kwargs + ): r""" Calculates the power curve of a wind farm. @@ -327,83 +359,123 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', """ # Check if all wind turbines have a power curve as attribute - for turbine in self.wind_turbine_fleet['wind_turbine']: + for turbine in self.wind_turbine_fleet["wind_turbine"]: if turbine.power_curve is None: - raise ValueError("For an aggregated wind farm power curve " + - "each wind turbine needs a power curve " + - "but `power_curve` of '{}' is None.".format( - turbine)) + raise ValueError( + "For an aggregated wind farm power curve " + + "each wind turbine needs a power curve " + + "but `power_curve` of '{}' is None.".format(turbine) + ) # Initialize data frame for power curve values - df=pd.DataFrame() + df = pd.DataFrame() for ix, row in self.wind_turbine_fleet.iterrows(): # Check if needed parameters are available and/or assign them if smoothing: - if (standard_deviation_method == 'turbulence_intensity' and - turbulence_intensity is None): - if 'roughness_length' in kwargs and \ - kwargs['roughness_length'] is not None: + if ( + standard_deviation_method == "turbulence_intensity" + and turbulence_intensity is None + ): + if ( + "roughness_length" in kwargs + and kwargs["roughness_length"] is not None + ): # Calculate turbulence intensity and write to kwargs - turbulence_intensity=( - tools.estimate_turbulence_intensity( - row['wind_turbine'].hub_height, - kwargs['roughness_length'])) - kwargs['turbulence_intensity']=turbulence_intensity + turbulence_intensity = tools.estimate_turbulence_intensity( + row["wind_turbine"].hub_height, + kwargs["roughness_length"], + ) + kwargs["turbulence_intensity"] = turbulence_intensity else: raise ValueError( - "`roughness_length` must be defined for using " + - "'turbulence_intensity' as " + - "`standard_deviation_method` if " + - "`turbulence_intensity` is not given") + "`roughness_length` must be defined for using " + + "'turbulence_intensity' as " + + "`standard_deviation_method` if " + + "`turbulence_intensity` is not given" + ) # Get original power curve - power_curve=pd.DataFrame(row['wind_turbine'].power_curve) + power_curve = pd.DataFrame(row["wind_turbine"].power_curve) # Editions to the power curves before the summation - if smoothing and smoothing_order == 'turbine_power_curves': - power_curve=power_curves.smooth_power_curve( - power_curve['wind_speed'], power_curve['value'], + if smoothing and smoothing_order == "turbine_power_curves": + power_curve = power_curves.smooth_power_curve( + power_curve["wind_speed"], + power_curve["value"], standard_deviation_method=standard_deviation_method, - block_width=block_width, **kwargs) + block_width=block_width, + **kwargs, + ) else: # Add value zero to start and end of curve as otherwise # problems can occur during the aggregation - if power_curve.iloc[0]['wind_speed'] != 0.0: - power_curve=pd.concat( - [pd.DataFrame(data={ - 'value': [0.0], 'wind_speed': [0.0]}), - power_curve], join='inner') - if power_curve.iloc[-1]['value'] != 0.0: - power_curve=pd.concat( - [power_curve, pd.DataFrame(data={ - 'wind_speed': [power_curve['wind_speed'].loc[ - power_curve.index[-1]] + 0.5], - 'value': [0.0]})], join='inner') + if power_curve.iloc[0]["wind_speed"] != 0.0: + power_curve = pd.concat( + [ + pd.DataFrame( + data={"value": [0.0], "wind_speed": [0.0]} + ), + power_curve, + ], + join="inner", + ) + if power_curve.iloc[-1]["value"] != 0.0: + power_curve = pd.concat( + [ + power_curve, + pd.DataFrame( + data={ + "wind_speed": [ + power_curve["wind_speed"].loc[ + power_curve.index[-1] + ] + + 0.5 + ], + "value": [0.0], + } + ), + ], + join="inner", + ) # Add power curves of all turbine types to data frame # (multiplied by turbine amount) - df=pd.concat( - [df, pd.DataFrame(power_curve.set_index(['wind_speed']) * - row['number_of_turbines'])], axis=1) + df = pd.concat( + [ + df, + pd.DataFrame( + power_curve.set_index(["wind_speed"]) + * row["number_of_turbines"] + ), + ], + axis=1, + ) # Aggregate all power curves - wind_farm_power_curve=pd.DataFrame( - df.interpolate(method='index').sum(axis=1)) - wind_farm_power_curve.columns=['value'] + wind_farm_power_curve = pd.DataFrame( + df.interpolate(method="index").sum(axis=1) + ) + wind_farm_power_curve.columns = ["value"] wind_farm_power_curve.reset_index(inplace=True) # Apply power curve smoothing and consideration of wake losses # after the summation - if smoothing and smoothing_order == 'wind_farm_power_curves': - wind_farm_power_curve=power_curves.smooth_power_curve( - wind_farm_power_curve['wind_speed'], - wind_farm_power_curve['value'], + if smoothing and smoothing_order == "wind_farm_power_curves": + wind_farm_power_curve = power_curves.smooth_power_curve( + wind_farm_power_curve["wind_speed"], + wind_farm_power_curve["value"], standard_deviation_method=standard_deviation_method, - block_width=block_width, **kwargs) - if wake_losses_model == 'wind_farm_efficiency': + block_width=block_width, + **kwargs, + ) + if wake_losses_model == "wind_farm_efficiency": if self.efficiency is not None: - wind_farm_power_curve=( - power_curves.wake_losses_to_power_curve( - wind_farm_power_curve['wind_speed'].values, - wind_farm_power_curve['value'].values, - wind_farm_efficiency=self.efficiency)) + wind_farm_power_curve = power_curves.wake_losses_to_power_curve( + wind_farm_power_curve["wind_speed"].values, + wind_farm_power_curve["value"].values, + wind_farm_efficiency=self.efficiency, + ) else: - logging.info("`wake_losses_model` is {} but wind farm ".format( - wake_losses_model) + "efficiency is NOT taken into " - "account as it is None.") - self.power_curve=wind_farm_power_curve + logging.info( + "`wake_losses_model` is {} but wind farm ".format( + wake_losses_model + ) + + "efficiency is NOT taken into " + "account as it is None." + ) + self.power_curve = wind_farm_power_curve return self diff --git a/windpowerlib/wind_speed.py b/windpowerlib/wind_speed.py index 60882805..7a1189a5 100644 --- a/windpowerlib/wind_speed.py +++ b/windpowerlib/wind_speed.py @@ -73,22 +73,33 @@ def logarithmic_profile(wind_speed, wind_speed_height, hub_height, """ if 0.7 * obstacle_height > wind_speed_height: - raise ValueError("To take an obstacle height of {0} m ".format( - obstacle_height) + "into consideration, wind " + - "speed data of a greater height is needed.") + raise ValueError( + "To take an obstacle height of {0} m ".format(obstacle_height) + + "into consideration, wind " + + "speed data of a greater height is needed." + ) # Return np.array if wind_speed is np.array - if (isinstance(wind_speed, np.ndarray) and - isinstance(roughness_length, pd.Series)): - roughness_length=np.array(roughness_length) - - return (wind_speed * np.log((hub_height - 0.7 * obstacle_height) / - roughness_length) / - np.log((wind_speed_height - 0.7 * obstacle_height) / - roughness_length)) - - -def hellman(wind_speed, wind_speed_height, hub_height, - roughness_length=None, hellman_exponent=None): + if isinstance(wind_speed, np.ndarray) and isinstance( + roughness_length, pd.Series + ): + roughness_length = np.array(roughness_length) + + return ( + wind_speed + * np.log((hub_height - 0.7 * obstacle_height) / roughness_length) + / np.log( + (wind_speed_height - 0.7 * obstacle_height) / roughness_length + ) + ) + + +def hellman( + wind_speed, + wind_speed_height, + hub_height, + roughness_length=None, + hellman_exponent=None, +): r""" Calculates the wind speed at hub height using the hellman equation. diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index b1ac7fa2..cb73f698 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -114,107 +114,131 @@ class WindTurbine(object): 1500000.0 """ - def __init__(self, hub_height, nominal_power=None, path='oedb', - power_curve=None, power_coefficient_curve=None, - rotor_diameter=None, turbine_type=None, **kwargs): - - self.hub_height=hub_height - self.turbine_type=turbine_type - self.rotor_diameter=rotor_diameter - self.nominal_power=nominal_power - self.power_curve=power_curve - self.power_coefficient_curve=power_coefficient_curve - - if path == 'oedb': - path=os.path.join(os.path.dirname(__file__), 'oedb') + def __init__( + self, + hub_height, + nominal_power=None, + path="oedb", + power_curve=None, + power_coefficient_curve=None, + rotor_diameter=None, + turbine_type=None, + **kwargs + ): + + self.hub_height = hub_height + self.turbine_type = turbine_type + self.rotor_diameter = rotor_diameter + self.nominal_power = nominal_power + self.power_curve = power_curve + self.power_coefficient_curve = power_coefficient_curve + + if path == "oedb": + path = os.path.join(os.path.dirname(__file__), "oedb") if turbine_type is not None and path is not None: if power_curve is None: try: - fn=os.path.join(path, 'power_curves.csv') - self.power_curve=get_turbine_data_from_file( - self.turbine_type, fn) + fn = os.path.join(path, "power_curves.csv") + self.power_curve = get_turbine_data_from_file( + self.turbine_type, fn + ) except KeyError: - msg="No power curve found for {0}" + msg = "No power curve found for {0}" logging.debug(msg.format(self.turbine_type)) if power_coefficient_curve is None: try: - fn=os.path.join(path, 'power_coefficient_curves.csv') - self.power_coefficient_curve=get_turbine_data_from_file( - self.turbine_type, fn) + fn = os.path.join(path, "power_coefficient_curves.csv") + self.power_coefficient_curve = get_turbine_data_from_file( + self.turbine_type, fn + ) except KeyError: - msg="No power coefficient curve found for {0}" + msg = "No power coefficient curve found for {0}" logging.debug(msg.format(self.turbine_type)) if nominal_power is None or ( - rotor_diameter is None and - self.power_coefficient_curve is not None): - turbine_data=None + rotor_diameter is None + and self.power_coefficient_curve is not None + ): + turbine_data = None try: - fn=os.path.join(path, 'turbine_data.csv') - turbine_data=get_turbine_data_from_file( - self.turbine_type, fn) + fn = os.path.join(path, "turbine_data.csv") + turbine_data = get_turbine_data_from_file( + self.turbine_type, fn + ) except KeyError: - msg="No turbine data found for {0}" + msg = "No turbine data found for {0}" logging.debug(msg.format(self.turbine_type)) if self.nominal_power is None and turbine_data is not None: - self.nominal_power=float(turbine_data['nominal_power']) + self.nominal_power = float(turbine_data["nominal_power"]) if self.rotor_diameter is None and turbine_data is not None: - self.rotor_diameter=float(turbine_data['rotor_diameter']) + self.rotor_diameter = float(turbine_data["rotor_diameter"]) if self.power_curve is None and self.power_coefficient_curve is None: - msg=("The WindTurbine has been initialised without a power curve" - " and without a power coefficient curve.\nYou will not be" - " able to calculate the power output.\n" - " Check if the turbine type {0} is in your database file" - " or if you passed a valid curve.") + msg = ( + "The WindTurbine has been initialised without a power curve" + " and without a power coefficient curve.\nYou will not be" + " able to calculate the power output.\n" + " Check if the turbine type {0} is in your database file" + " or if you passed a valid curve." + ) warnings.warn(msg.format(turbine_type), WindpowerlibUserWarning) else: # power (coefficient) curve to pd.DataFrame in case of being dict if isinstance(self.power_curve, dict): - self.power_curve=pd.DataFrame(self.power_curve) + self.power_curve = pd.DataFrame(self.power_curve) if isinstance(self.power_coefficient_curve, dict): - self.power_coefficient_curve=pd.DataFrame( - self.power_coefficient_curve) + self.power_coefficient_curve = pd.DataFrame( + self.power_coefficient_curve + ) # sort power (coefficient) curve by wind speed if isinstance(self.power_curve, pd.DataFrame): - self.power_curve.sort_values(by='wind_speed') + self.power_curve.sort_values(by="wind_speed") elif self.power_curve is not None: - msg="Type of power curve of {} is {} but should be " \ - "pd.DataFrame or dict." - raise TypeError(msg.format(self.__repr__(), - type(self.power_curve))) + msg = ( + "Type of power curve of {} is {} but should be " + "pd.DataFrame or dict." + ) + raise TypeError( + msg.format(self.__repr__(), type(self.power_curve)) + ) if isinstance(self.power_coefficient_curve, pd.DataFrame): - self.power_coefficient_curve.sort_values(by='wind_speed') + self.power_coefficient_curve.sort_values(by="wind_speed") elif self.power_coefficient_curve is not None: - msg="Type of power coefficient curve of {} is {} but " \ - "should be pd.DataFrame or dict." - raise TypeError(msg.format(self.__repr__(), - type(self.power_coefficient_curve))) + msg = ( + "Type of power coefficient curve of {} is {} but " + "should be pd.DataFrame or dict." + ) + raise TypeError( + msg.format( + self.__repr__(), type(self.power_coefficient_curve) + ) + ) def __repr__(self): - info=[] + info = [] if self.nominal_power is not None: - info.append('nominal power={} W'.format(self.nominal_power)) + info.append("nominal power={} W".format(self.nominal_power)) if self.hub_height is not None: - info.append('hub height={} m'.format(self.hub_height)) + info.append("hub height={} m".format(self.hub_height)) if self.rotor_diameter is not None: - info.append('rotor diameter={} m'.format(self.rotor_diameter)) + info.append("rotor diameter={} m".format(self.rotor_diameter)) if self.power_coefficient_curve is not None: - info.append('power_coefficient_curve={}'.format('True')) + info.append("power_coefficient_curve={}".format("True")) else: - info.append('power_coefficient_curve={}'.format('False')) + info.append("power_coefficient_curve={}".format("False")) if self.power_curve is not None: - info.append('power_curve={}'.format('True')) + info.append("power_curve={}".format("True")) else: - info.append('power_curve={}'.format('False')) + info.append("power_curve={}".format("False")) if self.turbine_type is not None: - turbine_repr='Wind turbine: {name} {info}'.format( - name=self.turbine_type, info=info) + turbine_repr = "Wind turbine: {name} {info}".format( + name=self.turbine_type, info=info + ) else: - turbine_repr='Wind turbine: {info}'.format(info=info) + turbine_repr = "Wind turbine: {info}".format(info=info) return turbine_repr @@ -271,22 +295,29 @@ def to_group(self, number_turbines=None, total_capacity=None): """ if number_turbines is not None and total_capacity is not None: - raise ValueError("The 'number' and the 'total_capacity' parameter " - "are mutually exclusive. Use just one of them.") + raise ValueError( + "The 'number' and the 'total_capacity' parameter " + "are mutually exclusive. Use just one of them." + ) elif total_capacity is not None: - number_turbines=total_capacity / self.nominal_power + number_turbines = total_capacity / self.nominal_power elif number_turbines is None: - number_turbines=1 + number_turbines = 1 return WindTurbineGroup( - wind_turbine=self, number_of_turbines=number_turbines) + wind_turbine=self, number_of_turbines=number_turbines + ) # This is working for Python >= 3.5. # There a cleaner solutions for Python >= 3.6, once the support of 3.5 is # dropped: https://stackoverflow.com/a/50038614 -class WindTurbineGroup(NamedTuple('WindTurbineGroup', [ - ('wind_turbine', WindTurbine), ('number_of_turbines', float)])): +class WindTurbineGroup( + NamedTuple( + "WindTurbineGroup", + [("wind_turbine", WindTurbine), ("number_of_turbines", float)], + ) +): """ A simple data container to define more than one turbine of the same type. Use the :func:`~windpowerlib.wind_turbine.WindTurbine.to_group` method to @@ -300,13 +331,16 @@ class WindTurbineGroup(NamedTuple('WindTurbineGroup', [ 'number_of_turbines' : float The number of turbines. The number is not restricted to integer values. """ - __slots__=() + + __slots__ = () -WindTurbineGroup.wind_turbine.__doc__=( - 'A :class:`~windpowerlib.wind_farm.WindTurbine` object.') -WindTurbineGroup.number_of_turbines.__doc__=( - 'Number of turbines of type WindTurbine') +WindTurbineGroup.wind_turbine.__doc__ = ( + "A :class:`~windpowerlib.wind_farm.WindTurbine` object." +) +WindTurbineGroup.number_of_turbines.__doc__ = ( + "Number of turbines of type WindTurbine" +) def get_turbine_data_from_file(turbine_type, path): @@ -349,28 +383,28 @@ def get_turbine_data_from_file(turbine_type, path): """ try: - df=pd.read_csv(path, index_col=0) + df = pd.read_csv(path, index_col=0) except FileNotFoundError: raise FileNotFoundError("The file '{}' was not found.".format(path)) - wpp_df=df[df.index == turbine_type].copy() + wpp_df = df[df.index == turbine_type].copy() # if turbine not in data file if wpp_df.shape[0] == 0: - msg="Wind converter type {0} not provided. Possible types: {1}" + msg = "Wind converter type {0} not provided. Possible types: {1}" raise KeyError(msg.format(turbine_type, list(df.index))) # if turbine in data file # get nominal power or power (coefficient) curve - if 'turbine_data' in path: + if "turbine_data" in path: return wpp_df else: wpp_df.dropna(axis=1, inplace=True) - wpp_df=wpp_df.transpose().reset_index() - wpp_df.columns=['wind_speed', 'value'] + wpp_df = wpp_df.transpose().reset_index() + wpp_df.columns = ["wind_speed", "value"] # transform wind speeds to floats - wpp_df['wind_speed']=wpp_df['wind_speed'].apply(lambda x: float(x)) + wpp_df["wind_speed"] = wpp_df["wind_speed"].apply(lambda x: float(x)) return wpp_df -def load_turbine_data_from_oedb(schema='supply', table='wind_turbine_library'): +def load_turbine_data_from_oedb(schema="supply", table="wind_turbine_library"): r""" Loads turbine library from the OpenEnergy database (oedb). @@ -393,58 +427,82 @@ def load_turbine_data_from_oedb(schema='supply', table='wind_turbine_library'): """ # url of OpenEnergy Platform that contains the oedb - oep_url='http://oep.iks.cs.ovgu.de/' + oep_url = "http://oep.iks.cs.ovgu.de/" # load data - result=requests.get( - oep_url + '/api/v0/schema/{}/tables/{}/rows/?'.format( - schema, table), ) + result = requests.get( + oep_url + "/api/v0/schema/{}/tables/{}/rows/?".format(schema, table), + ) if not result.status_code == 200: - raise ConnectionError("Database connection not successful. " - "Response: [{}]".format(result.status_code)) + raise ConnectionError( + "Database connection not successful. " + "Response: [{}]".format(result.status_code) + ) # extract data to dataframe - turbine_data=pd.DataFrame(result.json()) + turbine_data = pd.DataFrame(result.json()) # standard file name for saving data - filename=os.path.join(os.path.dirname(__file__), 'oedb', - '{}.csv') + filename = os.path.join(os.path.dirname(__file__), "oedb", "{}.csv") # get all power (coefficient) curves and save to file # for curve_type in ['power_curve', 'power_coefficient_curve']: - for curve_type in ['power_curve', 'power_coefficient_curve']: - curves_df=pd.DataFrame(columns=['wind_speed']) + for curve_type in ["power_curve", "power_coefficient_curve"]: + curves_df = pd.DataFrame(columns=["wind_speed"]) for index in turbine_data.index: - if (turbine_data['{}_wind_speeds'.format(curve_type)][index] - and turbine_data['{}_values'.format(curve_type)][index]): - df=pd.DataFrame(data=[ - eval(turbine_data['{}_wind_speeds'.format(curve_type)][ - index]), - eval(turbine_data['{}_values'.format(curve_type)][ - index])]).transpose().rename( - columns={0: 'wind_speed', - 1: turbine_data['turbine_type'][index]}) - curves_df=pd.merge(left=curves_df, right=df, how='outer', - on='wind_speed') - curves_df=curves_df.set_index('wind_speed').sort_index().transpose() + if ( + turbine_data["{}_wind_speeds".format(curve_type)][index] + and turbine_data["{}_values".format(curve_type)][index] + ): + df = ( + pd.DataFrame( + data=[ + eval( + turbine_data[ + "{}_wind_speeds".format(curve_type) + ][index] + ), + eval( + turbine_data["{}_values".format(curve_type)][ + index + ] + ), + ] + ) + .transpose() + .rename( + columns={ + 0: "wind_speed", + 1: turbine_data["turbine_type"][index], + } + ) + ) + curves_df = pd.merge( + left=curves_df, right=df, how="outer", on="wind_speed" + ) + curves_df = curves_df.set_index("wind_speed").sort_index().transpose() # power curve values in W - if curve_type == 'power_curve': + if curve_type == "power_curve": curves_df *= 1000 - curves_df.index.name='turbine_type' - curves_df.to_csv(filename.format('{}s'.format(curve_type))) + curves_df.index.name = "turbine_type" + curves_df.to_csv(filename.format("{}s".format(curve_type))) # get turbine data and save to file (excl. curves) - turbine_data_df=turbine_data.drop( - ['power_curve_wind_speeds', 'power_curve_values', - 'power_coefficient_curve_wind_speeds', - 'power_coefficient_curve_values', - 'thrust_coefficient_curve_wind_speeds', - 'thrust_coefficient_curve_values'], axis=1).set_index('turbine_type') + turbine_data_df = turbine_data.drop( + [ + "power_curve_wind_speeds", + "power_curve_values", + "power_coefficient_curve_wind_speeds", + "power_coefficient_curve_values", + "thrust_coefficient_curve_wind_speeds", + "thrust_coefficient_curve_values", + ], + axis=1, + ).set_index("turbine_type") # nominal power in W - turbine_data_df['nominal_power']=turbine_data_df[ - 'nominal_power'] * 1000 - turbine_data_df.to_csv(filename.format('turbine_data')) + turbine_data_df["nominal_power"] = turbine_data_df["nominal_power"] * 1000 + turbine_data_df.to_csv(filename.format("turbine_data")) return turbine_data -def get_turbine_types(turbine_library='local', print_out=True, filter_=True): +def get_turbine_types(turbine_library="local", print_out=True, filter_=True): r""" Get all provided wind turbine types provided. @@ -506,26 +564,34 @@ def get_turbine_types(turbine_library='local', print_out=True, filter_=True): Name: 1, dtype: object """ - if turbine_library == 'local': - filename=os.path.join(os.path.dirname(__file__), 'oedb', 'turbine_data.csv') - df=pd.read_csv(filename, index_col=0).reset_index() - elif turbine_library == 'oedb': - df=load_turbine_data_from_oedb() + if turbine_library == "local": + filename = os.path.join( + os.path.dirname(__file__), "oedb", "turbine_data.csv" + ) + df = pd.read_csv(filename, index_col=0).reset_index() + elif turbine_library == "oedb": + df = load_turbine_data_from_oedb() else: - raise ValueError("`turbine_library` is '{}' ".format(turbine_library) + - "but must be 'local' or 'oedb'.") + raise ValueError( + "`turbine_library` is '{}' ".format(turbine_library) + + "but must be 'local' or 'oedb'." + ) if filter_: - cp_curves_df=df.loc[df['has_cp_curve']][ - ['manufacturer', 'turbine_type', 'has_cp_curve']] - p_curves_df=df.loc[df['has_power_curve']][ - ['manufacturer', 'turbine_type', 'has_power_curve']] - curves_df=pd.merge(p_curves_df, cp_curves_df, how='outer', - sort=True).fillna(False) + cp_curves_df = df.loc[df["has_cp_curve"]][ + ["manufacturer", "turbine_type", "has_cp_curve"] + ] + p_curves_df = df.loc[df["has_power_curve"]][ + ["manufacturer", "turbine_type", "has_power_curve"] + ] + curves_df = pd.merge( + p_curves_df, cp_curves_df, how="outer", sort=True + ).fillna(False) else: - curves_df=df[['manufacturer', 'turbine_type', 'has_power_curve', - 'has_cp_curve']] + curves_df = df[ + ["manufacturer", "turbine_type", "has_power_curve", "has_cp_curve"] + ] if print_out: - pd.set_option('display.max_rows', len(curves_df)) + pd.set_option("display.max_rows", len(curves_df)) print(curves_df) - pd.reset_option('display.max_rows') + pd.reset_option("display.max_rows") return curves_df diff --git a/windpowerlib/wind_turbine_cluster.py b/windpowerlib/wind_turbine_cluster.py index 74d2ecb8..0f2f7f8c 100644 --- a/windpowerlib/wind_turbine_cluster.py +++ b/windpowerlib/wind_turbine_cluster.py @@ -37,23 +37,24 @@ class WindTurbineCluster(object): :py:func:`assign_power_curve` for more information. """ - def __init__(self, wind_farms, name='', **kwargs): - self.wind_farms=wind_farms - self.name=name + def __init__(self, wind_farms, name="", **kwargs): - self.hub_height=None - self._nominal_power=None - self.power_curve=None + self.wind_farms = wind_farms + self.name = name + + self.hub_height = None + self._nominal_power = None + self.power_curve = None def __repr__(self): - if self.name != '': - wf_repr='Wind turbine cluster: {name}'.format(name=self.name) + if self.name != "": + wf_repr = "Wind turbine cluster: {name}".format(name=self.name) else: - info=[] + info = [] for wind_farm in self.wind_farms: info.append(wind_farm) - wf_repr=r'Wind turbine cluster with: {info}'.format(info=info) + wf_repr = r"Wind turbine cluster with: {info}".format(info=info) return wf_repr @property @@ -69,13 +70,14 @@ def nominal_power(self): """ if not self._nominal_power: - self.nominal_power=sum(wind_farm.nominal_power - for wind_farm in self.wind_farms) + self.nominal_power = sum( + wind_farm.nominal_power for wind_farm in self.wind_farms + ) return self._nominal_power @nominal_power.setter def nominal_power(self, nominal_power): - self._nominal_power=nominal_power + self._nominal_power = nominal_power def mean_hub_height(self): r""" @@ -113,16 +115,25 @@ def mean_hub_height(self): p. 35 """ - self.hub_height=np.exp(sum( - np.log(wind_farm.hub_height) * wind_farm.nominal_power for - wind_farm in self.wind_farms) / self.nominal_power) + self.hub_height = np.exp( + sum( + np.log(wind_farm.hub_height) * wind_farm.nominal_power + for wind_farm in self.wind_farms + ) + / self.nominal_power + ) return self - def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', - smoothing=False, block_width=0.5, - standard_deviation_method='turbulence_intensity', - smoothing_order='wind_farm_power_curves', - turbulence_intensity=None, **kwargs): + def assign_power_curve( + self, + wake_losses_model="wind_farm_efficiency", + smoothing=False, + block_width=0.5, + standard_deviation_method="turbulence_intensity", + smoothing_order="wind_farm_power_curves", + turbulence_intensity=None, + **kwargs + ): r""" Calculates the power curve of a wind turbine cluster. @@ -180,20 +191,31 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency', # Assign wind farm power curve farm.assign_power_curve( wake_losses_model=wake_losses_model, - smoothing=smoothing, block_width=block_width, + smoothing=smoothing, + block_width=block_width, standard_deviation_method=standard_deviation_method, smoothing_order=smoothing_order, - turbulence_intensity=turbulence_intensity, **kwargs) + turbulence_intensity=turbulence_intensity, + **kwargs, + ) # Create data frame from power curves of all wind farms - df=pd.concat([farm.power_curve.set_index(['wind_speed']).rename( - columns={'value': i}) for - farm, i in zip(self.wind_farms, - list(range(len(self.wind_farms))))], axis=1) + df = pd.concat( + [ + farm.power_curve.set_index(["wind_speed"]).rename( + columns={"value": i} + ) + for farm, i in zip( + self.wind_farms, list(range(len(self.wind_farms))) + ) + ], + axis=1, + ) # Sum up power curves - cluster_power_curve=pd.DataFrame( - df.interpolate(method='index').sum(axis=1)) - cluster_power_curve.columns=['value'] + cluster_power_curve = pd.DataFrame( + df.interpolate(method="index").sum(axis=1) + ) + cluster_power_curve.columns = ["value"] # Return wind speed (index) to a column of the data frame cluster_power_curve.reset_index(inplace=True) - self.power_curve=cluster_power_curve + self.power_curve = cluster_power_curve return self From fb4f10b2a39a7445bbc2537ccebbaa574d596d0b Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 12 Dec 2019 15:27:49 +0000 Subject: [PATCH 16/16] Fixing style errors. --- windpowerlib/power_output.py | 39 +++++++++++++++++++++++++++--------- windpowerlib/wind_speed.py | 11 +++++----- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/windpowerlib/power_output.py b/windpowerlib/power_output.py index a9554020..4db874b9 100644 --- a/windpowerlib/power_output.py +++ b/windpowerlib/power_output.py @@ -237,18 +237,37 @@ def power_curve_density_correction( """ if density is None: - raise TypeError("`density` is None. For the calculation with a " + - "density corrected power curve density at hub " + - "height is needed.") - power_output=[(np.interp( - wind_speed[i], power_curve_wind_speeds * (1.225 / density[i]) ** ( - np.interp(power_curve_wind_speeds, [7.5, 12.5], [1/3, 2/3])), - power_curve_values, left=0, right=0)) for i in range(len(wind_speed))] + raise TypeError( + "`density` is None. For the calculation with a " + + "density corrected power curve density at hub " + + "height is needed." + ) + power_output = [ + ( + np.interp( + wind_speed[i], + power_curve_wind_speeds + * (1.225 / density[i]) + ** ( + np.interp( + power_curve_wind_speeds, [7.5, 12.5], [1 / 3, 2 / 3] + ) + ), + power_curve_values, + left=0, + right=0, + ) + ) + for i in range(len(wind_speed)) + ] # Power_output as pd.Series if wind_speed is pd.Series (else: np.array) if isinstance(wind_speed, pd.Series): - power_output=pd.Series(data=power_output, index=wind_speed.index, - name='feedin_power_plant') + power_output = pd.Series( + data=power_output, + index=wind_speed.index, + name="feedin_power_plant", + ) else: - power_output=np.array(power_output) + power_output = np.array(power_output) return power_output diff --git a/windpowerlib/wind_speed.py b/windpowerlib/wind_speed.py index 7a1189a5..c620dd43 100644 --- a/windpowerlib/wind_speed.py +++ b/windpowerlib/wind_speed.py @@ -171,10 +171,11 @@ def hellman( if hellman_exponent is None: if roughness_length is not None: # Return np.array if wind_speed is np.array - if (isinstance(wind_speed, np.ndarray) and - isinstance(roughness_length, pd.Series)): - roughness_length=np.array(roughness_length) - hellman_exponent=1 / np.log(hub_height / roughness_length) + if isinstance(wind_speed, np.ndarray) and isinstance( + roughness_length, pd.Series + ): + roughness_length = np.array(roughness_length) + hellman_exponent = 1 / np.log(hub_height / roughness_length) else: - hellman_exponent=1/7 + hellman_exponent = 1 / 7 return wind_speed * (hub_height / wind_speed_height) ** hellman_exponent