Skip to content

Commit

Permalink
merge with Misha's WHOC branch of hercules
Browse files Browse the repository at this point in the history
  • Loading branch information
Zachary committed Dec 12, 2023
2 parents 3bc1246 + 23f5c3f commit af2e7ad
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 213 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,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
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
Expand Up @@ -158,8 +158,7 @@ Actuator.UniformCtDisk.num_points_r = 20
Actuator.UniformCtDisk.num_points_t = 5


Actuator.labels = T00 T01
# T02 T03 T04 T05 T06 T07
Actuator.labels = T00 T01 T02 T03 T04 T05 T06 T07
Actuator.JoukowskyDisk.thrust_coeff = 8.1672e-01 7.9044e-01 7.8393e-01 7.8624e-01 7.8824e-01 7.8942e-01 7.8902e-01 7.8740e-01 7.8503e-01 7.8237e-01 7.7955e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.6922e-01 7.4270e-01 5.5949e-01 4.6163e-01 3.8786e-01 3.2901e-01 2.8093e-01 2.4114e-01 2.0795e-01 1.8010e-01 1.5663e-01 1.3679e-01 1.1995e-01 1.0562e-01 9.3384e-02 8.2908e-02 7.3910e-02 6.6159e-02 5.9463e-02 5.3662e-02 4.8622e-02 4.4230e-02
Actuator.JoukowskyDisk.wind_speed = 3.0000e+00 3.5495e+00 4.0679e+00 4.5539e+00 5.0064e+00 5.4244e+00 5.8069e+00 6.1530e+00 6.4619e+00 6.7330e+00 6.9655e+00 7.1589e+00 7.3128e+00 7.4269e+00 7.5009e+00 7.5345e+00 7.5412e+00 7.5883e+00 7.6757e+00 7.8031e+00 7.9702e+00 8.1767e+00 8.4221e+00 8.7059e+00 9.0273e+00 9.3856e+00 9.7800e+00 1.0210e+01 1.0659e+01 1.0673e+01 1.1170e+01 1.1699e+01 1.2259e+01 1.2848e+01 1.3465e+01 1.4109e+01 1.4778e+01 1.5471e+01 1.6185e+01 1.6921e+01 1.7674e+01 1.8445e+01 1.9231e+01 2.0030e+01 2.0841e+01 2.1661e+01 2.2489e+01 2.3323e+01 2.4160e+01 2.5000e+01
Actuator.JoukowskyDisk.rpm = 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0861e+00 5.1954e+00 5.2765e+00 5.3290e+00 5.3529e+00 5.3577e+00 5.3912e+00 5.4532e+00 5.5437e+00 5.6625e+00 5.8092e+00 5.9836e+00 6.1851e+00 6.4135e+00 6.6681e+00 6.9483e+00 7.2535e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00
Expand All @@ -175,7 +174,13 @@ Actuator.JoukowskyDisk.use_root_correction = true
Actuator.JoukowskyDisk.epsilon = 5.0
Actuator.JoukowskyDisk.vortex_core_size = 24.0

Actuator.UniformCtDisk.yaw = 240.0
Actuator.JoukowskyDisk.yaw = 240.0

Actuator.T00.base_position = 2000.0 2000.0 0.0
Actuator.T01.base_position = 2500.0 2500.0 0.0
Actuator.T00.base_position               = 2000    1000    0
Actuator.T01.base_position               = 1321.17749    1678.82251    0
Actuator.T02.base_position               = 642.35498    2357.64502    0
Actuator.T03.base_position               = 2509.116882    2187.939392    0
Actuator.T04.base_position               = 1830.294372    2866.761902    0
Actuator.T05.base_position               = 3697.056274    2697.056274    0
Actuator.T06.base_position               = 3018.233764    3375.878784    0
Actuator.T07.base_position               = 2339.411254    4054.701294    0
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
38 changes: 38 additions & 0 deletions hercules/controller_standin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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.
"""

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

58 changes: 44 additions & 14 deletions hercules/dummy_amr_wind.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,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 @@ -78,6 +83,7 @@ def read_amr_wind_input(amr_wind_input):
turbine_locations.append(locations)

return_dict = {
"dt": dt,
"num_turbines": num_turbines,
"turbine_labels": turbine_labels,
"rotor_diameter": D,
Expand All @@ -104,6 +110,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 +124,7 @@ def run(self):
# Initialize the values
turbine_powers = np.zeros(self.num_turbines)
sim_time_s = 0.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 @@ -151,21 +162,27 @@ def run(self):
# SIMULATE A CALCULATION STEP IN AMR WIND=========================
logger.info("Calculating simulation time: %.1f" % sim_time_s)

amr_wind_speed, amr_wind_direction, turbine_powers = self.get_step(
sim_time_s
)

(
amr_wind_speed,
amr_wind_direction,
turbine_powers,
turbine_wind_directions,
) = self.get_step(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
message_from_client_array = (
[
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 @@ -190,8 +207,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 Down Expand Up @@ -228,6 +246,8 @@ def get_step(self, sim_time_s):
for turb in range(self.num_turbines)
]

turbine_wind_directions = np.zeros(self.num_turbines)

else:
amr_wind_speed = 8.0
amr_wind_direction = 240.0
Expand All @@ -246,7 +266,17 @@ def get_step(self, sim_time_s):
# Convert to a list
turbine_powers = turbine_powers.tolist()

return amr_wind_speed, amr_wind_direction, turbine_powers
turbine_wind_directions = list(
amr_wind_direction + 5.0 * np.random.randn(self.num_turbines)
)
turbine_wind_directions = [sim_time_s + 0.01, sim_time_s + 0.02]

return (
amr_wind_speed,
amr_wind_direction,
turbine_powers,
turbine_wind_directions,
)

def process_endpoint_event(self, msg):
pass
Expand All @@ -267,7 +297,7 @@ def launch_dummy_amr_wind(amr_input_file, amr_standin_data_file=None):
"name": "dummy_amr_wind",
"gridpack": {},
"helics": {
"deltat": 1,
"deltat": 1, # Will be overridden by input file value
"subscription_topics": ["control"],
"publication_topics": ["status"],
"endpoints": [],
Expand Down
Loading

0 comments on commit af2e7ad

Please sign in to comment.