Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating controller to align with WHOC #41

Merged
merged 43 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
162d655
Skeleton for a turbine yaw simulator.
Feb 7, 2023
6910ea7
Implementation mostly in place.
Feb 8, 2023
86ea395
Merging in changes from develop branch.
Mar 28, 2023
c62b5cf
Simple yaw controller running on dummy. Need to make back compatible.
Mar 28, 2023
6036258
Handling case where no yaw simulator specified (or specified as none)
Mar 28, 2023
40d4117
Removing input_dict.echo from git repo. Can indo if needed.
Mar 28, 2023
c15ed2d
Removing previous, more realistic implementation that has not yet bee…
Mar 28, 2023
391becd
Clean up commit.
Mar 30, 2023
e8e62fc
Updating for new dummyamr wind
Apr 13, 2023
cdb9d93
Running, but seems theres a timing issue.
Apr 13, 2023
8b0638b
Small updates to installation procedure; also updated intstuctions fo…
Apr 19, 2023
360576a
Updates to allow example_06 to run
misi9170 Apr 20, 2023
45bee5c
Merge branch 'feature/readme-update' into feature/yaw-simulator
misi9170 Apr 20, 2023
d3dde26
Renaming dummy example for clarity.
misi9170 Apr 20, 2023
0b2ce14
Reverting; plan to use one directory only, if possible.
misi9170 Apr 20, 2023
fd96a1b
Runs on eagle and local.
misi9170 Apr 20, 2023
c36a148
Revert, take 2.
misi9170 Apr 20, 2023
ea7c517
Removing old yaw simulator from pysims.
Apr 21, 2023
7b83aa5
Removing temporary examples.
Apr 21, 2023
495d0b5
Merging in develop; likely not running.
misi9170 Jul 14, 2023
3102e5c
Starting renaming to hercules.
misi9170 Jul 14, 2023
017b696
More name updates.
misi9170 Jul 14, 2023
7f1d212
Cleaning up, renaming more.
misi9170 Jul 15, 2023
7512b33
AMR wind version now runs.
misi9170 Jul 21, 2023
9083cd8
Removing controller.py in favor of controllers/controller_base.py
misi9170 Jul 21, 2023
0aca070
Switching helicsport (not sure if needed?)
Jul 23, 2023
e7364cc
Updates to read in time step.
Jul 26, 2023
98e93b1
Reorganizing emulator somewhat to allow clearer execution of main loo…
Jul 26, 2023
3d0b8fa
Commiting to change branch.
Dec 6, 2023
8c3e911
Removing unneded controllers in favor of whoc.
Dec 8, 2023
8078d97
Emulator controller set up as desired; still tbd where time should co…
Dec 8, 2023
03ff765
Adding back a pass-through controller in case WHOC not available.
Dec 8, 2023
a999f89
Replacing controllers/control_base with controller_standin.
Dec 8, 2023
5d38604
Adding comment about time issue.
Dec 8, 2023
8a8359f
Merge branch 'develop' into feature/controller
Dec 8, 2023
23f5c3f
Reinstating nominal yaw control in pass-through.
Dec 8, 2023
5f64aab
Add comments to explain temporary AD connection.
Dec 12, 2023
a36307b
Copying in old controller code for possible later use.
Dec 12, 2023
486e5f5
Aligning with develop branch.
Dec 12, 2023
5eab3a1
Add KAFKA code back in, commented out, in case needed later.
Dec 12, 2023
8c789ff
Changing helicsport to sidestep bug with not connecting on correct port.
Dec 12, 2023
a0d48ca
put sim_tim_s_amr_wind in emulator main_dict in init
Dec 12, 2023
e3861e6
Change back to 32000.
Dec 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ hercules/local_amr_wind_demo/sample_copy.nc
t_00*
logdummy
loghercules
*echo
*echo
2 changes: 1 addition & 1 deletion example_case_folders/01_amr_wind_only/batch_script.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ python3 hercules_runscript.py hercules_input_000.yaml >> loghercules 2>&1 & # S

# Now go back to scratch folder and launch the job
# cd /scratch/pfleming/c2c/example_sim_02
mpirun -n 72 /home/pfleming/amr-wind/build/amr_wind amr_input.inp >> logamr 2>&1
mpirun -n 72 /home/pfleming/amr-wind/build/amr_wind amr_input.inp >> logamr 2>&1
4 changes: 2 additions & 2 deletions example_case_folders/01_amr_wind_only/hercules_runscript.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hercules.emulator import Emulator
from hercules.controller import Controller
from hercules.controller_standin import ControllerStandin
from hercules.py_sims import PySims
from hercules.utilities import load_yaml

Expand All @@ -9,7 +9,7 @@

input_dict = load_yaml(sys.argv[1])

controller = Controller(input_dict)
controller = ControllerStandin(input_dict)
py_sims = PySims(input_dict)


Expand Down
2 changes: 1 addition & 1 deletion example_case_folders/02_amr_wind_dummy_only/amr_input.inp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ ABL.stats_output_format = netcdf

# Whether to use helics
helics.activated = true
helics.broker_port =32000
helics.broker_port = 32000

#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
# ADAPTIVE MESH REFINEMENT #
Expand Down
3 changes: 2 additions & 1 deletion example_case_folders/02_amr_wind_dummy_only/bash_script.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export HELICS_PORT=32000
#make sure you use the same port number in the amr_input.inp and hercules_input_000.yaml files.

# Set up the helics broker
helics_broker -f 2 --consoleloglevel=trace --loglevel=debug --local_port=$HELICS_PORT &
helics_broker -t zmq -f 2 --loglevel="debug" --local_port=$HELICS_PORT &
#helics_broker -f 2 --consoleloglevel=trace --loglevel=debug --local_port=$HELICS_PORT >> loghelics &

# Need to set this to your hercules folder
# cd /home/pfleming/hercules/hercules
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hercules.emulator import Emulator
from hercules.controller import Controller
from hercules.controller_standin import ControllerStandin
from hercules.py_sims import PySims
from hercules.utilities import load_yaml

Expand All @@ -10,7 +10,7 @@
input_dict = load_yaml(sys.argv[1])


controller = Controller(input_dict)
controller = ControllerStandin(input_dict)
py_sims = PySims(input_dict)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hercules.emulator import Emulator
from hercules.controller import Controller
from hercules.controller_standin import ControllerStandin
from hercules.py_sims import PySims
from hercules.utilities import load_yaml

Expand All @@ -9,7 +9,7 @@

input_dict = load_yaml(sys.argv[1])

controller = Controller(input_dict)
controller = ControllerStandin(input_dict)
py_sims = PySims(input_dict)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hercules.emulator import Emulator
from hercules.controller import Controller
from hercules.controller_standin import ControllerStandin
from hercules.py_sims import PySims
from hercules.utilities import load_yaml

Expand All @@ -9,7 +9,7 @@

input_dict = load_yaml(sys.argv[1])

controller = Controller(input_dict)
controller = ControllerStandin(input_dict)
py_sims = PySims(input_dict)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from hercules.emulator import Emulator
from hercules.controller import Controller
from hercules.controller_standin import ControllerStandin
from hercules.py_sims import PySims
from hercules.utilities import load_yaml

Expand All @@ -10,7 +10,7 @@

input_dict = load_yaml(sys.argv[1])

controller = Controller(input_dict)
controller = ControllerStandin(input_dict)
py_sims = PySims(input_dict)


Expand Down
16 changes: 0 additions & 16 deletions hercules/controller.py

This file was deleted.

58 changes: 58 additions & 0 deletions hercules/controller_standin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from abc import abstractmethod

class ControllerStandin():
"""
This class is a pass-through stand-in for a plant-level controller.
Actual controllers should be implemented in WHOC
(https://github.com/NREL/wind-hybrid-open-controller). However, this
has been left in to allow users to run Hercules without plant-level
control, if desired.

This assumes Hercules is running with actuator disk turbine models, and
will be updated (to be simply a pass-through) when the ROSCO/FAST turbine
models are incorporated.
"""

def __init__(self, input_dict):

# Get wind farm information (assumes exactly one wind farm)
self.wf_name = list(input_dict["hercules_comms"]["amr_wind"].keys())[0]

@abstractmethod
def step(self, main_dict):

num_turbines = main_dict["hercules_comms"]\
["amr_wind"]\
[self.wf_name]\
["num_turbines"]

# Set turbine yaw angles based on current AMR-Wind wind direction
wd = main_dict["hercules_comms"]\
["amr_wind"]\
[self.wf_name]\
["wind_direction"]
main_dict["hercules_comms"]\
["amr_wind"]\
[self.wf_name]\
["turbine_yaw_angles"] = num_turbines*[wd]

# TODO: does there need to be a seperate "controller" dict?
# Might make understanding the log easier?
return main_dict


# Can uncomment the below and work on once the ROSCO/FAST connection is
# in place and we are no longer using actuator disks.

# class Controller():

# def __init__(self, input_dict):
# pass

# def step(self, main_dict):

# pass

# def get_controller_dict(self):

# return {}
45 changes: 38 additions & 7 deletions hercules/dummy_amr_wind.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ def read_amr_wind_input(amr_wind_input):
with open(amr_wind_input) as fp:
Lines = fp.readlines()

# Get the simulation time step
for line in Lines:
if 'time.fixed_dt' in line:
dt = float(line.split()[2])

# Find the actuators
for line in Lines:
if 'Actuator.labels' in line:
Expand All @@ -76,11 +81,18 @@ def read_amr_wind_input(amr_wind_input):
for f in line.split()[-3:-1]])
turbine_locations.append(locations)

# Get the helics port
for line in Lines:
if 'helics.broker_port' in line:
broker_port = int(line.split()[2])

return_dict = {
'dt':dt,
'num_turbines': num_turbines,
'turbine_labels': turbine_labels,
'rotor_diameter': D,
'turbine_locations': turbine_locations
'turbine_locations': turbine_locations,
'helics_port': broker_port,
}


Expand All @@ -103,6 +115,10 @@ def __init__(self, config_dict ,amr_wind_input):
self.amr_wind_input = amr_wind_input
self.amr_wind_input_dict = read_amr_wind_input(self.amr_wind_input)

# Get the simulation time step
self.dt = self.amr_wind_input_dict['dt']
self.config_dict['helics']['deltat'] = self.dt

# Get the number of turbines
self.num_turbines = self.amr_wind_input_dict['num_turbines']

Expand All @@ -114,6 +130,7 @@ def run(self):
# Initialize the values
turbine_powers = np.zeros(self.num_turbines)
sim_time_s = 0. # initialize time to 0
time_step = 0 # Initialize time step counter to 0
amr_wind_speed = 8.0
amr_wind_direction = 240.0

Expand Down Expand Up @@ -166,14 +183,23 @@ def run(self):
# Convert to a list
turbine_powers = turbine_powers.tolist()

# Set dummy wind directions to be passed out
turbine_wind_directions = list(
amr_wind_direction + 5.*np.random.randn(self.num_turbines)
)
turbine_wind_directions = [sim_time_s+0.01, sim_time_s+0.02]

amr_wind_direction = sim_time_s

# ================================================================
# Communicate with control center
# Send the turbine powers for this time step and get wind speed and wind direction for the
# nex time step
logger.info('Time step: %d' % sim_time_s)
logger.info('Time step: %d' % time_step)
logger.info("** Communicating with control center")
message_from_client_array = [
sim_time_s, amr_wind_speed, amr_wind_direction] + turbine_powers
sim_time_s, amr_wind_speed, amr_wind_direction
] + turbine_powers + turbine_wind_directions

# Send helics message to Control Center
# publish on topic: status
Expand All @@ -195,8 +221,9 @@ def run(self):

# Note dummy doesn't currently use received info for anything

# Advance simulation time
sim_time_s += 1
# Advance simulation time and time step counter
sim_time_s += self.dt
time_step += 1
self.sync_time_helics(self.absolute_helics_time + self.deltat)

# TODO cleanup code to move publish and subscribe here.
Expand All @@ -217,12 +244,15 @@ def process_subscription_messages(self, msg):

def launch_dummy_amr_wind(amr_input_file):

temp = read_amr_wind_input(amr_input_file)
print(temp["helics_port"])

config = {
"name": "dummy_amr_wind",
"gridpack": {
},
"helics": {
"deltat": 1,
"deltat": 1, # Will be overridden by input file value
"subscription_topics": [
"control"

Expand All @@ -232,7 +262,8 @@ def launch_dummy_amr_wind(amr_input_file):

],
"endpoints": [
]
],
"helicsport":temp["helics_port"],
},

"publication_interval": 1,
Expand Down
Loading