4.1 Advanced PV Power: Setting up and Using PV Sites
The SDK provides 'Rooftop' and 'Advanced' PV power estimates. The advanced estimates use a more sophisticated PV model with comprehensive and flexible site configuration options. Advanced PV power estimates are available for the live
and forecast
modules. They require that a PV Power Site has been set up in the Solcast API to specify the configuration. Site configurations can be managed via the pv_power_sites
module.
In this example, we will use the SDK for the following.
- Get forecast PV power estimates at an existing site
- Create a new PV Power Site
- Get PV power timeseries and adjust the site's configuration
- Adjust the Advanced PV Power settings for snow soiling
Some of the example code below consumes requests from your API request quota. If you want to test the Advanced PV Power live and forecast endpoints without consuming API requests, you can use the test sites for unmetered locations as shown in the first section below. Calls to functions in the pv_power_sites
module do not consume any of your API request quota.
import pandas as pd
from solcast import live, forecast, pv_power_sites
Get Data at an Existing Site¶
You can list the PV Power Sites available to you. These include test sites at Solcast's unmetered locations, as well as any sites you have set up for yourself. For instance, you can list the available PV Power Sites and find the test site at the Giza Pyramid Complex.
res = pv_power_sites.list_pv_power_sites()
[s for s in res.to_dict() if s["name"] == 'Test Site: Giza Pyramid Complex']
[{'resource_id': '8d10-f530-af85-5cbb', 'name': 'Test Site: Giza Pyramid Complex', 'latitude': 29.977296, 'longitude': 31.132496, 'capacity': 145, 'capacity_dc': 180, 'azimuth': 180, 'tilt': 27.28, 'tracking_type': 'horizontal_single_axis', 'install_date': '2021-07-01T00:00:00.0000000Z', 'module_type': 'poly-si', 'ground_coverage_ratio': 0.36, 'derating_temp_module': 0.0039, 'derating_age_system': 0.0059, 'derating_other_system': 0.0221, 'inverter_peak_efficiency': 0.985, 'tracker_axis_azimuth': 0, 'tracker_max_rotation_angle': 60, 'tracker_back_tracking': True, 'tracker_smart_tracking': False, 'terrain_slope': 0, 'terrain_azimuth': 0, 'dust_soiling_average': [0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015], 'bifacial_system': False, 'site_ground_albedo': 0.25, 'bifaciality_factor': 0.7, 'pvrow_height': 1.5, 'pvrow_width': 2, 'is_unmetered': True, 'confirmed_metadata': '2022-11-04T03:13:07.6874000Z'}]
A Solcast PV Power Site is identified by a unique ID code, referred to as a resource_id
. This can found in the site configuration, in this case '8d10-f530-af85-5cbb'. The resource_id
is used to request and update the site's configuration and to fetch PV generation estimates. For instance, here we use it to access forecasts modelled according to this site's configuration, which is for a 145 kW capacity tracking array.
# This will not consume an API request, as it is an unmetered test site.
res = forecast.advanced_pv_power("8d10-f530-af85-5cbb")
res.to_pandas().plot(figsize=[15, 4])
<Axes: xlabel='period_end'>
Create a Site¶
We will now show how to make your own site configuration. Initially we specify a minimal set of parameters for a PV plant with trackers and 1MW AC capacity. Defaults are used for other parameters.
lat, lon = 35.978120, -118.339086
res = pv_power_sites.create_pv_power_site(
latitude=lat,
longitude=lon,
name="my test site",
capacity=1000,
capacity_dc=1200,
tracking_type='horizontal_single_axis',
install_date="2024-02-13",
)
metadata = res.to_dict()
metadata
{'resource_id': '94af-4847-f15c-4dee', 'name': 'my test site', 'latitude': 35.97812, 'longitude': -118.339086, 'capacity': 1000, 'capacity_dc': 1200, 'tracking_type': 'horizontal_single_axis', 'install_date': '2024-02-13T00:00:00.0000000Z', 'module_type': 'poly-si', 'ground_coverage_ratio': 0.36, 'derating_temp_module': 0.0039, 'derating_age_system': 0.0059, 'derating_other_system': 0.0175, 'inverter_peak_efficiency': 0.985, 'tracker_axis_azimuth': 0, 'tracker_max_rotation_angle': 60, 'tracker_back_tracking': True, 'tracker_smart_tracking': False, 'terrain_slope': 0, 'terrain_azimuth': 0, 'dust_soiling_average': [0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015], 'bifacial_system': False, 'site_ground_albedo': 0.25, 'bifaciality_factor': 0.7, 'pvrow_height': 1.5, 'pvrow_width': 2, 'is_unmetered': False}
Power Timeseries and Adjusting the Site's Configuration¶
We can use the resource_id
to obtain a timeseries of PV power modelled based on the specifications of the site. For instance, the following will give estimates for the last 7 days.
resource_id = metadata["resource_id"]
timeseries = {}
# NOTE: this will consume an API request!
res = live.advanced_pv_power(resource_id)
timeseries["initial"] = res.to_pandas()
timeseries["initial"].plot(figsize=[15, 4])
<Axes: xlabel='period_end'>
We can adjust the configuration of our site using pv_power_sites.patch_pv_power_site
. You can see definitions of the various available parameters in the Advanced PV Power documentation. Let's say we know our site has bifacial panels and that the tracker axis is oriented 10 degrees from north towards the east. We can adjust the site's settings accordingly.
res = pv_power_sites.patch_pv_power_site(
resource_id=resource_id,
bifacial_system=True,
tracker_axis_azimuth=-10,
)
res.to_dict()
{'resource_id': '94af-4847-f15c-4dee', 'name': 'my test site', 'latitude': 35.97812, 'longitude': -118.339086, 'capacity': 1000, 'capacity_dc': 1200, 'tracking_type': 'horizontal_single_axis', 'install_date': '2024-02-13T00:00:00.0000000Z', 'module_type': 'poly-si', 'ground_coverage_ratio': 0.36, 'derating_temp_module': 0.0039, 'derating_age_system': 0.0059, 'derating_other_system': 0.0175, 'inverter_peak_efficiency': 0.985, 'tracker_axis_azimuth': -10, 'tracker_max_rotation_angle': 60, 'tracker_back_tracking': True, 'tracker_smart_tracking': False, 'terrain_slope': 0, 'terrain_azimuth': 0, 'dust_soiling_average': [0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015], 'bifacial_system': True, 'site_ground_albedo': 0.25, 'bifaciality_factor': 0.7, 'pvrow_height': 1.5, 'pvrow_width': 2, 'is_unmetered': False, 'confirmed_metadata': '2024-02-20T23:01:38.9434961Z'}
# NOTE: this will consume an API request!
res = live.advanced_pv_power(resource_id)
timeseries["updated"] = res.to_pandas()
pd.concat(
timeseries.values(),
keys=timeseries.keys(),
axis="columns",
names=["Version", "Parameter"]
).plot(figsize=[15, 4])
<Axes: xlabel='period_end'>
Adjusting Advanced PV Power Settings¶
As well as being able to adjust the configuration of your PV site, you can also modify other aspects of the power model through settings provided to the advanced_pv_power
endpoint. This can be useful for responding to operational changes. We will give a snow soiling example, but there are also other adjustments that can be made, such as to apply dust soiling, constraints, reduced availability and inactive trackers.
Snow Soiling¶
In the example shown here, say our observed production reached 640 kW on the last day. It turns out that there was snow at this location in the last few days, and the PV model by default applies a snow soiling adjustment in these conditions. However, we know that we have cleared the snow off our panels. By turning off the snow soiling in the PV model as follows, we get estimates which now match our observed peak production.
# NOTE: this will consume an API request!
res = live.advanced_pv_power(resource_id, apply_snow_soiling=0)
timeseries["no snow soiling"] = res.to_pandas()
pd.concat(
timeseries.values(),
keys=timeseries.keys(),
axis="columns",
names=["Version", "Parameter"]
).plot(figsize=[15, 4])
<Axes: xlabel='period_end'>
Direct Comparison to Measurements¶
If you have a timeseries of near real-time measurements, you can use these for comparison with the pv_power_advanced estimates and to assist with fine-tuning PV Site configuration. When using measurements, it is important to correctly time-align the data and perform quality control. These example notebooks suggest some approaches for irradiance, many of which are applicable to PV power as well:
- 3.1 Comparing to Measurements: Timezone and Time Period alignment
- 3.2 Comparing to Measurements [GHI]: Quality Controlling and Gap Filling Measurements with Solcast Actuals
An additional factor for PV power is curtailment of generation, where the maximum output of the PV plant is capped for a period due to market regulations. If generation is curtailed for the entire time period, this can be included in the PV model via the apply_constraint
PV model setting. If only some sub-periods are curtailed, those periods should be excluded from comparison.