Skip to content

Commit

Permalink
Add external controls for solar PySAM module (#107)
Browse files Browse the repository at this point in the history
* Allow external power setpoints to be passed in; move handling of None setpoint to control() method.

* Add handling for possibility that py_sims not on the input dict.

* Add test for control setpoint passed.

* AMR wind speed collected in main_dict.
  • Loading branch information
misi9170 authored May 16, 2024
1 parent cb6e99a commit ad29cf8
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 12 deletions.
3 changes: 3 additions & 0 deletions hercules/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ def receive_amrwind_data(self):
self.main_dict["hercules_comms"]["amr_wind"][self.amr_wind_names[0]][
"wind_direction"
] = wind_direction_amr_wind
self.main_dict["hercules_comms"]["amr_wind"][self.amr_wind_names[0]][
"wind_speed"
] = wind_speed_amr_wind

return None

Expand Down
27 changes: 15 additions & 12 deletions hercules/python_simulators/solar_pysam.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def return_outputs(self):
"aoi": self.aoi,
}

def control(self, power_setpoint_mw):
def control(self, power_setpoint_mw=None):
"""
Low-level controller to enforce PV plant power setpoints
Notes:
Expand All @@ -79,10 +79,13 @@ def control(self, power_setpoint_mw):
- power_setpoint_mw: [MW] the desired total PV plant output
"""
# modify power output based on setpoint
if self.power_mw > power_setpoint_mw:
self.power_mw = power_setpoint_mw
# Keep track of power that could go to charging battery
self.excess_power = self.power_mw - power_setpoint_mw
if power_setpoint_mw is not None:
print('power_setpoint = ', power_setpoint_mw)
if self.power_mw > power_setpoint_mw:
self.power_mw = power_setpoint_mw
# Keep track of power that could go to charging battery
self.excess_power = self.power_mw - power_setpoint_mw
print('self.power_mw after control = ',self.power_mw)

def step(self, inputs):
# print('-------------------')
Expand Down Expand Up @@ -158,15 +161,15 @@ def step(self, inputs):
# self.dc_power_mw = dc[0]
print("self.power_mw = ", self.power_mw)

# print("inputs[external_signals]",inputs["external_signals"])
if "external_signals" in inputs.keys():
# Apply control, if setpoint is provided
if "py_sims" in inputs and "solar_setpoint_mw" in inputs["py_sims"]["inputs"]:
P_setpoint = inputs["py_sims"]["inputs"]["solar_setpoint_mw"]
elif "external_signals" in inputs.keys():
if "solar_power_reference_mw" in inputs["external_signals"].keys():
P_setpoint = inputs["external_signals"]["solar_power_reference_mw"]
print('power_setpoint = ',P_setpoint)

self.control(P_setpoint)

print('self.power_mw after control = ',self.power_mw)
else:
P_setpoint = None
self.control(P_setpoint)

if self.power_mw < 0.0:
self.power_mw = 0.0
Expand Down
6 changes: 6 additions & 0 deletions tests/python_simulators_test/solar_pysam_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,9 @@ def test_step(SPS: SolarPySAM):
assert_almost_equal(SPS.power_mw, 32.17650018440107, decimal=8)
# assert_almost_equal(SPS.dc_power_mw, 33.26240852125279, decimal=8)
assert_almost_equal(SPS.ghi, 68.23037719726561, decimal=8)

def test_control(SPS: SolarPySAM):
power_setpoint_mw = 30
step_inputs = {"time": 0, "py_sims": {"inputs": {"solar_setpoint_mw": power_setpoint_mw}}}
SPS.step(step_inputs)
assert_almost_equal(SPS.power_mw, power_setpoint_mw, decimal=8)

0 comments on commit ad29cf8

Please sign in to comment.