Skip to content

Commit

Permalink
Merge pull request NREL#354 from Bartdoekemeijer/feature/wfc_controll…
Browse files Browse the repository at this point in the history
…er_as_class

Feature: Change wfc_controller from function to a class to allow access to all turbine signals and memory
  • Loading branch information
abhineet-gupta authored Jun 13, 2024
2 parents e95511c + 37788a5 commit c3c2296
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 31 deletions.
10 changes: 8 additions & 2 deletions Examples/17a_zeromq_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ def run_zmq(logfile=None):
server = wfc_zmq_server(network_address, timeout=60.0, verbose=False, logfile=logfile)

# Provide the wind farm control algorithm as the wfc_controller method of the server
server.wfc_controller = wfc_controller
server.wfc_controller = wfc_controller()

# Run the server to receive measurements and send setpoints
server.runserver()

def wfc_controller(id,current_time,measurements):
class wfc_controller():
def __init__(self):
return None

def update(self, id,current_time,measurements):
if current_time <= 10.0:
yaw_setpoint = 0.0
else:
Expand All @@ -62,8 +66,10 @@ def wfc_controller(id,current_time,measurements):
setpoints['ZMQ_PitOffset(1)'] = col_pitch_command
setpoints['ZMQ_PitOffset(2)'] = col_pitch_command
setpoints['ZMQ_PitOffset(3)'] = col_pitch_command

return setpoints


def sim_rosco():
# Load yaml file
this_dir = os.path.dirname(os.path.abspath(__file__))
Expand Down
60 changes: 32 additions & 28 deletions Examples/17b_zeromq_multi_openfast.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,44 @@ def run_zmq(logfile=None):
server = wfc_zmq_server(network_address, timeout=60.0, verbose=False, logfile = logfile)

# Provide the wind farm control algorithm as the wfc_controller method of the server
server.wfc_controller = wfc_controller
server.wfc_controller = wfc_controller()

# Run the server to receive measurements and send setpoints
server.runserver()


def wfc_controller(id, current_time, measurements):
"""
Users needs to define this function to implement wind farm controller.
The user defined function should take as argument the turbine id, the
current time and current measurements and return the setpoints
for the particular turbine for the current time. It should ouput the
setpoints as a dictionary whose keys should be as defined in
wfc_zmq_server.wfc_interface. The wfc_controller method of the wfc_zmq_server
should be overwriten with this fuction, otherwise, an exception is raised and
the simulation stops.
"""
if current_time <= 10.0:
YawOffset = 0.0
col_pitch_command = 0.0
else:
col_pitch_command = np.deg2rad(2) * np.sin(0.1 * current_time) + np.deg2rad(2) # Implement dynamic induction control
if id == 1:
YawOffset = DESIRED_YAW_OFFSET[0]
class wfc_controller():
def __init__(self):
return None

def update(self, id, current_time, measurements):
"""
Users needs to define this function to implement wind farm controller.
The user defined function should take as argument the turbine id, the
current time and current measurements and return the setpoints
for the particular turbine for the current time. It should ouput the
setpoints as a dictionary whose keys should be as defined in
wfc_zmq_server.wfc_interface. The wfc_controller method of the wfc_zmq_server
should be overwriten with this fuction, otherwise, an exception is raised and
the simulation stops.
"""
if current_time <= 10.0:
YawOffset = 0.0
col_pitch_command = 0.0
else:
YawOffset = DESIRED_YAW_OFFSET[1]


setpoints = {}
setpoints["ZMQ_YawOffset"] = YawOffset
setpoints['ZMQ_PitOffset(1)'] = col_pitch_command
setpoints['ZMQ_PitOffset(2)'] = col_pitch_command
setpoints['ZMQ_PitOffset(3)'] = col_pitch_command
return setpoints
col_pitch_command = np.deg2rad(2) * np.sin(0.1 * current_time) + np.deg2rad(2) # Implement dynamic induction control
if id == 1:
YawOffset = DESIRED_YAW_OFFSET[0]
else:
YawOffset = DESIRED_YAW_OFFSET[1]


setpoints = {}
setpoints["ZMQ_YawOffset"] = YawOffset
setpoints['ZMQ_PitOffset(1)'] = col_pitch_command
setpoints['ZMQ_PitOffset(2)'] = col_pitch_command
setpoints['ZMQ_PitOffset(3)'] = col_pitch_command
return setpoints


def sim_openfast_1():
Expand Down
2 changes: 1 addition & 1 deletion rosco/toolbox/control_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def _get_setpoints(self, id, measurements):
logger.debug(
f"Asking wfc_controller for setpoints at time = {current_time} for id = {id}"
)
setpoints = self.wfc_controller(id, current_time, measurements)
setpoints = self.wfc_controller.update(id, current_time, measurements)
logger.info(f"Received setpoints {setpoints} from wfc_controller for time = {current_time} and id = {id}")

for s in self.wfc_interface["setpoints"]:
Expand Down

0 comments on commit c3c2296

Please sign in to comment.