Optimization of Surface Position¶
Following we show a few examples on how to use the optimizer for the surface position in PVGIS.
Optimization of Surface Position
- Optimisation of Tilt, Orientation or both
- Supported by optimizers implemented in SciPy
Multiple examples
- Examples for a single day, single and multi-year timestamps
Programmatic preamble¶
from pvgis import (TemperatureSeries, WindSpeedSeries, SpectralFactorSeries, LinkeTurbidityFactor,
Longitude, Latitude, Elevation, SurfaceOrientation, SurfaceTilt,
)
from pvgis.api.power.photovoltaic_module import PhotovoltaicModuleModel
from pvgis.api.datetime.datetimeindex import generate_datetime_series
from zoneinfo import ZoneInfo
from pvgis.api.surface.graph_power_output import graph_power_output
from pvgis.api.surface.positioning import optimise_surface_position
from pvgis.api.surface.parameter_models import (SurfacePositionOptimizerMethod,
SurfacePositionOptimizerMode)
import math
from pvgis.constants import (
DEGREES,
MEAN_PHOTOVOLTAIC_POWER_NAME,
SURFACE_ORIENTATION_NAME,
SURFACE_TILT_NAME,
)
Data preparation¶
First, we define some basic parameters for a location, in which case it is a solar panel located behind the ESTI Lab, in the JRC, European Commission.
latitude = Latitude(value=45.812, unit=DEGREES)
longitude = Longitude(value=8.628, unit=DEGREES)
elevation = 214
timezone = ZoneInfo("UTC")
spectral_factor_series = SpectralFactorSeries(value=1)
photovoltaic_module = PhotovoltaicModuleModel.CIS_FREE_STANDING
temperature_series = TemperatureSeries(value=12)
wind_speed_series = WindSpeedSeries(value=2)
linke_turbidity_factor_series = LinkeTurbidityFactor(value=1)
Optimization of Position¶
Optimal Tilt for a Single Day¶
For this first example, we will optimize the tilt of the panel on the 1st January 2010. We define the dates, the optimization mode as "Tilt", and the surface orientation of our panel
start_time = '2010-01-01'
end_time = '2010-01-02'
timestamps = generate_datetime_series(start_time=start_time, end_time=end_time, frequency="h")
mode = SurfacePositionOptimizerMode.Tilt
surface_orientation = math.radians(180)
Now, we call the optimise_surface_position() function to calculate which is the optimal tilt for this case
result = optimise_surface_position(longitude = longitude.radians,
latitude = latitude.radians,
elevation = elevation,
timestamps = timestamps,
timezone = timezone,
spectral_factor_series = spectral_factor_series,
photovoltaic_module = photovoltaic_module,
temperature_series = temperature_series,
wind_speed_series = wind_speed_series,
linke_turbidity_factor_series = linke_turbidity_factor_series,
mode = mode,
surface_orientation = surface_orientation
)
print(result)
{'surface_orientation': SurfaceOrientation(value=3.141592653589793, unit='radians', min_radians=0, max_radians=6.283185307179586, min_degrees=0, max_degrees=360, optimal=False, optimizer=None), 'surface_tilt': SurfaceTilt(value=1.3024720402090582, unit='radians', min_radians=0, max_radians=3.141592653589793, min_degrees=0, max_degrees=180, optimal=True, optimizer='L-BFGS-B'), 'Mean PV Power': np.float32(243.69215), 'unit': 'radians', 'time_algorithm': 'Milne1921'}
We can plot the photovoltaic power output against the surface tilt angle along with the point of maximum output
graph_power_output(longitude = longitude.radians,
latitude = latitude.radians,
elevation = elevation,
timestamps = timestamps,
timezone = timezone,
spectral_factor_series = spectral_factor_series,
photovoltaic_module = photovoltaic_module,
temperature_series = temperature_series,
wind_speed_series = wind_speed_series,
linke_turbidity_factor_series = linke_turbidity_factor_series,
mode = mode,
surface_orientation = result[SURFACE_ORIENTATION_NAME].value,
optimal_surface_tilt = result[SURFACE_TILT_NAME].value,
optimal_pv_power = result[MEAN_PHOTOVOLTAIC_POWER_NAME],
alt='Photovoltaic power versus surface tilt for a single day with the optimal tilt marked')
Optimal Tilt over a year¶
In this example, we optimize the tilt of the panel for the year 2010, considering the same panel orientation as before. First we need to define the new timestamps.
start_time = '2010-01-01'
end_time = '2010-12-31'
timestamps = generate_datetime_series(start_time=start_time, end_time=end_time, frequency="h")
We run the optimizer
result = optimise_surface_position(longitude = longitude.radians,
latitude = latitude.radians,
elevation = elevation,
timestamps = timestamps,
timezone = timezone,
spectral_factor_series = spectral_factor_series,
photovoltaic_module = photovoltaic_module,
temperature_series = temperature_series,
wind_speed_series = wind_speed_series,
linke_turbidity_factor_series = linke_turbidity_factor_series,
mode = mode,
surface_orientation = surface_orientation
)
print(result)
{'surface_orientation': SurfaceOrientation(value=3.141592653589793, unit='radians', min_radians=0, max_radians=6.283185307179586, min_degrees=0, max_degrees=360, optimal=False, optimizer=None), 'surface_tilt': SurfaceTilt(value=0.7697836051656269, unit='radians', min_radians=0, max_radians=3.141592653589793, min_degrees=0, max_degrees=180, optimal=True, optimizer='L-BFGS-B'), 'Mean PV Power': np.float32(274.5391), 'unit': 'radians', 'time_algorithm': 'Milne1921'}
And now we plot the PV Power
graph_power_output(longitude = longitude,
latitude = latitude,
elevation = elevation,
timestamps = timestamps,
timezone = timezone,
spectral_factor_series = spectral_factor_series,
photovoltaic_module = photovoltaic_module,
temperature_series = temperature_series,
wind_speed_series = wind_speed_series,
linke_turbidity_factor_series = linke_turbidity_factor_series,
mode = mode,
surface_orientation = result[SURFACE_ORIENTATION_NAME].value,
optimal_surface_tilt = result[SURFACE_TILT_NAME].value,
optimal_pv_power = result[MEAN_PHOTOVOLTAIC_POWER_NAME],
alt='Photovoltaic power versus surface tilt over one year with the optimal tilt marked')
Optimal Tilt & Orientation angles over 15 years¶
In this last example, we will optimize the tilt and orientation of the panel from 2005 to 2010. Let's define the new timestamps, and change our mode to "Tilt and Orientation"
start_time = '2005-01-01'
end_time = '2020-01-01'
timestamps = generate_datetime_series(start_time=start_time, end_time=end_time, frequency="h")
mode = SurfacePositionOptimizerMode.Orientation_and_Tilt
result = optimise_surface_position(longitude = longitude.radians,
latitude = latitude.radians,
elevation = elevation,
timestamps = timestamps,
timezone = timezone,
spectral_factor_series = spectral_factor_series,
photovoltaic_module = photovoltaic_module,
temperature_series = temperature_series,
wind_speed_series = wind_speed_series,
linke_turbidity_factor_series = linke_turbidity_factor_series,
mode = mode,
)
print(result)
{'surface_orientation': SurfaceOrientation(value=3.150324324133287, unit='radians', min_radians=0, max_radians=6.283185307179586, min_degrees=0, max_degrees=360, optimal=True, optimizer='L-BFGS-B'), 'surface_tilt': SurfaceTilt(value=0.7712275528158917, unit='radians', min_radians=0, max_radians=3.141592653589793, min_degrees=0, max_degrees=180, optimal=True, optimizer='L-BFGS-B'), 'Mean PV Power': np.float32(274.4322), 'unit': 'radians', 'time_algorithm': 'Milne1921'}
graph_power_output(longitude = longitude,
latitude = latitude,
elevation = elevation,
timestamps = timestamps,
timezone = timezone,
spectral_factor_series = spectral_factor_series,
photovoltaic_module = photovoltaic_module,
temperature_series = temperature_series,
wind_speed_series = wind_speed_series,
linke_turbidity_factor_series = linke_turbidity_factor_series,
mode = mode,
optimal_surface_tilt = result[SURFACE_TILT_NAME].value,
optimal_surface_orientation= result[SURFACE_ORIENTATION_NAME].value,
optimal_pv_power = result[MEAN_PHOTOVOLTAIC_POWER_NAME],
alt='Photovoltaic power versus surface tilt and orientation over 15 years with the optimum marked')