Skip to content

Commit

Permalink
Update comments
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhar-abbas committed Sep 13, 2019
1 parent bf762ad commit 3364264
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 84 deletions.
62 changes: 33 additions & 29 deletions WTC_toolbox/control_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class ConInt():
def __init__(self, lib_name):
"""
Setup the interface
Parameters:
-----------
lib_name = str
name of dynamic library containing controller, (.dll,.so,.dylib)
"""
self.lib_name = lib_name
self.param_name = 'DISCON.IN' # this appears to be hard-coded so match here for now
Expand All @@ -40,12 +45,11 @@ def __init__(self, lib_name):
# Initialize
self.pitch = 0
self.torque = 0

# -- discon
self.discon = cdll.LoadLibrary(self.lib_name)

self.avrSWAP = np.zeros(self.avr_size)

# Define avrSWAP some
# Define some avrSWAP parameters
self.avrSWAP[2] = self.DT
self.avrSWAP[60] = self.num_blade

Expand All @@ -57,51 +61,56 @@ def __init__(self, lib_name):
self.avrSWAP[49] = self.char_buffer
self.avrSWAP[50] = self.char_buffer

# Initialize DISCON and related
self.aviFAIL = c_int32() # 1
self.accINFILE = self.param_name.encode('utf-8')
self.avcOUTNAME = create_string_buffer(1000) # 'DEMO'.encode('utf-8')
self.avcMSG = create_string_buffer(1000)

# self.discon.DISCON.argtypes = [ndpointer(c_double, flags="C_CONTIGUOUS"), POINTER(c_int32), c_char_p, c_char_p, c_char_p] # (all defined by ctypes)
self.discon.DISCON.argtypes = [POINTER(c_float), POINTER(c_int32), c_char_p, c_char_p, c_char_p] # (all defined by ctypes)

# Run DISCON
self.call_discon()


# First call
# self.discon.DISCON(self.avrSWAP, byref(self.aviFAIL), self.accINFILE, self.avcOUTNAME, self.avcMSG)


# Code as not first run
self.avrSWAP[0] = 1


def call_discon(self):

# Convert AVR swap to the right thing
'''
Call DISCON.dll (or .so,.dylib)
'''
# Convert AVR swap to the c pointer
c_float_p = POINTER(c_float)
data = self.avrSWAP.astype(np.float32)
data_p = data.ctypes.data_as(c_float_p)
p_data = data.ctypes.data_as(c_float_p)

# Run DISCON
self.discon.DISCON(p_data, byref(self.aviFAIL), self.accINFILE, self.avcOUTNAME, self.avcMSG)

# Push back to avr swap
# print(data_p[47])
# print(self.avrSWAP[47])
#for i in range(len(self.avrSWAP)):
# self.avrSWAP
#print('len',len(data_p),len(self.avrSWAP))


self.avrSWAP = data


def call_controller(self,t,dt,pitch,genspeed,rotspeed,ws):
'''
Runs the controller. Passes current turbine state to the controller, and returns control inputs back


Parameters:
-----------
t: float
time, (s)
dt: float
timestep, (s)
pitch: float
blade pitch, (rad)
genspeed: float
generator speed, (rad/s)
rotspeed: float
rotor speed, (rad/s)
ws: float
wind speed, (m/s)
'''

# Add states to avr
self.avrSWAP[1] = t
self.avrSWAP[2] = dt
Expand All @@ -111,17 +120,12 @@ def call_controller(self,t,dt,pitch,genspeed,rotspeed,ws):
self.avrSWAP[26] = ws

self.call_discon()
# self.discon.DISCON(self.avrSWAP, byref(self.aviFAIL), self.accINFILE, self.avcOUTNAME, self.avcMSG)

self.pitch = self.avrSWAP[41]
self.torque = self.avrSWAP[47]
self.torque = self.avrSWAP[46]

return(self.torque,self.pitch)

def show_control_values(self):
print('Pitch',self.pitch)
print('Torque',self.torque)


#discon.DISCON.argtypes = [POINTER(c_float), c_int, c_char_p, c_char_p, c_char_p] # (all defined by ctypes)
# discon.DISCON(byref(avrSWAP), aviFAIL, accINFILE, avcOUTNAME, avcMSG)
print('Torque',self.torque)
99 changes: 44 additions & 55 deletions WTC_toolbox/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,29 @@ def __init__(self, turbine, controller_int):
self.gen_eff = 0.95


def sim_ws_series(self,t_array,ws_array,rotor_rpm_init=10,init_pitch=0.0):

# Store some for conveniente
def sim_ws_series(self,t_array,ws_array,rotor_rpm_init=10,init_pitch=0.0, make_plots=True):
'''
Simulate simplified turbine model using a complied controller (.dll or similar).
- currently a 1DOF rotor model
Parameters:
-----------
t_array: float
Array of time steps, (s)
ws_array: float
Array of wind speeds, (s)
rotor_rpm_init: float, optional
initial rotor speed, (rpm)
init_pitch: float, optional
initial blade pitch angle, (deg)
make_plots: bool, optional
True: generate plots, False: don't.
'''
# Store turbine data for conveniente
dt = t_array[1] - t_array[0]
R = self.turbine.RotorRad
GBRatio = self.turbine.Ng


# Declare output arrays
pitch = np.ones_like(t_array) * init_pitch
rot_speed = np.ones_like(t_array) * rotor_rpm_init * rpm2RadSec # represent rot speed in rad / s
Expand All @@ -53,7 +68,8 @@ def sim_ws_series(self,t_array,ws_array,rotor_rpm_init=10,init_pitch=0.0):
gen_torque = np.ones_like(t_array) # * trq_cont(turbine_dict, gen_speed[0])
gen_power = np.ones_like(t_array) * 0.0


# Test for cc_blade Cq information.
# - If not, assume available matrices loaded from text file, and interpolate those
try:
self.turbine.cc_rotor.evaluate(ws_array[1], [rot_speed[0]/rpm2RadSec],
[pitch[0]],
Expand All @@ -67,8 +83,9 @@ def sim_ws_series(self,t_array,ws_array,rotor_rpm_init=10,init_pitch=0.0):
for i, t in enumerate(t_array):
if i == 0:
continue # Skip the first run

ws = ws_array[i]

# Load current Cq data
if use_interpolated:
tsr = rot_speed[i-1] * self.turbine.RotorRad / ws
cq = self.turbine.Cq.interp_surface([pitch[i-1]],tsr)
Expand All @@ -77,33 +94,10 @@ def sim_ws_series(self,t_array,ws_array,rotor_rpm_init=10,init_pitch=0.0):
[rot_speed[i-1]/rpm2RadSec],
[pitch[i-1]],
coefficients=True)
# try:
# P, T, Q, M, Cp, Ct, cq, CM = self.turbine.rotor.evaluate([ws],
# [rot_speed[i-1]/rpm2RadSec],
# [pitch[i-1]],
# coefficients=True)
# except:
# print('CC BLADE PROBLEM')
# e = sys.exc_info()[0]
# print(e)
# # carry through the past values and continue
# pitch[i] = pitch[i-1]
# rot_speed[i] = rot_speed[i-1]
# gen_speed[i] = gen_speed[i-1]
# aero_torque[i] = aero_torque[i-1]
# gen_torque[i] = gen_torque[i-1]
# gen_power[i] = gen_power[i-1]
# continue

# Update the turbine state
# -- 1DOF model: rotor speed and generator speed (scaled by Ng)
aero_torque[i] = 0.5 * self.turbine.rho * (np.pi * R**2) * cq * R * ws**2

# # Save these values for plotting
# cq_array[i] = cq
# cp_array[i] = Cp[0]
# ct_array[i] = Ct[0]
# tsr_array[i] = tsr

# Update the rotor speed and generator speed
rot_speed[i] = rot_speed[i-1] + (dt/self.turbine.J)*(aero_torque[i] * self.gb_eff - self.turbine.Ng * gen_torque[i-1])
gen_speed[i] = rot_speed[i] * self.turbine.Ng

Expand All @@ -123,28 +117,23 @@ def sim_ws_series(self,t_array,ws_array,rotor_rpm_init=10,init_pitch=0.0):
self.t_array = t_array
self.ws_array = ws_array


fig, axarr = plt.subplots(4,1,sharex=True,figsize=(6,10))



ax = axarr[0]
ax.plot(self.t_array,self.ws_array,label='Wind Speed')
ax.grid()
ax.legend()

ax = axarr[1]
ax.plot(self.t_array,self.rot_speed,label='Rot Speed')
ax.grid()
ax.legend()

ax = axarr[2]
ax.plot(self.t_array,self.gen_torque,label='Gen Torque')
ax.grid()
ax.legend()

ax = axarr[3]
ax.plot(self.t_array,self.pitch,label='Bld Pitch')
ax.grid()
ax.legend()
if make_plots:
fig, axarr = plt.subplots(4,1,sharex=True,figsize=(6,10))

ax = axarr[0]
ax.plot(self.t_array,self.ws_array,label='Wind Speed')
ax.grid()
ax.legend()
ax = axarr[1]
ax.plot(self.t_array,self.rot_speed,label='Rot Speed')
ax.grid()
ax.legend()
ax = axarr[2]
ax.plot(self.t_array,self.gen_torque,label='Gen Torque')
ax.grid()
ax.legend()
ax = axarr[3]
ax.plot(self.t_array,self.pitch,label='Bld Pitch')
ax.grid()
ax.legend()

0 comments on commit 3364264

Please sign in to comment.