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"])
import wecgrid
example3 = wecgrid.Engine()
example3.case("./grid_models/IEEE_39_bus.raw")
example3.load(["pypsa"])
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-09-06 00:00:00 300 0.000135 0.0 -0.003430 2025-09-06 00:05:00 600 0.000135 0.0 -0.003430 2025-09-06 00:10:00 900 0.000197 0.0 0.002427 2025-09-06 00:15:00 1200 0.000192 0.0 0.001373 2025-09-06 00:20:00 1500 0.000151 0.0 0.000987
Out[5]:
<AxesSubplot:title={'center':'Wave Elevation - RM3'}, xlabel='time(s)', ylabel='meters'>
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-09-06 00:00:00 300 0.000135 0.0 -0.003430 2025-09-06 00:05:00 600 0.000135 0.0 -0.003430 2025-09-06 00:10:00 900 0.000197 0.0 0.002427 2025-09-06 00:15:00 1200 0.000192 0.0 0.001373 2025-09-06 00:20:00 1500 0.000151 0.0 0.000987
Out[6]:
<AxesSubplot:title={'center':'Wave Elevation'}, xlabel='time(s)', ylabel='meters'>
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 [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)
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
PyPSA Simulating: 0%| | 0/288 [00:00<?, ?step/s]
PyPSA Simulating: 100%|āāāāāāāāāā| 288/288 [02:00<00:00, 2.38step/s]
Out[10]:
SolveReport: āā Converged: Successful āā Simulation Time: 120.86 s āā Num Steps: 288 āā Case: IEEE 39 bus āā Modeler: pypsa
Lets review our solve report first¶
In [11]:
Copied!
report = example3.pypsa.report.dataframe
report
report = example3.pypsa.report.dataframe
report
Out[11]:
iter_time | converged | pf_solve_time | pf_solve_iter | snapshot_time | snapshot | message | |
---|---|---|---|---|---|---|---|
0 | 0.507838 | 1 | 0.356890 | 4 | 0.143951 | 2025-09-06 00:00:00 | converged |
1 | 0.495973 | 1 | 0.350481 | 4 | 0.143494 | 2025-09-06 00:05:00 | converged |
2 | 0.492415 | 1 | 0.330468 | 4 | 0.160948 | 2025-09-06 00:10:00 | converged |
3 | 0.499115 | 1 | 0.320513 | 4 | 0.175604 | 2025-09-06 00:15:00 | converged |
4 | 0.877876 | 1 | 0.681783 | 4 | 0.192094 | 2025-09-06 00:20:00 | converged |
... | ... | ... | ... | ... | ... | ... | ... |
283 | 0.419026 | 1 | 0.303061 | 4 | 0.114963 | 2025-09-06 23:35:00 | converged |
284 | 0.515340 | 1 | 0.405365 | 4 | 0.108978 | 2025-09-06 23:40:00 | converged |
285 | 0.383005 | 1 | 0.256556 | 4 | 0.124436 | 2025-09-06 23:45:00 | converged |
286 | 0.417869 | 1 | 0.285910 | 4 | 0.129960 | 2025-09-06 23:50:00 | converged |
287 | 0.479465 | 1 | 0.348888 | 4 | 0.127578 | 2025-09-06 23:55:00 | converged |
288 rows Ć 7 columns
In [12]:
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')
Analyze and Visualize Results¶
Create comprehensive plots to analyze WEC performance and grid impact over time.
In [13]:
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'])
In [ ]:
Copied!