Skip to content

Commit

Permalink
Merge pull request WISDEM#55 from dzalkind/f/deallocate
Browse files Browse the repository at this point in the history
Deallocate ROSCO arrays
  • Loading branch information
nikhar-abbas authored Jul 7, 2021
2 parents 874c760 + 1c8b9a1 commit 05e9eef
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/CI_rosco-toolbox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ jobs:
run: |
conda install -y compilers
conda install -y wisdem
- name: Add dependencies windows specific
if: true == contains( matrix.os, 'windows')
run: |
conda install -y m2w64-toolchain libpython
conda install -y wisdem
# Install ROSCO toolbox
Expand Down
16 changes: 13 additions & 3 deletions Examples/example_05.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@


# Load controller library
controller_int = ROSCO_ci.ControllerInterface(lib_name,param_filename=param_filename)
controller_int = ROSCO_ci.ControllerInterface(lib_name,param_filename=param_filename,sim_name='sim1')

# Load the simulator
sim = ROSCO_sim.Sim(turbine,controller_int)
sim_1 = ROSCO_sim.Sim(turbine,controller_int)

# Define a wind speed history
dt = 0.025
Expand All @@ -88,7 +88,17 @@
ws[i] = ws[i] + t[i]//100

# Run simulator and plot results
sim.sim_ws_series(t,ws,rotor_rpm_init=4)
sim_1.sim_ws_series(t,ws,rotor_rpm_init=4)

# Load controller library again to see if we deallocated properly
controller_int = ROSCO_ci.ControllerInterface(lib_name,param_filename=param_filename,sim_name='sim_2')

# Run simulator again and plot results
sim_2 = ROSCO_sim.Sim(turbine,controller_int)
sim_2.sim_ws_series(t,ws,rotor_rpm_init=4)

# Check if simulations are equal
np.testing.assert_almost_equal(sim_1.gen_speed,sim_2.gen_speed)

if False:
plt.show()
Expand Down
4 changes: 4 additions & 0 deletions ROSCO/src/DISCON.F90
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ SUBROUTINE DISCON(avrSWAP, aviFAIL, accINFILE, avcOUTNAME, avcMSG) BIND (C, NAME
!------------------------------------------------------------------------------------------------------------------------------
! Read avrSWAP array into derived types/variables
CALL ReadAvrSWAP(avrSWAP, LocalVar)

! Set Control Parameters
CALL SetParameters(avrSWAP, accINFILE, SIZE(avcMSG), CntrPar, LocalVar, objInst, PerfData, ErrVar)

! Filter signals
CALL PreFilterMeasuredSignals(CntrPar, LocalVar, objInst)

IF ((LocalVar%iStatus >= 0) .AND. (ErrVar%aviFAIL >= 0)) THEN ! Only compute control calculations if no error has occurred and we are not on the last time step
Expand Down
80 changes: 75 additions & 5 deletions ROSCO_toolbox/control_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from ctypes import byref, cdll, c_int, POINTER, c_float, c_char_p, c_double, create_string_buffer, c_int32, c_void_p
import numpy as np
from numpy.ctypeslib import ndpointer
import platform, ctypes

# Some useful constants
deg2rad = np.deg2rad(1)
Expand Down Expand Up @@ -75,6 +76,14 @@ def init_discon(self):
self.avrSWAP[20] = 1.0 # HARD CODE initial rot speed = 1 rad/s
self.avrSWAP[82] = 0 # HARD CODE initial nacIMU = 0
self.avrSWAP[26] = 10 # HARD CODE initial wind speed = 10 m/s

# Blade pitch initial conditions
self.avrSWAP[3] = 0 * np.deg2rad(1)
self.avrSWAP[32] = 0 * np.deg2rad(1)
self.avrSWAP[33] = 0 * np.deg2rad(1)

# Torque initial condition
self.avrSWAP[22] = 0


# Code this as first casll
Expand Down Expand Up @@ -173,14 +182,75 @@ def show_control_values(self):

def kill_discon(self):
'''
Unload the dylib from memory: https://stackoverflow.com/questions/359498/how-can-i-unload-a-dll-using-ctypes-in-python
This is unix-specific, but there seems to be a windows solution as well
Unload the dylib from memory: https://github.com/bwoodsend/cslug/blob/master/cslug/_stdlib.py
'''

print('Shutting down {}'.format(self.lib_name))
handle = self.discon._handle
dlclose_func = self.discon.dlclose
dlclose_func.argtypes = [c_void_p]

# Start copy here
OS = platform.system()

def null_free_dll(*spam): # pragma: no cover
pass

# Try to find a good runtime library which is always available and contains
# the standard library C functions such as malloc() or printf().
# XXX: Keep chosen library names in sync with the table in `cslug/stdlib.py`.

extra_libs = []

if OS == "Windows": # pragma: Windows
_dlclose = ctypes.windll.kernel32.FreeLibrary
dlclose = lambda handle: 0 if _dlclose(handle) else 1
# There's some controversy as to whether this DLL is guaranteed to exist.
# It always has so far but isn't documented. However, MinGW assumes that it
# is so, should this DLL be removed, then we have much bigger problems than
# just this line. There is also vcruntime140.dll which isn't a standard part
# of the OS but is always shipped with Python so we can guarantee its
# presence. But vcruntime140 contains only a tiny strict-subset of msvcrt.
stdlib = ctypes.CDLL("msvcrt")

elif OS == "Darwin": # pragma: Darwin
try:
try:
# macOS 11 (Big Sur). Possibly also later macOS 10s.
stdlib = ctypes.CDLL("libc.dylib")
except OSError: # pragma: no cover
stdlib = ctypes.CDLL("libSystem")
except OSError: # pragma: no cover
# Older macOSs. Not only is the name inconsistent but it's
# not even in PATH.
_stdlib = "/usr/lib/system/libsystem_c.dylib"
if os.path.exists(_stdlib):
stdlib = ctypes.CDLL(_stdlib)
else:
stdlib = None
if stdlib is not None: # pragma: no branch
dlclose = stdlib.dlclose
else: # pragma: no cover
# I hope this never happens.
dlclose = null_free_dll

elif OS == "Linux": # pragma: Linux
try:
stdlib = ctypes.CDLL("")
except OSError: # pragma: no cover
# Either Alpine Linux or Android.
# Unfortunately, there doesn't seem to be any practical way
# to tell them apart.
stdlib = ctypes.CDLL("libc.so")

# Android, like FreeBSD puts its math functions
# in a dedicated `libm.so`.
# The only way to know that this is not Alpine is to check if the math
# functions are already available in `libc.so`.
if not hasattr(stdlib, "sin"):
extra_libs.append(ctypes.CDLL("libm.so"))
dlclose = stdlib.dlclose

# End copy here
dlclose.argtypes = [c_void_p]
dlclose(handle)

del self.discon
dlclose_func(handle)
3 changes: 3 additions & 0 deletions ROSCO_toolbox/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ def sim_ws_series(self,t_array,ws_array,rotor_rpm_init=10,init_pitch=0.0, make_p
self.t_array = t_array
self.ws_array = ws_array

# Close shared library when finished
self.controller_int.kill_discon()

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

Expand Down

0 comments on commit 05e9eef

Please sign in to comment.