Solar PV Simulation Workflow#

This example shows the different results of the different PV simulation workflows

Workflow:

  1. Import required packages

  2. Create locations DataFrame for single location

  3. Run simulation for single location

  4. Plot Capacity factor for single location

  5. Computate single location, only using ERA5 weather data

  6. Computate single location with Tracking

  7. Simulate multiple locations

import reskit as rk
import pandas as pd

import matplotlib.pyplot as plt

%matplotlib inline

Single Location based on Sarah and ERA5 Data.#

# Make a dataframe for a single placement
placements = pd.DataFrame()
placements["lon"] = [
    6.083,
]  # Longitude
placements["lat"] = [
    50.775,
]  # Latitude
placements["tilt"] = [
    32,
]  # System tilt in degrees
placements["azimuth"] = [
    180,
]  # System azimuth in degrees
placements["capacity"] = [
    2000,
]  # Total system capacity in kW
placements["elev"] = [
    250,
]  # Altitude in meters

placements
lon lat tilt azimuth capacity elev
0 6.083 50.775 32 180 2000 250
out = rk.solar.openfield_pv_sarah_unvalidated(
    placements=placements,
    sarah_path=rk.TEST_DATA["sarah-like"],
    era5_path=rk.TEST_DATA["era5-like"],
    module="WINAICO WSx-240P6",  # PV module to use for simulation
)

print("Output is of type:", type(out))
print("Variables in output:")
for i, var in enumerate(list(out.variables)):
    print(" {i:2d}: {name:30s} - Dimensions:{dim}".format(i=i, name=var, dim=out[var].dims))
Output is of type: <class 'xarray.core.dataset.Dataset'>
Variables in output:
  0: location                       - Dimensions:('location',)
  1: lon                            - Dimensions:('location',)
  2: lat                            - Dimensions:('location',)
  3: tilt                           - Dimensions:('location',)
  4: azimuth                        - Dimensions:('location',)
  5: capacity                       - Dimensions:('location',)
  6: elev                           - Dimensions:('location',)
  7: time                           - Dimensions:('time',)
  8: direct_normal_irradiance       - Dimensions:('time', 'location')
  9: global_horizontal_irradiance   - Dimensions:('time', 'location')
 10: surface_wind_speed             - Dimensions:('time', 'location')
 11: surface_pressure               - Dimensions:('time', 'location')
 12: surface_air_temperature        - Dimensions:('time', 'location')
 13: surface_dew_temperature        - Dimensions:('time', 'location')
 14: solar_azimuth                  - Dimensions:('time', 'location')
 15: apparent_solar_zenith          - Dimensions:('time', 'location')
 16: extra_terrestrial_irradiance   - Dimensions:('time', 'location')
 17: air_mass                       - Dimensions:('time', 'location')
 18: diffuse_horizontal_irradiance  - Dimensions:('time', 'location')
 19: angle_of_incidence             - Dimensions:('time', 'location')
 20: poa_global                     - Dimensions:('time', 'location')
 21: poa_direct                     - Dimensions:('time', 'location')
 22: poa_diffuse                    - Dimensions:('time', 'location')
 23: poa_sky_diffuse                - Dimensions:('time', 'location')
 24: poa_ground_diffuse             - Dimensions:('time', 'location')
 25: cell_temperature               - Dimensions:('time', 'location')
 26: module_dc_power_at_mpp         - Dimensions:('time', 'location')
 27: module_dc_voltage_at_mpp       - Dimensions:('time', 'location')
 28: capacity_factor                - Dimensions:('time', 'location')
 29: total_system_generation        - Dimensions:('time', 'location')
# Plot of the capacity factor time series for the single placement
out.capacity_factor.plot()
[<matplotlib.lines.Line2D at 0x71074aae32c0>]
../../_images/33f484e6cae5a55691f80b0be70adffcbaa3e722ed71c1ec1a4ab1bb11c92568.png

Simulate single location, but only using ERA-5#

out = rk.solar.openfield_pv_era5(
    placements=placements,
    era5_path=rk.TEST_DATA["era5-like"],
    global_solar_atlas_ghi_path=rk.TEST_DATA["gsa-ghi-like.tif"],
    global_solar_atlas_dni_path=rk.TEST_DATA["gsa-dni-like.tif"],
    module="WINAICO WSx-240P6",  # PV module to use for simulation
)

print("Output is of type:", type(out))
print("Variables in output:")
for i, var in enumerate(list(out.variables)):
    print(" {i:2d}: {name:30s} - Dimensions:{dim}".format(i=i, name=var, dim=out[var].dims))
Output is of type: <class 'xarray.core.dataset.Dataset'>
Variables in output:
  0: location                       - Dimensions:('location',)
  1: lon                            - Dimensions:('location',)
  2: lat                            - Dimensions:('location',)
  3: tilt                           - Dimensions:('location',)
  4: azimuth                        - Dimensions:('location',)
  5: capacity                       - Dimensions:('location',)
  6: elev                           - Dimensions:('location',)
  7: LRA_factor_global_horizontal_irradiance - Dimensions:('location',)
  8: LRA_factor_direct_normal_irradiance - Dimensions:('location',)
  9: time                           - Dimensions:('time',)
 10: global_horizontal_irradiance   - Dimensions:('time', 'location')
 11: direct_horizontal_irradiance   - Dimensions:('time', 'location')
 12: surface_wind_speed             - Dimensions:('time', 'location')
 13: surface_pressure               - Dimensions:('time', 'location')
 14: surface_air_temperature        - Dimensions:('time', 'location')
 15: surface_dew_temperature        - Dimensions:('time', 'location')
 16: solar_azimuth                  - Dimensions:('time', 'location')
 17: apparent_solar_zenith          - Dimensions:('time', 'location')
 18: direct_normal_irradiance       - Dimensions:('time', 'location')
 19: extra_terrestrial_irradiance   - Dimensions:('time', 'location')
 20: air_mass                       - Dimensions:('time', 'location')
 21: diffuse_horizontal_irradiance  - Dimensions:('time', 'location')
 22: angle_of_incidence             - Dimensions:('time', 'location')
 23: poa_global                     - Dimensions:('time', 'location')
 24: poa_direct                     - Dimensions:('time', 'location')
 25: poa_diffuse                    - Dimensions:('time', 'location')
 26: poa_sky_diffuse                - Dimensions:('time', 'location')
 27: poa_ground_diffuse             - Dimensions:('time', 'location')
 28: cell_temperature               - Dimensions:('time', 'location')
 29: module_dc_power_at_mpp         - Dimensions:('time', 'location')
 30: module_dc_voltage_at_mpp       - Dimensions:('time', 'location')
 31: capacity_factor                - Dimensions:('time', 'location')
 32: total_system_generation        - Dimensions:('time', 'location')
out.capacity_factor.fillna(0).plot()
[<matplotlib.lines.Line2D at 0x71074ac7e8a0>]
../../_images/97c176d07d0784e874fa8c178a5746e6afe76f3fc2571934ed3d372c6f538d3e.png

Single Location with Tracking#

out = rk.solar.openfield_pv_era5(
    placements=placements,
    era5_path=rk.TEST_DATA["era5-like"],
    global_solar_atlas_ghi_path=rk.TEST_DATA["gsa-ghi-like.tif"],
    global_solar_atlas_dni_path=rk.TEST_DATA["gsa-dni-like.tif"],
    module="WINAICO WSx-240P6",  # Module to use for simulation
    tracking="single_axis",
)
out.capacity_factor.fillna(0).plot()
[<matplotlib.lines.Line2D at 0x710749194380>]
../../_images/f8dff6e91d4d516f84aafdf1030bc5ad8d61b81cb2be9b553f1c0d41301cb496.png

Simulating multiple locations is the same as simulating a single location#

  • It is recommended to simulate multiple locations at once!

# Make a placements dataframe with multiple locations
placements = pd.DataFrame()
placements["lon"] = [
    6.083,
    6.090,
    6.095,
    6.100,
    6.105,
]  # Longitude
placements["lat"] = [
    50.775,
    50.780,
    50.785,
    50.790,
    50.795,
]  # Latitude
placements["tilt"] = [
    32,
    25,
    20,
    35,
    40,
]  # System tilt in degrees
placements["azimuth"] = [
    180,
    180,
    180,
    180,
    180,
]  # System azimuth in degrees
placements["capacity"] = [
    2000,
    2000,
    2000,
    2000,
    2000,
]  # Total system capacity in kW
placements["elev"] = [
    250,
    300,
    350,
    1000,
    -100,
]  # Altitude in meters

placements
lon lat tilt azimuth capacity elev
0 6.083 50.775 32 180 2000 250
1 6.090 50.780 25 180 2000 300
2 6.095 50.785 20 180 2000 350
3 6.100 50.790 35 180 2000 1000
4 6.105 50.795 40 180 2000 -100
# Run simulation with ERA5 workflow
out = rk.solar.openfield_pv_era5(
    placements=placements,
    era5_path=rk.TEST_DATA["era5-like"],
    global_solar_atlas_ghi_path=rk.TEST_DATA["gsa-ghi-like.tif"],
    global_solar_atlas_dni_path=rk.TEST_DATA["gsa-dni-like.tif"],
    module="WINAICO WSx-240P6",  # Module to use for simulation
)
# Same plot as in single examples, but now for multiple placements
plt.figure(figsize=(6, 4))
for i in range(placements.shape[0]):
    out.capacity_factor[:, i].fillna(0).plot(label=i)

plt.legend(ncol=3, title="Placement ID")
plt.title("Capacity Factor Generation")
plt.show()

# Same Plot function as in single examples
out.capacity_factor.fillna(0).plot()
../../_images/8f73bfba633c7bde04d7d6d47ff818aa58c090ee08c229411e601b1589618898.png
<matplotlib.collections.QuadMesh at 0x7107491c9d00>
../../_images/f9c98296f0ab8fc356f84ed8a02140c2ca1adac9a0a9982a7359c2d92f039cee.png