def start(self, start_time, time_step_input_ref='-1'): """ Starts the FMU :param start_time: not used in this blueprint :param time_step_input_ref: optional value for custom time_step input """ if int(time_step_input_ref) >= 0: self.time_step_input_ref = int(time_step_input_ref) # with open(os.devnull, 'w') as outfile: # os.dup2(outfile.fileno(), 1) print("self.file", self.file, "path", os.path.realpath("./"), "unzipdirectory", fmpy.extract(self.file, os.path.realpath('./'))) self.fmu = fmi2.FMU2Slave( guid=self.model_description.guid, unzipDirectory=fmpy.extract(self.file, os.path.realpath('./')), modelIdentifier=self.model_description.coSimulation. modelIdentifier, instanceName=os.path.basename(os.path.realpath(os.curdir))) print("insantiated fmu") self.fmu.instantiate() self.fmu.setupExperiment(startTime=self.t) self.fmu.enterInitializationMode() self.fmu.exitInitializationMode()
def compile_platform_binary(filename, output_filename=None, target_platform=None, compiler_options=None): """ Compile the binary of an FMU for the current platform and add it to the FMU Parameters: filename: filename of the source code FMU output_filename: filename of the FMU with the compiled binary (None: overwrite existing FMU) compiler_options: custom compiler options """ from . import read_model_description, extract, platform, platform_tuple import zipfile from shutil import copyfile, rmtree from os.path import join, basename, relpath, exists, normpath, isfile, splitext unzipdir = extract(filename) model_description = read_model_description(filename) if target_platform is None: target_platform = platform if model_description.fmiVersion in ['1.0', '2.0'] else platform_tuple binary = compile_dll(model_description=model_description, sources_dir=join(unzipdir, 'sources'), target_platform=target_platform, compiler_options=compiler_options) unzipdir2 = extract(filename) target_platform_dir = join(unzipdir2, 'binaries', target_platform) if not exists(target_platform_dir): os.makedirs(target_platform_dir) copyfile(src=binary, dst=join(target_platform_dir, basename(binary))) debug_database = splitext(binary)[0] + '.pdb' if isfile(debug_database): copyfile(src=debug_database, dst=join(target_platform_dir, basename(debug_database))) if output_filename is None: output_filename = filename # overwrite the existing archive # create a new archive from the existing files + compiled binary with zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED) as zf: base_path = normpath(unzipdir2) for dirpath, dirnames, filenames in os.walk(unzipdir2): for name in sorted(dirnames): path = normpath(join(dirpath, name)) zf.write(path, relpath(path, base_path)) for name in filenames: path = normpath(join(dirpath, name)) if isfile(path): zf.write(path, relpath(path, base_path)) # clean up rmtree(unzipdir, ignore_errors=True) rmtree(unzipdir2, ignore_errors=True)
def create_cmake_project(filename, project_dir): """ Create a CMake project from a C code FMU Parameters: filename filename of the C code FMU project_dir existing directory for the CMake project """ from zipfile import ZipFile from fmpy import read_model_description, extract model_description = read_model_description(filename) extract(filename, unzipdir=project_dir) fmpy_dir = os.path.dirname(__file__) source_dir = os.path.join(fmpy_dir, 'c-code') with open(os.path.join(source_dir, 'CMakeLists.txt'), 'r') as cmake_file: txt = cmake_file.read() definitions = [] if model_description.coSimulation is not None: definitions.append('CO_SIMULATION') if model_description.modelExchange is not None: definitions.append('MODEL_EXCHANGE') with ZipFile(filename, 'r') as archive: # don't add the current directory resources = list( filter(lambda n: not n.startswith('.'), archive.namelist())) # always add the binaries resources.append('binaries') # use the first source file set of the first build configuration build_configuration = model_description.buildConfigurations[0] source_file_set = build_configuration.sourceFileSets[0] sources = ['sources/' + file for file in source_file_set.sourceFiles] # substitute the variables txt = txt.replace('%MODEL_NAME%', model_description.modelName) txt = txt.replace('%MODEL_IDENTIFIER%', build_configuration.modelIdentifier) txt = txt.replace('%DEFINITIONS%', ' '.join(definitions)) txt = txt.replace('%INCLUDE_DIRS%', '"' + source_dir.replace('\\', '/') + '"') txt = txt.replace('%SOURCES%', ' '.join(sources)) txt = txt.replace('%RESOURCES%', '\n '.join('"' + r + '"' for r in resources)) with open(os.path.join(project_dir, 'CMakeLists.txt'), 'w') as outfile: outfile.write(txt)
def create_cmake_project(filename, project_dir): """ Create a CMake project from a C code FMU Parameters: filename filename of the C code FMU project_dir existing directory for the CMake project """ from fmpy import read_model_description, extract import shutil model_description = read_model_description(filename) extract(filename, unzipdir=project_dir) fmpy_dir = os.path.dirname(__file__) source_dir = os.path.join(fmpy_dir, 'c-code', 'fmi2') # copy the FMI headers and the source FMU wrapper for source_file in [ 'fmi2_wrapper.c', 'fmi2Functions.h', 'fmi2FunctionTypes.h', 'fmi2TypesPlatform.h' ]: shutil.copy(os.path.join(source_dir, source_file), os.path.join(project_dir, 'sources')) with open(os.path.join(source_dir, 'CMakeLists.txt'), 'r') as cmake_file: txt = cmake_file.read() definitions = [] if model_description.coSimulation is not None: implementation = model_description.coSimulation definitions.append('CO_SIMULATION') else: implementation = model_description.modelExchange if model_description.modelExchange is not None: definitions.append('MODEL_EXCHANGE') sources = ['modelDescription.xml', 'sources/fmi2_wrapper.c'] sources += ['sources/' + file for file in implementation.sourceFiles] # substitute the variables txt = txt.replace('%MODEL_NAME%', model_description.modelName) txt = txt.replace('%MODEL_IDENTIFIER%', implementation.modelIdentifier) txt = txt.replace('%DEFINITIONS%', ' '.join(definitions)) txt = txt.replace('%SOURCES%', ' '.join(sources)) with open(os.path.join(project_dir, 'CMakeLists.txt'), 'w') as outfile: outfile.write(txt)
def compile_platform_binary(filename, output_filename=None): """ Compile the binary of an FMU for the current platform and add it to the FMU Parameters: filename: filename of the source code FMU output_filename: filename of the FMU with the compiled binary (None: overwrite existing FMU) """ from . import read_model_description, extract, platform import zipfile from shutil import copyfile, rmtree unzipdir = extract(filename) md = read_model_description(filename) binary = compile_dll(model_description=md, sources_dir=os.path.join(unzipdir, 'sources')) unzipdir2 = extract(filename) platform_dir = os.path.join(unzipdir2, 'binaries', platform) # if os.path.exists(platform_dir): # rmtree(platform_dir) if not os.path.exists(platform_dir): os.makedirs(platform_dir) copyfile(src=binary, dst=os.path.join(platform_dir, os.path.basename(binary))) if output_filename is None: output_filename = filename # overwrite the existing archive # create a new archive from the existing files + compiled binary with zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED) as zf: base_path = os.path.normpath(unzipdir2) for dirpath, dirnames, filenames in os.walk(unzipdir2): for name in sorted(dirnames): path = os.path.normpath(os.path.join(dirpath, name)) zf.write(path, os.path.relpath(path, base_path)) for name in filenames: path = os.path.normpath(os.path.join(dirpath, name)) if os.path.isfile(path): zf.write(path, os.path.relpath(path, base_path)) # clean up rmtree(unzipdir) rmtree(unzipdir2)
def reference_fmus_repo_dir(resources_dir): version = '0.0.14' checksum = '93ffb56774b15130b6993d345dff1795ddce7872706c0b4d8f4d8edd361a8a7a' zip_file = download_file( url= f'https://github.com/modelica/Reference-FMUs/archive/v{version}.zip', checksum=checksum) extract(filename=zip_file, unzipdir=resources_dir) repo_dir = resources_dir / f'Reference-FMUs-{version}' yield repo_dir
def reference_fmus_dist_dir(resources_dir): version = '0.0.16' checksum = '9817c0ee19c8648ae681a4529bac805542743c29ab81f643165e2c828eb2beed' zip_file = download_file( url= f'https://github.com/modelica/Reference-FMUs/releases/download/v{version}/Reference-FMUs-{version}.zip', checksum=checksum) dist_dir = resources_dir / 'Reference-FMUs-dist' extract(filename=zip_file, unzipdir=dist_dir) yield dist_dir
def get_fmu(self): import shutil from fmpy import read_model_description, extract from fmpy.fmi2 import FMU2Slave shutil.copyfile(self.orig_fmu_path, self.dest_fmu_path) # read the model description self.model_description = read_model_description(self.dest_fmu_path) # collect the value references self.vrs = {} for variable in self.model_description.modelVariables: self.vrs[variable.name] = variable.valueReference #print(variable) # extract the FMU self.unzipdir = extract(self.dest_fmu_path) self.contr_sys = FMU2Slave(guid=self.model_description.guid, unzipDirectory=self.unzipdir, modelIdentifier=self.model_description. coSimulation.modelIdentifier, instanceName='instance1') #print(self.contr_sys) self.contr_sys.instantiate() self.contr_sys.setupExperiment(startTime=0.0) self.contr_sys.enterInitializationMode() self.contr_sys.exitInitializationMode()
def simulate_with_input(): # os.chdir(r"C:\arash\PHD\IEA Projects\Annex\common exercise\ajab") os.chdir(path="C:/Users/gerar/PycharmProjects/untitled1/venv/Scripts") fmuf = 'TwinHouses71_new.fmu' start_time = 30463200 # stop_time = 31676400 # step_size = 3600 #dump(fmuf) model_description = read_model_description(fmuf) vrs = {} for variable in model_description.modelVariables: vrs[variable.name] = variable.valueReference # print(variable) vr_output1 = vrs['Tav'] # temperature vr_output2 = vrs['hp_el'] # heat pump consumption vr_input1 = vrs['hp_s'] # heat pump status vr_input2 = vrs['hp_wt'] # heat water temperature #vr_outputs2 =vrs['lagtemp'] #hourly lagged temperature unzipdir = extract(fmuf) fmu = FMU2Slave( guid=model_description.guid, modelIdentifier=model_description.coSimulation.modelIdentifier, unzipDirectory=unzipdir, instanceName='instance1') fmu.instantiate() fmu.setupExperiment(startTime=start_time) fmu.enterInitializationMode() fmu.exitInitializationMode() # fmu.callbacks # output1=20 return fmu, vr_input1, vr_input2, vr_output1, vr_output2
def instantiate_fmu(component, ssp_unzipdir, start_time, parameters={}): fmu_filename = os.path.join(ssp_unzipdir, component.source) component.unzipdir = extract(fmu_filename) # read the model description model_description = read_model_description(fmu_filename, validate=False) # collect the value references component.variables = {} for variable in model_description.modelVariables: # component.vrs[variable.name] = variable.valueReference component.variables[variable.name] = variable fmu_kwargs = { 'guid': model_description.guid, 'unzipDirectory': component.unzipdir, 'modelIdentifier': model_description.coSimulation.modelIdentifier, 'instanceName': component.name } if model_description.fmiVersion == '1.0': component.fmu = FMU1Slave(**fmu_kwargs) component.fmu.instantiate() set_parameters(component, parameters) component.fmu.initialize() else: component.fmu = FMU2Slave(**fmu_kwargs) component.fmu.instantiate() component.fmu.setupExperiment(startTime=start_time) set_parameters(component, parameters) component.fmu.enterInitializationMode() component.fmu.exitInitializationMode()
def __init__(self, path_fmu): # define the model name and simulation parameters start_time = 0.0 stop_time = 10.0 self.step_size = 1e-2 # read the model description model_description = read_model_description(path_fmu) # collect the value references vrs = {} for variable in model_description.modelVariables: vrs[variable.name] = variable.valueReference # get the value references for the variables we want to get/set self.vr_inputs = vrs['u'] self.vr_output = vrs['Out1'] # extract the FMU unzipdir = extract(path_fmu) self.fmu = FMU2Slave( guid=model_description.guid, unzipDirectory=unzipdir, modelIdentifier=model_description.coSimulation.modelIdentifier, instanceName='instance1') # initialize self.fmu.instantiate() self.fmu.setupExperiment(startTime=start_time) self.fmu.enterInitializationMode() self.fmu.exitInitializationMode() self.time = start_time
def create_cmake_project(filename, project_dir): """ Create a CMake project from a C code FMU Parameters: filename filename of the C code FMU project_dir existing directory for the CMake project """ from fmpy import read_model_description, extract model_description = read_model_description(filename) extract(filename, unzipdir=project_dir) fmpy_dir = os.path.dirname(__file__) source_dir = os.path.join(fmpy_dir, 'c-code') with open(os.path.join(source_dir, 'CMakeLists.txt'), 'r') as cmake_file: txt = cmake_file.read() definitions = [] if model_description.coSimulation is not None: implementation = model_description.coSimulation definitions.append('CO_SIMULATION') else: implementation = model_description.modelExchange if model_description.modelExchange is not None: definitions.append('MODEL_EXCHANGE') # use the first source file set of the first build configuration source_file_set = implementation.buildConfigurations[0].sourceFileSets[0] sources = ['sources/' + file for file in source_file_set.sourceFiles] # substitute the variables txt = txt.replace('%MODEL_NAME%', model_description.modelName) txt = txt.replace('%MODEL_IDENTIFIER%', implementation.modelIdentifier) txt = txt.replace('%DEFINITIONS%', ' '.join(definitions)) txt = txt.replace('%INCLUDE_DIRS%', '"' + source_dir.replace('\\', '/') + '"') txt = txt.replace('%SOURCES%', ' '.join(sources)) with open(os.path.join(project_dir, 'CMakeLists.txt'), 'w') as outfile: outfile.write(txt)
def runSimulation(): # extract the FMU to a temporary directory unzipdir = fmpy.extract(fmu) # read the model description model_description = fmpy.read_model_description(unzipdir) # instantiate the FMU fmu_instance = fmpy.instantiate_fmu(unzipdir, model_description, 'CoSimulation') cf = fun_lib.importCostFunction(dir = 'Combined\\') params = readInitParams() cost = 1e300 # shuffledParams = copy. for iter in range(niter): # todo paralelize this cur_params = shuffleParams(params) # reset the FMU instance instead of creating a new one fmu_instance.reset() result = fmpy.simulate_fmu(unzipdir, stop_time=1, start_values=cur_params, model_description=model_description, fmu_instance=fmu_instance, fmi_call_logger=lambda s: print('[FMI] ' + s) ) var_set = {} for name in result.dtype.names: var_set[name] = result[name] if DRAW_PLOTS: var_set['__draw_plots'] = True var_set['__plot_title'] = "Run %i" % (fun_lib.getRunNumber()) var_set['__saveFig_path'] = "%sFitFig_%03d.png" % (fun_lib.getSafeLogDir('Schedules'), fun_lib.getRunNumber()) objectives = cf.getObjectives(var_set, targetsFolder = r"../data/Valsalva/") cur_cost = fun_lib.countTotalSumCost(objectives) if cur_cost < cost: # woohoo, better costs! cost = cur_cost params = cur_params writeSchedule(params, cost, iter) print(result) # free the FMU instance and unload the shared library fmu_instance.freeInstance() # delete the temporary directory shutil.rmtree(unzipdir, ignore_errors=True) print('that is all, folks') pass
def END_fmu(fmu): unzipdir = extract(fmuf) fmu.terminate() fmu.freeInstance() shutil.rmtree(unzipdir) return
def test_get_directional_derivative(self): fmu_filename = 'Rectifier.fmu' download_test_file('2.0', 'CoSimulation', 'Dymola', '2017', 'Rectifier', fmu_filename) model_description = read_model_description(filename=fmu_filename) unzipdir = extract(fmu_filename) fmu = FMU2Slave( guid=model_description.guid, unzipDirectory=unzipdir, modelIdentifier=model_description.coSimulation.modelIdentifier) fmu.instantiate() fmu.setupExperiment() fmu.enterInitializationMode() # get the partial derivative for an initial unknown unknown = model_description.initialUnknowns[1] self.assertEqual('iAC[1]', unknown.variable.name) vrs_unknown = [unknown.variable.valueReference] vrs_known = [v.valueReference for v in unknown.dependencies] dv_known = [1.0] * len(unknown.dependencies) partial_der = fmu.getDirectionalDerivative(vUnknown_ref=vrs_unknown, vKnown_ref=vrs_known, dvKnown=dv_known) self.assertEqual([-2.0], partial_der) fmu.exitInitializationMode() # get the partial derivative for three output variables unknowns = model_description.outputs[4:7] self.assertEqual(['uAC[1]', 'uAC[2]', 'uAC[3]'], [u.variable.name for u in unknowns]) vrs_unknown = [u.variable.valueReference for u in unknowns] vrs_known = [v.valueReference for v in unknowns[0].dependencies] dv_known = [1.0] * len(vrs_known) partial_der = fmu.getDirectionalDerivative(vUnknown_ref=vrs_unknown, vKnown_ref=vrs_known, dvKnown=dv_known) self.assertAlmostEqual(-1500, partial_der[0]) self.assertAlmostEqual(0, partial_der[1]) self.assertAlmostEqual(1500, partial_der[2]) fmu.terminate() fmu.freeInstance() rmtree(unzipdir)
def add_remoting(filename): from . import extract, read_model_description, supported_platforms from shutil import copyfile, rmtree import zipfile import os platforms = supported_platforms(filename) if 'win32' not in platforms: raise Exception("The FMU does not support the platform \"win32\".") if 'win64' in platforms: raise Exception("The FMU already supports \"win64\".") model_description = read_model_description(filename) current_dir = os.path.dirname(__file__) client = os.path.join(current_dir, 'remoting', 'client.dll') server = os.path.join(current_dir, 'remoting', 'server.exe') license = os.path.join(current_dir, 'remoting', 'license.txt') tempdir = extract(filename) if model_description.coSimulation is not None: model_identifier = model_description.coSimulation.modelIdentifier else: model_identifier = model_description.modelExchange.modelIdentifier # copy the binaries & license os.mkdir(os.path.join(tempdir, 'binaries', 'win64')) copyfile( client, os.path.join(tempdir, 'binaries', 'win64', model_identifier + '.dll')) copyfile(server, os.path.join(tempdir, 'binaries', 'win64', 'server.exe')) licenses_dir = os.path.join(tempdir, 'documentation', 'licenses') if not os.path.isdir(licenses_dir): os.mkdir(licenses_dir) copyfile( license, os.path.join(tempdir, 'documentation', 'licenses', 'fmpy-remoting-binaries.txt')) # create a new archive from the existing files + remoting binaries with zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED) as zf: base_path = os.path.normpath(tempdir) for dirpath, dirnames, filenames in os.walk(tempdir): for name in sorted(dirnames): path = os.path.normpath(os.path.join(dirpath, name)) zf.write(path, os.path.relpath(path, base_path)) for name in filenames: path = os.path.normpath(os.path.join(dirpath, name)) if os.path.isfile(path): zf.write(path, os.path.relpath(path, base_path)) # clean up rmtree(tempdir, ignore_errors=True)
def initialize(self): """Initializes simulation object. Instantiates FMPy FMUSalve1 or FMUSlave2 object based on FMI version detected. """ init_time = str(time.time())[0:10] random_id = str(uuid.uuid4().fields[-1])[:7] fmu_path = os.path.join(self.runs_path, init_time + "_" + random_id) os.mkdir(fmu_path) self.unzipdir = extract(self.fmu_file, unzipdir=fmu_path) weather_folder = Path(self.unzipdir) / "resources" possible_weather_files = list(weather_folder.rglob("*.mos")) + list( weather_folder.rglob("*.epw") ) weather_default_file_path = weather_folder / possible_weather_files[0] try: os.remove(weather_default_file_path) shutil.copy(self.weather_file_path, weather_default_file_path) except BaseException as e: logging.error(e) logging.error("Problem with the weather file handling") # initialize instance_name = "instance" + init_time # model identifier if self.fmi_type == "modex": model_id = self.model_description.modelExchange.modelIdentifier else: model_id = self.model_description.coSimulation.modelIdentifier kwargs = dict( guid=self.model_description.guid, unzipDirectory=self.unzipdir, modelIdentifier=model_id, instanceName=instance_name, ) if self.fmi_version == "1.0": if self.fmi_type == "cosim": self.fmu = FMU1Slave(**kwargs) else: self.fmu = FMU1Model(**kwargs) elif self.fmi_version == "2.0": if self.fmi_type == "cosim": self.fmu = FMU2Slave(**kwargs) else: self.fmu = FMU2Model(**kwargs) self.fmu.instantiate(loggingOn=True) if self.fmi_version == "2.0": self.fmu.setupExperiment(startTime=self.start_time, stopTime=self.stop_time) # Initialize time and the last_output values self.time = self.start_time
def load_fmu(instance_name, path): """A function to read an FMU and go through default initialization""" mdl_desc = fmpy.read_model_description(path) unzip_dir = fmpy.extract(path) fmu = FMU2Slave(instanceName=instance_name, guid=mdl_desc.guid, modelIdentifier=mdl_desc.coSimulation.modelIdentifier, unzipDirectory=unzip_dir) return Slave(mdl_desc, fmu)
def __init__(self, fmu_path, step_size, stop_time, timestamp_key, start_time=None, target_keys=None, input_keys=None, control_keys=None): """Loads and executes Functional Mockup Unit (FMU) modules Handles FMU archives adhering to the Functional Mockup Interface standard 2.0 as a part of a digital twin experiment. We make extensive use of FMPY library. The full FMI spec can be found at https://fmi-standard.org/ Args: fmu_path (str): Path to the FMI-compliant zip-archive start_time (float): Value of time variable supplied to the FMU at the first timestep of the simulation. None (def) translates to 0.0 stop_time (float): (Optional) final value of the time variable in the simulation. A valid FMU will report an error state if master tries to simulate past stop_time step_size (float): The default communication step size for the model. Can be be overridden in individual calls to step method to accommodate dynamical stepping timestamp_key: String identifier of the timestamp key target_keys (List(str)): Dependent variable names in the simulation input_keys (List(str)): Independent variable names in the simulation control_keys (List(str)): (Optional) Variable names e.g. for validating the simulation output, in meas-vs-sim style """ super(FMUModelHandler, self).__init__(target_keys=target_keys, input_keys=input_keys, control_keys=control_keys) self.model_description = read_model_description(fmu_path) self.fmu_filename = fmu_path self.start_time = 0 if start_time is None else start_time # TODO parse default stop_time from model_description self.stop_time = stop_time # TODO parse default step_size from model_description self.step_size = step_size # TODO should make this work with datetimes as well as integers self.timestamp_key = timestamp_key self.unzipdir = extract(fmu_path) self.vrs = {} self._fmu = None self._vr_input = None self._vr_output = None self._get_value_references()
def __init__(self, file: str): self.file = file logger.info('Opening twin %s in %s', self.file, os.getcwd()) self.model_description = read_model_description(file) self.variables = ModelVariables(self.model_description) self.unzipped_directory = extract(file) self.fmu = FMU2Slave(guid=self.model_description.guid, unzipDirectory=self.unzipped_directory, modelIdentifier=self.model_description. coSimulation.modelIdentifier, instanceName='instance') self.running = False self.time = 0
async def initialize(request): global FACTORY global FMU global TIME global RESULTS if request.body_exists: data = await request.read() data = json.loads(data.decode("utf-8")) # ??? FACTORY["pathToFMU"] = data["target"] FACTORY["modelDescription"] = fm.read_model_description( FACTORY["pathToFMU"]) FACTORY["unzipdir"] = fm.extract(FACTORY["pathToFMU"]) # Get variable references and input variables FACTORY["vrs"] = {} for variable in FACTORY["modelDescription"].modelVariables: FACTORY["vrs"][variable.name] = variable.valueReference if variable.causality == "input": FACTORY["inputVars"][variable.name] = None FMU = FMU2Slave(guid=FACTORY["modelDescription"].guid, unzipDirectory=FACTORY["unzipdir"], modelIdentifier=FACTORY["modelDescription"]. coSimulation.modelIdentifier, instanceName="instance1") ### ### ### ### ### ### # Init FMU FACTORY["startTime"] = data["startTime"] FACTORY["endTime"] = data["endTime"] FACTORY["stepSize"] = data["stepSize"] TIME = FACTORY["startTime"] RESULTS = [] # list to record the results FMU.instantiate() FMU.setupExperiment(startTime=FACTORY["startTime"]) FMU.enterInitializationMode() FMU.exitInitializationMode() return web.json_response({"description": "Service initialized."}, status=200) return web.json_response({"description": "Wrong init information"}, status=500)
def test_serialize_fmu_state(self): fmu_filename = 'Rectifier.fmu' # download the FMU download_test_file('2.0', 'cs', 'MapleSim', '2016.2', 'Rectifier', fmu_filename) # read the model description model_description = read_model_description(fmu_filename) # extract the FMU unzipdir = extract(fmu_filename) # instantiate the FMU fmu = FMU2Slave( guid=model_description.guid, unzipDirectory=unzipdir, modelIdentifier=model_description.coSimulation.modelIdentifier) # initialize fmu.instantiate() fmu.setupExperiment() fmu.enterInitializationMode() fmu.exitInitializationMode() # get the FMU state state = fmu.getFMUstate() # serialize the FMU state serialized_state = fmu.serializeFMUstate(state) # de-serialize the FMU state fmu.deSerializeFMUstate(serialized_state, state) # set the FMU state fmu.setFMUstate(state) # free the FMU state fmu.freeFMUstate(state) fmu.terminate() fmu.freeInstance() # clean up shutil.rmtree(unzipdir)
def change_fmu(input_file, output_file=None, start_values={}): """ Make changes to an FMU """ from lxml import etree import zipfile from fmpy import extract from shutil import rmtree if output_file is None: output_file = input_file tempdir = extract(input_file) # read the model description with zipfile.ZipFile(input_file, 'r') as zf: xml = zf.open('modelDescription.xml') tree = etree.parse(xml) root = tree.getroot() # apply the start values for variable in root.find('ModelVariables'): if variable.get("name") in start_values: for child in variable.getchildren(): if child.tag in [ 'Real', 'Integer', 'Enumeration', 'Boolean', 'String' ]: child.set('start', start_values[variable.get("name")]) # write the new model description tree.write(os.path.join(tempdir, 'modelDescription.xml')) # create a new archive from the modified files with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as zf: base_path = os.path.normpath(tempdir) for dirpath, dirnames, filenames in os.walk(tempdir): for name in sorted(dirnames): path = os.path.normpath(os.path.join(dirpath, name)) zf.write(path, os.path.relpath(path, base_path)) for name in filenames: path = os.path.normpath(os.path.join(dirpath, name)) if os.path.isfile(path): zf.write(path, os.path.relpath(path, base_path)) # clean up rmtree(tempdir, ignore_errors=True)
def unpack_model(f): """Unpack the model from file expand_path(f). This sets module variables tmp and fmu to point at a newly created tempfile.TemporaryDirectory and the extracted fmu, respectively. It also registers an atexit hook to remove tmp. Does nothing if tmp and fmu are already set to non-None values. """ global tmp, fmu if tmp is None: atexit.register(cleanup) tmp = tempfile.TemporaryDirectory() fmu = None if fmu is None: fmu = fmpy.extract(expand_path(f), tmp.name) logger.info("Extracted FMU to %s", fmu)
def __init__(self, fmupath, outputs=None, states=None, parameters=None, verbose=False): """ :param fmupath: str, path to FMU :param outputs: list(str), monitored outputs names :param states: list(str), monitored states names :param parameters: dict, parameters names and values :param verbose: bool, whether to suppress pyfmi prints """ if parameters is None: parameters = {} if states is None: states = [] if outputs is None: outputs = [] self.logger = logging.getLogger(type(self).__name__) print(fmupath) self.logger.debug("Loading FMU") # Load FMU model_description = read_model_description(fmupath) self.model_description = model_description self.unzipdir = extract(fmupath) self.fmupath = fmupath self.fmu = instantiate_fmu(self.unzipdir, model_description) self.outputs = outputs self.states = states self.parameters = parameters self.verbose = verbose # Get initial state # Comment: # The model has to be initialized to read the state variables. #dummy_result = self.fmu.initialize(tStart=0, stopTime=None) self.fmu.setupExperiment(startTime=0) self.fmu.enterInitializationMode() self.fmu.exitInitializationMode() self.x0 = self._get_state() # Reset the FMU self.fmu.reset()
def setUpClass(cls): # store various useful FMU arguments from the model description cls._model_description = read_model_description(fmu_path) cls._fmi_types = [] if cls._model_description.coSimulation is not None: cls._fmi_types.append('CoSimulation') if cls._model_description.modelExchange is not None: cls._fmi_types.append('ModelExchange') if not cls._fmi_types: raise Exception('fmi_type must contain at least "ModelExchange" or "CoSimulation"') cls._experiment = cls._model_description.defaultExperiment if cls._experiment is not None and cls._experiment.startTime is not None: cls._start_time = cls._experiment.startTime else: cls._start_time = 0.0 start_time = float(cls._start_time) if cls._experiment is not None and cls._experiment.stopTime is not None: cls._stop_time = cls._experiment.stopTime else: cls._stop_time = start_time + 1.0 stop_time = float(cls._stop_time) if cls._experiment is not None: cls._relative_tolerance = cls._experiment.tolerance total_time = stop_time - start_time cls._step_size = 10 ** (np.round(np.log10(total_time)) - 3) if 'CoSimulation' in cls._fmi_types and cls._experiment is not None and cls._experiment.stepSize is not None: cls._output_interval = cls._experiment.stepSize while (stop_time - start_time) / cls._output_interval > 1000: cls._output_interval *= 2 if path.isfile(path.join(fmu_path, 'modelDescription.xml')): cls._unzipdir = fmu_path cls._tempdir = None else: cls._tempdir = extract(fmu_path) cls._unzipdir = cls._tempdir
def setup(self): self.t_next = self.start_time if self.exist: self.unzipDir = self.fmu_location else: self.unzipDir = extract(self.fmu_location) self.modelDescription = read_model_description(self.fmu_location, validate=self.validate) self.is_fmi1 = self.modelDescription.fmiVersion == '1.0' logger = printLogMessage if self.is_fmi1: callbacks = fmi1CallbackFunctions() callbacks.logger = fmi1CallbackLoggerTYPE(logger) callbacks.allocateMemory = fmi1CallbackAllocateMemoryTYPE(allocateMemory) callbacks.freeMemory = fmi1CallbackFreeMemoryTYPE(freeMemory) callbacks.stepFinished = None else: callbacks = fmi2CallbackFunctions() callbacks.logger = fmi2CallbackLoggerTYPE(logger) callbacks.allocateMemory = fmi2CallbackAllocateMemoryTYPE(allocateMemory) callbacks.freeMemory = fmi2CallbackFreeMemoryTYPE(freeMemory) #define var values for input and output variables self.vrs = {} for variable in self.modelDescription.modelVariables: self.vrs[variable.name] = [variable.valueReference, variable.type] if self.is_fmi1: self.fmu = FMU1Slave(guid = self.modelDescription.guid, unzipDirectory=self.unzipDir, modelIdentifier=self.modelDescription.coSimulation.modelIdentifier, instanceName=self.instanceName) self.fmu.instantiate(functions=callbacks) else: self.fmu = FMU2Slave(guid = self.modelDescription.guid, unzipDirectory=self.unzipDir, modelIdentifier=self.modelDescription.coSimulation.modelIdentifier, instanceName=self.instanceName) self.fmu.instantiate(callbacks=callbacks) self.fmu.setupExperiment(startTime=self.start_time, tolerance=self.tolerance) self.input = Input(self.fmu, self.modelDescription, None)
def instantiate_fmu(component, ssp_unzipdir, start_time, stop_time=None, parameter_set=None): """ Instantiate an FMU """ fmu_filename = os.path.join(ssp_unzipdir, component.source) component.unzipdir = extract(fmu_filename) # read the model description model_description = read_model_description(fmu_filename, validate=False) if model_description.coSimulation is None: raise Exception("%s does not support co-simulation." % component.source) # collect the value references component.variables = {} for variable in model_description.modelVariables: # component.vrs[variable.name] = variable.valueReference component.variables[variable.name] = variable fmu_kwargs = { 'guid': model_description.guid, 'unzipDirectory': component.unzipdir, 'modelIdentifier': model_description.coSimulation.modelIdentifier, 'instanceName': component.name } if model_description.fmiVersion == '1.0': component.fmu = FMU1Slave(**fmu_kwargs) component.fmu.instantiate() if parameter_set is not None: set_parameters(component, parameter_set) component.fmu.initialize(stopTime=stop_time) else: component.fmu = FMU2Slave(**fmu_kwargs) component.fmu.instantiate() component.fmu.setupExperiment(startTime=start_time) if parameter_set is not None: set_parameters(component, parameter_set) component.fmu.enterInitializationMode() component.fmu.exitInitializationMode()
def test_extracted_fmu(self): """ Simulate an extracted FMU """ download_test_file('2.0', 'cs', 'MapleSim', '2016.2', 'CoupledClutches', 'CoupledClutches.fmu') # extract the FMU tempdir = extract('CoupledClutches.fmu') # load the model description before the simulation model_description = read_model_description(tempdir) result = simulate_fmu(tempdir, model_description=model_description) self.assertIsNotNone(result) # clean up shutil.rmtree(tempdir)
def initFmus() -> list: fmu_init = [] for model_info in model_infos: (prefix, cf_folder, fmu) = model_info # extract the FMU to a temporary directory unzipdir = fmpy.extract(fmu) # read the model description model_description = fmpy.read_model_description(unzipdir) # instantiate the FMU fmu_instance = fmpy.instantiate_fmu(unzipdir, model_description, 'CoSimulation') # fmu_instance = fmpy.instantiate_fmu(unzipdir, model_description, 'CoSimulation', debug_logging=True, fmi_call_logger=logger, visible=True) # TODO this might be obsolete atm cf = fun_lib.importCostFunction(dir='..\\' + cf_folder + '\\') fmu_init.append((fmu_instance, model_description, cf, prefix)) return fmu_init