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

Feature/update dummy amr #13

Merged
merged 6 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ emu_python/local_amr_wind_demo/sample_copy.nc
t_00*
logdummy
logemu
*echo
129 changes: 78 additions & 51 deletions emu_python/dummy_amr_wind.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,12 @@
# - - Sleep for 1 s

import ast
import datetime
import logging
import os
import random
import sys
import time
from io import StringIO

import numpy as np
import pandas as pd
import zmq
from SEAS.federate_agent import FederateAgent

# PARAMETERS
num_turbines = 2

# Initialize to all zeros
turbine_powers = np.zeros(num_turbines)
from SEAS.federate_agent import FederateAgent

# Set up the logger
# Useful for when running on eagle
Expand All @@ -58,15 +46,78 @@
logger.info(
"Emulator dummy_amr_wind (standing in for AMR-Wind) connecting to server")

# Define a function to read the amrwind input file
# Note simply copied from emulator
def read_amr_wind_input(amr_wind_input):

# Probably want a file not found error instead
return_dict = {}

with open(amr_wind_input) as fp:
Lines = fp.readlines()

# Find the actuators
for line in Lines:
if 'Actuator.labels' in line:
turbine_labels = line.split()[2:]
num_turbines = len(turbine_labels)

# Find the diameter
for line in Lines:
if 'rotor_diameter' in line:
D = float(line.split()[-1])

# Get the turbine locations
turbine_locations = []
for label in turbine_labels:
for line in Lines:
if 'Actuator.%s.base_position' % label in line:
locations = tuple([float(f)
for f in line.split()[-3:-1]])
turbine_locations.append(locations)

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


return return_dict


class DummyAMRWind(FederateAgent):
def __init__(self, config_dict):
def __init__(self, config_dict ,amr_wind_input):
super(DummyAMRWind, self).__init__(
name=config_dict['name'], feeder_num=0, starttime=config_dict['starttime'], endtime=config_dict['stoptime'], agent_num=0, config_dict=config_dict)
name=config_dict['name'],
feeder_num=0,
starttime=config_dict['starttime'],
endtime=config_dict['stoptime'],
agent_num=0,
config_dict=config_dict)

self.config_dict = config_dict

# Read the amrwind input file
self.amr_wind_input = amr_wind_input
self.amr_wind_input_dict = read_amr_wind_input(self.amr_wind_input)

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

# Print the number of turbines
logger.info("Number of turbines: {}".format(self.num_turbines))

def run(self):

# Initialize the values
turbine_powers = np.zeros(self.num_turbines)
sim_time_s = 0. # initialize time to 0
amr_wind_speed = 8.0
amr_wind_direction = 240.0


# Before starting the main time loop need to do an initial connection to the
# Control center to get the starting wind speed and wind direction
# Code the time step as -1 and -1 (to ensure it is an array)
Expand All @@ -92,33 +143,25 @@ def run(self):
self.sync_time_helics(self.absolute_helics_time + self.deltat)
logger.info("** Initial Received reply: {}".format(message_from_server))

# # Unpack the reply and update wind speed and wind direction
# Initialize variables
# This case only happens in the first time-step.
if message_from_server == None:
received_data = [7, 270]
received_data = [7, 270]
wind_speed = 8 # float(received_data[0]) #TODO: HARDCODED
wind_direction = 270 # float(received_data[1]) #TODO: HARDCODED
logger.info("** Intial Wind Speed: {}".format(wind_speed))
logger.info("** Intial Wind Direction: {}".format(wind_direction))
logger.info("** Intial Wind Speed: {}".format(amr_wind_speed))
logger.info("** Intial Wind Direction: {}".format(amr_wind_direction))
logger.info("...STARTING TIME LOOP...")

sim_time_s = 0. # initialize time to 0

self.message_from_server = None
# while True:

while self.absolute_helics_time < (self.endtime - self.starttime + 1):

# SIMULATE A CALCULATION STEP IN AMR WIND=========================
logger.info("Calculating simulation time: %.1f" % sim_time_s)

# Compute the turbine power using a simple formula
turbine_powers = np.ones(
num_turbines) * wind_speed**3 + np.random.rand(num_turbines) * 50
self.num_turbines) * amr_wind_speed**3 + np.random.rand(self.num_turbines) * 50

# Scale down later turbines as if waked
turbine_powers[int(num_turbines/2):] = 0.75 * \
turbine_powers[int(num_turbines/2):]
turbine_powers[int(self.num_turbines/2):] = 0.75 * \
turbine_powers[int(self.num_turbines/2):]

# Convert to a list
turbine_powers = turbine_powers.tolist()
Expand All @@ -129,18 +172,8 @@ def run(self):
# nex time step
logger.info('Time step: %d' % sim_time_s)
logger.info("** Communicating with control center")

# Write the turbine values to seperate files
for t_idx, p_val in enumerate(turbine_powers):
t_file = 't_%04d' % t_idx
with open(t_file, "a") as file_object:
file_object.write('%.1f %.1f\n' % (sim_time_s, p_val))

# Pass the current simulation time and the turbine powers from the previous time step
message_code = 0
# [34 + random.random(), 45.3+random.random() , 67+random.random()]
message_from_client_array = [
sim_time_s] + [wind_speed, wind_direction] + turbine_powers
sim_time_s, amr_wind_speed, amr_wind_direction] + turbine_powers

# Send helics message to Control Center
# publish on topic: status
Expand All @@ -160,12 +193,7 @@ def run(self):
logger.info(
"** Received reply {}: {}".format(sim_time_s, self.message_from_server))

# Unpack the reply and update wind speed and wind direction
# Get wind speed and wind direction for the next time step

received_data = self.message_from_server
wind_speed = float(received_data[1])
wind_direction = float(received_data[2])
# Note dummy doesn't currently use received info for anything

# Advance simulation time
sim_time_s += 1
Expand All @@ -187,7 +215,8 @@ def process_subscription_messages(self, msg):
pass


def launch_dummy_amr_wind():
def launch_dummy_amr_wind(amr_input_file):

config = {
"name": "dummy_amr_wind",
"gridpack": {
Expand All @@ -213,10 +242,8 @@ def launch_dummy_amr_wind():
"Agent": "dummy_amr_wind"

}
obj = DummyAMRWind(config)
obj = DummyAMRWind(config, amr_input_file)
obj.run_helics_setup()
obj.enter_execution(function_targets=[],
function_arguments=[[]])


launch_dummy_amr_wind()
2 changes: 1 addition & 1 deletion example_case_folders/example_sim_05/bash_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ helics_broker -t zmq -f 2 --loglevel="debug" &
python3 emu_runscript.py emu_input_000.yaml >> logemu 2>&1 & # Start the controller center and pass in input file


python3 emu_runscript_dummy_amr.py >> logdummy 2>&1
python3 emu_runscript_dummy_amr.py amr_input.inp >> logdummy 2>&1
# Now go back to scratch folder and launch the job

# cd /scratch/pfleming/c2c/example_sim_02
Expand Down
12 changes: 11 additions & 1 deletion example_case_folders/example_sim_05/emu_runscript_dummy_amr.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import sys
from emu_python.dummy_amr_wind import launch_dummy_amr_wind

# Check that one command line argument was given
if len(sys.argv) != 2:
raise Exception("Usage: python emu_runscript_dummy_amr.py <amr_input_file>")

# # Get the first command line argument
# This is the name of the file to read
amr_input_file = sys.argv[1]
print(f"Running AMR-Wind dummy with input file: {amr_input_file}")

launch_dummy_amr_wind()

launch_dummy_amr_wind(amr_input_file)