WEC-Grid
    • IntroductionIntroductionIntroduction
    • Software Design
    • Installation
    • Engine
        • Base
        • Grid State
        • PSS/E
        • PyPSA
        • Runner
      • WEC Module
      • WEC Farm
      • WEC Device
      • Database
      • Time
      • Plot
      • Example 1
      • Example 2
      • Example 3
        • Multiple WEC-Farm with load curve
        • Apply the WEC-Farms
        • Review WEC-Farm / WEC-Device Data
        • Review Grid data
        • Run Time Series Simulation
        • Lets review our solve report first
        • Analyze and Visualize Results
      • Example 4
      • Grid Models
      • WEC Models
      • Database
    • API Reference
    • Troubleshooting
    • Citation
GitHub
« Previous
Next »
WEC-Grid
  • Examples & Data »
  • Jupyter notebooks

Example 3¶

Multiple WEC-Farm with load curve¶

This notebook demonstrates applying Multiple WEC-Farm configurations:

  • Setting up a grid system with 3 WEC farms
  • Reviewing Load curve
  • Running time-domain simulations
  • Analyzing WEC performance and grid impact

This example uses the IEEE 39 case system with wave energy converters and load curve.

In [1]:
Copied!
import wecgrid

example3 = wecgrid.Engine()

example3.case("./grid_models/IEEE_39_bus.raw")
example3.load(["pypsa","psse"])
import wecgrid example3 = wecgrid.Engine() example3.case("./grid_models/IEEE_39_bus.raw") example3.load(["pypsa","psse"])
PSS®E software initialized

Apply the WEC-Farms¶

Lets create 3 WEC Farm. Two of the Farms will have 10 RM3 devices each, while the fourth will have 10 LUPA devices. The LUPA simulation data was pulled from the pre-loaded WEC-Grid database found here. Specifics about the LUPA run can be found in the documentation.

In [2]:
Copied!
#Information about the wec-sim runs in database can accessed using 
example3.database.wecsim_runs()
#Information about the wec-sim runs in database can accessed using example3.database.wecsim_runs()
Out[2]:
wec_sim_id model_type sim_duration_sec delta_time wave_height_m wave_period_sec wave_spectrum wave_class wave_seed simulation_hash created_at
0 2 LUPA 86400.0 0.1 2.5 8.0 PM irregular 8 LUPA_2.5m_8.0s_8 2025-08-19 19:59:49
1 1 RM3 86400.0 0.1 2.5 8.0 PM irregular 94 RM3_2.5m_8.0s_94 2025-08-19 19:45:01
In [3]:
Copied!
###### RM3 Farm 
example3.apply_wec(
   farm_name = "RM3-FARM",
   size = 10, 
   wec_sim_id = 1,
   bus_location=40, # create a new bus for farm  
   connecting_bus = 39, 
)

###### RM3 Farm 2
example3.apply_wec(
   farm_name = "RM3-FARM2",
   size = 10, 
   wec_sim_id = 1,
   bus_location=41, # create a new bus for farm  
   connecting_bus = 25, 
)


###### LUPA Farm 
example3.apply_wec(
   farm_name = "LUPA-FARM",
   size = 10, 
   wec_sim_id = 2, # LUPA
   bus_location=42, # create a new bus for farm  
   connecting_bus = 29, # Connect to bus 1 or swing bus
)
###### RM3 Farm example3.apply_wec( farm_name = "RM3-FARM", size = 10, wec_sim_id = 1, bus_location=40, # create a new bus for farm connecting_bus = 39, ) ###### RM3 Farm 2 example3.apply_wec( farm_name = "RM3-FARM2", size = 10, wec_sim_id = 1, bus_location=41, # create a new bus for farm connecting_bus = 25, ) ###### LUPA Farm example3.apply_wec( farm_name = "LUPA-FARM", size = 10, wec_sim_id = 2, # LUPA bus_location=42, # create a new bus for farm connecting_bus = 29, # Connect to bus 1 or swing bus )
WEC Farm added: RM3-FARM
WEC Farm added: RM3-FARM2
WEC Farm added: LUPA-FARM

Review WEC-Farm / WEC-Device Data¶

In [4]:
Copied!
# Farm Data
WECFarms = example3.wec_farms # list 

RM3_Farm_1 = WECFarms[0]
LUPA_Farm_1 = WECFarms[1]
print(RM3_Farm_1)
print(LUPA_Farm_1)
# Farm Data WECFarms = example3.wec_farms # list RM3_Farm_1 = WECFarms[0] LUPA_Farm_1 = WECFarms[1] print(RM3_Farm_1) print(LUPA_Farm_1)
WECFarm:
        ├─ name: 'RM3-FARM'
        ├─ size: 10
        ├─ model: 'RM3'
        ├─ bus_location: 40
        ├─ connecting_bus: 39
        └─ sim_id: 1

        Base: 100.0 MVA

    
WECFarm:
        ├─ name: 'RM3-FARM2'
        ├─ size: 10
        ├─ model: 'RM3'
        ├─ bus_location: 41
        ├─ connecting_bus: 25
        └─ sim_id: 1

        Base: 100.0 MVA

    
In [5]:
Copied!
# WEC Device Data (RM3)
RM3_WEC = RM3_Farm_1.wec_devices[0]
print(RM3_WEC)
print(RM3_WEC.dataframe.head())

RM3_WEC.dataframe.plot("time", "p", title= "Active Power - RM3",ylabel='pu', xlabel='time(s)')
RM3_WEC.dataframe.plot("time", "eta", title= "Wave Elevation - RM3", ylabel='meters',xlabel='time(s)')
# WEC Device Data (RM3) RM3_WEC = RM3_Farm_1.wec_devices[0] print(RM3_WEC) print(RM3_WEC.dataframe.head()) RM3_WEC.dataframe.plot("time", "p", title= "Active Power - RM3",ylabel='pu', xlabel='time(s)') RM3_WEC.dataframe.plot("time", "eta", title= "Wave Elevation - RM3", ylabel='meters',xlabel='time(s)')
WECDevice:
    ├─ name: 'RM3_1_0'
    ├─ model: 'RM3'
    ├─ bus_location: 40
    ├─ sim_id: 1
    └─ rows: 288
    
                     time         p    q       eta
snapshots                                         
2025-08-31 00:00:00   300  0.000135  0.0 -0.003430
2025-08-31 00:05:00   600  0.000135  0.0 -0.003430
2025-08-31 00:10:00   900  0.000197  0.0  0.002427
2025-08-31 00:15:00  1200  0.000192  0.0  0.001373
2025-08-31 00:20:00  1500  0.000151  0.0  0.000987
Out[5]:
<AxesSubplot:title={'center':'Wave Elevation - RM3'}, xlabel='time(s)', ylabel='meters'>
No description has been provided for this image
No description has been provided for this image
In [6]:
Copied!
# WEC Device Data (RM3)
LUPA_WEC = LUPA_Farm_1.wec_devices[0]
print(LUPA_WEC)
print(LUPA_WEC.dataframe.head())

LUPA_WEC.dataframe.plot("time", "p", title= "Active Power - LUPA",ylabel='pu', xlabel='time(s)')
LUPA_WEC.dataframe.plot("time", "eta", title= "Wave Elevation", ylabel='meters',xlabel='time(s)')
# WEC Device Data (RM3) LUPA_WEC = LUPA_Farm_1.wec_devices[0] print(LUPA_WEC) print(LUPA_WEC.dataframe.head()) LUPA_WEC.dataframe.plot("time", "p", title= "Active Power - LUPA",ylabel='pu', xlabel='time(s)') LUPA_WEC.dataframe.plot("time", "eta", title= "Wave Elevation", ylabel='meters',xlabel='time(s)')
WECDevice:
    ├─ name: 'RM3_1_0'
    ├─ model: 'RM3'
    ├─ bus_location: 41
    ├─ sim_id: 1
    └─ rows: 288
    
                     time         p    q       eta
snapshots                                         
2025-08-31 00:00:00   300  0.000135  0.0 -0.003430
2025-08-31 00:05:00   600  0.000135  0.0 -0.003430
2025-08-31 00:10:00   900  0.000197  0.0  0.002427
2025-08-31 00:15:00  1200  0.000192  0.0  0.001373
2025-08-31 00:20:00  1500  0.000151  0.0  0.000987
Out[6]:
<AxesSubplot:title={'center':'Wave Elevation'}, xlabel='time(s)', ylabel='meters'>
No description has been provided for this image
No description has been provided for this image

Review Grid data¶

In [7]:
Copied!
grid = example3.pypsa.grid
grid
grid = example3.pypsa.grid grid
Out[7]:
GridState:
├─ Components:
│   ├─ bus:   42 components
│   ├─ gen:   13 components
│   ├─ line:  37 components
│   └─ load:  31 components
├─ Case: IEEE 39 bus
└─ Modeler: pypsa
In [8]:
Copied!
example3.plot.sld() # not working well for this case
example3.plot.sld() # not working well for this case
SLD Data Summary:
  Buses: 42
  Lines: 37
  Generators: 13
  Loads: 31
No description has been provided for this image
In [9]:
Copied!
load_curves = example3.generate_load_curves()
load_curves.plot(ylabel='pu', title='Load Curves for All Buses', legend=False)
load_curves = example3.generate_load_curves() load_curves.plot(ylabel='pu', title='Load Curves for All Buses', legend=False)
Out[9]:
<AxesSubplot:title={'center':'Load Curves for All Buses'}, xlabel='time', ylabel='pu'>
No description has been provided for this image

Run Time Series Simulation¶

In [10]:
Copied!
example3.simulate(load_curve=True) # takes some time!
example3.pypsa.report
example3.simulate(load_curve=True) # takes some time! example3.pypsa.report
PSS®E Simulating:   0%|          | 1/288 [00:00<01:02,  4.57step/s]
PSS®E Simulating: 100%|██████████| 288/288 [00:55<00:00,  5.15step/s]
PyPSA Simulating: 100%|██████████| 288/288 [03:09<00:00,  1.52step/s]
Out[10]:
SolveReport:
├─ Converged: Successful
├─ Simulation Time: 189.40 s
├─ Num Steps: 288
├─ Case: IEEE 39 bus
└─ Modeler: pypsa

Lets review our solve report first¶

In [ ]:
Copied!
report = example3.pypsa.report.dataframe
report
report = example3.pypsa.report.dataframe report
Out[ ]:
iter_time converged pf_solve_time pf_solve_iter snapshot_time snapshot message
0 0.640627 1 0.437494 4 0.203133 2025-08-31 00:00:00 converged
1 0.625019 1 0.421890 4 0.203129 2025-08-31 00:05:00 converged
2 0.640651 1 0.421881 4 0.203135 2025-08-31 00:10:00 converged
3 0.640644 1 0.437521 4 0.203123 2025-08-31 00:15:00 converged
4 0.765651 1 0.562525 4 0.203126 2025-08-31 00:20:00 converged
... ... ... ... ... ... ... ...
283 0.625022 1 0.421889 4 0.203133 2025-08-31 23:35:00 converged
284 0.640640 1 0.421882 4 0.218758 2025-08-31 23:40:00 converged
285 0.625014 1 0.421882 4 0.203132 2025-08-31 23:45:00 converged
286 0.640640 1 0.406255 4 0.218755 2025-08-31 23:50:00 converged
287 0.625016 1 0.421888 4 0.203128 2025-08-31 23:55:00 converged

288 rows × 7 columns

In [19]:
Copied!
report.plot('snapshot', ['iter_time', 'pf_solve_time', 'snapshot_time'], xlabel='time', ylabel='seconds')
report.plot('snapshot', 'pf_solve_iter', xlabel='time', ylabel='iterations')
report.plot('snapshot', ['iter_time', 'pf_solve_time', 'snapshot_time'], xlabel='time', ylabel='seconds') report.plot('snapshot', 'pf_solve_iter', xlabel='time', ylabel='iterations')
Out[19]:
<AxesSubplot:xlabel='time', ylabel='iterations'>
No description has been provided for this image
No description has been provided for this image

Analyze and Visualize Results¶

Create comprehensive plots to analyze WEC performance and grid impact over time.

In [ ]:
Copied!
plot = example3.plot
plot.bus()
plot.bus(bus=['Bus_31']) # Swing Bus
plot.bus(bus=['Bus_40', 'Bus_41','Bus_42']) # WEC-Farm Buses
plot.bus(parameter='v_mag',bus=['Bus_40', 'Bus_41','Bus_42'])
plot = example3.plot plot.bus() plot.bus(bus=['Bus_31']) # Swing Bus plot.bus(bus=['Bus_40', 'Bus_41','Bus_42']) # WEC-Farm Buses plot.bus(parameter='v_mag',bus=['Bus_40', 'Bus_41','Bus_42'])
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
Out[ ]:
(<Figure size 1200x600 with 1 Axes>,
 <AxesSubplot:title={'center':'PYPSA: Bus Voltage Magnitude'}, xlabel='Time', ylabel='Voltage (pu)'>)
In [ ]:
Copied!
plot.wec_analysis()
plot.wec_analysis()
No description has been provided for this image
In [ ]:
Copied!

Previous
Next

Built with MkDocs using Ivory theme.