gym
gym copied to clipboard
Could not find platform dependent libraries and kernel always busy. Im waiting and kernel still busy but my energyplus was completed succesfully.
Could not find platform dependent libraries and kernel always busy. Im waiting and kernel still busy but my energyplus was completed succesfully.
[2024-03-08 14:58:19,486] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:Could not find platform independent libraries
[2024-03-08 14:58:19,486] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:Could not find platform independent libraries
[2024-03-08 14:58:19,575] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:Could not find platform dependent libraries <exec_prefix>
[2024-03-08 14:58:19,575] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:Could not find platform dependent libraries <exec_prefix>
[2024-03-08 14:58:19,580] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:Consider setting $PYTHONHOME to [:<exec_prefix>]
[2024-03-08 14:58:19,580] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:Consider setting $PYTHONHOME to [:<exec_prefix>]
[2024-03-08 14:58:47,259] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:EnergyPlus Completed Successfully.
[2024-03-08 14:58:47,259] EPLUS_ENV_TesisDivEnv_MainThread-EPLUSPROCESS_EPI_0 ERROR:EnergyPlus Completed Successfully.
my kernel still busy and i cannot to next cell
Could you provide example code to reproduce the issue?
env = gym.make('TesisDivEnv') ob = env.reset()
this code still make kernel busy, it's possible the problem in my Object Oriented Program or Python Library etc?
#Wrap the EnergyPLus simulator into the Openai gym env #Author: Zhiang Zhang, Hadi Christian
import socket import os import time import copy import signal import _thread import logging import subprocess import threading import numpy as np
from shutil import copyfile, rmtree from gym import Env, spaces from gym.envs.registration import register from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from ..util.logger import Logger from ..util.time import (get_hours_to_now, get_time_string, get_delta_seconds, WEEKDAY_ENCODING)
YEAR = 1991 # Non leap year CWD = os.getcwd(); LOG_LEVEL_MAIN = 'INFO'; LOG_LEVEL_EPLS = 'ERROR'; LOG_FMT = "[%(asctime)s] %(name)s %(levelname)s:%(message)s";
class TesisDivEnv(Env): """EnergyPlus gym environment
Args:
eplus_path: String
EnergyPlus executive command path.
weather_path: String
EnergyPlus weather file path (.epw).
bcvtb_path: String
BCVTB installation path.
variable_path: String
variable.cfg path.
idf_path: String
EnergyPlus input description file (.idf) path.
env_name: str
The environment name.
act_repeat: int
The number of times to repeat the control action.
max_ep_data_store_num: int
The number of simulation results to keep.
"""
def __init__(self, eplus_path, weather_path, bcvtb_path, variable_path, idf_path, env_name,
act_repeat = 1, max_ep_data_store_num = 10):
self._env_name = env_name;
self._thread_name = threading.current_thread().getName();
self.logger_main = Logger().getLogger('EPLUS_ENV_%s_%s_ROOT'%(env_name, self._thread_name),
LOG_LEVEL_MAIN, LOG_FMT);
# Set the environment variable for bcvtb
os.environ['BCVTB_HOME'] = bcvtb_path;
# Create a socket for communication with the EnergyPlus
self.logger_main.debug('Creating socket for communication...')
s = socket.socket()
host = socket.gethostname() # Get local machine name
s.bind((host, 0)) # Bind to the host and any available port
sockname = s.getsockname();
port = sockname[1]; # Get the port number
s.listen(60) # Listen on request
self.logger_main.debug('Socket is listening on host %s port %d'%(sockname));
self._env_working_dir_parent = self._get_eplus_working_folder(CWD, '-%s-res'%(env_name));
os.makedirs(self._env_working_dir_parent);
self._host = host;
self._port = port;
self._socket = s;
self._eplus_path = eplus_path
self._weather_path = weather_path
self._variable_path = variable_path
self._idf_path = idf_path
self._episode_existed = False;
(self._eplus_run_st_mon, self._eplus_run_st_day,
self._eplus_run_ed_mon, self._eplus_run_ed_day,
self._eplus_run_st_weekday,
self._eplus_run_stepsize) = self._get_eplus_run_info(idf_path);
self._eplus_run_stepsize = 3600 / self._eplus_run_stepsize # Stepsize in second
self._eplus_one_epi_len = self._get_one_epi_len(self._eplus_run_st_mon,
self._eplus_run_st_day,
self._eplus_run_ed_mon,
self._eplus_run_ed_day);
self._epi_num = 0;
self._act_repeat = act_repeat;
self._max_ep_data_store_num = max_ep_data_store_num;
self._last_action = [20.0];
# Variabel untuk RL
self.action_space = spaces.MultiDiscrete([7, 7, 7, 7]);
self.observation_space = spaces.Box(low = 0, high = np.inf, shape=(6,));
def reset(self):
"""Reset the environment.
This method does the followings:
1: Make a new EnergyPlus working directory
2: Copy .idf and variables.cfg file to the working directory
3: Create the socket.cfg file in the working directory
4: Create the EnergyPlus subprocess
5: Establish the socket connection with EnergyPlus
6: Read the first sensor data from the EnergyPlus
Return: (float, [float], boolean)
The index 0 is current_simulation_time in second,
index 1 is EnergyPlus results in 1-D python list requested by the
variable.cfg, index 2 is the boolean indicating whether the episode terminates.
"""
ret = [];
# End the last episode if exists
if self._episode_existed:
self._end_episode()
self.logger_main.info('Last EnergyPlus process has been closed. ')
self._epi_num += 1;
# Create EnergyPlus simulaton process
self.logger_main.info('Creating EnergyPlus simulation environment...')
eplus_working_dir = self._get_eplus_working_folder(
self._env_working_dir_parent, '-sub_run');
os.makedirs(eplus_working_dir); # Create the Eplus working directory
self._rm_past_history_dir(eplus_working_dir, '-sub_run'); # Remove redundant past working directories
eplus_working_idf_path = (eplus_working_dir +
'/' +
self._get_file_name(self._idf_path));
eplus_working_var_path = (eplus_working_dir +
'/' +
'variables.cfg'); # Variable file must be with this name
eplus_working_out_path = (eplus_working_dir +
'/' +
'output');
copyfile(self._idf_path, eplus_working_idf_path);
# Copy the idf file to the working directory
copyfile(self._variable_path, eplus_working_var_path);
# Copy the variable.cfg file to the working dir
self._create_socket_cfg(self._host,
self._port,
eplus_working_dir);
# Create the socket.cfg file in the working dir
self.logger_main.info('EnergyPlus working directory is in %s'
%(eplus_working_dir));
eplus_process = self._create_eplus(self._eplus_path, self._weather_path,
eplus_working_idf_path,
eplus_working_out_path,
eplus_working_dir);
self.logger_main.debug('EnergyPlus process is still running ? %r'
%self._get_is_subprocess_running(eplus_process))
self._eplus_process = eplus_process;
# Log the Eplus output
eplus_logger = Logger().getLogger('EPLUS_ENV_%s_%s-EPLUSPROCESS_EPI_%d'
%(self._env_name, self._thread_name, self._epi_num),
LOG_LEVEL_EPLS, LOG_FMT);
_thread.start_new_thread(self._log_subprocess_info,
(eplus_process.stdout,
eplus_logger));
_thread.start_new_thread(self._log_subprocess_err,
(eplus_process.stderr,
eplus_logger));
# Establish connection with EnergyPlus
conn, addr = self._socket.accept() # Establish connection with client.
self.logger_main.debug('Got connection from %s at port %d.'%(addr));
# Start the first data exchange
rcv_1st = conn.recv(2048).decode(encoding = 'ISO-8859-1');
self.logger_main.debug('Got the first message successfully: ' + rcv_1st);
version, flag, nDb, nIn, nBl, curSimTim, Dblist \
= self._disassembleMsg(rcv_1st);
ret.append(curSimTim);
ret.append(Dblist);
# Remember the message header, useful when send data back to EnergyPlus
self._eplus_msg_header = [version, flag];
self._curSimTim = curSimTim;
# Check if episode terminates
is_terminal = False;
if curSimTim >= self._eplus_one_epi_len:
is_terminal = True;
ret.append(is_terminal);
# Change some attributes
self._conn = conn;
self._eplus_working_dir = eplus_working_dir;
self._episode_existed = True;
# Process for episode terminal
if is_terminal:
self._end_episode();
obs = self._get_observation(Dblist);
return obs
def step(self, action):
"""Execute the specified action.
This method does the followings:
1: Send a list of float to EnergyPlus
2: Recieve EnergyPlus results for the next step (state)
Parameters
----------
action: python list of float
Control actions that will be passed to the EnergyPlus
Return: (float, [float], boolean)
The index 0 is current_simulation_time in second,
index 1 is EnergyPlus results in 1-D python list requested by the
variable.cfg, index 2 is the boolean indicating whether the episode terminates.
"""
# Send to the EnergyPlus
action = action + np.ones((4,), dtype=np.int8)*22 # Aksi yang dikirim berupa temperatur antara 20-26 sebanyak 7
curSimTim = self._curSimTim;
self.logger_main.debug('Perform one step.')
header = self._eplus_msg_header;
runFlag = 0 # 0 is normal flag
tosend = self._assembleMsg(header[0], runFlag, len(action), 0,
0, curSimTim, action);
self._conn.send(tosend.encode());
# Recieve from the EnergyPlus
rcv = self._conn.recv(2048).decode(encoding = 'ISO-8859-1');
self.logger_main.debug('Got message successfully: ' + rcv);
# Process received msg
version, flag, nDb, nIn, nBl, curSimTim, Dblist \
= self._disassembleMsg(rcv);
if curSimTim < self._eplus_one_epi_len:
is_terminal = False;
elif curSimTim >= self._eplus_one_epi_len:
is_terminal = True;
# Remember the last action
self._last_action = action;
# Change some attributes
self._curSimTim = curSimTim;
obs = self._get_observation(Dblist);
reward = self._get_reward(obs, Dblist);
info = {}
return obs, reward, is_terminal, info
def render(self, mode='human', close=False):
pass;
def _seed(self):
return 1;
def _rm_past_history_dir(self, cur_eplus_working_dir, dir_sig):
"""Remove the past simulation results.
Args:
cur_eplus_working_dir: str
The current eplus working directory
dir_sig: str
The directory split signature
Reture: None
"""
cur_dir_name, cur_dir_id = cur_eplus_working_dir.split(dir_sig)
cur_dir_id = int(cur_dir_id);
if cur_dir_id - self._max_ep_data_store_num > 0:
rm_dir_id = cur_dir_id - self._max_ep_data_store_num;
rm_dir_full_name = cur_dir_name + dir_sig + str(rm_dir_id);
rmtree(rm_dir_full_name);
def _create_eplus(self, eplus_path, weather_path,
idf_path, out_path, eplus_working_dir):
eplus_process = subprocess.Popen('%s -w %s -d %s -x %s'
%(eplus_path + '/energyplus', weather_path,
out_path, idf_path),
shell = True,
cwd = eplus_working_dir,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
preexec_fn=os.setsid);
return eplus_process;
def _get_eplus_working_folder(self, parent_dir, dir_sig = '-run'):
"""Return Eplus output folder.
Assumes folders in the parent_dir have suffix -run{run
number}. Finds the highest run number and sets the output folder
to that number + 1.
Parameters
----------
parent_dir: str
Parent dir of the Eplus output directory.
Returns
-------
parent_dir/run_dir
Path to Eplus save directory.
"""
os.makedirs(parent_dir, exist_ok=True)
experiment_id = 0
for folder_name in os.listdir(parent_dir):
if not os.path.isdir(os.path.join(parent_dir, folder_name)):
continue
try:
folder_name = int(folder_name.split(dir_sig)[-1])
if folder_name > experiment_id:
experiment_id = folder_name
except:
pass
experiment_id += 1
parent_dir = os.path.join(parent_dir, 'Eplus-env')
parent_dir = parent_dir + '%s%d'%(dir_sig, experiment_id)
return parent_dir
def _create_socket_cfg(self, host, port, write_dir):
"""
Create the socket.cfg required by BCVTB.
Args:
host: String
Socket host name.
port: int
Socket port number.
write_dir: String
The write directory.
Return: None
"""
top = Element('BCVTB-client');
ipc = SubElement(top, 'ipc');
socket = SubElement(ipc, 'socket'
,{'port':str(port),
'hostname':host,})
xml_str = tostring(top, encoding='ISO-8859-1').decode();
with open(write_dir + '/' + 'socket.cfg', 'w+') as socket_file:
socket_file.write(xml_str);
def _get_file_name(self, file_path):
path_list = file_path.split('/');
return path_list[-1];
def _log_subprocess_info(self, out, logger):
for line in iter(out.readline, b''):
logger.info(line.decode())
def _log_subprocess_err(self, out, logger):
for line in iter(out.readline, b''):
logger.error(line.decode())
def _get_is_subprocess_running(self, subprocess):
if subprocess.poll() is None:
return True;
else:
return False;
def get_is_eplus_running(self):
return self._get_is_subprocess_running(self._eplus_process);
def end_env(self):
"""
This method is called after finishing using the environment.
"""
self._end_episode();
self._socket.shutdown(socket.SHUT_RDWR);
self._socket.close();
def end_episode(self):
self._end_episode();
def _end_episode(self):
"""
This method terminates the current EnergyPlus subprocess.
This method is usually called by the reset() function before it
resets the EnergyPlus environment.
"""
# Send the final msg to EnergyPlus
header = self._eplus_msg_header;
flag = 1.0; # Terminate flag is 1.0, specified by EnergyPlus
action = self._last_action;
action_size = len(self._last_action);
tosend = self._assembleMsg(header[0], flag, action_size, 0,
0, self._curSimTim, action);
self.logger_main.debug('Send the final msg to Eplus.');
self._conn.send(tosend.encode());
# Recieve the final msg from Eplus
rcv = self._conn.recv(2048).decode(encoding = 'ISO-8859-1');
self.logger_main.debug('Final msh from Eplus: %s', rcv)
self._conn.send(tosend.encode()); # Send again, don't know why
# Remove the connection
self._conn.close();
self._conn = None;
# Process the output
time.sleep(1);# Sleep the thread so EnergyPlus has time to do the
# post processing
# Kill subprocess
os.killpg(self._eplus_process.pid, signal.SIGTERM);
self._episode_existed = False;
def _run_eplus_outputProcessing(self):
eplus_outputProcessing_process =\
subprocess.Popen('%s'
%(self._eplus_path + '/PostProcess/ReadVarsESO'),
shell = True,
cwd = self._eplus_working_dir + '/output',
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
preexec_fn=os.setsid)
def _assembleMsg(self, version, flag, nDb, nIn, nBl, curSimTim, Dblist):
"""
Assemble the send msg to the EnergyPlus based on the protocal.
Send msg must a blank space seperated string, [verison, flag, nDb
, nIn, nBl, curSimTim, float, float, float ....]
Return:
The send msg.
"""
ret = '';
ret += '%d'%(version);
ret += ' ';
ret += '%d'%(flag);
ret += ' ';
ret += '%d'%(nDb);
ret += ' ';
ret += '%d'%(nIn);
ret += ' ';
ret += '%d'%(nBl);
ret += ' ';
ret += '%20.15e'%(curSimTim);
ret += ' ';
for i in range(len(Dblist)):
ret += '%20.15e'%(Dblist[i]);
ret += ' ';
ret += '\n';
return ret;
def _disassembleMsg(self, rcv):
rcv = rcv.split(' ');
version = int(rcv[0]);
flag = int(rcv[1]);
nDb = int(rcv[2]);
nIn = int(rcv[3]);
nBl = int(rcv[4]);
curSimTim = float(rcv[5]);
Dblist = [];
for i in range(6, len(rcv) - 1):
Dblist.append(float(rcv[i]));
return (version, flag, nDb, nIn, nBl, curSimTim, Dblist);
def _get_eplus_run_info(self, idf_path):
"""
This method read the .idf file and find the running start month, start
date, end month, end date and the step size.
Args:
idf_path: String
The .idf file path.
Return: (int, int, int, int, int, int)
(start month, start date, end month, end date, start weekday,
step size)
"""
ret = [];
with open(idf_path, encoding = 'ISO-8859-1') as idf:
contents = idf.readlines();
# Run period
tgtIndex = None;
for i in range(len(contents)):
line = contents[i];
effectiveContent = line.strip().split('!')[0] # Ignore contents after '!'
effectiveContent = effectiveContent.strip().split(',')[0]
# Remove tailing ','
if effectiveContent.lower() == 'runperiod':
tgtIndex = i;
break;
for i in range(2, 7):
if i != 4:
ret.append(int(contents[tgtIndex + i].strip()
.split('!')[0]
.strip()
.split(',')[0]
.strip()
.split(';')[0]));
# Start weekday
ret.append(WEEKDAY_ENCODING[contents[tgtIndex + i + 2].strip()
.split('!')[0]
.strip()
.split(',')[0]
.strip()
.split(';')[0]
.strip()
.lower()]);
# Step size
line_count = 0;
for line in contents:
effectiveContent = line.strip().split('!')[0] # Ignore contents after '!'
effectiveContent = effectiveContent.strip().split(',');
if effectiveContent[0].strip().lower() == 'timestep':
if len(effectiveContent) > 1 and len(effectiveContent[1]) > 0:
ret.append(int(effectiveContent[1]
.split(';')[0]
.strip()));
else:
ret.append(int(contents[line_count + 1].strip()
.split('!')[0]
.strip()
.split(',')[0]
.strip()
.split(';')[0]));
break;
line_count += 1;
return tuple(ret);
def _get_one_epi_len(self, st_mon, st_day, ed_mon, ed_day):
"""
Get the length of one episode (One EnergyPlus process run to the end).
Args:
st_mon, st_day, ed_mon, ed_day: int
The EnergyPlus simulation start month, start day, end month,
end day.
Return: int
The simulation time step that the simulation ends.
"""
return get_delta_seconds(YEAR, st_mon, st_day, ed_mon, ed_day);
def _get_observation(self, Dblist):
"""
Convert all observations to distance and normalize them
"""
Phvac = Dblist[5];
PMV = Dblist[7];
obs = [];
for i in range(4):
distemp = np.abs((Dblist[i]-24)/(27-24));
obs.append(distemp);
obs.append(Phvac);
obs.append(PMV);
return obs
def _get_reward(self, obs, Dblist):
"""
Calculate reward suitable for the objective
"""
Phvac = Dblist[5];
PMV = Dblist[7];
hvac_reward = 0;
pmv_reward = 0;
pmv_reward += 1 - PMV**0.4
pmv_reward = pmv_reward/4;
ratio_energy = Phvac/12115
hvac_reward = 1-ratio_energy**0.4;
reward = hvac_reward+pmv_reward;
return reward;
@property
def start_year(self):
"""
Return the EnergyPlus simulaton year.
Return: int
"""
return YEAR;
@property
def start_mon(self):
"""
Return the EnergyPlus simulaton start month.
Return: int
"""
return self._eplus_run_st_mon;
@property
def start_day(self):
"""
Return the EnergyPlus simulaton start day of the month.
Return: int
"""
return self._eplus_run_st_day;
@property
def start_weekday(self):
"""
Return the EnergyPlus simulaton start weekday. 0 is Monday, 6 is Sunday.
Return: int
"""
return self._eplus_run_st_weekday;
@property
def env_name(self):
"""
Return the environment name.
Return: string
"""
return self._env_name;
I would add debug statements (prints) for lines in reset
in order to find which statement isn't printed. This should allow you to identify where the problems are