def dymola_simulation(model_info, path_dymola, solver, printInfo = True): ''' ''' # Retrieving model information root_path = model_info['root_path'] library_path = model_info['library_path'] model_path = model_info['model_path'] model_name = model_info['model_name'] output_path = model_info['output_path'] dymola = None try: if printInfo: print("Creating and starting Dymola instance") # Creating dymola instance dymola = DymolaInterface(dymolapath = path_dymola) if printInfo: print(f"Using Dymola port:" + str(dymola._portnumber)) print(f"Changing working directory to: {output_path}") try: if not os.path.exists(output_path): os.makedirs(output_path) print("Working directory created") except OSError as ex: print("1: Failed to create folder for working directory") # CHANGING THE PATH TO OPENING THE LIBRARY AND THE MODEL result = dymola.cd(root_path) if not result: print("1: Failed to change working directory") # Opening OpenIPSL library dymola.openModel(library_path) if result and printInfo: print("Library opened") # Opening model dymola.openModel(model_path) if result and printInfo: print("Model opened") # CHANGING THE PATH FOR THE WORKING DIRECTORY # Note that the model is already opened result = dymola.cd(output_path) if not result: print("1: Failed to change working directory") dymola.ExecuteCommand("Advanced.TranslationInCommandLog = true") # Simulating the model if solver == 'dassl': dymola.ExecuteCommand("Advanced.Define.DAEsolver = true") print("DAE setting changed for dassl") if solver in ["Rkfix2", "Rkfix4", "Euler"]:
def simulate_optimal(ladephasen, entladephasen, simulationsdauer, dir_laden_daten, dir_modell_sim, name_modell_sim, Root_simulationsergebnisse): ladephasen = clear_phasen(ladephasen) entladephasen = clear_phasen(entladephasen) input_laden = merge(ladephasen, dir_laden_daten) input_entladen = merge(entladephasen, dir_laden_daten) try: #erzeuge Instanz von Dymola dymola = DymolaInterface() dymola.openModel(path=dir_modell_sim) dymola.translateModel(problem=name_modell_sim) dymola.ExecuteCommand("laden.table=" + input_laden) dymola.ExecuteCommand("entladen.table=" + input_entladen) result = dymola.simulateExtendedModel(problem=name_modell_sim, stopTime=simulationsdauer * 3600, method='radau IIa', finalNames=['Stromkosten.y'], resultFile=os.path.join( Root_simulationsergebnisse, 'simulation_optimal')) print(result[0]) Stromkosten = result[1] print('optimale Stromkosten', Stromkosten[0]) if not result: print("Simulation failed. Below is the translation log.") log = dymola.getLastError() print(log) dymola.plot(["elektrische_leistungsaufnahme.y"]) dymola.ExportPlotAsImage( os.path.join(Root_simulationsergebnisse, "Leistungsaufnahme_optimal.png")) dymola.plot(["__ctt__strompreis.y[1]"]) dymola.ExportPlotAsImage( os.path.join(Root_simulationsergebnisse, "Strompreis.png")) dymola.plot(["cost_calculation1.out_kkm1_drehzahl_min_unterschritten"]) dymola.ExportPlotAsImage( os.path.join(Root_simulationsergebnisse, "Drehzahl_unterschritten.png")) dymola.plot(["cost_calculation1.out_Investitionskosten_kkm1"]) dymola.ExportPlotAsImage( os.path.join(Root_simulationsergebnisse, "Invest_KKM.png")) dymola.plot(["cost_calculation1.out_Investitionskosten_Speicher"]) dymola.ExportPlotAsImage( os.path.join(Root_simulationsergebnisse, "Invest_Speicher.png")) except DymolaException as ex: print("Error: " + str(ex)) if dymola is not None: dymola.close() dymola = None return input_laden, input_entladen, ladephasen, entladephasen
def _CreateIBPSALog(self): from dymola.dymola_interface import DymolaInterface from dymola.dymola_exception import DymolaException import buildingspy.development.regressiontest as u """ Check the IBPSA Model Automatical """ cmd = "git clone https://github.com/ibpsa/modelica-ibpsa.git" returned_value = os.system(cmd) # returns the exit code in unix print('returned value:', returned_value) cmd = "cd modelica-ibpsa-master" os.system(cmd) Library = IBPSA/package.mo ut = u.Tester(tool = self.tool) ### Set Number of Threads ut.setNumberOfThreads(self.n_pro) ### Set GUI Show ut.showGUI(self.show_gui) ### Set in Batch Mode ut.batchMode(self.batch) ### Sets the Dymola path to activate the GUI dymola = DymolaInterface(dymolapath="/usr/local/bin/dymola") ### Writes all information in the log file, not only the last entries dymola.ExecuteCommand("Advanced.TranslationInCommandLog:=true;") dym_sta_lic_available = dymola.ExecuteCommand('RequestOption("Standard");') if not dym_sta_lic_available: dymola.ExecuteCommand('DymolaCommands.System.savelog("Log_NO_DYM_STANDARD_LIC_AVAILABLE.txt");') print("No Dymola License is available") dymola.close() exit(1) else: print("Dymola License is available") PackageCheck = dymola.openModel(Library) if PackageCheck == True: print("Found AixLib Library and start Checkmodel Tests \n Check Package " + self.Package+" \n") elif PackageCheck == None: print("Library Path is wrong. Please Check Path of AixLib Library Path") exit(1) result=dymola.checkModel(self.Package) dymola.savelog(self.Package+"-log.txt") Log = dymola.getLastError() if result == True: print('\n Check of Package '+self.Package+' was Successful! \n') dymola.close() #exit(0) if result == False: print('\n ModelCheck Failed in Package ' + self.Package+ ' Show Savelog \n') print(Log) dymola.clearlog() dymola.close()
def dym_check_lic(): from dymola.dymola_interface import DymolaInterface from dymola.dymola_exception import DymolaException if platform.system() == "Windows": dymola = DymolaInterface() else: dymola = DymolaInterface(dymolapath="/usr/local/bin/dymola") dymola.ExecuteCommand("Advanced.TranslationInCommandLog:=true;") dym_sta_lic_available = dymola.ExecuteCommand('RequestOption("Standard");') if not dym_sta_lic_available: dymola.ExecuteCommand( 'DymolaCommands.System.savelog("Log_NO_DYM_STANDARD_LIC_AVAILABLE.txt");' ) print("No Dymola License is available") dymola.close() else: print("Dymola License is available")
def TranslateModel(model_path, name, position): """ Function to handle the Compilation of Modelica models inputs model_path: path of the model name: name of the subsystems position: position number of the subsystems returns: None """ global gl_model_compiled if gl_model_compiled[position - 1] == False: import os import sys global dymola """ Dymola configurations""" if dymola is None: # Work-around for the environment variable sys.path.insert( 0, os.path.join( r'C:\Program Files\Dymola 2018 FD01\Modelica\Library\python_interface\dymola.egg' )) # Import Dymola Package from dymola.dymola_interface import DymolaInterface # Start the interface dymola = DymolaInterface() """ Compilation """ # Open dymola library for lib in Init.path_lib: check1 = dymola.openModel(os.path.join(lib, 'package.mo')) print("Opening successful " + str(check1)) # Force Dymola to use 64 bit compiler dymola.ExecuteCommand("Advanced.CompileWith64=2") dymola.cd(Init.path_res + '\\' + Init.name_wkdir + '\\' + name) # Translate the model check2 = dymola.translateModel(model_path) print("Translation successful " + str(check2)) if check2 is True: gl_model_compiled[position - 1] = True
def simulate_flex(model_name, model_path, sim_duration, flex_var, param_dict): dymola = DymolaInterface() #Model muss noch geöffnet sein openModel = dymola.openModel(path=model_path) print(openModel) translateModel = dymola.translateModel(problem=model_name) print(translateModel) if flex_var == 1: #erste Ebene dymola.ExecuteCommand("konf_Bivalenz=true") dymola.ExecuteCommand("konf_HK=true") dymola.ExecuteCommand("konf_BHKW_stromgefuehrt=false") #zweite Ebene dymola.ExecuteCommand(str("konf_BHKW=" + param_dict["konf_BHKW"])) dymola.ExecuteCommand(str("konf_WRG=" + param_dict["konf_WRG"])) dymola.ExecuteCommand(str("konf_Puffer=" + param_dict["konf_Puffer"])) dymola.ExecuteCommand(str("Anzahl_HK=" + param_dict["Anzahl_HK"])) #die if-Bedingung ist nur zur Sicherheit if param_dict["konf_WRG"] == "true": dymola.ExecuteCommand(str("Anzahl_WRG=" + param_dict["Anzahl_WRG"])) else: dymola.ExecuteCommand("Anzahl_WRG=0") elif flex_var == 2: #erste Ebene dymola.ExecuteCommand("konf_BHKW=true") dymola.ExecuteCommand("konf_Bivalenz=false") dymola.ExecuteCommand("konf_BHKW_Puffer=true") dymola.ExecuteCommand("konf_BHKW_stromgefuehrt=true") #zweite Ebene dymola.ExecuteCommand(str("konf_HK=" + param_dict["konf_HK"])) dymola.ExecuteCommand(str("konf_WRG=" + param_dict["konf_WRG"])) #die if-Bedingung ist nur zur Sicherheit if param_dict["konf_HK"] == "true": dymola.ExecuteCommand(str("Anzahl_HK=" + param_dict["Anzahl_HK"])) else: dymola.ExecuteCommand("Anzahl_HK=0") #die if-Bedingung ist nur zur Sicherheit if param_dict["konf_WRG"] == "true": dymola.ExecuteCommand(str("Anzahl_WRG=" + param_dict["Anzahl_WRG"])) else: dymola.ExecuteCommand("Anzahl_WRG=0") else: print("Auswahl der Flexibilisierungsmaßnahme fehlerhaft") result = dymola.simulateExtendedModel(problem=model_name, stopTime=sim_duration, finalNames=[ "konf_Bivalenz", "konf_HK", "konf_BHKW_stromgefuehrt", "konf_BHKW", "konf_WRG", "konf_Puffer", "Anzahl_WRG", "Anzahl_HK" ]) if not result[0]: print("Simulation failed. Below is the translation log.") log = dymola.getLastError() print(log) print('ERGEBNIS_Inhalt:', "konf_Bivalenz", "konf_HK", "konf_BHKW_stromgefuehrt", "konf_BHKW", "konf_WRG", "konf_Puffer", "Anzahl_WRG", "Anzahl_HK") #saveModel=dymola.saveTotalModel('C:/Users/theisinger_l/waerme_save.mo', "waerme") #Achtung Dymola speichert mit saveTotalModel anscheinend nicht parameterwerte ab.. #print(saveModel) dymola.close() return result
class DymolaBaseEnv(gym.Env): """ A variation of the ModelicaGym FMU interface that uses the Dymola API. To install dymola API add dymola.exe to the system PATH variable. """ def __init__(self): """ :param model_path: path to the model FMU. Absolute path is advised. :param mode: FMU exporting mode "CS" or "ME" :param config: dictionary with model specifications: model_input_names - names of parameters to be used as action. model_output_names - names of parameters to be used as state descriptors. model_parameters - dictionary of initial parameters of the model time_step - time difference between simulation steps positive_reward - (optional) positive reward for default reward policy. Is returned when episode goes on. negative_reward - (optional) negative reward for default reward policy. Is returned when episode is ended :param log_level: level of logging to be used """ with open(self.conf_file) as f: config = json.load(f) logger.setLevel(config['log_level']) self.model_name = config['mo_name'] self.dymola = None self.libs = config['libs'] self.reset_dymola() # Parameters required by this implementation self.tau = config['time_step'] self.model_input_names = [] for i in range(len(config['action_names'])): if config['action_len'][i] <= 1: self.model_input_names += [config['action_names'][i]] else: self.model_input_names += [ f"{config['action_names'][i]}[{x}]" for x in range(1, 1 + config['action_len'][i]) ] self.model_output_names = config['state_names'] self.model_parameters = config['model_parameters'] self.default_action = config['default_action'] self.add_names = config['additional_debug_states'] self.method = config['method'] self.negative_reward = config['negative_reward'] self.positive_reward = config['positive_reward'] if not len(self.model_input_names) == len(self.default_action): raise Exception( "The number of action names and the default action values should be the same length." ) # initialize the model time and state self.start = 0 self.stop = self.tau self.done = False self.state = self.reset() # OpenAI Gym requirements self.action_space = self._get_action_space() self.observation_space = self._get_observation_space() self.debug_data = {name: [] for name in self.model_output_names} self.rbc_action_names = [] for i in range(len(config['rbc_action_names'])): if config['rbc_action_len'][i] <= 1: self.rbc_action_names += [config['rbc_action_names'][i]] else: foo = config['rbc_action_names'][i] bar = config['rbc_action_len'][i] self.rbc_action_names += [ f"{foo}[{x}]" for x in range(1, 1 + bar) ] self.rbc_action = [] self.data = None self.tracker = 0 self.exception_flag = False # OpenAI Gym API def render(self, **kwargs): """ OpenAI Gym API. Determines how current environment state should be rendered. :param kwargs: :return: implementation should return rendering result """ pass def reset(self): """ OpenAI Gym API. Determines restart procedure of the environment :return: environment state after restart """ logger.info( "Resetting the environment and deleting old results files.") if os.path.isdir('temp_dir'): # print("Removing old files...") for file in os.listdir('temp_dir'): try: os.remove(os.path.join(os.getcwd(), 'temp_dir', file)) except: pass self.action = self.default_action self.start = 0 self.stop = self.tau logger.info("The model is being reset") res = self.dymola.simulateExtendedModel( self.model_name, startTime=self.start, stopTime=self.stop, initialNames=self.model_input_names, initialValues=self.action, finalNames=self.model_output_names) self.state = res[1] self.cached_values = None self.cached_state = None self.debug_data = { name: [] for name in self.model_output_names + self.add_names } self.state = self.postprocess_state(self.state) self.done = not (res[0]) if self.done: logger.error( f"Model failed to reset. Dymola simulation from time {self.start} to {self.stop} failed with error message: {self.dymola.getLastError()}" ) return flatten(self.state) def reset_dymola(self): if self.dymola: # this doesn't really seem to be working. It hangs self.dymola.close() self.dymola = DymolaInterface() self.dymola.ExecuteCommand("Advanced.Define.DAEsolver = true") # load libraries loaded = [] #self.dymola.eraseClasses('Modelica') for lib in self.libs: # all paths relative to the cwd loaded += [self.dymola.openModel(lib, changeDirectory=False)] if not loaded[-1]: logger.error(f"Could not find library {lib}") if not False in loaded: logger.debug("Successfully loaded all libraries.") if not os.path.isdir('temp_dir'): os.mkdir('temp_dir') self.temp_dir = os.path.join(os.getcwd(), "temp_dir") self.dymola.cd('temp_dir') logger.debug("Dymola has been reset") return def step(self, action): """ OpenAI Gym API. Determines how one simulation step is performed for the environment. Simulation step is execution of the given action in a current state of the environment. :param action: action to be executed. :return: resulting state """ logger.debug("Experiment next step was called.") if self.done: logger.warning( """You are calling 'step()' even though this environment has already returned done = True. You should always call 'reset' once you receive 'done = True' -- any further steps are undefined behavior.""") return np.array(self.state), self.negative_reward, self.done, {} # check if action is a list. If not - create list of length 1 try: iter(action) except TypeError: action = [action] logger.warning( "Model input values (action) should be passed as a list") # Check if number of model inputs equals number of values passed if len(action) != len(list(self.model_input_names)): message = "List of values for model inputs should be of the length {}," \ "equal to the number of model inputs. Actual length {}".format( len(list(self.model_input_names)), len(action)) logger.error(message) raise ValueError(message) # Set input values of the model logger.debug("model input: {}, values: {}".format( self.model_input_names, action)) try: self.done, state = self.do_simulation() self.state = state self.start += self.tau self.stop += self.tau except: print("exception") self.reset() self.exception_flag = True return flatten(self.state), self._reward_policy(), self.done, {} # logging def get_log_file_name(self): log_date = datetime.datetime.utcnow() log_file_name = "{}-{}-{}_{}.txt".format(log_date.year, log_date.month, log_date.day, self.model_name) return log_file_name # internal logic def _get_action_space(self): """ Returns action space according to OpenAI Gym API requirements. :return: one of gym.spaces classes that describes action space according to environment specifications. """ low = -1 * np.ones(len(self.model_input_names)) high = 1 * np.ones(len(self.model_input_names)) return spaces.Box(low, high) def _get_observation_space(self): """ Returns state space according to OpenAI Gym API requirements. :return: one of gym.spaces classes that describes state space according to environment specifications. """ low = -1 * np.ones(len(self.model_output_names)) high = 1 * np.ones(len(self.model_output_names)) return spaces.Box(low, high) def _is_done(self, results): """ Determines logic when experiment is considered to be done. :return: boolean flag if current state of the environment indicates that experiment has ended. """ return not results[0] def do_simulation(self): """ Executes simulation by FMU in the time interval [start_time; stop_time] currently saved in the environment. :return: resulting state of the environment. """ #print("============================") logger.debug("Simulation started for time interval {}-{}".format( self.start, self.stop)) self.act = self.action + self.rbc_action #self.debug_points[-1*self.n_points:] found = self.dymola.importInitialResult('dsres.mat', atTime=self.start) print(found) x = self.dymola.simulateExtendedModel( self.model_name, startTime=self.start, stopTime=self.stop, initialNames=self.model_input_names + self.rbc_action_names, initialValues=self.act, finalNames=self.model_output_names) finished, state = x if finished == False: print('finished = False') print(self.dymola.getLastError()) state = self.reset() finished = True self.get_state_values() logger.debug("Simulation results: {}".format(state)) return not finished, state def _reward_policy(self): """ Determines reward based on the current environment state. By default, implements simple logic of penalizing for experiment end and rewarding each step. :return: reward associated with the current state """ if self.exception_flag: self.exception_flag = False if self.done: reward = self.negative_reward else: reward = self.positive_reward return reward def get_state_values(self): """ Extracts the values of model outputs at the end of modeling time interval from simulation result :return: Values of model outputs as tuple in order specified in `model_outputs` attribute """ self.data = DyMat.DyMatFile('temp_dir/dsres.mat') for name in self.debug_data: self.debug_data[name] += self.data[name].tolist() for name in self.add_names + self.model_input_names + self.rbc_action_names: if not name in self.debug_data: self.debug_data.update({name: []}) self.debug_data[name] += self.data[name].tolist() return def _set_init_parameter(self): """ Sets initial parameters of a model. :return: environment """ if self.model_parameters is not None: self.model.set(list(self.model_parameters), list(self.model_parameters.values())) return self
def optimierung(liste_minima, liste_maxima, liste_ladephasen, array_names, simulationsdauer, dir_laden_daten, dir_modell_sim, name_modell_sim, Root_simulationsergebnisse, ergebnis_compare): Zyklenanzahl = len(liste_ladephasen) Zyklus = 1 liste_entladephasen = np.zeros(np.shape(liste_ladephasen)) #ein Zyklus bedeutet die Zeitdauer von Anfang eines Minimum bis zum Ende des darauffolgenden Maximums while Zyklus < Zyklenanzahl + 1: print('Aktueller Strompreiszyklus in dem Optimiert wird:', Zyklus) SOC = get_SOC(array_names, liste_ladephasen, Zyklus) entladedauer = get_entladedauer(array_names, SOC, Zyklus) ladedauer = reverse_ladedauer(array_names, SOC, Zyklus) print('SOC', SOC) print('entladedauer', entladedauer) print('ladedauer', ladedauer) liste_ladephasen[Zyklus - 1, 0] = liste_minima[Zyklus - 1] - (ladedauer / (2 * 3600)) liste_ladephasen[Zyklus - 1, 1] = liste_minima[Zyklus - 1] + (ladedauer / (2 * 3600)) print('liste_ladephasen', liste_ladephasen) liste_entladephasen[Zyklus - 1, 0] = liste_maxima[Zyklus - 1] - (entladedauer / (3 * 3600)) # &&& liste_entladephasen[Zyklus - 1, 1] = liste_maxima[Zyklus - 1] + (2 * entladedauer / (3 * 3600)) # &&& print('liste_entladephasen', liste_entladephasen) correct_left_result = correct_left(liste_ladephasen, liste_entladephasen, Zyklus, liste_minima) liste_ladephasen[Zyklus - 1, :] = correct_left_result[0][Zyklus - 1, :] liste_entladephasen[Zyklus - 1, :] = correct_left_result[1][Zyklus - 1, :] print('liste_phasen nach correct left', liste_ladephasen, liste_entladephasen) correct_right_result = correct_right(liste_ladephasen, liste_entladephasen, Zyklus, liste_maxima, liste_minima, array_names) liste_ladephasen[Zyklus - 1, :] = correct_right_result[0][Zyklus - 1, :] liste_entladephasen[Zyklus - 1, :] = correct_right_result[1][Zyklus - 1, :] print('liste_phasen nach correct right', liste_ladephasen, liste_entladephasen) ergebnis = np.array([[0, 0]]) ladedauer_neu = liste_ladephasen[Zyklus - 1, 1] - liste_ladephasen[Zyklus - 1, 0] print('ladedauer_neu_check', ladedauer_neu) better = True opt = 1 #Nummer des Optimierungsdurchgangs in dem jeweiligen Strompreiszyklus while better == True: #solange sich die Stromkosten verkleinern werden die Phasen verkürzt if liste_ladephasen[Zyklus - 1, 0] == 0 and liste_ladephasen[Zyklus - 1, 1] == 0: break ladephase_neu = np.array([[ liste_minima[Zyklus - 1] - (ladedauer_neu / (2)), liste_minima[Zyklus - 1] + (ladedauer_neu / (2)) ]]) SOC_neu = get_SOC(array_names, ladephase_neu, Zyklus) entladedauer_neu = get_entladedauer(array_names, SOC_neu, Zyklus) print('SOC:', SOC_neu) print('entladedauer:', entladedauer_neu) entladephase_neu = np.array([[ liste_maxima[Zyklus - 1] - (entladedauer_neu / (3 * 3600)), liste_maxima[Zyklus - 1] + (2 * entladedauer_neu / (3 * 3600)) ]]) # &&& print('ladephase die getestet wird:', ladephase_neu) print('entladephase die getestet wird:', entladephase_neu) input_laden = merge(ladephase_neu, dir_laden_daten) input_entladen = merge(entladephase_neu, dir_laden_daten) try: #erzeuge Instanz von Dymola dymola = DymolaInterface() dymola.openModel(path=dir_modell_sim) dymola.translateModel(problem=name_modell_sim) dymola.ExecuteCommand("laden.table=" + input_laden) dymola.ExecuteCommand("entladen.table=" + input_entladen) result = dymola.simulateExtendedModel( problem=name_modell_sim, stopTime=simulationsdauer * 3600, method='radau IIa', finalNames=['Stromkosten.y'], resultFile=os.path.join(Root_simulationsergebnisse, 'optimization_test')) Stromkosten = result[1] column = np.array([ladedauer_neu, Stromkosten[0]]) ergebnis = np.vstack((ergebnis, column)) print('aktuelle Stromkosten', Stromkosten[0]) if not result: print("Simulation failed. Below is the translation log.") log = dymola.getLastError() print(log) dymola.plot(["elektrische_leistungsaufnahme.y"]) dymola.ExportPlotAsImage( os.path.join( Root_simulationsergebnisse, "Ergebnis_von" + str(Zyklus) + str(opt) + ".png")) except DymolaException as ex: print("Error: " + str(ex)) if dymola is not None: dymola.close() dymola = None print( 'Optimierungsdurchgang der in dem Entsprechenden Strompreiszyklus durchgeführt wurde', opt) if opt > 1: if ergebnis[opt, 1] < ergebnis[opt - 1, 1]: better = True else: better = False else: better = True print('better:', better) if better == True: liste_ladephasen[Zyklus - 1, :] = ladephase_neu liste_entladephasen[Zyklus - 1, :] = entladephase_neu ladedauer_neu = ladedauer_neu * 0.9 #ladedauer wird um 10% verkürzt opt = opt + 1 if ergebnis[opt - 2, 1] > ergebnis_compare: print('hier_ergebnis', ergebnis) print('hier_ladeph', liste_ladephasen) print('hier_opt', opt) liste_ladephasen[Zyklus - 1, :] = np.zeros((1, 2)) liste_entladephasen[Zyklus - 1, :] = np.zeros((1, 2)) print('hier_ladeph', liste_ladephasen) Zyklus = Zyklus + 1 print('ergebnis_tabelle des Zyklusses', ergebnis) #&&& hier einfügen, dass eine Lade/und Entladephase nur verwendet wird, wenn das ergebnis besser als das vergleichsergebnis ist return liste_ladephasen, liste_entladephasen
def main(): """Create a system and multiple subsystems""" AHU = System.System() subsystems = AHU.GenerateSubSys() """Prepare the working Directory""" os.chdir(Init.path_res) os.mkdir(str(Init.name_wkdir)) os.chdir(str(Init.name_wkdir)) """Create one directory for each of the subsystems and one for the inputs""" for s in subsystems: os.mkdir(s._name) os.mkdir("Inputs") """Load the FMU model, set the experiment and initialize the inputs""" global dymola dymola = None # Work-around for the environment variable sys.path.insert(0, os.path.join(str(Init.path_dymola))) # Import Dymola Package from dymola.dymola_interface import DymolaInterface # Start the interface dymola = DymolaInterface() """ Simulation """ # Open dymola library for lib in Init.path_lib: check1 = dymola.openModel(os.path.join(lib, 'package.mo')) print('Opening successful ' + str(check1)) dymola.cd(Init.path_res + '\\' + Init.name_wkdir) # Translate the model to FMU if Init.create_FMU: dymola.ExecuteCommand('translateModelFMU("' + Init.path_fmu + '", true, "' + Init.name_fmu + '", "1", "cs", false, 0)') else: shutil.copyfile( Init.path_res + "\\" + Init.name_fmu + ".fmu", Init.path_res + '\\' + Init.name_wkdir + '\\' + Init.name_fmu + '.fmu') model = load_fmu(Init.path_res + '\\' + Init.name_wkdir + '\\' + Init.name_fmu + '.fmu') model.set('humidifierWSP1', 0) model.set('valveHRS', 0) model.set('valvePreHeater', 0) model.set('valveHeater', 0) model.set('valveCooler', 0) model.initialize() model.do_step(0, Init.sync_rate) """Variables storing (time) steps""" time_step = Init.sync_rate time_storage = 0 start = time.time() counter = 0 """Variables storing commands""" storage_commands = np.zeros([5, 1]) supplyTemps = [] """There are currently three different options: 1. NC-OPT algorithm 2. NC-OPT algorithm using parallel computing 3. BExMoC algorithm """ """The algorithms work with a discrete *time_step*. In each step, the current measurements are taken using the :func:`GetMeasurements' method. """ while time_step <= Init.sync_rate * Init.stop_time: # Variable for the final commands of all subsystems command_all = [] if Init.algorithm == 'NC_DMPC': if time_step - time_storage >= Init.optimization_interval or time_step == Init.sync_rate: """ Consider the subsystems in multiple iterations, either in parallel or in sequential order """ for k in range(4): command_all = [] if Init.parallelization: def f(s): commands = s.CalcDVvalues(time_step, time_storage, k, model) return commands p = Pool(4) commands = p.map(f, [ subsystems[0], subsystems[1], subsystems[2], subsystems[3], subsystems[4] ]) command_all = commands else: for s in subsystems: commands = s.CalcDVvalues(time_step, time_storage, k, model) print(k, s._name, commands) command_all.append(commands) elif Init.algorithm == 'BExMoC': #Consider each subsystem sequentially for s in subsystems: print(s._name) """The main calculations are carried out by invoking the :func:'CalcDVvalues' method. The BExMoC algorithm exchanges tables between the subsystems in a .mat format""" commands = (s.CalcDVvalues(time_step, time_storage, 0, model)) command_all.append(commands) #Save the look-up tables in .mat files (sio.savemat( (Init.path_res + '\\' + Init.name_wkdir + '\\' + s._name + '\\' + 'DV_lookUpTable' + str(counter) + '.mat'), {'DV_lookUpTable': s.lookUpTables[1]})) (sio.savemat( (Init.path_res + '\\' + Init.name_wkdir + '\\' + s._name + '\\' + 'Costs_lookUpTable' + str(counter) + '.mat'), {'Cost_lookUpTable': s.lookUpTables[0]})) (sio.savemat( (Init.path_res + '\\' + Init.name_wkdir + '\\' + s._name + '\\' + 'Output_Table' + str(counter) + '.mat'), {'Output_Table': s.lookUpTables[2]})) (sio.savemat( (Init.path_res + '\\' + Init.name_wkdir + '\\' + s._name + '\\' + 'command' + str(counter) + '.mat'), {'Output_Table': commands})) #For real time experiments, the excecution needs to be paused if Init.realtime: if time_step > 0: time.sleep(max(Init.sync_rate - time.time() + start, 0)) start = time.time() else: length = len(Init.name) for l, val in enumerate(command_all): if Init.names_DVs[length - l - 1] != None: model.set(Init.names_DVs[length - l - 1], val) print(val) model.do_step(time_step, Init.sync_rate) print('Proceding') if time_step - time_storage >= Init.optimization_interval: time_storage = time_step time_step += Init.sync_rate counter += 1 Objective_Function.CloseDymola()
def _CheckStyle(self): DymolaVersion = self.DymolaVersion from dymola.dymola_interface import DymolaInterface from dymola.dymola_exception import DymolaException import buildingspy.development.regressiontest as u ut = u.Tester(tool=self.tool) if platform.system() == "Windows": dymola = DymolaInterface(showwindow=True) else: dymola = DymolaInterface(dymolapath="/usr/local/bin/dymola") # Load AixLib LibraryCheck = dymola.openModel(self.Library) if LibraryCheck == True: print("Found AixLib Library and start style check") elif LibraryCheck == False: print( "Library Path is wrong. Please Check Path of AixLib Library Path" ) exit(1) # Load ModelManagement if platform.system() == "Windows": dymola.ExecuteCommand( 'cd("C:\Program Files\Dymola ' + DymolaVersion + '\Modelica\Library\ModelManagement 1.1.8\package.moe");') else: dymola.ExecuteCommand( 'cd("/opt/dymola-' + DymolaVersion + '-x86_64/Modelica/Library/ModelManagement 1.1.8/package.moe");' ) # Start CheckLibrary in ModelManagement print("Start Style Check") if self.Changedmodels == False: print("Check package or model " + self.Package) dymola.ExecuteCommand( 'ModelManagement.Check.checkLibrary(false, false, false, true, "' + self.Package + '", translationStructure=false);') Logfile = self.Library.replace( "package.mo", self.Package + "_StyleCheckLog.html") else: changed_model_list = [] list_mo_models = git_models(".mo", self.Package) model_list = list_mo_models.sort_mo_models() for l in model_list: print("Check package or model " + l) path = self.Library.replace("package.mo", "") dymola.ExecuteCommand( 'ModelManagement.Check.checkLibrary(false, false, false, true, "' + l + '", translationStructure=false);') inputfile = path + l + "_StyleCheckLog.html" log = codecs.open(inputfile, "r", encoding='utf8') for line in log: changed_model_list.append(line) log.close() os.remove(inputfile) path_outfile = "ChangedModels_StyleCheckLog.html" all_logs = codecs.open(path + path_outfile, "w", encoding='utf8') for i in changed_model_list: all_logs.write(i) all_logs.close() Logfile = path + path_outfile dymola.close() print("Style Check Complete") return Logfile, model_list
def simulate(simSettings, showWindow=False, closeWindow=True, simID='', seed=0, singleTranslate=True): ''' simSettings => dictionary of setting parameters (see below for details) showWindow => =True to launch Dymola GUI closeWindow => =False to prevent auto-closing of the Dymola GUI when done simID => simulation ID to differentiate output files (e.g., simID_dsres0.mat vs. dsres0.mat) seed => starting seed value for output file naming (e.g., seed+0, ..., seed+len(experiments)) singleTranslate => =True to only translate the model once - !!! If variables needed to be changed require retranslation then add them to problem name. i.e., simSettings['problem']=['Example.Test(var1=1,var2=5)'] or try to set 'annotation(Evaluate=false)' in the model simSettings details: - All settings, besides `=None`, must be enclosed in brackets [] - !!! 'initialNames' and 'initialValues' are set different than others. Specify each variable indepenently. The script will generate the tests and collapse all 'non-standard' keys. - 'problem', 'resultFile', and 'autoLoad' only support 1 or None entries - Only specify 'numberOfIntervals' or 'outputInterval', not both - 'fixedstepsize' is only for fixed step size solvers - showWindow=True and closeWindow=False only a specified number of simulations are retained in memory according, not all simulations. - The experiments generated are a list of dictionaries which are saved as experiments.pickle in the working directory of the Modelica simulation (cwdMOD). To open the pickle in python: with open(os.path.join('PATHTOPICKLE,'experiments.pickle'), 'rb') as handle: experiments = pickle.load(handle) - !!! Settings not specified assume Dymola default settings. Any simulation settings (tolerance, solver, etc.) located in the model are ignored. Default Settings: 'problem' = '' => Modelica file (.mo) to be run (e.g., ['TRANSFORM.Fluid.Examples.RankineCycl'] ) 'startTime' = 0 => Start time of simulation 'stopTime' = 1 => Stop time of simulation 'numberOfIntervals' = 500 => Number of intervals to be saved to result file 'outputInterval' = 0 => Time (seconds) between intervals to be saved to result file 'method' = 'dassl' => Solver 'tolerance' = 0.0001 => Solver tolerance 'fixedstepsize' = 0 => Step size for solver (certain solvers only, e.g., Euler) 'resultFile' = 'dsres.mat' => Name of the result file 'initialNames' = '' => Names of variables in model 'initialValues' = '' => Value of variables in model (len(initialNames) = len(initialValues)) 'finalNames' = '' => Variable for Dymola to print to screen when simulation is finished 'autoLoad' = true => Automatically load (true) the result file into the Dymola plot window Possible Methods: 'methods' = Lsodar, dassl, Euler, Rkfix2, Rkfix3, Rkfix4, Esdirk23a, Esdirk34a, Esdirk45a, Dopri45, Dopri853, Sdirk34hw, Cerk23, Cerk34, Cerk34, Cvode For the current supported solvers and their use see Dymola ''' # Check User Input checkInput(simSettings) try: if int(seed) >= 0: seed = int(seed) else: raise NameError("seedNum must be a positive integer") except: raise NameError("seedNum must be a positive integer") # Modify simID for naminc conventions if simID != '': simID = simID + '_' # Generate all experiment permutations experimentsRaw = genExperimentsRaw(simSettings) # Filter experiments to generate key/value pairs for 'initialNames' and 'initialValues' experiments = genExperiments(experimentsRaw) # Instantiate the Dymola interface and start Dymola dymola = None result_tran = False try: # Open Dymola dymola = DymolaInterface(showwindow=showWindow) # Get working directory cwdMod = dymola.ExecuteCommand( 'Modelica.Utilities.System.getWorkDirectory();') # Translate the model if singleTranslate: result_tran = dymola.translateModel(experiments[0]['problem']) if not result_tran: raise Exception( "Translation failed. Aborting parametric simulation. Investigate model in IDE for details." ) # Run all experiments saveResult = [] j = seed print('Total experiments = {} for simID = "{}"'.format( len(experiments), simID)) print('Experiment numbering started at seed = {}'.format(seed)) for i, value in enumerate(experiments): j = seed + i print('Experiment {} (= {}/{})'.format(j, i + 1, len(experiments))) print(value) # ModelTranslate = "Dymola.Path.To.Your.Model(Dymola.Path.to.Variable=1000)" if not singleTranslate: result_tran = False result_tran = dymola.translateModel(value['problem']) if not result_tran: print( "Translation failed. Aborting parametric simulation. Investigate model in IDE for details." ) break # Simulate the model result = dymola.simulateExtendedModel(**value)[0] # Save the result (success/fail) saveResult.append(result) # Rename the log files and return new log file for debugging ref. dslogNew = renameFiles(simID, j, value, cwdMod, result) # Print last line of error if not result: print( "Simulation failed. Below is the translation log. For more details see: {}" .format(dslogNew)) log = dymola.getLastErrorLog() print('### Log Start ###\n' + log + '### Log End ###') except DymolaException as ex: print(("Error: " + str(ex))) except Exception as inst: print('{}'.format(inst.message)) finally: if dymola is not None: if showWindow == True and closeWindow == False: pass else: dymola.close() if result_tran: # Save experiment dictionary as pickle in cwdMod with open( os.path.join( cwdMod, '{}experiments_{}to{}.pickle'.format(simID, seed, j)), 'wb') as handle: pickle.dump(experiments, handle, protocol=pickle.HIGHEST_PROTOCOL) # Save summary off success/fail (true/false) of simulations with open( os.path.join(cwdMod, '{}summary_{}to{}.txt'.format(simID, seed, j)), 'w') as fil: fil.write('Summary of success/fail (true/false) of experiments\n') for i, val in enumerate(saveResult): fil.write('\t'.join( ['Experiment', '{}'.format(i), '{}'.format(val)]) + '\n')
def _WriteWhiteList(self): #_listAllModel #rootdir = r"D:\Gitlab\modelica-ibpsa\IBPSA" Package = self.Package.replace("AixLib","IBPSA") Package = Package.split(".")[0] Package = Package.replace(".",os.sep) rootdir = "IBPSA"+os.sep+Package ModelList = [] for subdir, dirs, files in os.walk(rootdir): for file in files: filepath = subdir + os.sep + file if filepath.endswith(".mo") and file != "package.mo": model = filepath model = model.replace(os.sep,".") model = model[model.rfind("IBPSA"):model.rfind(".mo")] ModelList.append(model) #_CheckModel from dymola.dymola_interface import DymolaInterface from dymola.dymola_exception import DymolaException import buildingspy.development.regressiontest as u ut = u.Tester(tool = self.tool) ### Set Number of Threads ut.setNumberOfThreads(self.n_pro) ### Set GUI Show ut.showGUI(self.show_gui) ### Set in Batch Mode ut.batchMode(self.batch) ### Sets the Dymola path to activate the GUI if platform.system() == "Windows": dymola = DymolaInterface() else: dymola = DymolaInterface(dymolapath="/usr/local/bin/dymola") ### Writes all information in the log file, not only the last entries #dymola.ExecuteCommand("Advanced.TranslationInCommandLog:=true;") Library = "IBPSA"+os.sep+"IBPSA"+os.sep+"package.mo" dymola.ExecuteCommand("Advanced.TranslationInCommandLog:=true;") dym_sta_lic_available = dymola.ExecuteCommand('RequestOption("Standard");') if not dym_sta_lic_available: dymola.ExecuteCommand('DymolaCommands.System.savelog("Log_NO_DYM_STANDARD_LIC_AVAILABLE.txt");') print("No Dymola License is available") dymola.close() exit(1) else: print("Dymola License is available") PackageCheck = dymola.openModel(Library) if PackageCheck == True: print("Found IBPSA Library and start Checkmodel Tests \n Check Package " + self.Package+" \n") elif PackageCheck == False: print("Library Path is wrong. Please Check Path of IBPSA Library Path") exit(1) ## Check the Package if len(ModelList) == 0: print("Wrong path") exit(1) ErrorList = [] for i in ModelList: result=dymola.checkModel(i) if result == True: print('\n Successful: '+i+'\n') if result == False: print('\ Error: '+i+'\n') Log = dymola.getLastError() print(Log) ErrorList.append(i) dymola.savelog("IBPSA-log.txt") dymola.close() IBPSA_PackageName = [] ### Write the Package Names of IBPSA for i in ModelList: i = i.split(".") i = i[1] if i not in IBPSA_PackageName: IBPSA_PackageName.append(i) filename= "bin"+os.sep+"03_WhiteLists"+os.sep+"WhiteList_CheckModel.txt" file = open(filename,"w") for i in IBPSA_PackageName: List = [] for l in ErrorList: Package = l.split(".")[1] if Package == i: List.append(l) file.write(i+"\n"+str(List)+"\n"+"\n") file.close() print("Write Whitelist")
def _SimulateModel(self): from dymola.dymola_interface import DymolaInterface from dymola.dymola_exception import DymolaException import buildingspy.development.regressiontest as u ut = u.Tester(tool = self.tool) ### Set Number of Threads ut.setNumberOfThreads(self.n_pro) ### Set GUI Show ut.showGUI(self.show_gui) ### Set in Batch Mode ut.batchMode(self.batch) ### Sets the Dymola path to activate the GUI if platform.system() == "Windows": dymola = DymolaInterface() else: dymola = DymolaInterface(dymolapath="/usr/local/bin/dymola") ### Writes all information in the log file, not only the last entries dymola.ExecuteCommand("Advanced.TranslationInCommandLog:=true;") dym_sta_lic_available = dymola.ExecuteCommand('RequestOption("Standard");') if not dym_sta_lic_available: dymola.ExecuteCommand('DymolaCommands.System.savelog("Log_NO_DYM_STANDARD_LIC_AVAILABLE.txt");') print("No Dymola License is available") dymola.close() exit(1) else: print("Dymola License is available") PackageCheck = dymola.openModel(self.Library) if PackageCheck == True: print("Found AixLib Library and start Checkmodel Tests \n Check Package " + self.Package+" \n") elif PackageCheck == None: print("Library Path is wrong. Please Check Path of AixLib Library Path") exit(1) ErrorList = [] if self.Changedmodels == False: ModelList = ValidateTest._listAllExamples(self) if len(ModelList) == 0: print("Wrong Path") exit(0) for i in ModelList: result=dymola.checkModel(i,simulate=True) if result == True: print('\n Successful: '+i+'\n') if result == False: print("Second Check Test") result=dymola.checkModel(i,simulate=True) if result == True: print('\n Successful: '+i+'\n') if result == False: ErrorList.append(i) Log = dymola.getLastError() print('\n Error: '+i+'\n') print(Log) if self.Changedmodels == True: list_path = 'bin'+os.sep+'03_WhiteLists'+os.sep+'changedmodels.txt' list_mo_models = git_models(".mo",self.Package, list_path) model_list= list_mo_models.sort_mo_models() ErrorList = [] for i in model_list: result=dymola.checkModel(i,simulate=True) if result == True: print('\n Successful: '+i+'\n') if result == False: print("Second Check Test") result=dymola.checkModel(i,simulate=True) if result == True: print('\n Successful: '+i+'\n') if result == False: ErrorList.append(i) Log = dymola.getLastError() print('\n Error: '+i+'\n') print(Log) dymola.savelog(self.Package+"-log.txt") dymola.close() logfile = self.Package+"-log.txt" ValidateTest._WriteErrorlog(self,logfile) return ErrorList
def _WriteWhiteList(): #_listAllModel rootdir = r"D:\Gitlab\modelica-ibpsa\IBPSA" #rootdir = self.Package ModelList = [] for subdir, dirs, files in os.walk(rootdir): for file in files: filepath = subdir + os.sep + file if filepath.endswith(".mo") and file != "package.mo": model = filepath if platform.system() == "Windows": model = model.replace("\\", ".") else: model = model.replace("//", ".") model = model[model.rfind("IBPSA"):model.rfind(".mo")] ModelList.append(model) #_CheckModel from dymola.dymola_interface import DymolaInterface from dymola.dymola_exception import DymolaException import buildingspy.development.regressiontest as u #ut = u.Tester(tool = self.tool) ### Set Number of Threads #ut.setNumberOfThreads(self.n_pro) ### Set GUI Show #ut.showGUI(self.show_gui) ### Set in Batch Mode #ut.batchMode(self.batch) ### Sets the Dymola path to activate the GUI if platform.system() == "Windows": dymola = DymolaInterface() else: dymola = DymolaInterface(dymolapath="/usr/local/bin/dymola") ### Writes all information in the log file, not only the last entries dymola.ExecuteCommand("Advanced.TranslationInCommandLog:=true;") Library = "IBPSA/package.mo" PackageCheck = dymola.openModel(Library) if PackageCheck == True: print( "Found AixLib Library and start Checkmodel Tests \n Check Package " + self.Package + " \n") elif PackageCheck == None: print( "Library Path is wrong. Please Check Path of AixLib Library Path") exit(1) ## Check the Package ErrorList = [] for i in ModelList: result = dymola.checkModel(i) if result == True: print('\n Check of Package ' + i + ' was Successful! \n') #dymola.close() #return 0 #exit(0) if result == False: #print('\n ModelCheck Failed in Package ' + i + ' Show Savelog \n') ErrorList.append(i) #print(Log) #dymola.clearlog() #dymola.close() #return 1 #exit(1)""" dymola.close() IBPSA_PackageName = [] ### Write the Package Names of IBPSA for i in ModelList: i = i.split(".") i = i[1] if i not in IBPSA_PackageName: IBPSA_PackageName.append(i) filename = r"D:\Gitlab\GitLabCI\WhiteLists\CheckModel\WhiteList_CheckModel.txt" file = open(filename, "w") for i in IBPSA_PackageName: List = [] for l in ModelList: Package = l.split(".")[1] if Package == i: List.append(l) file.write(i + "\n" + str(List) + "\n" + "\n") file.close() print("Write Whitelist")
def list_regression_tests(self): ### List all models, that have changed before changed_model_list = Extended_model.list_changed_models(self) ## List and compare all regression examples that have changed, but no changes in the used classes regression_model_list = Extended_model.list_changed_examples( self, changed_model_list) models_test_regression = [] if platform.system() == "Windows": _setEnvironmentVariables( "PATH", os.path.join(os.path.abspath('.'), "Resources", "Library", "win32")) sys.path.insert( 0, os.path.join('C:\\', 'Program Files', 'Dymola ' + self.DymolaVersion, 'Modelica', 'Library', 'python_interface', 'dymola.egg')) print("operating system Windows") else: print("operating system Linux") _setEnvironmentVariables( "LD_LIBRARY_PATH", os.path.join(os.path.abspath('.'), "Resources", "Library", "linux32") + ":" + os.path.join(os.path.abspath('.'), "Resources", "Library", "linux64")) sys.path.insert( 0, os.path.join('opt', 'dymola-' + self.DymolaVersion + '-x86_64', 'Modelica', 'Library', 'python_interface', 'dymola.egg')) sys.path.append( os.path.join(os.path.abspath('.'), "..", "..", "BuildingsPy")) if len(regression_model_list) == 0: print("No modified regression models") exit(0) else: ## Load AixLib Library DymolaVersion = self.DymolaVersion from dymola.dymola_interface import DymolaInterface from dymola.dymola_exception import DymolaException if platform.system() == "Windows": dymola = DymolaInterface(showwindow=True) else: dymola = DymolaInterface(dymolapath="/usr/local/bin/dymola") # Load AixLib LibraryCheck = dymola.openModel(self.library) if LibraryCheck == True: print("Found AixLib Library and regression test starts") elif LibraryCheck == False: print( "Library Path is wrong. Please Check Path of AixLib Library Path" ) exit(1) # Load ModelManagement if platform.system() == "Windows": dymola.ExecuteCommand( 'cd("C:\Program Files\Dymola ' + self.DymolaVersion + '\Modelica\Library\ModelManagement 1.1.8\package.moe");') else: dymola.ExecuteCommand( 'cd("/opt/dymola-' + self.DymolaVersion + '-x86_64/Modelica/Library/ModelManagement 1.1.8/package.moe");' ) ### Modified regression examples for l in regression_model_list: ## Search for all used classes in the example ## Start CheckLibrary in ModelManagement usedmodels = dymola.ExecuteCommand( 'ModelManagement.Structure.Instantiated.UsedModels("' + l + '");') #extendedmodels = dymola.ExecuteCommand('ModelManagement.Structure.AST.ExtendsInClass("'+l+'");') regression_model = Extended_model.compare_change_used_models( self, usedmodels, l, changed_model_list) if regression_model is None: continue elif len(regression_model) > 0: models_test_regression.append(regression_model) dymola.close() if len(models_test_regression) > 0: print( "These models have been changed and a regression test is started" ) for l in models_test_regression: print('Check Example "' + l + '"') return models_test_regression